From 2fc6f709d9ae124470fad658d0e7cab7d542de3d Mon Sep 17 00:00:00 2001 From: Roman Khlopkov <roman.khlopkov@demlabs.net> Date: Fri, 28 Feb 2025 18:47:58 +0700 Subject: [PATCH] [*] Condition owner collect & check corrections --- dap-sdk | 2 +- modules/net/dap_chain_ledger.c | 304 ++++++------------ modules/net/include/dap_chain_ledger.h | 22 +- .../service/voting/dap_chain_net_srv_voting.c | 65 ++-- 4 files changed, 133 insertions(+), 260 deletions(-) diff --git a/dap-sdk b/dap-sdk index d9b03ffb93..3491640b76 160000 --- a/dap-sdk +++ b/dap-sdk @@ -1 +1 @@ -Subproject commit d9b03ffb93d4003cb1a33c6470612a7f88ad6005 +Subproject commit 3491640b76de5715eb3936ccd377abd51d88b99e diff --git a/modules/net/dap_chain_ledger.c b/modules/net/dap_chain_ledger.c index 1a883dd8dd..03fcb33ba6 100644 --- a/modules/net/dap_chain_ledger.c +++ b/modules/net/dap_chain_ledger.c @@ -288,8 +288,6 @@ typedef struct dap_ledger_private { #define PVT(a) ( (dap_ledger_private_t *) a->_internal ) -static dap_ledger_tx_item_t* tx_item_find_by_addr(dap_ledger_t *a_ledger, - const dap_chain_addr_t *a_addr, const char * a_token, dap_chain_hash_fast_t *a_tx_first_hash); static void s_threshold_emissions_proc( dap_ledger_t * a_ledger); static void s_threshold_txs_proc( dap_ledger_t * a_ledger); static void s_threshold_txs_free(dap_ledger_t *a_ledger); @@ -5273,8 +5271,8 @@ uint256_t dap_ledger_calc_balance_full(dap_ledger_t *a_ledger, const dap_chain_a * a_public_key_size[in] public key size * a_tx_first_hash [in/out] hash of the initial transaction/ found transaction, if 0 start from the beginning */ -static dap_ledger_tx_item_t *tx_item_find_by_addr(dap_ledger_t *a_ledger, const dap_chain_addr_t *a_addr, - const char * a_token, dap_chain_hash_fast_t *a_tx_first_hash) +dap_chain_datum_tx_t *dap_ledger_tx_find_by_addr(dap_ledger_t *a_ledger, const char *a_token, + const dap_chain_addr_t *a_addr, dap_chain_hash_fast_t *a_tx_first_hash) { if(!a_addr || !a_tx_first_hash) return NULL; @@ -5331,20 +5329,7 @@ static dap_ledger_tx_item_t *tx_item_find_by_addr(dap_ledger_t *a_ledger, const break; } pthread_rwlock_unlock(&l_ledger_pvt->ledger_rwlock); - return is_tx_found ? l_iter_current : NULL; -} - -/** - * @brief dap_ledger_tx_find_by_addr - * @param a_addr - * @param a_tx_first_hash - * @return - */ - dap_chain_datum_tx_t* dap_ledger_tx_find_by_addr(dap_ledger_t *a_ledger , const char * a_token , - const dap_chain_addr_t *a_addr, dap_chain_hash_fast_t *a_tx_first_hash) -{ - dap_ledger_tx_item_t* l_tx_item = tx_item_find_by_addr(a_ledger, a_addr, a_token, a_tx_first_hash); - return (l_tx_item) ? l_tx_item->tx : NULL; + return is_tx_found ? l_iter_current->tx : NULL; } bool dap_ledger_tx_check_recipient(dap_ledger_t* a_ledger, dap_chain_hash_fast_t* a_tx_prev_hash, dap_chain_addr_t *a_addr) @@ -5374,52 +5359,6 @@ static dap_ledger_tx_item_t *tx_item_find_by_addr(dap_ledger_t *a_ledger, const return false; } -/** - * Get the transaction in the cache by the public key that signed the transaction, - * starting from the next hash after a_tx_first_hash - * - * a_public_key[in] public key that signed the transaction - * a_public_key_size[in] public key size - * a_tx_first_hash [in/out] hash of the initial transaction/ found transaction, if 0 start from the beginning - */ -const dap_chain_datum_tx_t* dap_ledger_tx_find_by_pkey(dap_ledger_t *a_ledger, - char *a_public_key, size_t a_public_key_size, dap_chain_hash_fast_t *a_tx_first_hash) -{ - if(!a_public_key || !a_tx_first_hash) - return NULL; - dap_ledger_private_t *l_ledger_pvt = 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_ledger_tx_item_t *l_iter_current, *l_item_tmp; - pthread_rwlock_rdlock(&l_ledger_pvt->ledger_rwlock); - HASH_ITER(hh, l_ledger_pvt->ledger_items , l_iter_current, l_item_tmp) { - dap_chain_datum_tx_t *l_tx_tmp = l_iter_current->tx; - dap_chain_hash_fast_t *l_tx_hash_tmp = &l_iter_current->tx_hash_fast; - // start searching from the next hash after a_tx_first_hash - if (!is_search_enable) { - is_search_enable = dap_hash_fast_compare(l_tx_hash_tmp, a_tx_first_hash); - continue; - } - // Get sign item from transaction - dap_chain_tx_sig_t *l_tx_sig = (dap_chain_tx_sig_t*) dap_chain_datum_tx_item_get(l_tx_tmp, NULL, - NULL, TX_ITEM_TYPE_SIG, NULL); - // Get dap_sign_t from item - dap_sign_t *l_sig = dap_chain_datum_tx_item_sign_get_sig(l_tx_sig); - if(l_sig) { - // compare public key in transaction with a_public_key - if(a_public_key_size == l_sig->header.sign_pkey_size && - !memcmp(a_public_key, l_sig->pkey_n_sign, a_public_key_size)) { - l_cur_tx = l_tx_tmp; - memcpy(a_tx_first_hash, l_tx_hash_tmp, sizeof(dap_chain_hash_fast_t)); - break; - } - } - } - pthread_rwlock_unlock(&l_ledger_pvt->ledger_rwlock); - return l_cur_tx; -} - /** * @brief Get all transactions from the cache with the out_cond item * @param a_ledger @@ -5442,93 +5381,6 @@ dap_list_t* dap_ledger_tx_cache_find_out_cond_all(dap_ledger_t *a_ledger, dap_ch return l_ret; } - -/** - * Get the transaction in the cache with the out_cond item - * - * a_addr[in] wallet address, whose owner can use the service - */ -dap_chain_datum_tx_t* dap_ledger_tx_cache_find_out_cond(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_subtype_t a_cond_type, - dap_chain_hash_fast_t *a_tx_first_hash, dap_chain_tx_out_cond_t **a_out_cond, int *a_out_cond_idx, char *a_token_ticker) -{ - if (!a_tx_first_hash) - return NULL; - dap_ledger_private_t *l_ledger_pvt = 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_ledger_tx_item_t *l_iter_current = NULL, *l_item_tmp = NULL; - dap_chain_tx_out_cond_t *l_tx_out_cond = NULL; - int l_tx_out_cond_idx = 0; - pthread_rwlock_rdlock(&l_ledger_pvt->ledger_rwlock); - HASH_ITER(hh, l_ledger_pvt->ledger_items, l_iter_current, l_item_tmp) { - dap_chain_datum_tx_t *l_tx_tmp = l_iter_current->tx; - dap_chain_hash_fast_t *l_tx_hash_tmp = &l_iter_current->tx_hash_fast; - // start searching from the next hash after a_tx_first_hash - if (!is_search_enable) { - is_search_enable = dap_hash_fast_compare(l_tx_hash_tmp, a_tx_first_hash); - continue; - } - // Get out_cond item from transaction - l_tx_out_cond = dap_chain_datum_tx_out_cond_get(l_tx_tmp, a_cond_type, &l_tx_out_cond_idx); - - if(l_tx_out_cond) { - l_cur_tx = l_tx_tmp; - memcpy(a_tx_first_hash, l_tx_hash_tmp, sizeof(dap_chain_hash_fast_t)); - if (a_token_ticker) { - strcpy(a_token_ticker, l_iter_current->cache_data.token_ticker); - } - break; - } - } - pthread_rwlock_unlock(&l_ledger_pvt->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; -} - -/** - * Get the value from all transactions in the cache with out_cond item - * - * a_addr[in] wallet address, whose owner can use the service - * a_sign [in] signature of a_addr hash for check valid key - * a_sign_size [in] signature size - * - * a_public_key[in] public key that signed the transaction - * a_public_key_size[in] public key size - */ -uint256_t dap_ledger_tx_cache_get_out_cond_value(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_subtype_t a_cond_type, - dap_chain_addr_t *a_addr, dap_chain_tx_out_cond_t **tx_out_cond) - -{ - uint256_t l_ret_value = {}; - - dap_chain_datum_tx_t *l_tx_tmp; - dap_chain_hash_fast_t l_tx_first_hash = { 0 }; // start hash - /* size_t l_pub_key_size = a_key_from->pub_key_data_size; - uint8_t *l_pub_key = dap_enc_key_serialize_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_ledger_tx_cache_find_out_cond(a_ledger, a_cond_type, &l_tx_first_hash, &l_tx_out_cond, NULL, NULL); - // Get out_cond item from transaction - if(l_tx_tmp) { - 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 = l_tx_out_cond; - } - } - } while(l_tx_tmp); - return l_ret_value; -} - /** * @brief dap_ledger_get_list_tx_outs_with_val * @param a_ledger @@ -5784,7 +5636,7 @@ dap_chain_datum_tx_t *dap_ledger_datum_iter_get_last(dap_ledger_datum_iter_t *a_ { dap_ledger_private_t *l_ledger_pvt = PVT(a_iter->net->pub.ledger); pthread_rwlock_rdlock(&l_ledger_pvt->ledger_rwlock); - a_iter->cur_ledger_tx_item = l_ledger_pvt->ledger_items->hh.prev; + a_iter->cur_ledger_tx_item = HASH_LAST(l_ledger_pvt->ledger_items); a_iter->cur = ((dap_ledger_tx_item_t *)(a_iter->cur_ledger_tx_item))->tx; a_iter->cur_hash = ((dap_ledger_tx_item_t *)(a_iter->cur_ledger_tx_item))->tx_hash_fast; a_iter->is_unspent = ((dap_ledger_tx_item_t *)(a_iter->cur_ledger_tx_item))->cache_data.ts_spent ? false : true; @@ -5793,72 +5645,116 @@ dap_chain_datum_tx_t *dap_ledger_datum_iter_get_last(dap_ledger_datum_iter_t *a_ return a_iter->cur; } - /** - * @brief dap_ledger_get_list_tx_cond_outs_with_val - * @param a_ledger - * @param a_token_ticker - * @param a_addr_from - * @param a_subtype - * @param a_value_need - * @param a_value_transfer - * @return + * Get the transaction in the cache by the addr in sig item + * + * a_addr[in] public key that signed the transaction + * a_tx_first_hash [in/out] hash of the initial transaction/ found transaction, if 0 start from the beginning */ -dap_list_t *dap_ledger_get_list_tx_cond_outs_with_val(dap_ledger_t *a_ledger, const char *a_token_ticker, const dap_chain_addr_t *a_addr_from, - dap_chain_tx_out_cond_subtype_t a_subtype, uint256_t a_value_need, uint256_t *a_value_transfer) +dap_chain_tx_out_cond_t *dap_ledger_out_cond_unspent_find_by_addr(dap_ledger_t *a_ledger, const char *a_token, dap_chain_tx_out_cond_subtype_t a_subtype, + const dap_chain_addr_t *a_addr, dap_chain_hash_fast_t *a_tx_first_hash, int *a_out_idx) { - dap_list_t *l_list_used_out = NULL; // list of transaction with 'out' items - dap_chain_hash_fast_t l_tx_cur_hash = { 0 }; - uint256_t l_value_transfer = { }; - dap_chain_datum_tx_t *l_tx; - while( compare256(l_value_transfer, a_value_need) == -1 - && ( l_tx = dap_ledger_tx_find_by_addr(a_ledger, a_token_ticker, a_addr_from, &l_tx_cur_hash)) ) - { - byte_t *it; size_t l_size; int i, l_out_idx_tmp = -1; - TX_ITEM_ITER_TX_TYPE(it, TX_ITEM_TYPE_OUT_COND, l_size, i, l_tx) { - ++l_out_idx_tmp; - dap_chain_tx_out_cond_t *l_out_cond = (dap_chain_tx_out_cond_t*) it; - if (a_subtype != l_out_cond->header.subtype || IS_ZERO_256(l_out_cond->header.value) ) - continue; - dap_chain_tx_used_out_item_t *l_item = DAP_NEW_Z(dap_chain_tx_used_out_item_t); - *l_item = (dap_chain_tx_used_out_item_t) { l_tx_cur_hash, (uint32_t)l_out_idx_tmp, l_out_cond->header.value }; - l_list_used_out = dap_list_append(l_list_used_out, l_item); - SUM_256_256(l_value_transfer, l_item->value, &l_value_transfer); - // already accumulated the required value, finish the search for 'out' items - if ( compare256(l_value_transfer, a_value_need) != -1 ) { + if (!a_addr || !a_token) + return NULL; + dap_ledger_private_t *l_ledger_pvt = PVT(a_ledger); + dap_chain_tx_out_cond_t *ret = NULL; + dap_ledger_tx_item_t *l_iter_start = NULL, *it; + pthread_rwlock_rdlock(&l_ledger_pvt->ledger_rwlock); + if (a_tx_first_hash && !dap_hash_fast_is_blank(a_tx_first_hash)) { + HASH_FIND(hh, l_ledger_pvt->ledger_items, a_tx_first_hash, sizeof(dap_hash_t), l_iter_start); + if (!l_iter_start || !l_iter_start->hh.next) { + pthread_rwlock_unlock(&l_ledger_pvt->ledger_rwlock); + return NULL; + } + // start searching from the next hash after a_tx_first_hash + l_iter_start = l_iter_start->hh.next; + } else + l_iter_start = l_ledger_pvt->ledger_items; + for (it = l_iter_start; it; it = it->hh.next) { + // If a_token is setup we check if its not our token - miss it + if (*it->cache_data.token_ticker && dap_strcmp(it->cache_data.token_ticker, a_token)) + continue; + ret = NULL; + // Get 'out_cond' item from transaction + byte_t *l_item; size_t l_size; int i, l_out_idx = 0; + TX_ITEM_ITER_TX_TYPE(l_item, TX_ITEM_TYPE_OUT_ALL, l_size, i, it->tx) { + if (*l_item == TX_ITEM_TYPE_OUT_COND && + ((dap_chain_tx_out_cond_t *)l_item)->header.subtype == a_subtype) { + ret = (dap_chain_tx_out_cond_t *)l_item; break; } + l_out_idx++; + } + // Don't return regular tx or spent conditions + if (!ret || !dap_hash_fast_is_blank(&it->cache_data.tx_hash_spent_fast[l_out_idx])) + continue; + dap_hash_fast_t l_owner_tx_hash = dap_ledger_get_first_chain_tx_hash(a_ledger, it->tx, a_subtype); + dap_chain_datum_tx_t *l_tx = dap_ledger_tx_find_by_hash(a_ledger, &l_owner_tx_hash); + if (!l_tx) { + log_it(L_ERROR, "Can't find owner for tx %s", dap_hash_fast_to_str_static(&it->tx_hash_fast)); + continue; + } + // Get sign item from transaction + dap_chain_tx_sig_t *l_tx_sig = (dap_chain_tx_sig_t*) dap_chain_datum_tx_item_get(l_tx, NULL, NULL, TX_ITEM_TYPE_SIG, NULL); + // Get dap_sign_t from item + dap_sign_t *l_sign = dap_chain_datum_tx_item_sign_get_sig(l_tx_sig); + // compare public key in transaction with a_public_key + dap_chain_hash_fast_t l_sign_hash = {}; + dap_sign_get_pkey_hash(l_sign, &l_sign_hash); + if (dap_hash_fast_compare(&l_sign_hash, &a_addr->data.hash_fast)) { + if (a_tx_first_hash) + *a_tx_first_hash = it->tx_hash_fast; + if (a_out_idx) + *a_out_idx = l_out_idx; + break; } } - return compare256(l_value_transfer, a_value_need) > -1 && l_list_used_out - ? ({ if (a_value_transfer) *a_value_transfer = l_value_transfer; l_list_used_out; }) - : ( dap_list_free_full(l_list_used_out, NULL), NULL ); + pthread_rwlock_unlock(&l_ledger_pvt->ledger_rwlock); + return ret; } -dap_list_t *dap_ledger_get_list_tx_cond_outs(dap_ledger_t *a_ledger, const char *a_token_ticker, const dap_chain_addr_t *a_addr_from, - dap_chain_tx_out_cond_subtype_t a_subtype, uint256_t *a_value_transfer) +dap_list_t *dap_ledger_get_list_tx_cond_outs(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_subtype_t a_subtype, + const char *a_token_ticker, const dap_chain_addr_t *a_addr_from) { dap_list_t *l_list_used_out = NULL; // list of transaction with 'out' items dap_chain_hash_fast_t l_tx_cur_hash = { }; - uint256_t l_value_transfer = { }; - dap_chain_datum_tx_t *l_tx; - while(( l_tx = dap_ledger_tx_find_by_addr(a_ledger, a_token_ticker, a_addr_from, &l_tx_cur_hash) )) { - byte_t *it; size_t l_size; int i, l_out_idx_tmp = -1; - TX_ITEM_ITER_TX_TYPE(it, TX_ITEM_TYPE_OUT_COND, l_size, i, l_tx) { - ++l_out_idx_tmp; - dap_chain_tx_out_cond_t *l_out_cond = (dap_chain_tx_out_cond_t*)it; - if ( a_subtype != l_out_cond->header.subtype || IS_ZERO_256(l_out_cond->header.value) ) - continue; - dap_chain_tx_used_out_item_t *l_item = DAP_NEW_Z(dap_chain_tx_used_out_item_t); - *l_item = (dap_chain_tx_used_out_item_t) { l_tx_cur_hash, (uint32_t)l_out_idx_tmp, l_out_cond->header.value }; - l_list_used_out = dap_list_append(l_list_used_out, l_item); - SUM_256_256(l_value_transfer, l_item->value, &l_value_transfer); - } + int l_out_idx; + dap_chain_tx_out_cond_t *l_cond; + while ( (l_cond = dap_ledger_out_cond_unspent_find_by_addr(a_ledger, a_token_ticker, a_subtype, a_addr_from, &l_tx_cur_hash, &l_out_idx)) ) { + dap_chain_tx_used_out_item_t *l_item = DAP_NEW_Z(dap_chain_tx_used_out_item_t); + *l_item = (dap_chain_tx_used_out_item_t) { l_tx_cur_hash, (uint32_t)l_out_idx, l_cond->header.value }; + l_list_used_out = dap_list_append(l_list_used_out, l_item); } + return l_list_used_out; +} - return l_list_used_out - ? ({ if (a_value_transfer) *a_value_transfer = l_value_transfer; l_list_used_out; }) - : ( dap_list_free_full(l_list_used_out, NULL), NULL ); +bool dap_ledger_check_condition_owner(dap_ledger_t *a_ledger, dap_hash_fast_t *a_tx_hash, dap_chain_tx_out_cond_subtype_t a_cond_subtype, + int a_out_idx, dap_sign_t *a_owner_sign) +{ + dap_return_val_if_fail(a_ledger && a_tx_hash && a_owner_sign, false); + // Get first tx + dap_chain_datum_tx_t *l_check_tx = dap_ledger_tx_find_by_hash(a_ledger, a_tx_hash); + if (!l_check_tx) { + log_it(L_ERROR, "Can't find tx %s", dap_hash_fast_to_str_static(a_tx_hash)); + return false; + } + dap_hash_fast_t l_first_tx_hash = dap_ledger_get_first_chain_tx_hash(a_ledger, l_check_tx, a_cond_subtype); + if (dap_hash_fast_is_blank(&l_first_tx_hash)) { + log_it(L_ERROR, "Can't find owner for tx %s", dap_hash_fast_to_str_static(a_tx_hash)); + return false; + } + dap_chain_datum_tx_t *l_first_tx = dap_ledger_tx_find_by_hash(a_ledger, &l_first_tx_hash); + if (!l_first_tx) { + log_it(L_ERROR, "Can't find owner tx %s", dap_hash_fast_to_str_static(&l_first_tx_hash)); + return false; + } + dap_chain_tx_sig_t *l_first_tx_sig = (dap_chain_tx_sig_t *)dap_chain_datum_tx_item_get(l_first_tx, NULL, NULL, TX_ITEM_TYPE_SIG, NULL); + dap_sign_t *l_sign = dap_chain_datum_tx_item_sign_get_sig((dap_chain_tx_sig_t *)l_first_tx_sig); + if (!l_sign) { + log_it(L_ERROR, "Can't find signature for tx %s", dap_hash_fast_to_str_static(&l_first_tx_hash)); + return false; + } + return dap_sign_compare_pkeys(a_owner_sign, l_sign); } void dap_ledger_tx_add_notify(dap_ledger_t *a_ledger, dap_ledger_tx_add_notify_t a_callback, void *a_arg) { diff --git a/modules/net/include/dap_chain_ledger.h b/modules/net/include/dap_chain_ledger.h index f2e43d962d..059b3142ee 100644 --- a/modules/net/include/dap_chain_ledger.h +++ b/modules/net/include/dap_chain_ledger.h @@ -418,21 +418,11 @@ dap_chain_datum_tx_t* dap_ledger_tx_find_by_addr(dap_ledger_t *a_ledger, const c bool dap_ledger_tx_check_recipient(dap_ledger_t* a_ledger, dap_chain_hash_fast_t* a_tx_prev_hash, dap_chain_addr_t *a_addr); -// Get the transaction in the cache by the public key that signed the transaction, starting with a_tx_first_hash -const dap_chain_datum_tx_t* dap_ledger_tx_find_by_pkey(dap_ledger_t *a_ledger, - 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_ledger_tx_cache_find_out_cond(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_subtype_t a_cond_type, - dap_chain_hash_fast_t *a_tx_first_hash, dap_chain_tx_out_cond_t **a_out_cond, - int *a_out_cond_idx, char *a_token_ticker); - // Get all transactions from the cache with the specified out_cond items dap_list_t* dap_ledger_tx_cache_find_out_cond_all(dap_ledger_t *a_ledger, dap_chain_net_srv_uid_t a_srv_uid); -// Get the value from all transactions in the cache with out_cond item -uint256_t dap_ledger_tx_cache_get_out_cond_value(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_subtype_t a_cond_type, dap_chain_addr_t *a_addr, - dap_chain_tx_out_cond_t **tx_out_cond); +dap_chain_tx_out_cond_t *dap_ledger_out_cond_unspent_find_by_addr(dap_ledger_t *a_ledger, const char *a_token, dap_chain_tx_out_cond_subtype_t a_subtype, + const dap_chain_addr_t *a_addr, dap_chain_hash_fast_t *a_tx_first_hash, int *a_out_idx); // Get the list of 'out' items from previous transactions with summary value >= than a_value_need // Put this summary value to a_value_transfer @@ -440,12 +430,8 @@ dap_list_t *dap_ledger_get_list_tx_outs_with_val(dap_ledger_t *a_ledger, const c uint256_t a_value_need, uint256_t *a_value_transfer); dap_list_t *dap_ledger_get_list_tx_outs(dap_ledger_t *a_ledger, const char *a_token_ticker, const dap_chain_addr_t *a_addr_from, uint256_t *a_value_transfer); -// Get the list of 'out_cond' items with summary value >= than a_value_need -dap_list_t *dap_ledger_get_list_tx_cond_outs_with_val(dap_ledger_t *a_ledger, const char *a_token_ticker, const dap_chain_addr_t *a_addr_from, - dap_chain_tx_out_cond_subtype_t a_subtype, uint256_t a_value_need, uint256_t *a_value_transfer); - -dap_list_t *dap_ledger_get_list_tx_cond_outs(dap_ledger_t *a_ledger, const char *a_token_ticker, const dap_chain_addr_t *a_addr_from, - dap_chain_tx_out_cond_subtype_t a_subtype, uint256_t *a_value_transfer); +dap_list_t *dap_ledger_get_list_tx_cond_outs(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_subtype_t a_subtype, const char *a_token_ticker, const dap_chain_addr_t *a_addr_from); +bool dap_ledger_check_condition_owner(dap_ledger_t *a_ledger, dap_hash_fast_t *a_tx_hash, dap_chain_tx_out_cond_subtype_t a_cond_subtype, int a_out_idx, dap_sign_t *a_owner_sign); // Add new verificator callback with associated subtype. Returns 1 if callback replaced, overwise returns 0 int dap_ledger_verificator_add(dap_chain_tx_out_cond_subtype_t a_subtype, dap_ledger_verificator_callback_t a_callback, dap_ledger_updater_callback_t a_callback_added, dap_ledger_delete_callback_t a_callback_deleted); diff --git a/modules/service/voting/dap_chain_net_srv_voting.c b/modules/service/voting/dap_chain_net_srv_voting.c index c74cf6fd33..3734ed953c 100644 --- a/modules/service/voting/dap_chain_net_srv_voting.c +++ b/modules/service/voting/dap_chain_net_srv_voting.c @@ -290,16 +290,9 @@ static int s_vote_verificator(dap_ledger_t *a_ledger, dap_chain_tx_item_type_t a } dap_hash_fast_t pkey_hash = {}; - int l_item_cnt = 0; - dap_list_t *l_signs_list = dap_chain_datum_tx_items_get(a_tx_in, TX_ITEM_TYPE_SIG, &l_item_cnt); - - if (!l_signs_list) { - log_it(L_WARNING, "Can't get signs from tx %s", dap_chain_hash_fast_to_str_static(a_tx_hash)); - return -9; - } - dap_chain_tx_sig_t *l_vote_sig = (dap_chain_tx_sig_t *)(dap_list_last(l_signs_list)->data); - dap_sign_get_pkey_hash((dap_sign_t*)l_vote_sig->sig, &pkey_hash); - dap_list_free(l_signs_list); + // Get sign item from transaction + dap_chain_tx_sig_t *l_tx_sig = (dap_chain_tx_sig_t*) dap_chain_datum_tx_item_get(a_tx_in, NULL, NULL, TX_ITEM_TYPE_SIG, NULL); + dap_sign_get_pkey_hash((dap_sign_t *)l_tx_sig->sig, &pkey_hash); if (!a_apply) { if (l_vote_tx_item->answer_idx > dap_list_length(l_voting->voting_params.option_offsets_list)) { @@ -345,25 +338,27 @@ static int s_vote_verificator(dap_ledger_t *a_ledger, dap_chain_tx_item_type_t a dap_tsd_t *l_tsd = (dap_tsd_t *)((dap_chain_tx_tsd_t*)it->data)->tsd; dap_hash_fast_t l_hash = ((dap_chain_tx_voting_tx_cond_t*)l_tsd->data)->tx_hash; int l_out_idx = ((dap_chain_tx_voting_tx_cond_t*)l_tsd->data)->out_idx; - if (l_tsd->type == VOTING_TSD_TYPE_VOTE_TX_COND) { - if (s_datum_tx_voting_coin_check_cond_out(a_ledger->net, l_vote_tx_item->voting_hash, l_hash, l_out_idx)) - continue; - dap_chain_datum_tx_t *l_tx_prev_temp = dap_ledger_tx_find_by_hash(a_ledger, &l_hash); - dap_chain_tx_out_cond_t *l_prev_out = (dap_chain_tx_out_cond_t*)dap_chain_datum_tx_item_get(l_tx_prev_temp, &l_out_idx, NULL, TX_ITEM_TYPE_OUT_COND, NULL); - if (!l_prev_out || l_prev_out->header.subtype != DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK) - continue; - if (SUM_256_256(l_weight, l_prev_out->header.value, &l_weight)) { - log_it(L_WARNING, "Integer overflow while parsing vote tx %s", dap_chain_hash_fast_to_str_static(a_tx_hash)); - return -DAP_LEDGER_CHECK_INTEGER_OVERFLOW; - } - - dap_chain_net_voting_cond_outs_t *l_item = DAP_NEW_Z_RET_VAL_IF_FAIL(dap_chain_net_voting_cond_outs_t, -DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY); - l_item->tx_hash = l_hash; - l_item->out_idx = l_out_idx; - pthread_rwlock_wrlock(&l_voting->s_tx_outs_rwlock); - HASH_ADD(hh, l_voting->voting_spent_cond_outs, tx_hash, sizeof(dap_hash_fast_t), l_item); - pthread_rwlock_unlock(&l_voting->s_tx_outs_rwlock); - } + if (l_tsd->type != VOTING_TSD_TYPE_VOTE_TX_COND) + return -14; + if (s_datum_tx_voting_coin_check_cond_out(a_ledger->net, l_vote_tx_item->voting_hash, l_hash, l_out_idx)) + return -15; + dap_chain_datum_tx_t *l_tx_prev_temp = dap_ledger_tx_find_by_hash(a_ledger, &l_hash); + dap_chain_tx_out_cond_t *l_prev_out = (dap_chain_tx_out_cond_t*)dap_chain_datum_tx_item_get(l_tx_prev_temp, &l_out_idx, NULL, TX_ITEM_TYPE_OUT_COND, NULL); + if (!l_prev_out || l_prev_out->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE) + return -16; + if (!dap_ledger_check_condition_owner(a_ledger, &l_hash, l_prev_out->header.subtype, l_out_idx, (dap_sign_t *)l_tx_sig->sig)) + return -17; + if (SUM_256_256(l_weight, l_prev_out->header.value, &l_weight)) { + log_it(L_WARNING, "Integer overflow while parsing vote tx %s", dap_chain_hash_fast_to_str_static(a_tx_hash)); + return -DAP_LEDGER_CHECK_INTEGER_OVERFLOW; + } + + dap_chain_net_voting_cond_outs_t *l_item = DAP_NEW_Z_RET_VAL_IF_FAIL(dap_chain_net_voting_cond_outs_t, -DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY); + l_item->tx_hash = l_hash; + l_item->out_idx = l_out_idx; + pthread_rwlock_wrlock(&l_voting->s_tx_outs_rwlock); + HASH_ADD(hh, l_voting->voting_spent_cond_outs, tx_hash, sizeof(dap_hash_fast_t), l_item); + pthread_rwlock_unlock(&l_voting->s_tx_outs_rwlock); } dap_list_free(l_tsd_list); // check inputs @@ -379,7 +374,7 @@ static int s_vote_verificator(dap_ledger_t *a_ledger, dap_chain_tx_item_type_t a dap_chain_datum_tx_t *l_tx_prev_temp = dap_ledger_tx_find_by_hash(a_ledger, &l_tx_in->header.tx_prev_hash); dap_chain_tx_out_t *l_prev_out_union = (dap_chain_tx_out_t *)dap_chain_datum_tx_out_get_by_out_idx(l_tx_prev_temp, l_tx_in->header.tx_out_prev_idx); if (!l_prev_out_union) - continue; + return -18; if ((l_prev_out_union->header.type == TX_ITEM_TYPE_OUT || l_prev_out_union->header.type == TX_ITEM_TYPE_OUT_EXT) && SUM_256_256(l_weight, l_prev_out_union->header.value, &l_weight)) { log_it(L_WARNING, "Integer overflow while parsing vote tx %s", dap_chain_hash_fast_to_str_static(a_tx_hash)); @@ -1487,14 +1482,11 @@ int dap_chain_net_vote_voting(dap_cert_t *a_cert, uint256_t a_fee, dap_chain_wal DAP_DEL_Z(l_vote_item); // add stake out conds items - dap_list_t *l_outs = dap_ledger_get_list_tx_cond_outs(l_ledger, a_net->pub.native_ticker, l_addr_from, - DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK, NULL); - dap_list_t *l_temp = l_outs; - while(l_temp){ - dap_chain_tx_used_out_item_t *l_out_item = (dap_chain_tx_used_out_item_t *)l_temp->data; + dap_list_t *l_outs = dap_ledger_get_list_tx_cond_outs(l_ledger, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK, a_net->pub.native_ticker, l_addr_from); + for (dap_list_t *it = l_outs; it; it = it->next) { + dap_chain_tx_used_out_item_t *l_out_item = (dap_chain_tx_used_out_item_t *)it->data; if (dap_ledger_tx_hash_is_used_out_item(a_net->pub.ledger, &l_out_item->tx_hash_fast, l_out_item->num_idx_out, NULL) || s_datum_tx_voting_coin_check_cond_out(a_net, a_hash, l_out_item->tx_hash_fast, l_out_item->num_idx_out ) != 0){ - l_temp = l_temp->next; continue; } dap_chain_tx_tsd_t *l_item = dap_chain_datum_voting_vote_tx_cond_tsd_create(l_out_item->tx_hash_fast, l_out_item->num_idx_out); @@ -1506,7 +1498,6 @@ int dap_chain_net_vote_voting(dap_cert_t *a_cert, uint256_t a_fee, dap_chain_wal } dap_chain_datum_tx_add_item(&l_tx, l_item); DAP_DEL_Z(l_item); - l_temp = l_temp->next; } dap_list_free_full(l_outs, NULL); -- GitLab