From fa76d09a9d94c7750a26f3f62c1c6fd2a811432d Mon Sep 17 00:00:00 2001 From: Roman Khlopkov <roman.khlopkov@demlabs.net> Date: Sat, 30 May 2020 03:32:07 +0300 Subject: [PATCH] [+] Cashback in srv_pay tx --- modules/chain/dap_chain_ledger.c | 29 ++++++----- modules/chain/include/dap_chain_ledger.h | 3 +- .../dap_stream_ch_chain_net_srv.c | 14 +++--- modules/mempool/dap_chain_mempool.c | 48 +++++++++++++++++-- 4 files changed, 69 insertions(+), 25 deletions(-) diff --git a/modules/chain/dap_chain_ledger.c b/modules/chain/dap_chain_ledger.c index af1201fd20..6c1d7bf8be 100644 --- a/modules/chain/dap_chain_ledger.c +++ b/modules/chain/dap_chain_ledger.c @@ -1672,15 +1672,17 @@ const dap_chain_datum_tx_t* dap_chain_ledger_tx_find_by_pkey(dap_ledger_t *a_led * a_addr[in] wallet address, whose owner can use the service */ dap_chain_datum_tx_t* dap_chain_ledger_tx_cache_find_out_cond(dap_ledger_t *a_ledger, - dap_chain_addr_t *a_addr, dap_chain_hash_fast_t *a_tx_first_hash) + dap_chain_hash_fast_t *a_tx_first_hash, dap_chain_tx_out_cond_t **a_out_cond, int *a_out_cond_idx) { - if(!a_addr || !a_tx_first_hash) + if (!a_tx_first_hash) return NULL; dap_ledger_private_t *l_ledger_priv = PVT(a_ledger); dap_chain_datum_tx_t *l_cur_tx = NULL; bool is_null_hash = dap_hash_fast_is_blank(a_tx_first_hash); bool is_search_enable = is_null_hash; dap_chain_ledger_tx_item_t *l_iter_current, *l_item_tmp; + dap_chain_tx_out_cond_t *l_tx_out_cond; + int l_tx_out_cond_idx; pthread_rwlock_wrlock(&l_ledger_priv->ledger_rwlock); HASH_ITER(hh, l_ledger_priv->ledger_items, l_iter_current, l_item_tmp) { @@ -1692,10 +1694,8 @@ dap_chain_datum_tx_t* dap_chain_ledger_tx_cache_find_out_cond(dap_ledger_t *a_le is_search_enable = true; continue; } - // Get sign item from transaction - int l_tx_out_cond_size = 0; - dap_chain_tx_out_cond_t *l_tx_out_cond = (dap_chain_tx_out_cond_t*) dap_chain_datum_tx_item_get( - l_tx_tmp, NULL, TX_ITEM_TYPE_OUT_COND, &l_tx_out_cond_size); + // Get out_cond item from transaction + l_tx_out_cond = dap_chain_datum_tx_out_cond_get(l_tx_tmp, &l_tx_out_cond_idx); if(l_tx_out_cond) { l_cur_tx = l_tx_tmp; @@ -1704,6 +1704,12 @@ dap_chain_datum_tx_t* dap_chain_ledger_tx_cache_find_out_cond(dap_ledger_t *a_le } } pthread_rwlock_unlock(&l_ledger_priv->ledger_rwlock); + if (a_out_cond) { + *a_out_cond = l_tx_out_cond; + } + if (a_out_cond_idx) { + *a_out_cond_idx = l_tx_out_cond_idx; + } return l_cur_tx; } @@ -1727,22 +1733,21 @@ uint64_t dap_chain_ledger_tx_cache_get_out_cond_value(dap_ledger_t *a_ledger, da //memcpy(&l_tx_first_hash, 0, sizeof(dap_chain_hash_fast_t)); /* size_t l_pub_key_size = a_key_from->pub_key_data_size; uint8_t *l_pub_key = dap_enc_key_serealize_pub_key(a_key_from, &l_pub_key_size);*/ - + dap_chain_tx_out_cond_t *l_tx_out_cond; // Find all transactions do { - l_tx_tmp = dap_chain_ledger_tx_cache_find_out_cond(a_ledger, a_addr, &l_tx_first_hash); + + l_tx_tmp = dap_chain_ledger_tx_cache_find_out_cond(a_ledger, &l_tx_first_hash, &l_tx_out_cond, NULL); // Get out_cond item from transaction if(l_tx_tmp) { - dap_chain_tx_out_cond_t *l_tx_out_cond =(dap_chain_tx_out_cond_t *)dap_chain_datum_tx_item_get( - l_tx_tmp, NULL, TX_ITEM_TYPE_OUT_COND, NULL); - + UNUSED(a_addr); // TODO check relations a_addr with cond_data and public key if(l_tx_out_cond) { l_ret_value += l_tx_out_cond->header.value; if(tx_out_cond) - *tx_out_cond = (dap_chain_tx_out_cond_t*) l_tx_out_cond; + *tx_out_cond = l_tx_out_cond; } } } while(l_tx_tmp); diff --git a/modules/chain/include/dap_chain_ledger.h b/modules/chain/include/dap_chain_ledger.h index 7639ead95a..1265e7f55f 100644 --- a/modules/chain/include/dap_chain_ledger.h +++ b/modules/chain/include/dap_chain_ledger.h @@ -175,8 +175,7 @@ const dap_chain_datum_tx_t* dap_chain_ledger_tx_find_by_pkey(dap_ledger_t *a_led char *a_public_key, size_t a_public_key_size, dap_chain_hash_fast_t *a_tx_first_hash); // Get the transaction in the cache with the out_cond item -dap_chain_datum_tx_t* dap_chain_ledger_tx_cache_find_out_cond(dap_ledger_t *a_ledger, - dap_chain_addr_t *a_addr, dap_chain_hash_fast_t *a_tx_first_hash); +dap_chain_datum_tx_t* dap_chain_ledger_tx_cache_find_out_cond(dap_ledger_t *a_ledger, dap_chain_hash_fast_t *a_tx_first_hash, dap_chain_tx_out_cond_t **a_out_cond, int *a_out_cond_used); // Get the value from all transactions in the cache with out_cond item uint64_t dap_chain_ledger_tx_cache_get_out_cond_value(dap_ledger_t *a_ledger, dap_chain_addr_t *a_addr, diff --git a/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.c b/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.c index bccec32e88..0ffa340dc7 100644 --- a/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.c +++ b/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.c @@ -432,27 +432,27 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg) char * l_tx_in_hash_str = dap_chain_hash_fast_to_str_new(l_tx_in_hash); log_it(L_NOTICE, "Formed tx %s for input with active receipt", l_tx_in_hash_str); - - // We could put transaction directly to chains + /* We could put transaction directly to chains if ( dap_chain_net_get_role( l_usage->net ).enums == NODE_ROLE_MASTER || dap_chain_net_get_role( l_usage->net ).enums == NODE_ROLE_CELL_MASTER || dap_chain_net_get_role( l_usage->net ).enums == NODE_ROLE_ROOT || dap_chain_net_get_role( l_usage->net ).enums == NODE_ROLE_ROOT_MASTER ){ dap_chain_net_proc_mempool( l_usage->net); - } + }*/ DAP_DELETE(l_tx_in_hash_str); }else log_it(L_ERROR, "Can't create input tx cond transaction!"); - if (l_tx_in_hash) - DAP_DELETE(l_tx_in_hash); - size_t l_success_size = sizeof (dap_stream_ch_chain_net_srv_pkt_success_hdr_t ); + size_t l_success_size = sizeof(dap_stream_ch_chain_net_srv_pkt_success_hdr_t) + sizeof(dap_chain_hash_fast_t); dap_stream_ch_chain_net_srv_pkt_success_t *l_success = DAP_NEW_Z_SIZE(dap_stream_ch_chain_net_srv_pkt_success_t, l_success_size); l_success->hdr.usage_id = l_usage->id; l_success->hdr.net_id.uint64 = l_usage->net->pub.id.uint64; l_success->hdr.srv_uid.uint64 = l_usage->service->uid.uint64; - + if (l_tx_in_hash) { + memcpy(l_success->custom_data, l_tx_in_hash, sizeof(dap_chain_hash_fast_t)); + DAP_DELETE(l_tx_in_hash); + } dap_stream_ch_pkt_write( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_SUCCESS , l_success, l_success_size); DAP_DELETE(l_success); diff --git a/modules/mempool/dap_chain_mempool.c b/modules/mempool/dap_chain_mempool.c index d103711c10..343fe26bbe 100644 --- a/modules/mempool/dap_chain_mempool.c +++ b/modules/mempool/dap_chain_mempool.c @@ -361,23 +361,64 @@ dap_chain_hash_fast_t* dap_chain_mempool_tx_create_cond_input(dap_chain_net_t * uint16_t pos=0; dap_chain_datum_tx_add_item(&l_tx, (byte_t*) l_receipt); pos++; + uint64_t l_value_send = l_receipt->receipt_info.value_datoshi; // add 'in_cond' items - dap_chain_datum_tx_t *l_cond_tx = dap_chain_ledger_tx_find_by_hash(l_ledger, a_tx_prev_hash); + dap_chain_datum_tx_t *l_tx_cond = dap_chain_ledger_tx_find_by_hash(l_ledger, a_tx_prev_hash); int l_prev_cond_idx; - dap_chain_datum_tx_out_cond_get(l_cond_tx, &l_prev_cond_idx); + dap_chain_tx_out_cond_t *l_out_cond = dap_chain_datum_tx_out_cond_get(l_tx_cond, &l_prev_cond_idx); + if (dap_chain_ledger_tx_hash_is_used_out_item(l_ledger, a_tx_prev_hash, l_prev_cond_idx)) { + dap_chain_datum_tx_t *l_tx_tmp; + dap_chain_hash_fast_t l_tx_cur_hash = { 0 }; // start hash + dap_chain_tx_out_cond_t *l_tmp_cond; + uint64_t l_value_cond = 0; + int l_tmp_cond_idx; + // Find all transactions + while (l_value_cond < l_value_send) { + l_tx_tmp = dap_chain_ledger_tx_cache_find_out_cond(l_ledger, &l_tx_cur_hash, &l_tmp_cond, &l_tmp_cond_idx); + if (!l_tx_tmp) { + break; + } + if (dap_chain_ledger_tx_hash_is_used_out_item(l_ledger, &l_tx_cur_hash, l_tmp_cond_idx)) + continue; + if (l_tmp_cond->header.subtype != l_out_cond->header.subtype) + continue; + if (l_tmp_cond->subtype.srv_pay.srv_uid.uint64 != l_out_cond->subtype.srv_pay.srv_uid.uint64) + continue; + if (l_tmp_cond->subtype.srv_pay.unit.uint32 != l_out_cond->subtype.srv_pay.unit.uint32) + continue; + if (l_tmp_cond->subtype.srv_pay.unit_price_max_datoshi != l_out_cond->subtype.srv_pay.unit_price_max_datoshi) + continue; + if (memcmp(&l_tmp_cond->subtype.srv_pay.pkey_hash, &l_out_cond->subtype.srv_pay.pkey_hash, sizeof(dap_chain_hash_fast_t))) + continue; + l_value_cond = l_tmp_cond->header.value; + } + if (l_value_cond < l_value_send) { + log_it(L_WARNING, "Requested conditional transaction is already used out"); + return NULL; + } + } if (dap_chain_datum_tx_add_in_cond_item(&l_tx, a_tx_prev_hash, l_prev_cond_idx, pos-1) != 0 ){ dap_chain_datum_tx_delete(l_tx); log_it( L_ERROR, "Cant add tx cond input"); return NULL; } - if(dap_chain_datum_tx_add_out_item(&l_tx, a_addr_to, l_receipt->receipt_info.value_datoshi) != 1) { + // add 'out' item + if (dap_chain_datum_tx_add_out_item(&l_tx, a_addr_to, l_value_send) != 1) { dap_chain_datum_tx_delete(l_tx); log_it( L_ERROR, "Cant add tx output"); return NULL; } + //add 'out_cond' item + size_t l_size = dap_chain_datum_item_tx_get_size((uint8_t *)l_out_cond); + dap_chain_tx_out_cond_t *l_out_cond_new = DAP_NEW_Z_SIZE(dap_chain_tx_out_cond_t, l_size); + memcpy(l_out_cond_new, l_out_cond, l_size); + l_out_cond_new->header.value -= l_value_send; + dap_chain_datum_tx_add_item(&l_tx, (const uint8_t *)l_out_cond_new); + DAP_DELETE(l_out_cond_new); + // add 'sign' items if (l_key_tx_sign){ if(dap_chain_datum_tx_add_sign_item(&l_tx, l_key_tx_sign) != 1) { @@ -874,7 +915,6 @@ void chain_mempool_proc(struct dap_http_simple *cl_st, void * arg) { dap_datum_mempool_free(datum_mempool); char *a_key = calc_datum_hash(request_str, (size_t) request_size); - char *a_value; switch (action) { case DAP_DATUM_MEMPOOL_ADD: // add datum in base -- GitLab