diff --git a/modules/chain/tests/dap_chain_ledger_tests.c b/modules/chain/tests/dap_chain_ledger_tests.c index e3b22cdbeadcb5e3390c39f2acdf7daed05c1faa..03f538efdb3aabce78fa2a45c072108196236196 100644 --- a/modules/chain/tests/dap_chain_ledger_tests.c +++ b/modules/chain/tests/dap_chain_ledger_tests.c @@ -100,22 +100,17 @@ dap_chain_datum_tx_t *dap_ledger_test_create_datum_base_tx( uint256_t l_value_need = a_emi->hdr.value; dap_chain_datum_tx_t *l_tx = DAP_NEW_Z_SIZE(dap_chain_datum_tx_t, sizeof(dap_chain_datum_tx_t)); l_tx->header.ts_created = time(NULL); - dap_chain_tx_in_ems_t *l_in_ems = DAP_NEW_Z(dap_chain_tx_in_ems_t); - l_in_ems->header.type = TX_ITEM_TYPE_IN_EMS; - l_in_ems->header.token_emission_chain_id.uint64 = 0; - l_in_ems->header.token_emission_hash = *l_emi_hash; - strcpy(l_in_ems->header.ticker, a_emi->hdr.ticker); - SUBTRACT_256_256(l_value_need, l_value_fee, &l_value_need); - dap_chain_tx_out_t *l_out = dap_chain_datum_tx_item_out_create(&a_addr_to, l_value_need); - dap_chain_tx_out_cond_t *l_tx_out_fee = dap_chain_datum_tx_item_out_cond_create_fee(l_value_fee); - dap_chain_datum_tx_add_item(&l_tx, (const uint8_t*) l_in_ems); - dap_chain_datum_tx_add_item(&l_tx, (const uint8_t*) l_out); - dap_chain_datum_tx_add_item(&l_tx, (const uint8_t*) l_tx_out_fee); + dap_chain_tx_in_ems_t l_in_ems = { .header.type = TX_ITEM_TYPE_IN_EMS, .header.token_emission_chain_id.uint64 = 0, .header.token_emission_hash = *l_emi_hash}; + strcpy(l_in_ems.header.ticker, a_emi->hdr.ticker); + dap_chain_datum_tx_add_item(&l_tx, (const uint8_t*) &l_in_ems); + if ( !strcmp(l_in_ems.header.ticker, s_token_ticker) ) { + SUBTRACT_256_256(l_value_need, l_value_fee, &l_value_need); + dap_chain_datum_tx_add_out_item(&l_tx, &a_addr_to, l_value_need); + dap_chain_datum_tx_add_fee_item(&l_tx, l_value_fee); + } else { + dap_chain_datum_tx_add_out_ext_item(&l_tx, &a_addr_to, l_value_need, l_in_ems.header.ticker); + } dap_chain_datum_tx_add_sign_item(&l_tx, a_cert->enc_key); - DAP_DEL_Z(l_in_ems); - DAP_DEL_Z(l_out); - DAP_DEL_Z(l_tx_out_fee); - return l_tx; } @@ -869,12 +864,12 @@ void dap_ledger_test_write_back_list(dap_ledger_t *a_ledger, dap_cert_t *a_cert, DAP_DELETE(l_ledger_tx_add_str); dap_hash_fast_t l_tx_addr4_hash = {0}; dap_chain_datum_tx_t *l_tx_to_addr4 = dap_ledger_test_create_tx(l_addr_1->enc_key, &l_btx_addr1_hash, - l_addr_4->addr, dap_chain_uint256_from(s_total_supply-s_fee)); + l_addr_4->addr, dap_chain_uint256_from(s_total_supply/*-s_fee*/)); dap_hash_fast(l_tx_to_addr4, dap_chain_datum_tx_get_size(l_tx_to_addr4), &l_tx_addr4_hash); dap_assert_PIF(!dap_ledger_tx_add(a_ledger, l_tx_to_addr4, &l_tx_addr4_hash, false, NULL), "Can't add transaction to address from white list in ledger"); dap_chain_datum_tx_t *l_tx_to_addr3 = dap_ledger_test_create_tx(l_addr_4->enc_key, &l_tx_addr4_hash, - l_addr_3->addr, dap_chain_uint256_from(s_total_supply-s_fee)); + l_addr_3->addr, dap_chain_uint256_from(s_total_supply/*-s_fee*/)); dap_hash_fast_t l_tx_addr3_hash = {0}; dap_hash_fast(l_tx_to_addr3, dap_chain_datum_tx_get_size(l_tx_to_addr3), &l_tx_addr3_hash); int res_add_tx = dap_ledger_tx_add(a_ledger, l_tx_to_addr3, &l_tx_addr3_hash, false, NULL); diff --git a/modules/net/dap_chain_ledger.c b/modules/net/dap_chain_ledger.c index adf20db1bcdeb6fc15d002ca229ad0378bae7e6a..fefa910dec10c9a7fefe4ade5859c6dd3c4cf4cb 100644 --- a/modules/net/dap_chain_ledger.c +++ b/modules/net/dap_chain_ledger.c @@ -3977,34 +3977,43 @@ static int s_tx_cache_check(dap_ledger_t *a_ledger, return l_err_num; } - // 6. Compare sum of values in 'out' items in the current transaction and in the previous transa // Calculate the sum of values in 'out' items from the current transaction - bool l_multichannel = false; - if (HASH_COUNT(l_values_from_prev_tx) > 1) { - l_multichannel = true; - if (HASH_COUNT(l_values_from_prev_tx) == 2 && !l_main_ticker) { - HASH_FIND_STR(l_values_from_prev_tx, a_ledger->net->pub.native_ticker, l_value_cur); - if (l_value_cur) { - l_value_cur = l_value_cur->hh.next ? l_value_cur->hh.next : l_value_cur->hh.prev; - l_main_ticker = l_value_cur->token_ticker; - } - } - } else { + // 6. Compare sum of values in 'out' items + + switch ( HASH_COUNT(l_values_from_prev_tx) ) { + case 1: l_value_cur = DAP_NEW_Z(dap_ledger_tokenizer_t); if ( !l_value_cur ) { log_it(L_CRITICAL, "%s", c_error_memory_alloc); - l_err_num = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY; if ( l_list_bound_items ) dap_list_free_full(l_list_bound_items, NULL); HASH_ITER(hh, l_values_from_prev_tx, l_value_cur, l_tmp) { HASH_DEL(l_values_from_prev_tx, l_value_cur); DAP_DELETE(l_value_cur); } - return l_err_num; + return DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY; } dap_stpcpy(l_value_cur->token_ticker, l_token); + HASH_ADD_STR(l_values_from_cur_tx, token_ticker, l_value_cur); if (!l_main_ticker) l_main_ticker = l_value_cur->token_ticker; - HASH_ADD_STR(l_values_from_cur_tx, token_ticker, l_value_cur); + break; + case 2: + case 3: + if (l_main_ticker) + break; + HASH_FIND_STR(l_values_from_prev_tx, a_ledger->net->pub.native_ticker, l_value_cur); + if (l_value_cur) { + l_value_cur = l_value_cur->hh.next ? l_value_cur->hh.next : l_value_cur->hh.prev; + l_main_ticker = l_value_cur->token_ticker; + } + break; + default: + dap_list_free_full(l_list_bound_items, NULL); + HASH_ITER(hh, l_values_from_prev_tx, l_value_cur, l_tmp) { + HASH_DEL(l_values_from_prev_tx, l_value_cur); + DAP_DELETE(l_value_cur); + } + return DAP_LEDGER_TX_CHECK_NO_MAIN_TICKER; } dap_chain_net_srv_stake_item_t *l_key_item = NULL; @@ -4025,7 +4034,8 @@ static int s_tx_cache_check(dap_ledger_t *a_ledger, switch ( *it ) { case TX_ITEM_TYPE_OUT_OLD: { dap_chain_tx_out_old_t *l_tx_out = (dap_chain_tx_out_old_t*)it; - if (l_multichannel) { // token ticker is mandatory for multichannel transactions + l_token = l_main_ticker; + if (!l_token) { l_err_num = DAP_LEDGER_TX_CHECK_NO_MAIN_TICKER; break; } @@ -4035,13 +4045,10 @@ static int s_tx_cache_check(dap_ledger_t *a_ledger, } break; case TX_ITEM_TYPE_OUT: { // 256 dap_chain_tx_out_t *l_tx_out = (dap_chain_tx_out_t *)it; - if (l_multichannel) { // token ticker is mandatory for multichannel transactions - if (l_main_ticker) - l_token = l_main_ticker; - else { - l_err_num = DAP_LEDGER_TX_CHECK_NO_MAIN_TICKER; - break; - } + l_token = l_main_ticker; + if (!l_token) { + l_err_num = DAP_LEDGER_TX_CHECK_NO_MAIN_TICKER; + break; } l_value = l_tx_out->header.value; l_tx_out_to = l_tx_out->addr; @@ -4056,16 +4063,10 @@ static int s_tx_cache_check(dap_ledger_t *a_ledger, } break; case TX_ITEM_TYPE_OUT_COND: { dap_chain_tx_out_cond_t *l_tx_out = (dap_chain_tx_out_cond_t *)it; - if (l_multichannel) { - if (l_tx_out->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE) - l_token = (char *)a_ledger->net->pub.native_ticker; - else if (l_main_ticker) - l_token = l_main_ticker; - else { - log_it(L_WARNING, "No conditional output support for multichannel transaction"); - l_err_num = DAP_LEDGER_TX_CHECK_NO_MAIN_TICKER; - break; - } + l_token = l_tx_out->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE ? a_ledger->net->pub.native_ticker : l_main_ticker; + if (!l_token) { + l_err_num = DAP_LEDGER_TX_CHECK_NO_MAIN_TICKER; + break; } l_value = l_tx_out->header.value; l_list_tx_out = dap_list_append(l_list_tx_out, l_tx_out); @@ -4093,18 +4094,16 @@ static int s_tx_cache_check(dap_ledger_t *a_ledger, if (l_err_num) break; - if (l_multichannel) { - HASH_FIND_STR(l_values_from_cur_tx, l_token, l_value_cur); - if (!l_value_cur) { - l_value_cur = DAP_NEW_Z(dap_ledger_tokenizer_t); - if ( !l_value_cur ) { - log_it(L_CRITICAL, "%s", c_error_memory_alloc); - l_err_num = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY; - break; - } - strcpy(l_value_cur->token_ticker, l_token); - HASH_ADD_STR(l_values_from_cur_tx, token_ticker, l_value_cur); + HASH_FIND_STR(l_values_from_cur_tx, l_token, l_value_cur); + if (!l_value_cur) { + l_value_cur = DAP_NEW_Z(dap_ledger_tokenizer_t); + if ( !l_value_cur ) { + log_it(L_CRITICAL, "%s", c_error_memory_alloc); + l_err_num = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY; + break; } + strcpy(l_value_cur->token_ticker, l_token); + HASH_ADD_STR(l_values_from_cur_tx, token_ticker, l_value_cur); } if (SUM_256_256(l_value_cur->sum, l_value, &l_value_cur->sum)) { debug_if(s_debug_more, L_WARNING, "Sum result overflow for tx_add_check with ticker %s", @@ -4136,7 +4135,7 @@ static int s_tx_cache_check(dap_ledger_t *a_ledger, } // Check for transaction consistency (sum(ins) == sum(outs)) - if (!l_err_num) { + if ( !l_err_num && !s_check_hal(a_ledger, a_tx_hash) ) { HASH_ITER(hh, l_values_from_prev_tx, l_value_cur, l_tmp) { HASH_FIND_STR(l_values_from_cur_tx, l_value_cur->token_ticker, l_res); if (!l_res || !EQUAL_256(l_res->sum, l_value_cur->sum) ) {