From a502ba383c8699ed4e3b13260013154c85a6dd39 Mon Sep 17 00:00:00 2001 From: "Constantin P." <papizh.konstantin@demlabs.net> Date: Thu, 20 Feb 2025 13:01:49 +0700 Subject: [PATCH 01/15] 15244 --- dap-sdk | 2 +- modules/ledger/dap_chain_ledger_tx.c | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/dap-sdk b/dap-sdk index 737ab3c966..d9b03ffb93 160000 --- a/dap-sdk +++ b/dap-sdk @@ -1 +1 @@ -Subproject commit 737ab3c9660c0e7133786ef256abfbd4bfec87fb +Subproject commit d9b03ffb93d4003cb1a33c6470612a7f88ad6005 diff --git a/modules/ledger/dap_chain_ledger_tx.c b/modules/ledger/dap_chain_ledger_tx.c index 9558151998..674d45ec29 100644 --- a/modules/ledger/dap_chain_ledger_tx.c +++ b/modules/ledger/dap_chain_ledger_tx.c @@ -875,10 +875,6 @@ static int s_tx_cache_check(dap_ledger_t *a_ledger, } break; case TX_ITEM_TYPE_OUT_EXT: { // 256 dap_chain_tx_out_ext_t *l_tx_out = (dap_chain_tx_out_ext_t *)it; - if (!l_multichannel) { // token ticker is forbiden for single-channel transactions - l_err_num = DAP_LEDGER_TX_CHECK_UNEXPECTED_TOKENIZED_OUT; - break; - } l_value = l_tx_out->header.value; l_token = l_tx_out->token; l_tx_out_to = l_tx_out->addr; -- GitLab From 145016b046e002255226d286ce7a4b0f4ecfb181 Mon Sep 17 00:00:00 2001 From: "daniil.frolov" <daniil.frolov@demlabs.net> Date: Sat, 25 Jan 2025 06:39:20 +0000 Subject: [PATCH 02/15] 13980 --- modules/type/blocks/dap_chain_cs_blocks.c | 44 +++++++++++++- .../type/blocks/include/dap_chain_cs_blocks.h | 3 + .../type/blocks/tests/dap_chain_blocks_test.c | 57 ++++++++++++++----- 3 files changed, 88 insertions(+), 16 deletions(-) diff --git a/modules/type/blocks/dap_chain_cs_blocks.c b/modules/type/blocks/dap_chain_cs_blocks.c index 253c1ad2dd..53f9415797 100644 --- a/modules/type/blocks/dap_chain_cs_blocks.c +++ b/modules/type/blocks/dap_chain_cs_blocks.c @@ -70,7 +70,7 @@ typedef struct dap_chain_cs_blocks_pvt { // All the blocks are here dap_chain_block_cache_t *blocks; - _Atomic uint64_t blocks_count; + _Atomic uint64_t blocks_count; // Brnches and forks size_t forked_br_cnt; @@ -93,6 +93,11 @@ typedef struct dap_chain_cs_blocks_pvt { uint64_t block_confirm_cnt; } dap_chain_cs_blocks_pvt_t; +typedef struct dap_chain_block_fork_resolved_notificator{ + dap_chain_cs_blocks_callback_fork_resolved_t callback; + void *arg; +} dap_chain_block_fork_resolved_notificator_t; + #define PVT(a) ((dap_chain_cs_blocks_pvt_t *)(a)->_pvt ) #define print_rdlock(blocks) log_it(L_DEBUG, "Try to rdlock, %s, %d, thread_id=%u", __FUNCTION__, __LINE__, dap_gettid());\ @@ -176,6 +181,7 @@ static int s_chain_cs_blocks_new(dap_chain_t * a_chain, dap_config_t * a_chain_c static bool s_seed_mode = false; static bool s_debug_more = false; +static dap_list_t *s_fork_resolved_notificators = NULL; /** * @brief dap_chain_cs_blocks_init @@ -391,6 +397,25 @@ dap_chain_block_cache_t * dap_chain_block_cache_get_by_hash(dap_chain_cs_blocks_ return l_ret; } +int dap_chain_block_add_fork_notificator(dap_chain_cs_blocks_callback_fork_resolved_t a_callback, void *a_arg) +{ + if (!a_callback) + return -100; + + dap_chain_block_fork_resolved_notificator_t *l_notificator = DAP_NEW_Z(dap_chain_block_fork_resolved_notificator_t); + if (!l_notificator) { + log_it(L_CRITICAL, "%s", c_error_memory_alloc); + return -1; + } + + l_notificator->arg = a_arg; + l_notificator->callback = a_callback; + + s_fork_resolved_notificators = dap_list_append(s_fork_resolved_notificators, l_notificator); + + return 0; +} + static char *s_blocks_decree_set_reward(dap_chain_net_t *a_net, dap_chain_t *a_chain, uint256_t a_value, dap_cert_t *a_cert) { dap_return_val_if_fail(a_net && a_cert && a_cert->enc_key && @@ -1659,6 +1684,10 @@ static bool s_select_longest_branch(dap_chain_cs_blocks_t * a_blocks, dap_chain_ } if (a_main_branch_length < l_longest_branch_length){ + dap_list_t *l_reverted_blocks_list= NULL; + uint64_t l_reverted_blocks_cnt = 0; + uint64_t l_main_blocks_cnt = 0; + log_it(L_INFO,"Found new longest branch. Start switching."); // Switch branches dap_chain_block_forked_branch_atoms_table_t *l_new_forked_branch = NULL; @@ -1671,8 +1700,11 @@ static bool s_select_longest_branch(dap_chain_cs_blocks_t * a_blocks, dap_chain_ l_new_item->block_cache = l_atom; l_new_item->block_hash = l_atom->block_hash; HASH_ADD(hh, l_new_forked_branch, block_hash, sizeof(dap_hash_fast_t), l_new_item); + l_reverted_blocks_cnt++; + dap_hash_fast_t *l_reverted_block_hash = DAP_DUP_SIZE(&l_atom->block_hash, sizeof(l_atom->block_hash)); + l_reverted_blocks_list = dap_list_prepend(l_reverted_blocks_list, l_reverted_block_hash); l_atom = l_atom->hh.next; - } + } // Next we must to remove all blocks from main branch and delete all datums in this atoms from storages dap_chain_block_forked_branch_atoms_table_t *l_last_new_forked_item = HASH_LAST(l_new_forked_branch); for (l_curr_index = 0; l_last_new_forked_item && l_curr_index < a_main_branch_length; l_last_new_forked_item = l_last_new_forked_item->hh.prev, ++l_curr_index){ @@ -1694,7 +1726,15 @@ static bool s_select_longest_branch(dap_chain_cs_blocks_t * a_blocks, dap_chain_ s_add_atom_datums(l_blocks, l_curr_atom); dap_chain_atom_notify(a_blocks->chain, l_curr_atom->block->hdr.cell_id, &l_curr_atom->block_hash, (byte_t*)l_curr_atom->block, l_curr_atom->block_size); HASH_DEL(new_main_branch, l_item); + l_main_blocks_cnt++; } + // Notify about branch switching + for (dap_list_t *l_temp = s_fork_resolved_notificators; l_temp; l_temp = l_temp->next){ + dap_chain_block_fork_resolved_notificator_t *l_notificator = (dap_chain_block_fork_resolved_notificator_t*)l_temp->data; + l_notificator->callback(l_blocks->chain, a_bcache->block_hash, l_reverted_blocks_list, l_reverted_blocks_cnt, l_main_blocks_cnt, l_notificator->arg); + } + + dap_list_free_full(l_reverted_blocks_list, NULL); // Next we save pointer to new forked branch (former main branch) instead of it l_longest_branch_cache_ptr->forked_branch_atoms = l_new_forked_branch; return true; diff --git a/modules/type/blocks/include/dap_chain_cs_blocks.h b/modules/type/blocks/include/dap_chain_cs_blocks.h index f04dafebc8..697270d7b3 100644 --- a/modules/type/blocks/include/dap_chain_cs_blocks.h +++ b/modules/type/blocks/include/dap_chain_cs_blocks.h @@ -35,6 +35,8 @@ typedef void (*dap_chain_cs_blocks_callback_op_results_t)(dap_chain_cs_blocks_t typedef int (*dap_chain_cs_blocks_callback_block_verify_t)(dap_chain_cs_blocks_t *a_cs_blocks, dap_chain_block_t *a_block, dap_hash_fast_t *a_block_hash, size_t a_block_size); typedef size_t (*dap_chain_cs_blocks_callback_block_sign_t)(dap_chain_cs_blocks_t *, dap_chain_block_t **, size_t); typedef dap_chain_block_t *(*dap_chain_cs_block_move_t)(dap_chain_cs_blocks_t *, size_t *); +typedef void (*dap_chain_cs_blocks_callback_fork_resolved_t)(dap_chain_t *a_chain, dap_hash_fast_t a_block_before_fork_hash, dap_list_t *a_reverted_blocks, + uint64_t a_reverted_blocks_cnt, uint64_t a_main_blocks_cnt, void * a_arg); typedef dap_chain_block_t * (*dap_chain_cs_blocks_callback_block_create_t)(dap_chain_cs_blocks_t *, dap_chain_datum_t *, dap_chain_hash_fast_t *, @@ -89,6 +91,7 @@ void dap_chain_cs_blocks_deinit(); dap_chain_block_cache_t *dap_chain_block_cache_get_by_hash(dap_chain_cs_blocks_t *a_blocks, dap_chain_hash_fast_t *a_block_hash); dap_chain_cs_blocks_hardfork_fees_t *dap_chain_cs_blocks_fees_aggregate(dap_chain_t *a_chain); +int dap_chain_block_add_fork_notificator(dap_chain_cs_blocks_callback_fork_resolved_t a_callback, void *a_arg); DAP_STATIC_INLINE char *dap_chain_cs_blocks_get_fee_group(const char *a_net_name) { diff --git a/modules/type/blocks/tests/dap_chain_blocks_test.c b/modules/type/blocks/tests/dap_chain_blocks_test.c index 1d1c7d7687..c515e951d4 100644 --- a/modules/type/blocks/tests/dap_chain_blocks_test.c +++ b/modules/type/blocks/tests/dap_chain_blocks_test.c @@ -6,12 +6,20 @@ #include "dap_chain_cs_blocks.h" #include "dap_chain_cs_esbocs.h" #include "dap_chain_cs.h" -// #include "dap_chain_cs_blocks.h" -dap_hash_fast_t g_last_confirmed_block_hash = {}; -dap_hash_fast_t g_last_notified_block_hash = {}; -int g_confirmed_blocks_counter = 0; -int g_custom_notify_counter = 0; +typedef struct { + dap_hash_fast_t block_before_fork_hash; + dap_list_t *reverted_blocks; + uint64_t reverted_blocks_cnt; + uint64_t main_blocks_cnt; +} last_fork_resolved_notification_data_t; + +static dap_hash_fast_t s_last_confirmed_block_hash = {}; +static dap_hash_fast_t s_last_notified_block_hash = {}; +static int s_confirmed_blocks_counter = 0; +static int s_custom_notify_counter = 0; + +static last_fork_resolved_notification_data_t s_fork_resolved_arg = {}; typedef struct { dap_hash_fast_t *last_notified_hash; @@ -25,6 +33,21 @@ void callback_notify(void *a_arg, dap_chain_t *a_chain, dap_chain_cell_id_t a_id *l_arg->last_notified_hash = *a_atom_hash; } +static void *s_callback_list_copy(const void *a_data, UNUSED_ARG void *a_usr_data) +{ + return DAP_DUP((dap_hash_fast_t *)a_data); +} + +void callback_fork_resolved_notify(dap_chain_t *a_chain, dap_hash_fast_t a_block_before_fork_hash, dap_list_t *a_reverted_blocks, + uint64_t a_reverted_blocks_cnt, uint64_t a_main_blocks_cnt, void * a_arg) +{ + last_fork_resolved_notification_data_t *l_arg = (last_fork_resolved_notification_data_t*)a_arg; + + l_arg->reverted_blocks = dap_list_copy_deep(a_reverted_blocks, s_callback_list_copy, NULL); + l_arg->main_blocks_cnt = a_main_blocks_cnt; + l_arg->reverted_blocks_cnt = a_reverted_blocks_cnt; + l_arg->block_before_fork_hash = a_block_before_fork_hash; +} dap_hash_fast_t dap_chain_block_test_add_new_block (dap_hash_fast_t *a_prev_block_hash, dap_chain_t *a_chain, dap_chain_block_t **a_block, size_t *a_block_size) { @@ -85,14 +108,16 @@ void dap_chain_blocks_test() notify_arg_t *l_arg = DAP_NEW_Z(notify_arg_t); - l_arg->cnt = &g_confirmed_blocks_counter; - l_arg->last_notified_hash = &g_last_confirmed_block_hash; + l_arg->cnt = &s_confirmed_blocks_counter; + l_arg->last_notified_hash = &s_last_confirmed_block_hash; dap_chain_atom_confirmed_notify_add(l_chain, callback_notify, (void*)l_arg, 0); l_arg = DAP_NEW_Z(notify_arg_t); - l_arg->cnt = &g_custom_notify_counter; - l_arg->last_notified_hash = &g_last_notified_block_hash; + l_arg->cnt = &s_custom_notify_counter; + l_arg->last_notified_hash = &s_last_notified_block_hash; dap_chain_atom_confirmed_notify_add(l_chain, callback_notify, (void*)l_arg, 2); + dap_chain_block_add_fork_notificator(callback_fork_resolved_notify, &s_fork_resolved_arg); + dap_hash_fast_t l_forked_block_hash = {}; dap_hash_fast_t l_block_hash = {}; dap_hash_fast_t l_genesis_block_hash = {}; @@ -138,14 +163,14 @@ void dap_chain_blocks_test() l_first_branch_atoms_list = dap_list_append(l_first_branch_atoms_list, l_block_hash_copy); - dap_assert_PIF((g_custom_notify_counter == 1 && dap_hash_fast_compare(&g_last_notified_block_hash, &l_genesis_block_hash)), "Check custom notify: "); + dap_assert_PIF((s_custom_notify_counter == 1 && dap_hash_fast_compare(&s_last_notified_block_hash, &l_genesis_block_hash)), "Check custom notify: "); l_block_hash = dap_chain_block_test_add_new_block (&l_block_hash, l_chain, &l_block_repeat_middle_forked, &l_block_repeat_middle_forked_size); l_block_repeat_middle_forked_hash = l_block_hash; l_block_hash_copy = DAP_DUP(&l_block_hash); l_first_branch_atoms_list = dap_list_append(l_first_branch_atoms_list, l_block_hash_copy); - dap_assert_PIF((g_custom_notify_counter == 2 && dap_hash_fast_compare(&g_last_notified_block_hash, &l_forked_block_hash)), "Check custom notify: "); + dap_assert_PIF((s_custom_notify_counter == 2 && dap_hash_fast_compare(&s_last_notified_block_hash, &l_forked_block_hash)), "Check custom notify: "); dap_chain_atom_verify_res_t ret_val = l_chain->callback_atom_add(l_chain, (dap_chain_atom_ptr_t)l_block_double_main_branch, l_block_double_main_branch_size, &l_block_double_main_branch_hash, false); dap_assert_PIF(ret_val == ATOM_PASS, "Add existing block into middle of main chain. Must be passed: "); @@ -177,6 +202,8 @@ void dap_chain_blocks_test() l_second_branch_atoms_list = dap_list_append(l_second_branch_atoms_list, l_block_hash_copy); dap_assert_PIF(dap_chain_block_test_compare_chain_hash_lists(l_chain, l_second_branch_atoms_list), "Check branches is switched: "); + dap_assert_PIF(dap_hash_fast_compare(&s_fork_resolved_arg.block_before_fork_hash, &l_forked_block_hash) && + s_fork_resolved_arg.main_blocks_cnt == 3 && s_fork_resolved_arg.reverted_blocks_cnt == 2, "Check branches is switched notification: "); dap_test_msg("Add block to former main branch"); l_block_hash = dap_chain_block_test_add_new_block ((dap_hash_fast_t*)dap_list_last(l_first_branch_atoms_list)->data, l_chain, NULL, NULL); @@ -192,10 +219,12 @@ void dap_chain_blocks_test() l_first_branch_atoms_list = dap_list_append(l_first_branch_atoms_list, l_block_hash_copy); dap_assert_PIF(dap_chain_block_test_compare_chain_hash_lists(l_chain, l_first_branch_atoms_list), "Check branches is switched: "); + + dap_hash_fast_t l_last_former_main_branch_hash = l_block_hash; // genesis block must be confirmed, check counter and hash of confirmed block - dap_assert_PIF((g_confirmed_blocks_counter == 1 && dap_hash_fast_compare(&g_last_confirmed_block_hash, &l_genesis_block_hash)), "Check confirmed block: "); + dap_assert_PIF((s_confirmed_blocks_counter == 1 && dap_hash_fast_compare(&s_last_confirmed_block_hash, &l_genesis_block_hash)), "Check confirmed block: "); /* ========================== Add second forked branch ======================= */ dap_test_msg("Add atom to second forked branch..."); @@ -221,7 +250,7 @@ void dap_chain_blocks_test() dap_assert_PIF(dap_chain_block_test_compare_chain_hash_lists(l_chain, l_third_branch_atoms_list), "Check branches is switched: "); // second block must be confirmed, check counter and hash of confirmed block - dap_assert_PIF((g_confirmed_blocks_counter == 2 && dap_hash_fast_compare(&g_last_confirmed_block_hash, &l_forked_block_hash)), "Check confirmed block: "); + dap_assert_PIF((s_confirmed_blocks_counter == 2 && dap_hash_fast_compare(&s_last_confirmed_block_hash, &l_forked_block_hash)), "Check confirmed block: "); ret_val = l_chain->callback_atom_add(l_chain, (dap_chain_atom_ptr_t)l_block_repeat_middle_forked, l_block_repeat_middle_forked_size, &l_block_repeat_middle_forked_hash, false); dap_assert_PIF(ret_val == ATOM_PASS, "Add existing block into middle of forked chain. Must be passed: "); @@ -232,7 +261,7 @@ void dap_chain_blocks_test() l_third_branch_atoms_list = dap_list_append(l_third_branch_atoms_list, l_block_hash_copy); // third block must be confirmed, check counter and hash of confirmed block - dap_assert_PIF((g_confirmed_blocks_counter == 3 && dap_hash_fast_compare(&g_last_confirmed_block_hash, &l_third_confirmed_block)), "Check confirmed block: "); + dap_assert_PIF((s_confirmed_blocks_counter == 3 && dap_hash_fast_compare(&s_last_confirmed_block_hash, &l_third_confirmed_block)), "Check confirmed block: "); // dap_test_msg("Add new block into former main chain..."); // size_t l_block_size = 0; -- GitLab From 93efa6e86fcd402a589571dc09593a87379ef09a Mon Sep 17 00:00:00 2001 From: Roman Khlopkov <roman.khlopkov@demlabs.net> Date: Tue, 28 Jan 2025 11:27:40 +0000 Subject: [PATCH 03/15] hotfix-15313 --- modules/node-cli/dap_chain_node_cli_cmd.c | 2 +- modules/wallet/dap_chain_wallet.c | 3 ++- modules/wallet/include/dap_chain_wallet.h | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/modules/node-cli/dap_chain_node_cli_cmd.c b/modules/node-cli/dap_chain_node_cli_cmd.c index e4d2c80e44..182b76a940 100644 --- a/modules/node-cli/dap_chain_node_cli_cmd.c +++ b/modules/node-cli/dap_chain_node_cli_cmd.c @@ -1844,7 +1844,7 @@ int l_arg_index = 1, l_rc, cmd_num = CMD_NONE; l_rc = l_ttl_str ? strtoul(l_ttl_str, NULL, 10) : 60; l_rc = cmd_num == CMD_WALLET_ACTIVATE - ? dap_chain_wallet_activate(l_wallet_name, strlen(l_wallet_name), l_pass_str, strlen(l_pass_str), l_rc) + ? dap_chain_wallet_activate(l_wallet_name, strlen(l_wallet_name), NULL, l_pass_str, strlen(l_pass_str), l_rc) : dap_chain_wallet_deactivate (l_wallet_name, strlen(l_wallet_name)); switch (l_rc) { diff --git a/modules/wallet/dap_chain_wallet.c b/modules/wallet/dap_chain_wallet.c index 76b4c24f88..3f55a5f9ec 100644 --- a/modules/wallet/dap_chain_wallet.c +++ b/modules/wallet/dap_chain_wallet.c @@ -141,6 +141,7 @@ dap_list_t* dap_chain_wallet_get_local_addr(){ int dap_chain_wallet_activate ( const char *a_name, ssize_t a_name_len, + const char *a_path, const char *a_pass, ssize_t a_pass_len, unsigned a_ttl @@ -198,7 +199,7 @@ char *c_wallets_path; /* * Check password by open/close BMF Wallet file */ - if ( !(c_wallets_path = (char *) dap_chain_wallet_get_path(g_config)) ) /* No path to wallets - nothing to do */ + if ( !(c_wallets_path = a_path ? (char *)a_path : (char *) dap_chain_wallet_get_path(g_config)) ) /* No path to wallets - nothing to do */ { memset(l_prec->pass, 0, l_prec->pass_len), l_prec->pass_len = 0; return log_it(L_ERROR, "Wallet's path has been not configured"), -EINVAL; diff --git a/modules/wallet/include/dap_chain_wallet.h b/modules/wallet/include/dap_chain_wallet.h index ddee0312db..2f227f550e 100644 --- a/modules/wallet/include/dap_chain_wallet.h +++ b/modules/wallet/include/dap_chain_wallet.h @@ -92,7 +92,7 @@ uint256_t dap_chain_wallet_get_balance(dap_chain_wallet_t *a_wallet, dap_chain_n int dap_chain_wallet_save_file( dap_chain_wallet_t * a_wallet); -int dap_chain_wallet_activate (const char *a_name, ssize_t a_name_len, const char *a_pass, ssize_t a_pass_len, unsigned a_ttl); +int dap_chain_wallet_activate (const char *a_name, ssize_t a_name_len, const char *a_path, const char *a_pass, ssize_t a_pass_len, unsigned a_ttl); int dap_chain_wallet_deactivate (const char *a_name, ssize_t a_name_len); const char* dap_chain_wallet_check_sign(dap_chain_wallet_t *a_wallet); @@ -109,4 +109,4 @@ dap_list_t* dap_chain_wallet_get_local_addr(); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif -- GitLab From 72b3f747fe93d3317d4243404be927fbd6b34707 Mon Sep 17 00:00:00 2001 From: "Constantin P." <papizh.konstantin@demlabs.net> Date: Thu, 30 Jan 2025 13:44:00 +0700 Subject: [PATCH 04/15] ... --- modules/wallet/dap_chain_wallet_cache.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/modules/wallet/dap_chain_wallet_cache.c b/modules/wallet/dap_chain_wallet_cache.c index 0ba0056cd4..35f07bc4d7 100644 --- a/modules/wallet/dap_chain_wallet_cache.c +++ b/modules/wallet/dap_chain_wallet_cache.c @@ -150,16 +150,9 @@ int dap_chain_wallet_cache_init() dap_atom_notify_arg_t *l_arg = DAP_NEW_Z(dap_atom_notify_arg_t); l_arg->chain = l_chain; l_arg->net = l_net; - /* dap_chain_datum_iter_t *l_iter = l_chain->callback_datum_iter_create(l_chain); - for (dap_chain_datum_t *l_datum = l_chain->callback_datum_iter_get_first(l_iter); - l_datum; - l_datum = l_chain->callback_datum_iter_get_next(l_iter)){ - - s_callback_datum_notify(l_arg, l_iter->cur_hash, l_iter->cur_atom_hash, l_datum, l_iter->cur_size, l_iter->ret_code, l_iter->action, l_iter->uid); - } - l_chain->callback_datum_iter_delete(l_iter); */ - dap_chain_add_callback_datum_index_notify(l_chain, s_callback_datum_notify, NULL, l_arg); - dap_chain_add_callback_datum_removed_from_index_notify(l_chain, s_callback_datum_removed_notify, NULL, l_arg); + dap_proc_thread_t *l_pt = dap_proc_thread_get_auto(); + dap_chain_add_callback_datum_index_notify(l_chain, s_callback_datum_notify, l_pt, l_arg); + dap_chain_add_callback_datum_removed_from_index_notify(l_chain, s_callback_datum_removed_notify, l_pt, l_arg); } } l_chain=l_chain->next; -- GitLab From fd5ddcff50d197fc649f84d967d8e7ea2e0e6ea8 Mon Sep 17 00:00:00 2001 From: "Constantin P." <papizh.konstantin@demlabs.net> Date: Thu, 20 Feb 2025 17:56:35 +0700 Subject: [PATCH 05/15] Tax check fix --- modules/ledger/dap_chain_ledger_tx.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/modules/ledger/dap_chain_ledger_tx.c b/modules/ledger/dap_chain_ledger_tx.c index 674d45ec29..a639855427 100644 --- a/modules/ledger/dap_chain_ledger_tx.c +++ b/modules/ledger/dap_chain_ledger_tx.c @@ -293,7 +293,7 @@ static int s_tx_cache_check(dap_ledger_t *a_ledger, uint256_t l_taxed_value = {}; if(a_tag) dap_ledger_deduct_tx_tag(a_ledger, a_tx, NULL, a_tag, a_action); - + bool l_tax_check = false; // find all previous transactions for (dap_list_t *it = l_list_in; it; it = it->next) { dap_ledger_tx_bound_t *l_bound_item = DAP_NEW_Z(dap_ledger_tx_bound_t); @@ -750,6 +750,7 @@ static int s_tx_cache_check(dap_ledger_t *a_ledger, l_bound_item->cond = l_tx_prev_out_cond; l_value = l_tx_prev_out_cond->header.value; if (l_tx_prev_out_cond->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE) { + l_tax_check = true; l_token = a_ledger->net->pub.native_ticker; // Overflow checked later with overall values sum SUM_256_256(l_taxed_value, l_value, &l_taxed_value); @@ -836,10 +837,10 @@ static int s_tx_cache_check(dap_ledger_t *a_ledger, l_main_ticker = l_value_cur->token_ticker; HASH_ADD_STR(l_values_from_cur_tx, token_ticker, l_value_cur); } - dap_chain_addr_t l_sovereign_addr; - uint256_t l_sovereign_tax; - bool l_tax_check = s_tax_callback ? s_tax_callback(a_ledger->net->pub.id, &l_tx_first_sign_pkey_hash, &l_sovereign_addr, &l_sovereign_tax) - : false; + dap_chain_addr_t l_sovereign_addr; uint256_t l_sovereign_tax; + l_tax_check = l_tax_check && s_tax_callback + ? s_tax_callback(a_ledger->net->pub.id, &l_tx_first_sign_pkey_hash, &l_sovereign_addr, &l_sovereign_tax) + : false; // find 'out' items bool l_cross_network = false; uint256_t l_value = {}, l_fee_sum = {}, l_tax_sum = {}; -- GitLab From 90adb23f14f65202b8f4dc01e6eab09c26df7d38 Mon Sep 17 00:00:00 2001 From: "Constantin P." <papizh.konstantin@demlabs.net> Date: Thu, 20 Feb 2025 18:06:06 +0700 Subject: [PATCH 06/15] Wallet cache ported --- modules/wallet/dap_chain_wallet_cache.c | 856 ++++++++++-------------- 1 file changed, 351 insertions(+), 505 deletions(-) diff --git a/modules/wallet/dap_chain_wallet_cache.c b/modules/wallet/dap_chain_wallet_cache.c index 35f07bc4d7..dfe8a27a44 100644 --- a/modules/wallet/dap_chain_wallet_cache.c +++ b/modules/wallet/dap_chain_wallet_cache.c @@ -58,13 +58,13 @@ typedef enum dap_s_wallets_cache_type{ typedef struct dap_wallet_tx_cache_input{ dap_chain_hash_fast_t tx_prev_hash; - uint32_t tx_out_prev_idx; + int tx_out_prev_idx; uint256_t value; } dap_wallet_tx_cache_input_t; typedef struct dap_wallet_tx_cache_output{ void* tx_out; - uint32_t tx_out_idx; + int tx_out_idx; } dap_wallet_tx_cache_output_t; typedef struct dap_wallet_tx_cache { @@ -74,16 +74,31 @@ typedef struct dap_wallet_tx_cache { char token_ticker[DAP_CHAIN_TICKER_SIZE_MAX]; bool multichannel; int ret_code; - dap_chain_srv_uid_t srv_uid; + dap_chain_srv_uid_t srv_uid; dap_chain_tx_tag_action_type_t action; dap_list_t *tx_wallet_inputs; dap_list_t *tx_wallet_outputs; UT_hash_handle hh; } dap_wallet_tx_cache_t; +typedef struct unspent_cache_hh_key { + dap_hash_fast_t tx_hash; + int out_idx; +} DAP_ALIGN_PACKED unspent_cache_hh_key; + +typedef struct dap_wallet_cache_unspent_outs { + unspent_cache_hh_key key; + dap_wallet_tx_cache_output_t *output; + char token_ticker[DAP_CHAIN_TICKER_SIZE_MAX]; + + UT_hash_handle hh; +} dap_wallet_cache_unspent_outs_t; + typedef struct dap_s_wallets_cache { dap_chain_addr_t wallet_addr; dap_wallet_tx_cache_t *wallet_txs; + dap_wallet_cache_unspent_outs_t *unspent_outputs; + _Atomic bool is_loading; UT_hash_handle hh; } dap_wallet_cache_t; @@ -95,17 +110,17 @@ typedef struct dap_atom_notify_arg { static dap_s_wallets_cache_type_t s_wallets_cache_type = DAP_WALLET_CACHE_TYPE_LOCAL; static dap_wallet_cache_t *s_wallets_cache = NULL; -static pthread_rwlock_t s_wallet_cache_rwlock = PTHREAD_RWLOCK_INITIALIZER; +static pthread_rwlock_t s_wallet_cache_rwlock; +static bool s_debug_more = false; -static int s_save_tx_into_wallet_cache(dap_chain_t *a_chain, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash, dap_hash_fast_t *a_atom_hash, int a_ret_code, char* a_main_token_ticker, - dap_chain_srv_uid_t a_srv_uid, dap_chain_tx_tag_action_type_t a_action); -static int s_save_tx_cache_for_addr(dap_chain_t *a_chain, dap_chain_addr_t *a_addr, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash, dap_hash_fast_t *a_atom_hash, int a_ret_code, char* a_main_token_ticker, - dap_chain_srv_uid_t a_srv_uid, dap_chain_tx_tag_action_type_t a_action); +static int s_save_tx_cache_for_addr(dap_chain_t *a_chain, dap_chain_addr_t *a_addr, dap_chain_datum_tx_t *a_tx, + dap_hash_fast_t *a_tx_hash, dap_hash_fast_t *a_atom_hash, int a_ret_code, char* a_main_token_ticker, + dap_chain_srv_uid_t a_srv_uid, dap_chain_tx_tag_action_type_t a_action, char a_cache_op); static int s_save_cache_for_addr_in_net(dap_chain_net_t *a_net, dap_chain_addr_t *a_addr); static void s_callback_datum_notify(void *a_arg, dap_chain_hash_fast_t *a_datum_hash, dap_hash_fast_t *a_atom_hash, void *a_datum, size_t a_datum_size, int a_ret_code, uint32_t a_action, dap_chain_srv_uid_t a_uid); -static void s_callback_datum_removed_notify(void *a_arg, dap_chain_hash_fast_t *a_datum_hash); +static void s_callback_datum_removed_notify(void *a_arg, dap_chain_hash_fast_t *a_datum_hash, dap_chain_datum_t *a_datum); static void s_wallet_opened_callback(dap_chain_wallet_t *a_wallet, void *a_arg); static char * s_wallet_cache_type_to_str(dap_s_wallets_cache_type_t a_type) @@ -126,20 +141,28 @@ int dap_chain_wallet_cache_init() { const char *l_walet_cache_type_str = dap_config_get_item_str(g_config, "wallets", "wallets_cache"); if (l_walet_cache_type_str){ - if (!dap_strcmp(l_walet_cache_type_str, "disable")) { + if (!dap_strcmp(l_walet_cache_type_str, "disable")){ s_wallets_cache_type = DAP_WALLET_CACHE_TYPE_DISABLED; - return log_it(L_WARNING, "Wallet cache is disabled"), 0; } else if (!dap_strcmp(l_walet_cache_type_str, "local")){ s_wallets_cache_type = DAP_WALLET_CACHE_TYPE_LOCAL; } else if (!dap_strcmp(l_walet_cache_type_str, "all")){ s_wallets_cache_type = DAP_WALLET_CACHE_TYPE_ALL; } else { - log_it( L_WARNING, "Unknown cache type in config. Remains default: %s", s_wallet_cache_type_to_str(s_wallets_cache_type)); + log_it( L_WARNING, "Unknown cache type in config. Remain default: %s", s_wallet_cache_type_to_str(s_wallets_cache_type)); } } + s_debug_more = dap_config_get_item_bool_default(g_config,"wallet","debug_more", s_debug_more); + + if (s_wallets_cache_type == DAP_WALLET_CACHE_TYPE_DISABLED){ + debug_if(s_debug_more, L_DEBUG, "Wallet cache is disabled."); + return 0; + } + log_it(L_INFO, "Wallet cache type: %s", s_wallet_cache_type_to_str(s_wallets_cache_type)); + pthread_rwlock_init(&s_wallet_cache_rwlock, NULL); + // Add notify callback for all chain with transactions in all nets for(dap_chain_net_t *l_net = dap_chain_net_iter_start(); l_net; l_net=dap_chain_net_iter_next(l_net)){ // Find chain with transactions @@ -160,7 +183,6 @@ int dap_chain_wallet_cache_init() } - dap_list_t *l_local_addr_list = dap_chain_wallet_get_local_addr(); pthread_rwlock_wrlock(&s_wallet_cache_rwlock); for(dap_list_t *it = l_local_addr_list; it; it=it->next){ @@ -170,17 +192,16 @@ int dap_chain_wallet_cache_init() HASH_FIND(hh, s_wallets_cache, l_addr, sizeof(dap_chain_addr_t), l_wallet_item); if (!l_wallet_item){ l_wallet_item = DAP_NEW_Z(dap_wallet_cache_t); - l_wallet_item->wallet_addr = *l_addr; + memcpy (&l_wallet_item->wallet_addr, l_addr, sizeof(dap_chain_addr_t)); HASH_ADD(hh, s_wallets_cache, wallet_addr, sizeof(dap_chain_addr_t), l_wallet_item); - log_it(L_DEBUG, "Wallet %s cached", dap_chain_addr_to_str_static(l_addr)); + debug_if(s_debug_more, L_DEBUG, "Wallet %s saved.", dap_chain_addr_to_str_static(l_addr)); } } pthread_rwlock_unlock(&s_wallet_cache_rwlock); dap_list_free_full(l_local_addr_list, NULL); dap_chain_wallet_add_wallet_opened_notify(s_wallet_opened_callback, NULL); dap_chain_wallet_add_wallet_created_notify(s_wallet_opened_callback, NULL); - - + return 0; } @@ -192,13 +213,17 @@ int dap_chain_wallet_cache_deinit() int dap_chain_wallet_cache_tx_find(dap_chain_addr_t *a_addr, char *a_token, dap_chain_datum_tx_t **a_datum, dap_hash_fast_t *a_tx_hash_curr, int* a_ret_code) { - if ( s_wallets_cache_type == DAP_WALLET_CACHE_TYPE_DISABLED ) - return -101; dap_wallet_cache_t *l_wallet_item = NULL; + + if (s_wallets_cache_type == DAP_WALLET_CACHE_TYPE_DISABLED){ + debug_if(s_debug_more, L_DEBUG, "Wallet cache is disabled."); + return -101; + } + pthread_rwlock_rdlock(&s_wallet_cache_rwlock); HASH_FIND(hh, s_wallets_cache, a_addr, sizeof(dap_chain_addr_t), l_wallet_item); if (!l_wallet_item || l_wallet_item->is_loading){ - log_it(L_ERROR, "Can't find wallet with address %s", dap_chain_addr_to_str_static(a_addr)); + log_it(L_INFO, "Can't find wallet with address %s", dap_chain_addr_to_str_static(a_addr)); pthread_rwlock_unlock(&s_wallet_cache_rwlock); return -101; } @@ -207,7 +232,7 @@ int dap_chain_wallet_cache_tx_find(dap_chain_addr_t *a_addr, char *a_token, dap_ // find start transaction HASH_FIND(hh, l_wallet_item->wallet_txs, a_tx_hash_curr, sizeof(dap_chain_hash_fast_t), l_current_wallet_tx); if (!l_current_wallet_tx){ - log_it(L_ERROR, "Can't find tx %s for address %s", dap_hash_fast_to_str_static(a_tx_hash_curr), dap_chain_addr_to_str_static(a_addr)); + debug_if(s_debug_more, L_DEBUG, "Can't find tx %s for address %s", dap_hash_fast_to_str_static(a_tx_hash_curr), dap_chain_addr_to_str_static(a_addr)); pthread_rwlock_unlock(&s_wallet_cache_rwlock); return 0; } @@ -274,17 +299,20 @@ int dap_chain_wallet_cache_tx_find(dap_chain_addr_t *a_addr, char *a_token, dap_ int dap_chain_wallet_cache_tx_find_in_history(dap_chain_addr_t *a_addr, char **a_token, int* a_ret_code, dap_chain_tx_tag_action_type_t *a_action, dap_chain_srv_uid_t *a_uid, dap_chain_datum_tx_t **a_datum, dap_hash_fast_t *a_tx_hash_curr) { - if ( s_wallets_cache_type == DAP_WALLET_CACHE_TYPE_DISABLED ) - return -101; dap_wallet_cache_t *l_wallet_item = NULL; + if (s_wallets_cache_type == DAP_WALLET_CACHE_TYPE_DISABLED){ + debug_if(s_debug_more, L_DEBUG, "Wallet cache is disabled."); + return -101; + } + if (!a_tx_hash_curr) return -100; pthread_rwlock_rdlock(&s_wallet_cache_rwlock); HASH_FIND(hh, s_wallets_cache, a_addr, sizeof(dap_chain_addr_t), l_wallet_item); if (!l_wallet_item || l_wallet_item->is_loading){ - log_it(L_ERROR, "Can't find wallet with address %s", dap_chain_addr_to_str_static(a_addr)); + debug_if(s_debug_more, L_DEBUG, "Can't find wallet with address %s", dap_chain_addr_to_str_static(a_addr)); pthread_rwlock_unlock(&s_wallet_cache_rwlock); return -101; } @@ -303,6 +331,7 @@ int dap_chain_wallet_cache_tx_find_in_history(dap_chain_addr_t *a_addr, char **a l_current_wallet_tx = l_wallet_item->wallet_txs; } + // Go iterate wallet txs if (l_current_wallet_tx){ // Now work with it @@ -320,9 +349,10 @@ int dap_chain_wallet_cache_tx_find_in_history(dap_chain_addr_t *a_addr, char **a pthread_rwlock_unlock(&s_wallet_cache_rwlock); return 0; } - + + if (a_tx_hash_curr) - *a_tx_hash_curr = (dap_hash_fast_t) { }; + memset(a_tx_hash_curr, 0, sizeof(*a_tx_hash_curr)); if (a_datum) *a_datum = NULL; if(a_ret_code) @@ -337,11 +367,10 @@ int dap_chain_wallet_cache_tx_find_in_history(dap_chain_addr_t *a_addr, char **a return 0; } -int dap_chain_wallet_cache_tx_find_outs_with_val(dap_chain_net_t *a_net, const char *a_token_ticker, const dap_chain_addr_t *a_addr, - dap_list_t **a_outs_list, uint256_t a_value_need, uint256_t *a_value_transfer) +int dap_chain_wallet_cache_tx_find_outs(dap_chain_net_t *a_net, const char *a_token_ticker, const dap_chain_addr_t *a_addr, + dap_list_t **a_outs_list, uint256_t *a_value_transfer) { - if ( s_wallets_cache_type == DAP_WALLET_CACHE_TYPE_DISABLED ) - return -101; + dap_list_t *l_list_used_out = NULL; // list of transaction with 'out' items uint256_t l_value_transfer = { }; dap_chain_datum_tx_t *l_tx; @@ -356,11 +385,6 @@ int dap_chain_wallet_cache_tx_find_outs_with_val(dap_chain_net_t *a_net, const c return -100; } - if (IS_ZERO_256(a_value_need)){ - log_it(L_ERROR, "Needed value is zero."); - return -100; - } - if (a_outs_list == NULL){ log_it(L_ERROR, "a_outs_list is NULL"); return -100; @@ -369,129 +393,74 @@ int dap_chain_wallet_cache_tx_find_outs_with_val(dap_chain_net_t *a_net, const c dap_wallet_cache_t *l_wallet_item = NULL; pthread_rwlock_rdlock(&s_wallet_cache_rwlock); HASH_FIND(hh, s_wallets_cache, a_addr, sizeof(dap_chain_addr_t), l_wallet_item); - if (!l_wallet_item || l_wallet_item->is_loading){ - log_it(L_ERROR, "Can't find wallet with address %s", dap_chain_addr_to_str_static(a_addr)); + if (!l_wallet_item|| l_wallet_item->is_loading){ + debug_if(s_debug_more, L_DEBUG, "Can't find wallet with address %s", dap_chain_addr_to_str_static(a_addr)); pthread_rwlock_unlock(&s_wallet_cache_rwlock); return -101; } - dap_wallet_tx_cache_t *l_current_wallet_tx = l_wallet_item->wallet_txs; - // Go iterate wallet txs - dap_wallet_tx_cache_t *l_current_wallet_tx_iter = NULL, *l_tmp = NULL; - HASH_ITER(hh, l_current_wallet_tx, l_current_wallet_tx_iter, l_tmp) { - if (l_current_wallet_tx_iter->ret_code != DAP_LEDGER_CHECK_OK) - continue; + dap_wallet_cache_unspent_outs_t *l_item_cur = NULL, *l_tmp = NULL; + HASH_ITER(hh, l_wallet_item->unspent_outputs, l_item_cur, l_tmp){ - - if (*l_current_wallet_tx_iter->token_ticker && - dap_strcmp(l_current_wallet_tx_iter->token_ticker, a_token_ticker) && - !l_current_wallet_tx_iter->multichannel) + if (dap_strcmp(l_item_cur->token_ticker, a_token_ticker)) continue; - else if (*l_current_wallet_tx_iter->token_ticker && dap_strcmp(l_current_wallet_tx_iter->token_ticker, a_token_ticker) && - l_current_wallet_tx_iter->multichannel){ - - bool skip = true; - for (dap_list_t *l_temp = l_current_wallet_tx_iter->tx_wallet_outputs; l_temp; l_temp=l_temp->next){ - dap_wallet_tx_cache_output_t *l_out_cur = (dap_wallet_tx_cache_output_t*)l_temp->data; - dap_chain_tx_item_type_t l_type = *(dap_chain_tx_item_type_t*)l_out_cur->tx_out; - uint256_t l_value = { }; - switch (l_type) { - case TX_ITEM_TYPE_OUT_EXT: { - dap_chain_tx_out_ext_t *l_out_ext = (dap_chain_tx_out_ext_t*)l_out_cur->tx_out; - if (dap_strcmp(l_out_ext->token, a_token_ticker)) - continue; - if (IS_ZERO_256(l_out_ext->header.value) ) - continue; - l_value = l_out_ext->header.value; - } break; - default: + else { + dap_wallet_tx_cache_output_t *l_out_cur = (dap_wallet_tx_cache_output_t*)l_item_cur->output; + dap_chain_tx_item_type_t l_type = *(dap_chain_tx_item_type_t*)l_out_cur->tx_out; + uint256_t l_value = { }; + switch (l_type) { + case TX_ITEM_TYPE_OUT_OLD: { + dap_chain_tx_out_old_t *l_out = (dap_chain_tx_out_old_t*)l_out_cur->tx_out; + if (!l_out->header.value) continue; - } - // Check whether used 'out' items - if ( !dap_ledger_tx_hash_is_used_out_item (a_net->pub.ledger, &l_current_wallet_tx_iter->tx_hash, l_out_cur->tx_out_idx, NULL) ) { - 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_current_wallet_tx_iter->tx_hash, (uint32_t)l_out_cur->tx_out_idx, l_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) >= 0 ) { - break; - } - } - } - } else { - bool skip = true; - for (dap_list_t *l_temp = l_current_wallet_tx_iter->tx_wallet_outputs; l_temp; l_temp=l_temp->next){ - dap_wallet_tx_cache_output_t *l_out_cur = (dap_wallet_tx_cache_output_t*)l_temp->data; - dap_chain_tx_item_type_t l_type = *(dap_chain_tx_item_type_t*)l_out_cur->tx_out; - uint256_t l_value = { }; - switch (l_type) { - case TX_ITEM_TYPE_OUT_OLD: { - dap_chain_tx_out_old_t *l_out = (dap_chain_tx_out_old_t*)l_out_cur->tx_out; - if (!l_out->header.value) - continue; - l_value = GET_256_FROM_64(l_out->header.value); - } break; - case TX_ITEM_TYPE_OUT: { - dap_chain_tx_out_t *l_out = (dap_chain_tx_out_t*)l_out_cur->tx_out; - if (IS_ZERO_256(l_out->header.value) ) - continue; - l_value = l_out->header.value; - } break; - case TX_ITEM_TYPE_OUT_EXT: { - // TODO: check ticker - dap_chain_tx_out_ext_t *l_out_ext = (dap_chain_tx_out_ext_t*)l_out_cur->tx_out; - if (dap_strcmp(l_out_ext->token, a_token_ticker)) - continue; - if (IS_ZERO_256(l_out_ext->header.value) ) - continue; - l_value = l_out_ext->header.value; - } break; - default: + l_value = GET_256_FROM_64(l_out->header.value); + } break; + case TX_ITEM_TYPE_OUT: { + dap_chain_tx_out_t *l_out = (dap_chain_tx_out_t*)l_out_cur->tx_out; + if (IS_ZERO_256(l_out->header.value) ) continue; - } - // Check whether used 'out' items - - if ( !dap_ledger_tx_hash_is_used_out_item (a_net->pub.ledger, &l_current_wallet_tx_iter->tx_hash, l_out_cur->tx_out_idx, NULL) ) { - 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_current_wallet_tx_iter->tx_hash, (uint32_t)l_out_cur->tx_out_idx, l_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) >= 0 ) { - break; - } - } + l_value = l_out->header.value; + } break; + case TX_ITEM_TYPE_OUT_EXT: { + dap_chain_tx_out_ext_t *l_out_ext = (dap_chain_tx_out_ext_t*)l_out_cur->tx_out; + if (dap_strcmp(l_out_ext->token, a_token_ticker)) + continue; + if (IS_ZERO_256(l_out_ext->header.value) ) + continue; + l_value = l_out_ext->header.value; + } break; + default: + continue; } - } - if ( compare256(l_value_transfer, a_value_need) >= 0 ) { - break; - } + + 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_item_cur->key.tx_hash, (uint32_t)l_item_cur->key.out_idx, l_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); + } } pthread_rwlock_unlock(&s_wallet_cache_rwlock); - if (compare256(l_value_transfer, a_value_need) >= 0 && l_list_used_out){ - *a_outs_list = l_list_used_out; - if (a_value_transfer) - *a_value_transfer = l_value_transfer; - } else { - *a_outs_list = NULL; - dap_list_free(l_list_used_out); - if (a_value_transfer) - *a_value_transfer = uint256_0; - } + *a_outs_list = l_list_used_out; + if (a_value_transfer) + *a_value_transfer = l_value_transfer; return 0; } -int dap_chain_wallet_cache_tx_find_outs(dap_chain_net_t *a_net, const char *a_token_ticker, const dap_chain_addr_t *a_addr, - dap_list_t **a_outs_list, uint256_t *a_value_transfer) +int dap_chain_wallet_cache_tx_find_outs_with_val(dap_chain_net_t *a_net, const char *a_token_ticker, const dap_chain_addr_t *a_addr, + dap_list_t **a_outs_list, uint256_t a_value_need, uint256_t *a_value_transfer) { dap_list_t *l_list_used_out = NULL; // list of transaction with 'out' items uint256_t l_value_transfer = { }; dap_chain_datum_tx_t *l_tx; + if (s_wallets_cache_type == DAP_WALLET_CACHE_TYPE_DISABLED){ + debug_if(s_debug_more, L_DEBUG, "Wallet cache is disabled."); + return -101; + } + if (!a_token_ticker){ log_it(L_ERROR, "Token ticker is not specified."); return -100; @@ -502,6 +471,11 @@ int dap_chain_wallet_cache_tx_find_outs(dap_chain_net_t *a_net, const char *a_to return -100; } + if (IS_ZERO_256(a_value_need)){ + log_it(L_ERROR, "Needed value is zero."); + return -100; + } + if (a_outs_list == NULL){ log_it(L_ERROR, "a_outs_list is NULL"); return -100; @@ -511,242 +485,68 @@ int dap_chain_wallet_cache_tx_find_outs(dap_chain_net_t *a_net, const char *a_to pthread_rwlock_rdlock(&s_wallet_cache_rwlock); HASH_FIND(hh, s_wallets_cache, a_addr, sizeof(dap_chain_addr_t), l_wallet_item); if (!l_wallet_item || l_wallet_item->is_loading){ - log_it(L_ERROR, "Can't find wallet with address %s", dap_chain_addr_to_str_static(a_addr)); + debug_if(s_debug_more, L_DEBUG, "Can't find wallet with address %s", dap_chain_addr_to_str_static(a_addr)); pthread_rwlock_unlock(&s_wallet_cache_rwlock); return -101; } - dap_wallet_tx_cache_t *l_current_wallet_tx = l_wallet_item->wallet_txs; - // Go iterate wallet txs - dap_wallet_tx_cache_t *l_current_wallet_tx_iter = NULL, *l_tmp = NULL; - HASH_ITER(hh, l_current_wallet_tx, l_current_wallet_tx_iter, l_tmp) { - if (l_current_wallet_tx_iter->ret_code != DAP_LEDGER_CHECK_OK) - continue; + dap_wallet_cache_unspent_outs_t *l_item_cur = NULL, *l_tmp = NULL; + HASH_ITER(hh, l_wallet_item->unspent_outputs, l_item_cur, l_tmp){ - - if (*l_current_wallet_tx_iter->token_ticker && - dap_strcmp(l_current_wallet_tx_iter->token_ticker, a_token_ticker) && - !l_current_wallet_tx_iter->multichannel) + if (dap_strcmp(l_item_cur->token_ticker, a_token_ticker)) continue; - else if (*l_current_wallet_tx_iter->token_ticker && dap_strcmp(l_current_wallet_tx_iter->token_ticker, a_token_ticker) && - l_current_wallet_tx_iter->multichannel){ - - bool skip = true; - for (dap_list_t *l_temp = l_current_wallet_tx_iter->tx_wallet_outputs; l_temp; l_temp=l_temp->next){ - dap_wallet_tx_cache_output_t *l_out_cur = (dap_wallet_tx_cache_output_t*)l_temp->data; - dap_chain_tx_item_type_t l_type = *(dap_chain_tx_item_type_t*)l_out_cur->tx_out; - uint256_t l_value = { }; - switch (l_type) { - case TX_ITEM_TYPE_OUT_EXT: { - dap_chain_tx_out_ext_t *l_out_ext = (dap_chain_tx_out_ext_t*)l_out_cur->tx_out; - if (dap_strcmp(l_out_ext->token, a_token_ticker)) - continue; - if (IS_ZERO_256(l_out_ext->header.value) ) - continue; - l_value = l_out_ext->header.value; - } break; - default: - continue; - } - // Check whether used 'out' items - if ( !dap_ledger_tx_hash_is_used_out_item (a_net->pub.ledger, &l_current_wallet_tx_iter->tx_hash, l_out_cur->tx_out_idx, NULL) ) { - 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_current_wallet_tx_iter->tx_hash, (uint32_t)l_out_cur->tx_out_idx, l_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); - } - } - } else { - bool skip = true; - for (dap_list_t *l_temp = l_current_wallet_tx_iter->tx_wallet_outputs; l_temp; l_temp=l_temp->next){ - dap_wallet_tx_cache_output_t *l_out_cur = (dap_wallet_tx_cache_output_t*)l_temp->data; - dap_chain_tx_item_type_t l_type = *(dap_chain_tx_item_type_t*)l_out_cur->tx_out; - uint256_t l_value = { }; - switch (l_type) { - case TX_ITEM_TYPE_OUT_OLD: { - dap_chain_tx_out_old_t *l_out = (dap_chain_tx_out_old_t*)l_out_cur->tx_out; - if (!l_out->header.value) - continue; - l_value = GET_256_FROM_64(l_out->header.value); - } break; - case TX_ITEM_TYPE_OUT: { - dap_chain_tx_out_t *l_out = (dap_chain_tx_out_t*)l_out_cur->tx_out; - if (IS_ZERO_256(l_out->header.value) ) - continue; - l_value = l_out->header.value; - } break; - case TX_ITEM_TYPE_OUT_EXT: { - // TODO: check ticker - dap_chain_tx_out_ext_t *l_out_ext = (dap_chain_tx_out_ext_t*)l_out_cur->tx_out; - if (dap_strcmp(l_out_ext->token, a_token_ticker)) - continue; - if (IS_ZERO_256(l_out_ext->header.value) ) - continue; - l_value = l_out_ext->header.value; - } break; - default: - continue; - } - // Check whether used 'out' items - - if ( !dap_ledger_tx_hash_is_used_out_item (a_net->pub.ledger, &l_current_wallet_tx_iter->tx_hash, l_out_cur->tx_out_idx, NULL) ) { - 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_current_wallet_tx_iter->tx_hash, (uint32_t)l_out_cur->tx_out_idx, l_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); - } - } - } - } - pthread_rwlock_unlock(&s_wallet_cache_rwlock); - - *a_outs_list = l_list_used_out; - if (a_value_transfer) - *a_value_transfer = l_value_transfer; - - return 0; -} - -static int s_save_tx_into_wallet_cache(dap_chain_t *a_chain, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash, - dap_hash_fast_t *a_atom_hash, int a_ret_code, char* a_main_token_ticker, - dap_chain_srv_uid_t a_srv_uid, dap_chain_tx_tag_action_type_t a_action) -{ - int l_ret_val = 0; - int l_items_cnt = 0; - - dap_list_t *l_out_list = dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_OUT_ALL, &l_items_cnt); - bool l_multichannel = false; - int l_out_idx = 0; - for (dap_list_t *it=l_out_list; it; it=it->next, l_out_idx++){ - uint8_t l_out_type = *(uint8_t *)it->data; - dap_chain_addr_t l_addr = {}; - switch(l_out_type){ + else { + dap_wallet_tx_cache_output_t *l_out_cur = (dap_wallet_tx_cache_output_t*)l_item_cur->output; + dap_chain_tx_item_type_t l_type = *(dap_chain_tx_item_type_t*)l_out_cur->tx_out; + uint256_t l_value = { }; + switch (l_type) { case TX_ITEM_TYPE_OUT_OLD: { - l_addr = ((dap_chain_tx_out_old_t*)it->data)->addr; + dap_chain_tx_out_old_t *l_out = (dap_chain_tx_out_old_t*)l_out_cur->tx_out; + if (!l_out->header.value) + continue; + l_value = GET_256_FROM_64(l_out->header.value); } break; case TX_ITEM_TYPE_OUT: { - l_addr = ((dap_chain_tx_out_t*)it->data)->addr; + dap_chain_tx_out_t *l_out = (dap_chain_tx_out_t*)l_out_cur->tx_out; + if (IS_ZERO_256(l_out->header.value) ) + continue; + l_value = l_out->header.value; } break; case TX_ITEM_TYPE_OUT_EXT: { - l_addr = ((dap_chain_tx_out_ext_t*)it->data)->addr; - l_multichannel = true; + dap_chain_tx_out_ext_t *l_out_ext = (dap_chain_tx_out_ext_t*)l_out_cur->tx_out; + if (dap_strcmp(l_out_ext->token, a_token_ticker)) + continue; + if (IS_ZERO_256(l_out_ext->header.value) ) + continue; + l_value = l_out_ext->header.value; } break; default: continue; - } - - if(!dap_chain_addr_is_blank(&l_addr) && ((s_wallets_cache_type == DAP_WALLET_CACHE_TYPE_LOCAL && - dap_chain_wallet_addr_cache_get_name(&l_addr) != NULL) || s_wallets_cache_type == DAP_WALLET_CACHE_TYPE_ALL) && - l_addr.net_id.uint64 == a_chain->net_id.uint64){ - pthread_rwlock_wrlock(&s_wallet_cache_rwlock); - dap_wallet_cache_t *l_wallet_item = NULL; - HASH_FIND(hh, s_wallets_cache, &l_addr, sizeof(dap_chain_addr_t), l_wallet_item); - if (!l_wallet_item){ - l_wallet_item = DAP_NEW_Z(dap_wallet_cache_t); - memcpy (&l_wallet_item->wallet_addr, &l_addr, sizeof(dap_chain_addr_t)); - HASH_ADD(hh, s_wallets_cache, wallet_addr, sizeof(dap_chain_addr_t), l_wallet_item); - } - dap_wallet_tx_cache_t *l_wallet_tx_item = NULL; - HASH_FIND(hh, l_wallet_item->wallet_txs, a_tx_hash, sizeof(dap_hash_fast_t), l_wallet_tx_item); - if (!l_wallet_tx_item){ - l_wallet_tx_item = DAP_NEW_Z(dap_wallet_tx_cache_t); - l_wallet_tx_item->tx_hash = *a_tx_hash; - l_wallet_tx_item->atom_hash = *a_atom_hash; - l_wallet_tx_item->tx = a_tx; - dap_strncpy(l_wallet_tx_item->token_ticker, a_main_token_ticker ? a_main_token_ticker : "0", DAP_CHAIN_TICKER_SIZE_MAX); - l_wallet_tx_item->ret_code = a_ret_code; - l_wallet_tx_item->srv_uid = a_srv_uid; - l_wallet_tx_item->action = a_action; - HASH_ADD(hh, l_wallet_item->wallet_txs, tx_hash, sizeof(dap_hash_fast_t), l_wallet_tx_item); - } - l_wallet_tx_item->multichannel = l_multichannel; - dap_wallet_tx_cache_output_t *l_out = DAP_NEW_Z(dap_wallet_tx_cache_output_t); - l_out->tx_out = it->data; - l_out->tx_out_idx = l_out_idx; - l_wallet_tx_item->tx_wallet_outputs = dap_list_append(l_wallet_tx_item->tx_wallet_outputs, l_out); - pthread_rwlock_unlock(&s_wallet_cache_rwlock); - } - } - - dap_list_t *l_in_list = dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_IN_ALL, &l_items_cnt); - for (dap_list_t *it=l_in_list; it; it=it->next ){ - uint8_t l_cond_type = *(uint8_t *)it->data; - uint256_t l_value = {}; - dap_chain_addr_t l_addr_from = {}; - if(l_cond_type == TX_ITEM_TYPE_IN){ - dap_hash_fast_t l_prev_tx_hash = ((dap_chain_tx_in_t*)it->data)->header.tx_prev_hash; - int l_prev_idx = ((dap_chain_tx_in_t*)it->data)->header.tx_out_prev_idx; - if (dap_hash_fast_is_blank(&l_prev_tx_hash)) - continue; - dap_chain_datum_t *l_prev_datum = a_chain->callback_datum_find_by_hash(a_chain, &l_prev_tx_hash, NULL, NULL); - dap_chain_datum_tx_t *l_tx_prev = l_prev_datum ? (dap_chain_datum_tx_t *)(l_prev_datum->data) : NULL; - if (!l_tx_prev){ - log_it(L_ERROR, "Can't find previous transactions (hash=%s)", dap_hash_fast_to_str_static(&l_prev_tx_hash)); - continue; - } - uint8_t* l_prev_item = dap_chain_datum_tx_item_get_nth(l_tx_prev, TX_ITEM_TYPE_OUT_ALL, l_prev_idx); - if (!l_prev_item){ - log_it(L_ERROR, "Can't find out with index %d in transaction %s", l_prev_idx, dap_hash_fast_to_str_static(&l_prev_tx_hash)); - continue; - } - uint8_t l_out_type = *(uint8_t *)l_prev_item; - switch(l_out_type){ - case TX_ITEM_TYPE_OUT_OLD: { - l_value = GET_256_FROM_64(((dap_chain_tx_out_old_t*)l_prev_item)->header.value); - l_addr_from = ((dap_chain_tx_out_old_t*)l_prev_item)->addr; - } break; - case TX_ITEM_TYPE_OUT: - case TX_ITEM_TYPE_OUT_EXT: { - l_value = ((dap_chain_tx_out_ext_t*)l_prev_item)->header.value; - l_addr_from = ((dap_chain_tx_out_ext_t*)l_prev_item)->addr; - } break; - default: - continue; - } - - if(!dap_chain_addr_is_blank(&l_addr_from) && ((s_wallets_cache_type == DAP_WALLET_CACHE_TYPE_LOCAL && - dap_chain_wallet_addr_cache_get_name(&l_addr_from) != NULL) || s_wallets_cache_type == DAP_WALLET_CACHE_TYPE_ALL)&& - l_addr_from.net_id.uint64 == a_chain->net_id.uint64){ - pthread_rwlock_wrlock(&s_wallet_cache_rwlock); - dap_wallet_cache_t *l_wallet_item = NULL; - HASH_FIND(hh, s_wallets_cache, &l_addr_from, sizeof(dap_chain_addr_t), l_wallet_item); - if (!l_wallet_item){ - l_wallet_item = DAP_NEW_Z(dap_wallet_cache_t); - memcpy (&l_wallet_item->wallet_addr, &l_addr_from, sizeof(dap_chain_addr_t)); - HASH_ADD(hh, s_wallets_cache, wallet_addr, sizeof(dap_chain_addr_t), l_wallet_item); - } - dap_wallet_tx_cache_t *l_wallet_tx_item = NULL; - HASH_FIND(hh, l_wallet_item->wallet_txs, a_tx_hash, sizeof(dap_hash_fast_t), l_wallet_tx_item); - if (!l_wallet_tx_item){ - l_wallet_tx_item = DAP_NEW_Z(dap_wallet_tx_cache_t); - l_wallet_tx_item->tx_hash = *a_tx_hash; - l_wallet_tx_item->atom_hash = *a_atom_hash; - l_wallet_tx_item->tx = a_tx; - dap_strncpy(l_wallet_tx_item->token_ticker, a_main_token_ticker ? a_main_token_ticker : "0", DAP_CHAIN_TICKER_SIZE_MAX); - l_wallet_tx_item->multichannel = l_multichannel; - l_wallet_tx_item->ret_code = a_ret_code; - l_wallet_tx_item->srv_uid = a_srv_uid; - l_wallet_tx_item->action = a_action; - HASH_ADD(hh, l_wallet_item->wallet_txs, tx_hash, sizeof(dap_hash_fast_t), l_wallet_tx_item); - } - dap_wallet_tx_cache_input_t *l_tx_in = DAP_NEW_Z(dap_wallet_tx_cache_input_t); - l_tx_in->tx_prev_hash = l_prev_tx_hash; - l_tx_in->tx_out_prev_idx = l_prev_idx; - l_tx_in->value = l_value; - l_wallet_tx_item->tx_wallet_inputs = dap_list_append(l_wallet_tx_item->tx_wallet_inputs, l_tx_in); - pthread_rwlock_unlock(&s_wallet_cache_rwlock); } + 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_item_cur->key.tx_hash, (uint32_t)l_item_cur->key.out_idx, l_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); + } + if ( compare256(l_value_transfer, a_value_need) >= 0 ) { + break; } } + pthread_rwlock_unlock(&s_wallet_cache_rwlock); - if (l_out_list) - dap_list_free(l_out_list); - - if (l_in_list) - dap_list_free(l_in_list); - - return l_ret_val; + if (compare256(l_value_transfer, a_value_need) >= 0 && l_list_used_out){ + *a_outs_list = l_list_used_out; + if (a_value_transfer) + *a_value_transfer = l_value_transfer; + } else { + *a_outs_list = NULL; + dap_list_free_full(l_list_used_out, NULL); + if (a_value_transfer) + *a_value_transfer = uint256_0; + } + + return 0; } @@ -763,7 +563,8 @@ static int s_save_cache_for_addr_in_net(dap_chain_net_t *a_net, dap_chain_addr_t l_datum = l_chain->callback_datum_iter_get_next(l_iter)){ if (l_datum->header.type_id == DAP_CHAIN_DATUM_TX) - s_save_tx_cache_for_addr(l_chain, a_addr, (dap_chain_datum_tx_t*)l_datum->data, l_iter->cur_hash, l_iter->cur_atom_hash, l_iter->ret_code, l_iter->token_ticker, l_iter->uid, l_iter->action); + s_save_tx_cache_for_addr(l_chain, a_addr, (dap_chain_datum_tx_t*)l_datum->data, l_iter->cur_hash,l_iter->cur_atom_hash, + l_iter->ret_code, l_iter->token_ticker, l_iter->uid, l_iter->action, 'a'); } l_chain->callback_datum_iter_delete(l_iter); break; @@ -775,22 +576,27 @@ static int s_save_cache_for_addr_in_net(dap_chain_net_t *a_net, dap_chain_addr_t return 0; } -static void s_callback_datum_notify(void *a_arg, dap_chain_hash_fast_t *a_datum_hash, dap_chain_hash_fast_t *a_atom_hash, - void *a_datum, size_t a_datum_size, int a_ret_code, uint32_t a_action, - dap_chain_srv_uid_t a_uid) +static void s_callback_datum_notify(void *a_arg, dap_chain_hash_fast_t *a_datum_hash, dap_chain_hash_fast_t *a_atom_hash, void *a_datum, + size_t a_datum_size, int a_ret_code, uint32_t a_action, dap_chain_srv_uid_t a_uid) { dap_atom_notify_arg_t *l_arg = (dap_atom_notify_arg_t*)a_arg; - dap_chain_datum_t *l_datum = (dap_chain_datum_t*)a_datum; if (!l_datum || l_datum->header.type_id != DAP_CHAIN_DATUM_TX) return; - dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t*)l_datum->data; - - const char* l_main_token_ticker = NULL; + s_save_tx_cache_for_addr(l_arg->chain, NULL, (dap_chain_datum_tx_t*)l_datum->data, a_datum_hash, a_atom_hash, a_ret_code, + (char*)dap_ledger_tx_get_token_ticker_by_hash(l_arg->net->pub.ledger, a_datum_hash), + a_uid, a_action, 'a'); +} + +static void s_callback_datum_removed_notify(void *a_arg, dap_chain_hash_fast_t *a_datum_hash, dap_chain_datum_t *a_datum) +{ + if (!a_datum_hash || !a_datum || a_datum->header.type_id != DAP_CHAIN_DATUM_TX) + return; - l_main_token_ticker = dap_ledger_tx_get_token_ticker_by_hash(l_arg->net->pub.ledger, a_datum_hash); - s_save_tx_into_wallet_cache(l_arg->chain, l_tx, a_datum_hash, a_atom_hash, a_ret_code, (char*)l_main_token_ticker, a_uid, a_action); + dap_atom_notify_arg_t *l_arg = (dap_atom_notify_arg_t*)a_arg; + s_save_tx_cache_for_addr(l_arg->chain, NULL, (dap_chain_datum_tx_t*)a_datum->data, a_datum_hash, NULL, 0, + NULL, (dap_chain_srv_uid_t){ }, DAP_CHAIN_TX_TAG_ACTION_UNKNOWN, 'd'); } typedef struct wallet_cache_load_args { @@ -806,11 +612,10 @@ static void *s_wallet_load(void *a_arg) s_save_cache_for_addr_in_net(l_args->net, &l_args->addr); l_args->wallet_item->is_loading = false; - DAP_DEL_Z(a_arg); - - return NULL; + return DAP_DELETE(a_arg), NULL; } + static void s_wallet_opened_callback(dap_chain_wallet_t *a_wallet, void *a_arg) { for(dap_chain_net_t *l_net = dap_chain_net_iter_start(); l_net; l_net=dap_chain_net_iter_next(l_net)){ @@ -844,172 +649,210 @@ static void s_wallet_opened_callback(dap_chain_wallet_t *a_wallet, void *a_arg) pthread_create(&l_tid, &attr, s_wallet_load, l_args); // s_save_cache_for_addr_in_net(l_net, l_addr); - DAP_DEL_Z(l_addr); } } +static int s_out_idx_cmp(dap_list_t *a_l1, dap_list_t *a_l2) { + dap_wallet_tx_cache_output_t *o1 = a_l1->data, + *o2 = a_l2->data; + return o1->tx_out_idx != o2->tx_out_idx; +} -static int s_save_tx_cache_for_addr(dap_chain_t *a_chain, dap_chain_addr_t *a_addr, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash, - dap_hash_fast_t *a_atom_hash, int a_ret_code, char* a_main_token_ticker, - dap_chain_srv_uid_t a_srv_uid, dap_chain_tx_tag_action_type_t a_action) +static int s_save_tx_cache_for_addr(dap_chain_t *a_chain, dap_chain_addr_t *a_addr, dap_chain_datum_tx_t *a_tx, + dap_hash_fast_t *a_tx_hash, dap_hash_fast_t *a_atom_hash, int a_ret_code, char* a_main_token_ticker, + dap_chain_srv_uid_t a_srv_uid, dap_chain_tx_tag_action_type_t a_action, char a_cache_op) { - int l_ret_val = 0; - int l_items_cnt = 0; - + int l_ret_val = 0, l_items_cnt = 0, l_out_idx = 0, l_prev_idx; bool l_multichannel = false; - int l_out_idx = 0; - uint8_t *l_tx_item = NULL; - size_t l_size; int i; - TX_ITEM_ITER_TX_TYPE(l_tx_item, TX_ITEM_TYPE_OUT_ALL, l_size, i, a_tx) { - uint8_t l_out_type = *(uint8_t *)l_tx_item; - dap_chain_addr_t l_addr = {}; - switch(l_out_type){ - case TX_ITEM_TYPE_OUT_OLD: { - l_addr = ((dap_chain_tx_out_old_t*)l_tx_item)->addr; - } break; - case TX_ITEM_TYPE_OUT: { - l_addr = ((dap_chain_tx_out_t*)l_tx_item)->addr; - } break; - case TX_ITEM_TYPE_OUT_EXT: { - l_addr = ((dap_chain_tx_out_ext_t*)l_tx_item)->addr; - l_multichannel = true; - } break; - default:{ - l_out_idx++; +#define m_check_addr(addr) ( \ + !dap_chain_addr_is_blank(&addr) && ( \ + a_addr ? dap_chain_addr_compare(&addr, a_addr) : \ + ( (s_wallets_cache_type == DAP_WALLET_CACHE_TYPE_LOCAL && dap_chain_wallet_addr_cache_get_name(&addr)) \ + || s_wallets_cache_type == DAP_WALLET_CACHE_TYPE_ALL ) ) \ + && addr.net_id.uint64 == a_chain->net_id.uint64 \ +) + uint8_t *l_tx_item; size_t l_size; + TX_ITEM_ITER_TX(l_tx_item, l_size, a_tx) { + dap_hash_fast_t l_prev_tx_hash; + dap_chain_addr_t l_addr; + uint256_t l_value; + uint8_t *l_prev_item = NULL; + int l_prev_idx; + uint8_t l_item_type = TX_ITEM_TYPE_ANY; + + switch(*l_tx_item) { + case TX_ITEM_TYPE_IN: { + l_prev_tx_hash = ((dap_chain_tx_in_t*)l_tx_item)->header.tx_prev_hash; + l_prev_idx = ((dap_chain_tx_in_t*)l_tx_item)->header.tx_out_prev_idx; + if ( dap_hash_fast_is_blank(&l_prev_tx_hash) ) + continue; + dap_chain_datum_t *l_prev_datum = a_chain->callback_datum_find_by_hash(a_chain, &l_prev_tx_hash, NULL, NULL); + dap_chain_datum_tx_t *l_tx_prev = l_prev_datum ? (dap_chain_datum_tx_t *)(l_prev_datum->data) : NULL; + if (!l_tx_prev) { + log_it(L_ERROR, "Can't find previous transaction by hash \"%s\"", dap_hash_fast_to_str_static(&l_prev_tx_hash)); + continue; + } + l_prev_item = dap_chain_datum_tx_item_get_nth(l_tx_prev, TX_ITEM_TYPE_OUT_ALL, l_prev_idx); + if (!l_prev_item) { + log_it(L_ERROR, "Can't find output %d in tx \"%s\"", l_prev_idx, dap_hash_fast_to_str_static(&l_prev_tx_hash)); continue; - } + } + switch (*l_prev_item) { + case TX_ITEM_TYPE_OUT_OLD: + l_value = GET_256_FROM_64(((dap_chain_tx_out_old_t*)l_prev_item)->header.value); + l_addr = ((dap_chain_tx_out_old_t*)l_prev_item)->addr; + break; + case TX_ITEM_TYPE_OUT: + case TX_ITEM_TYPE_OUT_EXT: + l_value = ((dap_chain_tx_out_ext_t*)l_prev_item)->header.value; + l_addr = ((dap_chain_tx_out_ext_t*)l_prev_item)->addr; + break; + default: + continue; + } + l_item_type = TX_ITEM_TYPE_IN; + } break; + case TX_ITEM_TYPE_OUT_OLD: + l_addr = ((dap_chain_tx_out_old_t*)l_tx_item)->addr; + l_item_type = TX_ITEM_TYPE_OUT_ALL; + break; + case TX_ITEM_TYPE_OUT: + l_addr = ((dap_chain_tx_out_t*)l_tx_item)->addr; + l_item_type = TX_ITEM_TYPE_OUT_ALL; + break; + case TX_ITEM_TYPE_OUT_EXT: + l_addr = ((dap_chain_tx_out_ext_t*)l_tx_item)->addr; + l_multichannel = true; + l_item_type = TX_ITEM_TYPE_OUT_ALL; + break; + case TX_ITEM_TYPE_OUT_COND: + /* Make it explicit for possible future STAKE_LOCK adoption */ + // TODO + ++l_out_idx; + default: + continue; } - if(!dap_chain_addr_is_blank(&l_addr) && dap_chain_addr_compare(&l_addr, a_addr) && - l_addr.net_id.uint64 == a_chain->net_id.uint64){ - pthread_rwlock_wrlock(&s_wallet_cache_rwlock); - dap_wallet_cache_t *l_wallet_item = NULL; - HASH_FIND(hh, s_wallets_cache, &l_addr, sizeof(dap_chain_addr_t), l_wallet_item); - if (!l_wallet_item){ + if ( !m_check_addr(l_addr) ) { + l_out_idx += (int)(l_item_type == TX_ITEM_TYPE_OUT_ALL); + continue; + } + + pthread_rwlock_wrlock(&s_wallet_cache_rwlock); + dap_wallet_cache_t *l_wallet_item = NULL; + dap_wallet_tx_cache_t *l_wallet_tx_item = NULL; + HASH_FIND(hh, s_wallets_cache, &l_addr, sizeof(dap_chain_addr_t), l_wallet_item); + switch (a_cache_op) { + case 'a': + if (!l_wallet_item) { l_wallet_item = DAP_NEW_Z(dap_wallet_cache_t); - memcpy (&l_wallet_item->wallet_addr, &l_addr, sizeof(dap_chain_addr_t)); + l_wallet_item->wallet_addr = l_addr; HASH_ADD(hh, s_wallets_cache, wallet_addr, sizeof(dap_chain_addr_t), l_wallet_item); } - dap_wallet_tx_cache_t *l_wallet_tx_item = NULL; + HASH_FIND(hh, l_wallet_item->wallet_txs, a_tx_hash, sizeof(dap_hash_fast_t), l_wallet_tx_item); - if (!l_wallet_tx_item){ - l_wallet_tx_item = DAP_NEW_Z(dap_wallet_tx_cache_t); - l_wallet_tx_item->tx_hash = *a_tx_hash; - l_wallet_tx_item->atom_hash = *a_atom_hash; - l_wallet_tx_item->tx = a_tx; + if (!l_wallet_tx_item) { + l_wallet_tx_item = DAP_NEW(dap_wallet_tx_cache_t); + *l_wallet_tx_item = (dap_wallet_tx_cache_t){ .tx_hash = *a_tx_hash, .atom_hash = *a_atom_hash, .tx = a_tx, + .multichannel = l_multichannel, .ret_code = a_ret_code, .srv_uid = a_srv_uid, .action = a_action }; dap_strncpy(l_wallet_tx_item->token_ticker, a_main_token_ticker ? a_main_token_ticker : "0", DAP_CHAIN_TICKER_SIZE_MAX); - l_wallet_tx_item->ret_code = a_ret_code; - l_wallet_tx_item->srv_uid = a_srv_uid; - l_wallet_tx_item->action = a_action; HASH_ADD(hh, l_wallet_item->wallet_txs, tx_hash, sizeof(dap_hash_fast_t), l_wallet_tx_item); - } - l_wallet_tx_item->multichannel = l_multichannel; - dap_wallet_tx_cache_output_t *l_out = DAP_NEW_Z(dap_wallet_tx_cache_output_t); - l_out->tx_out = l_tx_item; - l_out->tx_out_idx = l_out_idx; - l_wallet_tx_item->tx_wallet_outputs = dap_list_append(l_wallet_tx_item->tx_wallet_outputs, l_out); - pthread_rwlock_unlock(&s_wallet_cache_rwlock); - } - } - - l_tx_item = NULL; - TX_ITEM_ITER_TX_TYPE(l_tx_item, TX_ITEM_TYPE_IN_ALL, l_size, i, a_tx) { - uint8_t l_cond_type = *l_tx_item; - uint256_t l_value = {}; - dap_chain_addr_t l_addr_from = {}; - if(l_cond_type == TX_ITEM_TYPE_IN){ - dap_hash_fast_t l_prev_tx_hash = ((dap_chain_tx_in_t*)l_tx_item)->header.tx_prev_hash; - int l_prev_idx = ((dap_chain_tx_in_t*)l_tx_item)->header.tx_out_prev_idx; - if (dap_hash_fast_is_blank(&l_prev_tx_hash)) - continue; - dap_chain_datum_t *l_prev_datum = a_chain->callback_datum_find_by_hash(a_chain, &l_prev_tx_hash, NULL, NULL); - dap_chain_datum_tx_t *l_tx_prev = l_prev_datum ? (dap_chain_datum_tx_t *)(l_prev_datum->data) : NULL; - if (!l_tx_prev) { - log_it(L_ERROR, "Can't find previous transactions (hash=%s)", dap_hash_fast_to_str_static(&l_prev_tx_hash)); - continue; - } - uint8_t* l_prev_item = dap_chain_datum_tx_item_get_nth(l_tx_prev, TX_ITEM_TYPE_OUT_ALL, l_prev_idx); - if (!l_prev_item) { - log_it(L_ERROR, "Can't find out with index %d in transaction %s", l_prev_idx, dap_hash_fast_to_str_static(&l_prev_tx_hash)); - continue; } - uint8_t l_out_type = *(uint8_t *)l_prev_item; - switch(l_out_type){ - case TX_ITEM_TYPE_OUT_OLD: { - l_value = GET_256_FROM_64(((dap_chain_tx_out_old_t*)l_prev_item)->header.value); - l_addr_from = ((dap_chain_tx_out_old_t*)l_prev_item)->addr; - } break; - case TX_ITEM_TYPE_OUT: - case TX_ITEM_TYPE_OUT_EXT: { - l_value = ((dap_chain_tx_out_ext_t*)l_prev_item)->header.value; - l_addr_from = ((dap_chain_tx_out_ext_t*)l_prev_item)->addr; - } break; - default: - continue; + break; + case 'd': { + if (l_wallet_item) { + HASH_FIND(hh, l_wallet_item->wallet_txs, a_tx_hash, sizeof(dap_hash_fast_t), l_wallet_tx_item); + if (l_wallet_tx_item){ + HASH_DEL(l_wallet_item->wallet_txs, l_wallet_tx_item); + dap_list_free_full(l_wallet_tx_item->tx_wallet_inputs, NULL); + dap_list_free_full(l_wallet_tx_item->tx_wallet_outputs, NULL); + DAP_DELETE(l_wallet_tx_item); + } } + } + default: break; + } + - if(!dap_chain_addr_is_blank(&l_addr_from) && dap_chain_addr_compare(&l_addr_from, a_addr) && - l_addr_from.net_id.uint64 == a_chain->net_id.uint64){ - pthread_rwlock_wrlock(&s_wallet_cache_rwlock); - dap_wallet_cache_t *l_wallet_item = NULL; - HASH_FIND(hh, s_wallets_cache, &l_addr_from, sizeof(dap_chain_addr_t), l_wallet_item); - if (!l_wallet_item){ - l_wallet_item = DAP_NEW_Z(dap_wallet_cache_t); - memcpy (&l_wallet_item->wallet_addr, &l_addr_from, sizeof(dap_chain_addr_t)); - HASH_ADD(hh, s_wallets_cache, wallet_addr, sizeof(dap_chain_addr_t), l_wallet_item); + switch (l_item_type) { + case TX_ITEM_TYPE_OUT_ALL: { + switch (a_cache_op) { + case 'a': { + dap_wallet_tx_cache_output_t *l_out = DAP_NEW(dap_wallet_tx_cache_output_t); + *l_out = (dap_wallet_tx_cache_output_t){ .tx_out = l_tx_item, .tx_out_idx = l_out_idx }; + l_wallet_tx_item->tx_wallet_outputs = dap_list_append(l_wallet_tx_item->tx_wallet_outputs, l_out); + /* Add unspent out to cache */ + if (!a_ret_code) { + dap_wallet_cache_unspent_outs_t *l_unspent_out = DAP_NEW(dap_wallet_cache_unspent_outs_t); + *l_unspent_out = (dap_wallet_cache_unspent_outs_t) { + .key = { .tx_hash = *a_tx_hash, .out_idx = l_out_idx }, + .output = l_out + }; + dap_strncpy(l_unspent_out->token_ticker, *l_tx_item == TX_ITEM_TYPE_OUT_EXT ? ((dap_chain_tx_out_ext_t*)l_tx_item)->token + : a_main_token_ticker ? a_main_token_ticker : "0", DAP_CHAIN_TICKER_SIZE_MAX); + HASH_ADD(hh, l_wallet_item->unspent_outputs, key, sizeof(unspent_cache_hh_key), l_unspent_out); } - dap_wallet_tx_cache_t *l_wallet_tx_item = NULL; - HASH_FIND(hh, l_wallet_item->wallet_txs, a_tx_hash, sizeof(dap_hash_fast_t), l_wallet_tx_item); - if (!l_wallet_tx_item){ - l_wallet_tx_item = DAP_NEW_Z(dap_wallet_tx_cache_t); - l_wallet_tx_item->tx_hash = *a_tx_hash; - l_wallet_tx_item->atom_hash = *a_atom_hash; - l_wallet_tx_item->tx = a_tx; - dap_strncpy(l_wallet_tx_item->token_ticker, a_main_token_ticker ? a_main_token_ticker : "0", DAP_CHAIN_TICKER_SIZE_MAX); - l_wallet_tx_item->multichannel = l_multichannel; - l_wallet_tx_item->ret_code = a_ret_code; - l_wallet_tx_item->srv_uid = a_srv_uid; - l_wallet_tx_item->action = a_action; - HASH_ADD(hh, l_wallet_item->wallet_txs, tx_hash, sizeof(dap_hash_fast_t), l_wallet_tx_item); + ++l_out_idx; + } break; + case 'd': { + if ( !l_wallet_item->wallet_txs ) { + HASH_DEL(s_wallets_cache, l_wallet_item); + DAP_DELETE(l_wallet_item); + } + unspent_cache_hh_key key = { .tx_hash = *a_tx_hash, .out_idx = l_out_idx }; + dap_wallet_cache_unspent_outs_t *l_item = NULL; + HASH_FIND(hh, l_wallet_item->unspent_outputs, &key, sizeof(unspent_cache_hh_key), l_item); + if (l_item) { + HASH_DEL(l_wallet_item->unspent_outputs, l_item); + DAP_DELETE(l_item); } - dap_wallet_tx_cache_input_t *l_tx_in = DAP_NEW_Z(dap_wallet_tx_cache_input_t); - l_tx_in->tx_prev_hash = l_prev_tx_hash; - l_tx_in->tx_out_prev_idx = l_prev_idx; - l_tx_in->value = l_value; + } break; + default: break; + } + } break; + case TX_ITEM_TYPE_IN: { + switch (a_cache_op) { + case 'a': { + dap_wallet_tx_cache_input_t *l_tx_in = DAP_NEW(dap_wallet_tx_cache_input_t); + *l_tx_in = (dap_wallet_tx_cache_input_t) { .tx_prev_hash = l_prev_tx_hash, .tx_out_prev_idx = l_prev_idx, .value = l_value }; l_wallet_tx_item->tx_wallet_inputs = dap_list_append(l_wallet_tx_item->tx_wallet_inputs, l_tx_in); - pthread_rwlock_unlock(&s_wallet_cache_rwlock); + /* Delete unspent out from cache */ + if (!a_ret_code) { + unspent_cache_hh_key key = { .tx_hash = l_prev_tx_hash, .out_idx = l_prev_idx }; + dap_wallet_cache_unspent_outs_t *l_item = NULL; + HASH_FIND(hh, l_wallet_item->unspent_outputs, &key, sizeof(unspent_cache_hh_key), l_item); + if (l_item) { + HASH_DEL(l_wallet_item->unspent_outputs, l_item); + DAP_DELETE(l_item); + } + } + } break; + case 'd': { + dap_wallet_tx_cache_t *l_wallet_prev_tx_item = NULL; + HASH_FIND(hh, l_wallet_item->wallet_txs, &l_prev_tx_hash, sizeof(dap_hash_fast_t), l_wallet_prev_tx_item); + if ( l_wallet_prev_tx_item && !l_wallet_prev_tx_item->ret_code ) { + dap_wallet_tx_cache_output_t l_sought_out = { .tx_out_idx = l_prev_idx }; + void *l_out = dap_list_find(l_wallet_prev_tx_item->tx_wallet_outputs, &l_sought_out, s_out_idx_cmp); + if (l_out) { + dap_wallet_cache_unspent_outs_t *l_unspent_out = DAP_NEW_Z(dap_wallet_cache_unspent_outs_t); + *l_unspent_out = (dap_wallet_cache_unspent_outs_t) { .key = { .tx_hash = l_prev_tx_hash, .out_idx = l_prev_idx }, + .output = l_out }; + dap_strncpy(l_unspent_out->token_ticker, *l_prev_item == TX_ITEM_TYPE_OUT_EXT ? ((dap_chain_tx_out_ext_t*)l_tx_item)->token + : l_wallet_prev_tx_item->token_ticker, DAP_CHAIN_TICKER_SIZE_MAX); + HASH_ADD(hh, l_wallet_item->unspent_outputs, key, sizeof(unspent_cache_hh_key), l_unspent_out); + } + } + } break; + default: break; } - + } break; + default: break; } + pthread_rwlock_unlock(&s_wallet_cache_rwlock); } - return l_ret_val; } -static void s_callback_datum_removed_notify(void *a_arg, dap_chain_hash_fast_t *a_datum_hash) -{ - if (!a_datum_hash) - return; - - pthread_rwlock_wrlock(&s_wallet_cache_rwlock); - dap_wallet_cache_t *l_wallet_item = NULL, *l_tmp; - HASH_ITER(hh, s_wallets_cache, l_wallet_item, l_tmp){ - dap_wallet_tx_cache_t *l_wallet_tx_item = NULL; - HASH_FIND(hh, l_wallet_item->wallet_txs, a_datum_hash, sizeof(dap_hash_fast_t), l_wallet_tx_item); - if (l_wallet_tx_item){ - HASH_DEL(l_wallet_item->wallet_txs, l_wallet_tx_item); - dap_list_free_full(l_wallet_tx_item->tx_wallet_inputs, NULL); - dap_list_free_full(l_wallet_tx_item->tx_wallet_outputs, NULL); - DAP_DELETE(l_wallet_tx_item); - } - if (!l_wallet_item->wallet_txs){ - HASH_DEL(s_wallets_cache, l_wallet_item); - DAP_DELETE(l_wallet_item); - } - } - pthread_rwlock_unlock(&s_wallet_cache_rwlock); -} - static void s_wallet_cache_iter_fill(dap_chain_wallet_cache_iter_t *a_cache_iter, dap_wallet_tx_cache_t *a_cache_index) { a_cache_iter->cur_item = (void*)a_cache_index; @@ -1064,6 +907,9 @@ void dap_chain_wallet_cache_iter_delete(dap_chain_wallet_cache_iter_t *a_iter) dap_chain_datum_tx_t *dap_chain_wallet_cache_iter_get(dap_chain_wallet_cache_iter_t *a_iter, dap_chain_wallet_getting_type_t a_type) { + if (!a_iter) + return NULL; + switch (a_type){ case DAP_CHAIN_WALLET_CACHE_GET_FIRST:{ pthread_rwlock_wrlock(&s_wallet_cache_rwlock); -- GitLab From 4db8c7c08e6bcee1a097eedcc1e5d4ed08c7afbe Mon Sep 17 00:00:00 2001 From: "Constantin P." <papizh.konstantin@demlabs.net> Date: Thu, 20 Feb 2025 18:11:43 +0700 Subject: [PATCH 07/15] Block dump fix --- modules/type/blocks/dap_chain_cs_blocks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/type/blocks/dap_chain_cs_blocks.c b/modules/type/blocks/dap_chain_cs_blocks.c index 53f9415797..1e9c27fb9d 100644 --- a/modules/type/blocks/dap_chain_cs_blocks.c +++ b/modules/type/blocks/dap_chain_cs_blocks.c @@ -786,7 +786,7 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply) // Header json_object* json_obj_inf = json_object_new_object(); json_object_object_add(json_obj_inf, "Block number", json_object_new_uint64(l_block_cache->block_number)); - json_object_object_add(json_obj_inf, "hash", json_object_new_string(l_subcmd_str_arg)); + json_object_object_add(json_obj_inf, "hash", json_object_new_string(l_hash_str)); snprintf(l_hexbuf, sizeof(l_hexbuf), "0x%04X",l_block->hdr.version); json_object_object_add(json_obj_inf, "version", json_object_new_string(l_hexbuf)); -- GitLab From 0bc1c8c00aee195f70d9a9aca7c26bc8b2dbb283 Mon Sep 17 00:00:00 2001 From: "daniil.frolov" <daniil.frolov@demlabs.net> Date: Wed, 19 Feb 2025 06:16:52 +0000 Subject: [PATCH 08/15] Conflict resolved --- modules/net-srv/dap_chain_net_srv_order.c | 24 ++++++++++++----------- modules/wallet/dap_chain_wallet.c | 8 ++++++-- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/modules/net-srv/dap_chain_net_srv_order.c b/modules/net-srv/dap_chain_net_srv_order.c index b3cda71447..c60143ca73 100644 --- a/modules/net-srv/dap_chain_net_srv_order.c +++ b/modules/net-srv/dap_chain_net_srv_order.c @@ -642,18 +642,20 @@ void dap_chain_net_srv_order_dump_to_json(const dap_chain_net_srv_order_t *a_ord json_object_object_add(a_json_obj_out, "node_location", json_object_new_string(buf_location)); DAP_DELETE(l_region); - l_hash_str = dap_strcmp(a_hash_out_type, "hex") + if (!dap_hash_fast_is_blank(&a_order->tx_cond_hash)){ + l_hash_str = dap_strcmp(a_hash_out_type, "hex") ? dap_enc_base58_encode_hash_to_str_static(&a_order->tx_cond_hash) - : dap_chain_hash_fast_to_str_static(&a_order->tx_cond_hash); - json_object_object_add(a_json_obj_out, "tx_cond_hash", json_object_new_string(l_hash_str)); - if (a_order->ext_size) { - char *l_ext_out = DAP_NEW_Z_SIZE(char, a_order->ext_size * 2 + 3); - memcpy(l_ext_out, "0x", 2); - dap_bin2hex(l_ext_out + 2, a_order->ext_n_sign, a_order->ext_size); - json_object_object_add(a_json_obj_out, "ext", json_object_new_string(l_ext_out)); - DAP_DELETE(l_ext_out); - } else - json_object_object_add(a_json_obj_out, "ext", json_object_new_string("0x0")); + : dap_chain_hash_fast_to_str_static(&a_order->tx_cond_hash); + json_object_object_add(a_json_obj_out, "tx_cond_hash", json_object_new_string(l_hash_str)); + } + json_object_object_add(a_json_obj_out, "ext_size", json_object_new_uint64(a_order->ext_size)); + // if (a_order->ext_size) { + // char *l_ext_out = DAP_NEW_Z_SIZE(char, a_order->ext_size * 2 + 3); + // dap_strncpy(l_ext_out, "0x", 2); + // dap_bin2hex(l_ext_out + 2, a_order->ext_n_sign, a_order->ext_size); + // + // DAP_DELETE(l_ext_out); + // } dap_sign_t *l_sign = (dap_sign_t*)((byte_t*)a_order->ext_n_sign + a_order->ext_size); dap_hash_fast_t l_sign_pkey = {0}; dap_sign_get_pkey_hash(l_sign, &l_sign_pkey); diff --git a/modules/wallet/dap_chain_wallet.c b/modules/wallet/dap_chain_wallet.c index 3f55a5f9ec..36af7b3f33 100644 --- a/modules/wallet/dap_chain_wallet.c +++ b/modules/wallet/dap_chain_wallet.c @@ -82,6 +82,8 @@ static const mode_t s_fileprot = ( S_IREAD | S_IWRITE) | (S_IREAD >> 3) | (S_IR #endif static char const s_wallet_ext [] = ".dwallet", *s_wallets_path = NULL; +static bool s_debug_more = false; + static pthread_rwlock_t s_wallet_n_pass_lock = PTHREAD_RWLOCK_INITIALIZER; /* Coordinate access to the hash-table */ static dap_chain_wallet_n_pass_t *s_wallet_n_pass; /* A hash table to keep passwords for wallets */ static dap_list_t *s_wallet_open_notificators = NULL; @@ -357,6 +359,8 @@ int dap_chain_wallet_init() dap_chain_wallet_t *l_wallet = NULL; size_t l_len = 0; + s_debug_more = dap_config_get_item_bool_default(g_config,"wallet","debug_more", s_debug_more); + if ( !(c_wallets_path = (char *) dap_chain_wallet_get_path(g_config)) ) /* No path to wallets - nothing to do */ return -1; @@ -820,7 +824,7 @@ uint32_t l_csum = CRC32C_INIT, l_csum2 = CRC32C_INIT; } if ( (l_file_hdr.version == DAP_WALLET$K_VER_2) && (!l_pass) ) { - log_it(L_DEBUG, "Wallet (%s) version 2 cannot be processed w/o password", a_file_name); + debug_if(s_debug_more, L_DEBUG, "Wallet (%s) version 2 cannot be processed w/o password", a_file_name); dap_fileclose(l_fh); if ( a_out_stat ) *a_out_stat = 4; @@ -851,7 +855,7 @@ uint32_t l_csum = CRC32C_INIT, l_csum2 = CRC32C_INIT; l_csum = crc32c(l_csum, &l_file_hdr, sizeof(l_file_hdr) ); /* Compute check sum of the Wallet file header */ l_csum = crc32c(l_csum, l_wallet_name, l_file_hdr.wallet_len); - log_it(L_DEBUG, "Wallet file: %s, Wallet[Version: %d, type: %d, name: '%.*s']", + debug_if(s_debug_more, L_DEBUG, "Wallet file: %s, Wallet[Version: %d, type: %d, name: '%.*s']", a_file_name, l_file_hdr.version, l_file_hdr.type, l_file_hdr.wallet_len, l_wallet_name); /* First run - count certs in file */ -- GitLab From 3e80228fe022e834a41809558cdf54e94df33099 Mon Sep 17 00:00:00 2001 From: "Constantin P." <papizh.konstantin@demlabs.net> Date: Fri, 21 Feb 2025 15:29:03 +0700 Subject: [PATCH 09/15] 15663 --- modules/chain/tests/dap_chain_ledger_tests.c | 25 ++--- modules/ledger/dap_chain_ledger.c | 10 +- modules/ledger/dap_chain_ledger_token.c | 35 ++---- modules/ledger/dap_chain_ledger_tx.c | 111 ++++++++----------- modules/ledger/include/dap_chain_ledger.h | 2 +- modules/net/dap_chain_net.c | 4 +- modules/type/dag/dap_chain_cs_dag.c | 2 +- 7 files changed, 76 insertions(+), 113 deletions(-) diff --git a/modules/chain/tests/dap_chain_ledger_tests.c b/modules/chain/tests/dap_chain_ledger_tests.c index 6c284f7f95..0b762718ae 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; } diff --git a/modules/ledger/dap_chain_ledger.c b/modules/ledger/dap_chain_ledger.c index d4f132c1d6..9a11c0d655 100644 --- a/modules/ledger/dap_chain_ledger.c +++ b/modules/ledger/dap_chain_ledger.c @@ -276,13 +276,13 @@ void dap_ledger_handle_free(dap_ledger_t *a_ledger) } -bool dap_ledger_datum_is_blacklisted(dap_ledger_t *a_ledger, dap_hash_fast_t a_hash) { - dap_ledger_hal_item_t *ret = NULL; - HASH_FIND(hh, PVT(a_ledger)->hrl_items, &a_hash, sizeof(dap_hash_fast_t), ret); - return debug_if(g_debug_ledger && ret, L_MSG, "Datum %s is blacklisted", dap_hash_fast_to_str_static(&a_hash)), !!ret; +bool dap_ledger_datum_is_enforced(dap_ledger_t *a_ledger, dap_hash_fast_t *a_hash, bool a_accept) { + dap_ledger_hal_item_t *l_wanted = NULL; + HASH_FIND(hh, a_accept ? PVT(a_ledger)->hal_items : PVT(a_ledger)->hrl_items, a_hash, sizeof(dap_hash_fast_t), l_wanted); + debug_if(g_debug_ledger && l_wanted, L_DEBUG, "Datum %s is %slisted", dap_hash_fast_to_str_static(&a_hash), a_accept ? "white" : "black"); + return !!l_wanted; } - /** * @brief s_tx_header_print * prepare data for print, add time diff --git a/modules/ledger/dap_chain_ledger_token.c b/modules/ledger/dap_chain_ledger_token.c index 4a3e5a3278..251edc83aa 100644 --- a/modules/ledger/dap_chain_ledger_token.c +++ b/modules/ledger/dap_chain_ledger_token.c @@ -37,14 +37,6 @@ dap_ledger_token_item_t *dap_ledger_pvt_find_token(dap_ledger_t *a_ledger, const return l_token_item; } -inline static dap_ledger_hal_item_t *s_check_hal(dap_ledger_t *a_ledger, dap_hash_fast_t *a_hal_hash) -{ - dap_ledger_hal_item_t *ret = NULL; - HASH_FIND(hh, PVT(a_ledger)->hal_items, a_hal_hash, sizeof(dap_hash_fast_t), ret); - debug_if(g_debug_ledger && ret, L_MSG, "Datum %s is whitelisted", dap_hash_fast_to_str_static(a_hal_hash)); - return ret; -} - /** * @brief GDB callback for loaded emissions from cache * @param a_global_db_context @@ -1020,17 +1012,15 @@ int s_token_add_check(dap_ledger_t *a_ledger, byte_t *a_token, size_t a_token_si pthread_rwlock_rdlock(&PVT(a_ledger)->tokens_rwlock); int ret = s_token_tsd_parse(l_token_item, l_token, a_ledger, l_token->tsd_n_signs, l_size_tsd_section, false); pthread_rwlock_unlock(&PVT(a_ledger)->tokens_rwlock); - dap_ledger_hal_item_t *l_hash_found = NULL; + bool l_is_whitelisted = false; if (ret != DAP_LEDGER_CHECK_OK) { - if (PVT(a_ledger)->hal_items) { - dap_hash_fast_t l_token_hash; - if (!dap_hash_fast_is_blank(&l_token_update_hash)) - l_token_hash = l_token_update_hash; - else - dap_hash_fast(a_token, a_token_size, &l_token_hash); - l_hash_found = s_check_hal(a_ledger, &l_token_hash); - } - if (!l_hash_found) { + dap_hash_fast_t l_token_hash; + if (!dap_hash_fast_is_blank(&l_token_update_hash)) + l_token_hash = l_token_update_hash; + else + dap_hash_fast(a_token, a_token_size, &l_token_hash); + + if (!( l_is_whitelisted = dap_ledger_datum_is_enforced(a_ledger, &l_token_hash, true) )) { DAP_DELETE(l_token); return ret; } @@ -1045,7 +1035,7 @@ int s_token_add_check(dap_ledger_t *a_ledger, byte_t *a_token, size_t a_token_si *a_tsd_total_size = l_size_tsd_section; if (a_signs_size) *a_signs_size = l_signs_size; - return l_hash_found ? DAP_LEDGER_CHECK_WHITELISTED : DAP_LEDGER_CHECK_OK; + return l_is_whitelisted ? DAP_LEDGER_CHECK_WHITELISTED : DAP_LEDGER_CHECK_OK; } int dap_ledger_token_add_check(dap_ledger_t *a_ledger, byte_t *a_token, size_t a_token_size) @@ -1424,7 +1414,7 @@ int s_emission_add_check(dap_ledger_t *a_ledger, byte_t *a_token_emission, size_ size_t l_sign_data_check_size = sizeof(dap_chain_datum_token_emission_t) + l_emission->data.type_auth.tsd_total_size >= sizeof(dap_chain_datum_token_emission_t) ? sizeof(dap_chain_datum_token_emission_t) + l_emission->data.type_auth.tsd_total_size : 0; if (l_sign_data_check_size > l_emission_size) { - if (!s_check_hal(a_ledger, a_emission_hash)) { + if ( !dap_ledger_datum_is_enforced(a_ledger, a_emission_hash, true) ) { log_it(L_WARNING, "Incorrect size %zu of datum emission, expected at least %zu", l_emission_size, l_sign_data_check_size); DAP_DELETE(l_emission); return DAP_LEDGER_CHECK_INVALID_SIZE; @@ -1445,7 +1435,7 @@ int s_emission_add_check(dap_ledger_t *a_ledger, byte_t *a_token_emission, size_ DAP_DELETE(l_signs); - if (!s_check_hal(a_ledger, a_emission_hash)) { + if ( !dap_ledger_datum_is_enforced(a_ledger, a_emission_hash, true) ) { log_it(L_WARNING, "The number of unique token signs %zu is less than total token signs set to %zu", l_signs_unique, l_token_item->auth_signs_total); @@ -1479,8 +1469,7 @@ int s_emission_add_check(dap_ledger_t *a_ledger, byte_t *a_token_emission, size_ l_emission->data.type_auth.tsd_n_signs_size = l_sign_auth_size; } DAP_DELETE(l_signs); - if (l_aproves < l_token_item->auth_signs_valid && - !s_check_hal(a_ledger, a_emission_hash)) { + if (l_aproves < l_token_item->auth_signs_valid && !dap_ledger_datum_is_enforced(a_ledger, a_emission_hash, true) ) { log_it(L_WARNING, "Emission of %s datoshi of %s:%s is wrong: only %zu valid aproves when %zu need", dap_uint256_to_char(l_emission->hdr.value, NULL), a_ledger->net->pub.name, l_emission->hdr.ticker, l_aproves, l_token_item->auth_signs_valid); diff --git a/modules/ledger/dap_chain_ledger_tx.c b/modules/ledger/dap_chain_ledger_tx.c index a639855427..17368e14cf 100644 --- a/modules/ledger/dap_chain_ledger_tx.c +++ b/modules/ledger/dap_chain_ledger_tx.c @@ -807,36 +807,27 @@ 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 transactions - // 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) { + // 6. Compare sum of values in 'out' items + if ( !l_main_ticker ) + switch ( HASH_COUNT(l_values_from_prev_tx) ) { + case 1: + l_main_ticker = l_value_cur->token_ticker; + case 2: 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 { - 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); + 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 l_err_num; + return DAP_LEDGER_TX_CHECK_NO_MAIN_TICKER; } - dap_stpcpy(l_value_cur->token_ticker, l_token); - 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); - } + dap_chain_addr_t l_sovereign_addr; uint256_t l_sovereign_tax; l_tax_check = l_tax_check && s_tax_callback ? s_tax_callback(a_ledger->net->pub.id, &l_tx_first_sign_pkey_hash, &l_sovereign_addr, &l_sovereign_tax) @@ -852,7 +843,7 @@ 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 + if (!( l_token = l_main_ticker )) { l_err_num = DAP_LEDGER_TX_CHECK_NO_MAIN_TICKER; break; } @@ -862,13 +853,9 @@ 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; - } + if (!( l_token = l_main_ticker )) { + 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; @@ -883,20 +870,9 @@ 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_tx_out->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE_STACK) - l_token = (char *)a_ledger->net->pub.native_ticker; - else if (l_main_ticker || (a_main_ticker && *a_main_ticker)) { - if (!l_main_ticker) - l_main_ticker = a_main_ticker; // It should be only in hardfork state - 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; - } + if (!( l_token = l_tx_out->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE ? a_ledger->net->pub.native_ticker : l_main_ticker )) { + 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); @@ -939,18 +915,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; } + dap_strncpy(l_value_cur->token_ticker, l_token, sizeof(l_value_cur->token_ticker)); + 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(g_debug_ledger, L_WARNING, "Sum result overflow for tx_add_check with ticker %s", @@ -982,20 +956,25 @@ static int s_tx_cache_check(dap_ledger_t *a_ledger, } // Check for transaction consistency (sum(ins) == sum(outs)) - if (!l_err_num) { - 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) ) { - if (g_debug_ledger) { - char *l_balance = dap_chain_balance_coins_print(l_res ? l_res->sum : uint256_0); - char *l_balance_cur = dap_chain_balance_coins_print(l_value_cur->sum); - log_it(L_ERROR, "Sum of values of out items from current tx (%s) is not equal outs from previous txs (%s) for token %s", - l_balance, l_balance_cur, l_value_cur->token_ticker); - DAP_DELETE(l_balance); - DAP_DELETE(l_balance_cur); + if ( !l_err_num && !dap_ledger_datum_is_enforced(a_ledger, a_tx_hash, true) ) { + if ( HASH_COUNT(l_values_from_prev_tx) != HASH_COUNT(l_values_from_cur_tx) ) { + log_it(L_ERROR, "Token tickers IN and OUT mismatch: %u != %u", + HASH_COUNT(l_values_from_prev_tx), HASH_COUNT(l_values_from_cur_tx)); + l_err_num = DAP_LEDGER_TX_CHECK_SUM_INS_NOT_EQUAL_SUM_OUTS; + } else { + 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) ) { + if (g_debug_ledger) { + char *l_balance = dap_chain_balance_coins_print(l_res ? l_res->sum : uint256_0), + *l_balance_cur = dap_chain_balance_coins_print(l_value_cur->sum); + log_it(L_ERROR, "Sum of values of out items from current tx (%s) is not equal outs from previous txs (%s) for token %s", + l_balance, l_balance_cur, l_value_cur->token_ticker); + DAP_DEL_MULTY(l_balance, l_balance_cur); + } + l_err_num = DAP_LEDGER_TX_CHECK_SUM_INS_NOT_EQUAL_SUM_OUTS; + break; } - l_err_num = DAP_LEDGER_TX_CHECK_SUM_INS_NOT_EQUAL_SUM_OUTS; - break; } } } diff --git a/modules/ledger/include/dap_chain_ledger.h b/modules/ledger/include/dap_chain_ledger.h index 0a1d3a1205..933b248621 100644 --- a/modules/ledger/include/dap_chain_ledger.h +++ b/modules/ledger/include/dap_chain_ledger.h @@ -486,7 +486,7 @@ dap_chain_datum_tx_t *dap_ledger_datum_iter_get_last(dap_ledger_datum_iter_t *a_ void dap_ledger_tx_add_notify(dap_ledger_t *a_ledger, dap_ledger_tx_add_notify_t a_callback, void *a_arg); void dap_ledger_bridged_tx_notify_add(dap_ledger_t *a_ledger, dap_ledger_bridged_tx_notify_t a_callback, void *a_arg); -bool dap_ledger_datum_is_blacklisted(dap_ledger_t *a_ledger, dap_hash_fast_t a_hash); +bool dap_ledger_datum_is_enforced(dap_ledger_t *a_ledger, dap_hash_fast_t *a_hash, bool a_accept); bool dap_ledger_cache_enabled(dap_ledger_t *a_ledger); void dap_ledger_set_cache_tx_check_callback(dap_ledger_t *a_ledger, dap_ledger_cache_tx_check_callback_t a_callback); diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c index 0b04a97d0f..0755a1b868 100644 --- a/modules/net/dap_chain_net.c +++ b/modules/net/dap_chain_net.c @@ -2675,8 +2675,8 @@ int dap_chain_datum_add(dap_chain_t *a_chain, dap_chain_datum_t *a_datum, size_t return -101; } dap_ledger_t *l_ledger = dap_chain_net_by_id(a_chain->net_id)->pub.ledger; - if ( dap_ledger_datum_is_blacklisted(l_ledger, *a_datum_hash) ) - return log_it(L_ERROR, "Datum is blackilsted"), -100; + if ( dap_ledger_datum_is_enforced(l_ledger, a_datum_hash, false) ) + return log_it(L_ERROR, "Datum is blacklisted"), -100; switch (a_datum->header.type_id) { case DAP_CHAIN_DATUM_DECREE: { dap_chain_datum_decree_t *l_decree = (dap_chain_datum_decree_t *)a_datum->data; diff --git a/modules/type/dag/dap_chain_cs_dag.c b/modules/type/dag/dap_chain_cs_dag.c index cc05a77946..31a20b53bf 100644 --- a/modules/type/dag/dap_chain_cs_dag.c +++ b/modules/type/dag/dap_chain_cs_dag.c @@ -879,7 +879,7 @@ void s_dag_events_lasts_process_new_last_event(dap_chain_cs_dag_t *a_dag, dap_ch s_dag_events_lasts_delete_linked_with_event(a_dag, a_event_item->event); //add self dap_chain_cs_dag_event_item_t *l_event_last = DAP_DUP_RET_IF_FAIL(a_event_item); - HASH_ADD(hh,PVT(a_dag)->events_lasts_unlinked,hash, sizeof(l_event_last->hash),l_event_last); + HASH_ADD(hh, PVT(a_dag)->events_lasts_unlinked, hash, sizeof(l_event_last->hash), l_event_last); } -- GitLab From d6ac2548d7786bc1cd9bb2144967072bd9e4c68c Mon Sep 17 00:00:00 2001 From: "Constantin P." <papizh.konstantin@demlabs.net> Date: Fri, 21 Feb 2025 16:17:47 +0700 Subject: [PATCH 10/15] ... --- dap-sdk | 2 +- modules/chain/tests/dap_chain_ledger_tests.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dap-sdk b/dap-sdk index d9b03ffb93..c5e865f2c9 160000 --- a/dap-sdk +++ b/dap-sdk @@ -1 +1 @@ -Subproject commit d9b03ffb93d4003cb1a33c6470612a7f88ad6005 +Subproject commit c5e865f2c9bfbc6a8770525d40bd1834c142e190 diff --git a/modules/chain/tests/dap_chain_ledger_tests.c b/modules/chain/tests/dap_chain_ledger_tests.c index 0b762718ae..5c49802de3 100644 --- a/modules/chain/tests/dap_chain_ledger_tests.c +++ b/modules/chain/tests/dap_chain_ledger_tests.c @@ -866,12 +866,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); -- GitLab From 31ccb48a175b69a6b3aef51c6a8bc0856f44e063 Mon Sep 17 00:00:00 2001 From: "Constantin P." <papizh.konstantin@demlabs.net> Date: Fri, 21 Feb 2025 17:08:22 +0700 Subject: [PATCH 11/15] More ports --- modules/chain/dap_chain.c | 9 +++++---- modules/chain/include/dap_chain.h | 4 ++-- modules/node-cli/dap_chain_node_cli.c | 2 +- modules/node-cli/dap_chain_node_cli_cmd_tx.c | 18 ++++++++---------- modules/type/blocks/dap_chain_cs_blocks.c | 2 +- 5 files changed, 17 insertions(+), 18 deletions(-) diff --git a/modules/chain/dap_chain.c b/modules/chain/dap_chain.c index d85b8c0bc1..29bc7d426a 100644 --- a/modules/chain/dap_chain.c +++ b/modules/chain/dap_chain.c @@ -751,6 +751,7 @@ struct chain_thread_datum_removed_notifier { dap_chain_t *chain; dap_chain_cell_id_t cell_id; dap_hash_fast_t hash; + dap_chain_datum_t *datum; int ret_code; }; @@ -781,7 +782,7 @@ static bool s_notify_datum_removed_on_thread(void *a_arg) { struct chain_thread_datum_removed_notifier *l_arg = a_arg; assert(l_arg->callback); - l_arg->callback(l_arg->callback_arg, &l_arg->hash); + l_arg->callback(l_arg->callback_arg, &l_arg->hash, l_arg->datum); DAP_DELETE(l_arg); return false; } @@ -891,7 +892,7 @@ void dap_chain_datum_notify(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id, } } -void dap_chain_datum_removed_notify(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id, dap_hash_fast_t *a_hash) { +void dap_chain_datum_removed_notify(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id, dap_hash_fast_t *a_hash, dap_chain_datum_t *a_datum) { #ifdef DAP_CHAIN_BLOCKS_TEST return; #endif @@ -908,8 +909,8 @@ void dap_chain_datum_removed_notify(dap_chain_t *a_chain, dap_chain_cell_id_t a_ } *l_arg = (struct chain_thread_datum_removed_notifier) { .callback = l_notifier->callback, .callback_arg = l_notifier->arg, - .chain = a_chain, .cell_id = a_cell_id, - .hash = *a_hash}; + .chain = a_chain, .cell_id = a_cell_id, + .hash = *a_hash, .datum = a_datum }; dap_proc_thread_callback_add_pri(l_notifier->proc_thread, s_notify_datum_removed_on_thread, l_arg, DAP_QUEUE_MSG_PRIORITY_LOW); } } diff --git a/modules/chain/include/dap_chain.h b/modules/chain/include/dap_chain.h index 62882bda5a..0fd5a0b9c5 100644 --- a/modules/chain/include/dap_chain.h +++ b/modules/chain/include/dap_chain.h @@ -130,7 +130,7 @@ typedef size_t (*dap_chain_callback_add_datums_t)(dap_chain_t * , dap_chain_datu typedef void (*dap_chain_callback_notify_t)(void *a_arg, dap_chain_t *a_chain, dap_chain_cell_id_t a_id, dap_chain_hash_fast_t *a_atom_hash, void *a_atom, size_t a_atom_size); //change in chain happened typedef void (*dap_chain_callback_datum_notify_t)(void *a_arg, dap_chain_hash_fast_t *a_datum_hash, dap_chain_hash_fast_t *a_atom_hash, void *a_datum, size_t a_datum_size, int a_ret_code, uint32_t a_action, dap_chain_srv_uid_t a_uid); //change in chain happened -typedef void (*dap_chain_callback_datum_removed_notify_t)(void *a_arg, dap_chain_hash_fast_t *a_datum_hash); //change in chain happened +typedef void (*dap_chain_callback_datum_removed_notify_t)(void *a_arg, dap_chain_hash_fast_t *a_datum_hash, dap_chain_datum_t *a_datum); //change in chain happened typedef uint64_t (*dap_chain_callback_get_count)(dap_chain_t *a_chain); typedef dap_list_t *(*dap_chain_callback_get_list)(dap_chain_t *a_chain, size_t a_count, size_t a_page, bool a_reverse); @@ -316,7 +316,7 @@ void dap_chain_add_callback_datum_removed_from_index_notify(dap_chain_t *a_chain void dap_chain_atom_confirmed_notify_add(dap_chain_t *a_chain, dap_chain_callback_notify_t a_callback, void *a_arg, uint64_t a_conf_cnt); void dap_chain_atom_notify(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id, dap_hash_fast_t *a_hash, const uint8_t *a_atom, size_t a_atom_size); void dap_chain_datum_notify(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id, dap_hash_fast_t *a_hash, dap_chain_hash_fast_t *a_atom_hash, const uint8_t *a_datum, size_t a_datum_size, int a_ret_code, uint32_t a_action, dap_chain_srv_uid_t a_uid); -void dap_chain_datum_removed_notify(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id, dap_hash_fast_t *a_hash); +void dap_chain_datum_removed_notify(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id, dap_hash_fast_t *a_hash, dap_chain_datum_t *a_datum); void dap_chain_atom_add_from_threshold(dap_chain_t *a_chain); dap_chain_atom_ptr_t dap_chain_get_atom_by_hash(dap_chain_t * a_chain, dap_chain_hash_fast_t * a_atom_hash, size_t * a_atom_size); bool dap_chain_get_atom_last_hash_num_ts(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id, dap_hash_fast_t *a_atom_hash, uint64_t *a_atom_num, dap_time_t *a_atom_timestamp); diff --git a/modules/node-cli/dap_chain_node_cli.c b/modules/node-cli/dap_chain_node_cli.c index 41b2d87d23..39ad250158 100644 --- a/modules/node-cli/dap_chain_node_cli.c +++ b/modules/node-cli/dap_chain_node_cli.c @@ -229,7 +229,7 @@ int dap_chain_node_cli_init(dap_config_t * g_config) "wallet activate -w <wallet_name> -password <password> [-ttl <password_ttl_in_minutes>]\n" "wallet deactivate -w <wallet_name> -password <password>\n" "wallet convert -w <wallet_name> -password <password>\n" - "wallet outputs {-addr <addr> | -w <wallet_name>} -net <net_name> -token <token_tiker> [-value <uint256_value>]"); + "wallet outputs {-addr <addr> | -w <wallet_name>} -net <net_name> -token <token_tiker> [-value <uint256_value>]\n"); dap_cli_server_cmd_add("mempool", com_mempool, "Command for working with mempool", "mempool list -net <net_name> [-chain <chain_name>] [-addr <addr>] [-brief] [-limit] [-offset]\n" diff --git a/modules/node-cli/dap_chain_node_cli_cmd_tx.c b/modules/node-cli/dap_chain_node_cli_cmd_tx.c index 598d41fa35..535e5608e8 100644 --- a/modules/node-cli/dap_chain_node_cli_cmd_tx.c +++ b/modules/node-cli/dap_chain_node_cli_cmd_tx.c @@ -414,10 +414,6 @@ json_object* dap_db_history_addr(json_object* a_json_arr_reply, dap_chain_addr_t uint256_t l_corr_value = {}, l_cond_value = {}; bool l_recv_from_cond = false, l_send_to_same_cond = false; json_object *l_corr_object = NULL, *l_cond_recv_object = NULL, *l_cond_send_object = NULL; - dap_list_t *l_list_in_items = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_IN_ALL, NULL); - if (!l_list_in_items) // a bad tx - goto next_step; - // all in items should be from the same address dap_chain_addr_t *l_src_addr = NULL; bool l_base_tx = false, l_reward_collect = false; @@ -431,23 +427,26 @@ json_object* dap_db_history_addr(json_object* a_json_arr_reply, dap_chain_addr_t dap_chain_srv_uid_t l_uid = l_from_cache ? l_wallet_cache_iter->uid : l_datum_iter->uid; int l_src_subtype = DAP_CHAIN_TX_OUT_COND_SUBTYPE_UNDEFINED; - for (dap_list_t *it = l_list_in_items; it; it = it->next) { + uint8_t *l_tx_item = NULL; + size_t l_size; int i, q = 0; + // Проход по входам + TX_ITEM_ITER_TX_TYPE(l_tx_item, TX_ITEM_TYPE_IN_ALL, l_size, i, l_tx) { dap_chain_hash_fast_t *l_tx_prev_hash = NULL; int l_tx_prev_out_idx; dap_chain_datum_tx_t *l_tx_prev = NULL; - switch (*(byte_t *)it->data) { + switch (*l_tx_item) { case TX_ITEM_TYPE_IN: { - dap_chain_tx_in_t *l_tx_in = (dap_chain_tx_in_t *)it->data; + dap_chain_tx_in_t *l_tx_in = (dap_chain_tx_in_t *)l_tx_item; l_tx_prev_hash = &l_tx_in->header.tx_prev_hash; l_tx_prev_out_idx = l_tx_in->header.tx_out_prev_idx; } break; case TX_ITEM_TYPE_IN_COND: { - dap_chain_tx_in_cond_t *l_tx_in_cond = (dap_chain_tx_in_cond_t *)it->data; + dap_chain_tx_in_cond_t *l_tx_in_cond = (dap_chain_tx_in_cond_t *)l_tx_item; l_tx_prev_hash = &l_tx_in_cond->header.tx_prev_hash; l_tx_prev_out_idx = l_tx_in_cond->header.tx_out_prev_idx; } break; case TX_ITEM_TYPE_IN_EMS: { - dap_chain_tx_in_ems_t *l_tx_in_ems = (dap_chain_tx_in_ems_t *)it->data; + dap_chain_tx_in_ems_t *l_tx_in_ems = (dap_chain_tx_in_ems_t *)l_tx_item; l_base_tx = true; l_noaddr_token = l_tx_in_ems->header.ticker; } break; @@ -492,7 +491,6 @@ json_object* dap_db_history_addr(json_object* a_json_arr_reply, dap_chain_addr_t break; //it's not our addr } - dap_list_free(l_list_in_items); // find OUT items bool l_header_printed = false; diff --git a/modules/type/blocks/dap_chain_cs_blocks.c b/modules/type/blocks/dap_chain_cs_blocks.c index 571a4385ff..2f87bdb0f5 100644 --- a/modules/type/blocks/dap_chain_cs_blocks.c +++ b/modules/type/blocks/dap_chain_cs_blocks.c @@ -1631,7 +1631,7 @@ static int s_delete_atom_datums(dap_chain_cs_blocks_t *a_blocks, dap_chain_block l_ret++; HASH_DEL(PVT(a_blocks)->datum_index, l_datum_index); // notify datum removed - dap_chain_datum_removed_notify(a_blocks->chain, a_block_cache->block->hdr.cell_id, l_datum_hash); + dap_chain_datum_removed_notify(a_blocks->chain, a_block_cache->block->hdr.cell_id, l_datum_hash, l_datum); } } debug_if(s_debug_more, L_DEBUG, "Block %s checked, %s", a_block_cache->block_hash_str, -- GitLab From a4db8329bce1d31cfff8285360437522a4454df7 Mon Sep 17 00:00:00 2001 From: "Constantin P." <papizh.konstantin@demlabs.net> Date: Fri, 21 Feb 2025 17:24:47 +0700 Subject: [PATCH 12/15] ... --- modules/ledger/dap_chain_ledger_tx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/ledger/dap_chain_ledger_tx.c b/modules/ledger/dap_chain_ledger_tx.c index 17368e14cf..631a9690f3 100644 --- a/modules/ledger/dap_chain_ledger_tx.c +++ b/modules/ledger/dap_chain_ledger_tx.c @@ -812,6 +812,7 @@ static int s_tx_cache_check(dap_ledger_t *a_ledger, switch ( HASH_COUNT(l_values_from_prev_tx) ) { case 1: l_main_ticker = l_value_cur->token_ticker; + break; case 2: HASH_FIND_STR(l_values_from_prev_tx, a_ledger->net->pub.native_ticker, l_value_cur); if (l_value_cur) { -- GitLab From 2ff7d7c5ab16c927ebbaae01eddddc57984dae45 Mon Sep 17 00:00:00 2001 From: "Constantin P." <papizh.konstantin@demlabs.net> Date: Fri, 21 Feb 2025 19:14:18 +0700 Subject: [PATCH 13/15] ... --- modules/ledger/dap_chain_ledger.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ledger/dap_chain_ledger.c b/modules/ledger/dap_chain_ledger.c index 9a11c0d655..1781764b02 100644 --- a/modules/ledger/dap_chain_ledger.c +++ b/modules/ledger/dap_chain_ledger.c @@ -279,7 +279,7 @@ void dap_ledger_handle_free(dap_ledger_t *a_ledger) bool dap_ledger_datum_is_enforced(dap_ledger_t *a_ledger, dap_hash_fast_t *a_hash, bool a_accept) { dap_ledger_hal_item_t *l_wanted = NULL; HASH_FIND(hh, a_accept ? PVT(a_ledger)->hal_items : PVT(a_ledger)->hrl_items, a_hash, sizeof(dap_hash_fast_t), l_wanted); - debug_if(g_debug_ledger && l_wanted, L_DEBUG, "Datum %s is %slisted", dap_hash_fast_to_str_static(&a_hash), a_accept ? "white" : "black"); + debug_if(g_debug_ledger && l_wanted, L_DEBUG, "Datum %s is %slisted", dap_hash_fast_to_str_static(a_hash), a_accept ? "white" : "black"); return !!l_wanted; } -- GitLab From 2373335edb1dbb2daae349a8d6db28a3ea6e87a0 Mon Sep 17 00:00:00 2001 From: "Constantin P." <papizh.konstantin@demlabs.net> Date: Mon, 24 Feb 2025 14:31:27 +0700 Subject: [PATCH 14/15] Improvements + segv fix --- modules/chain/dap_chain_cell.c | 62 +++++++++++++++----------- modules/chain/include/dap_chain_cell.h | 1 + 2 files changed, 37 insertions(+), 26 deletions(-) diff --git a/modules/chain/dap_chain_cell.c b/modules/chain/dap_chain_cell.c index cf8255d136..9e905f80ff 100644 --- a/modules/chain/dap_chain_cell.c +++ b/modules/chain/dap_chain_cell.c @@ -380,31 +380,14 @@ DAP_STATIC_INLINE int s_cell_load_from_file(dap_chain_cell_t *a_cell) return l_ret; } -DAP_STATIC_INLINE int s_cell_open(dap_chain_t *a_chain, const char *a_filename, const char a_mode) { - dap_chain_cell_id_t l_cell_id = { }; - { /* Check filename */ - char l_fmt[20] = "", l_ext[ sizeof(CELL_FILE_EXT) ] = "", l_ext2 = '\0'; - snprintf(l_fmt, sizeof(l_fmt), "%s%lu%s", "%"DAP_UINT64_FORMAT_x".%", sizeof(CELL_FILE_EXT) - 1, "[^.].%c"); - - switch ( sscanf(a_filename, l_fmt, &l_cell_id.uint64, l_ext, &l_ext2) ) { - case 3: - // TODO: X.dchaincell.* - case 2: - if ( !dap_strncmp(l_ext, CELL_FILE_EXT, sizeof(l_ext)) ) - break; - default: - return log_it(L_ERROR, "Invalid cell file name \"%s\"", a_filename), EINVAL; - } - } - char file_storage_path[MAX_PATH], mode[] = { a_mode, '+', 'b', '\0' }; - snprintf(file_storage_path, MAX_PATH, "%s/%s", DAP_CHAIN_PVT(a_chain)->file_storage_dir, a_filename); +DAP_STATIC_INLINE int s_cell_open(dap_chain_t *a_chain, const char *a_filepath, dap_chain_cell_id_t a_cell_id, const char a_mode) { + char mode[] = { a_mode, '+', 'b', '\0' }, *const a_filename = strrchr(a_filepath, '/') + 1; dap_chain_cell_t *l_cell = NULL; #define m_ret_err(err, ...) return ({ if (l_cell->file_storage) fclose(l_cell->file_storage); \ DAP_DELETE(l_cell); log_it(L_ERROR, ##__VA_ARGS__), err; }) - dap_chain_cell_mmap_data_t l_cell_map_data = { }; - HASH_FIND(hh, a_chain->cells, &l_cell_id, sizeof(dap_chain_cell_id_t), l_cell); + HASH_FIND(hh, a_chain->cells, &a_cell_id, sizeof(dap_chain_cell_id_t), l_cell); if (l_cell) { if (a_mode == 'w') { /* Attention! File rewriting requires that ledger was already purged */ @@ -415,19 +398,20 @@ DAP_STATIC_INLINE int s_cell_open(dap_chain_t *a_chain, const char *a_filename, m_ret_err(EEXIST, "Cell \"%s\" is already loaded in chain \"%s : %s\"", a_filename, a_chain->net_name, a_chain->name); } - FILE *l_file = fopen(file_storage_path, mode); + FILE *l_file = fopen(a_filepath, mode); if ( !l_file ) m_ret_err(errno, "Cell \"%s : %s / \"%s\" cannot be opened, error %d", a_chain->net_name, a_chain->name, a_filename, errno); l_cell = DAP_NEW_Z(dap_chain_cell_t); *l_cell = (dap_chain_cell_t) { - .id = l_cell_id, + .id = a_cell_id, .chain = a_chain, + .mapping = a_chain->is_mapped ? DAP_NEW_Z(dap_chain_cell_mmap_data_t) : NULL, .file_storage = l_file, //.storage_rwlock = PTHREAD_RWLOCK_INITIALIZER }; - dap_strncpy(l_cell->file_storage_path, file_storage_path, MAX_PATH); + dap_strncpy(l_cell->file_storage_path, a_filepath, MAX_PATH); switch (*mode) { case 'a': { @@ -448,12 +432,12 @@ DAP_STATIC_INLINE int s_cell_open(dap_chain_t *a_chain, const char *a_filename, .type = DAP_CHAIN_CELL_FILE_TYPE_RAW, .chain_id = a_chain->id, .chain_net_id = a_chain->net_id, - .cell_id = l_cell_id + .cell_id = a_cell_id }; if ( !fwrite(&l_hdr, sizeof(l_hdr), 1, l_cell->file_storage) ) m_ret_err(errno, "fwrite() error %d", errno); fflush(l_cell->file_storage); - l_cell->file_storage = freopen(file_storage_path, "a+b", l_cell->file_storage); + l_cell->file_storage = freopen(a_filepath, "a+b", l_cell->file_storage); if ( a_chain->is_mapped && s_cell_map_new_volume(l_cell, 0, false) ) m_ret_err(EINVAL, "Error on mapping the first volume"); } @@ -468,8 +452,34 @@ DAP_STATIC_INLINE int s_cell_open(dap_chain_t *a_chain, const char *a_filename, } int dap_chain_cell_open(dap_chain_t *a_chain, const char *a_filename, const char a_mode) { + dap_chain_cell_id_t l_cell_id = { }; + { /* Check filename */ + char l_fmt[32] = "", l_ext[ sizeof(CELL_FILE_EXT) ] = "", l_ext2 = '\0'; + snprintf(l_fmt, sizeof(l_fmt), "%s%lu%s", "%"DAP_UINT64_FORMAT_x".%", sizeof(CELL_FILE_EXT) - 1, "[^.].%c"); + + switch ( sscanf(a_filename, l_fmt, &l_cell_id.uint64, l_ext, &l_ext2) ) { + case 3: + // TODO: X.dchaincell.* + case 2: + if ( !dap_strncmp(l_ext, CELL_FILE_EXT, sizeof(l_ext)) ) + break; + default: + return log_it(L_ERROR, "Invalid cell file name \"%s\"", a_filename), EINVAL; + } + } + const char l_full_path[MAX_PATH]; + snprintf(l_full_path, MAX_PATH, "%s/%s", DAP_CHAIN_PVT(a_chain)->file_storage_dir, a_filename); + pthread_rwlock_wrlock(&a_chain->cell_rwlock); + int l_ret = s_cell_open(a_chain, l_full_path, l_cell_id, a_mode); + pthread_rwlock_unlock(&a_chain->cell_rwlock); + return l_ret; +} + +int dap_chain_cell_open_by_id(dap_chain_t *a_chain, const dap_chain_cell_id_t a_cell_id, const char a_mode) { + const char l_full_path[MAX_PATH]; + snprintf(l_full_path, MAX_PATH, "%s/%"DAP_UINT64_FORMAT_x"."CELL_FILE_EXT, DAP_CHAIN_PVT(a_chain)->file_storage_dir, a_cell_id.uint64); pthread_rwlock_wrlock(&a_chain->cell_rwlock); - int l_ret = s_cell_open(a_chain, a_filename, a_mode); + int l_ret = s_cell_open(a_chain, l_full_path, a_cell_id, a_mode); pthread_rwlock_unlock(&a_chain->cell_rwlock); return l_ret; } diff --git a/modules/chain/include/dap_chain_cell.h b/modules/chain/include/dap_chain_cell.h index 74efe15fdb..93df116932 100644 --- a/modules/chain/include/dap_chain_cell.h +++ b/modules/chain/include/dap_chain_cell.h @@ -77,6 +77,7 @@ typedef struct dap_chain_cell_decl{ int dap_chain_cell_init(void); int dap_chain_cell_open(dap_chain_t *a_chain, const char *a_filename, const char a_mode); +int dap_chain_cell_open_by_id(dap_chain_t *a_chain, const dap_chain_cell_id_t a_cell_id, const char a_mode); DAP_INLINE dap_chain_cell_t *dap_chain_cell_find_by_id(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id) { dap_chain_cell_t *l_cell = NULL; -- GitLab From 58585afbb9346ecb9a4b5d176ecba8dac17fb23a Mon Sep 17 00:00:00 2001 From: "Constantin P." <papizh.konstantin@demlabs.net> Date: Mon, 24 Feb 2025 15:23:52 +0700 Subject: [PATCH 15/15] Warnings fix --- modules/chain/dap_chain_cell.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/chain/dap_chain_cell.c b/modules/chain/dap_chain_cell.c index 9e905f80ff..f2b61e19c8 100644 --- a/modules/chain/dap_chain_cell.c +++ b/modules/chain/dap_chain_cell.c @@ -467,7 +467,7 @@ int dap_chain_cell_open(dap_chain_t *a_chain, const char *a_filename, const char return log_it(L_ERROR, "Invalid cell file name \"%s\"", a_filename), EINVAL; } } - const char l_full_path[MAX_PATH]; + char l_full_path[MAX_PATH]; snprintf(l_full_path, MAX_PATH, "%s/%s", DAP_CHAIN_PVT(a_chain)->file_storage_dir, a_filename); pthread_rwlock_wrlock(&a_chain->cell_rwlock); int l_ret = s_cell_open(a_chain, l_full_path, l_cell_id, a_mode); @@ -476,7 +476,7 @@ int dap_chain_cell_open(dap_chain_t *a_chain, const char *a_filename, const char } int dap_chain_cell_open_by_id(dap_chain_t *a_chain, const dap_chain_cell_id_t a_cell_id, const char a_mode) { - const char l_full_path[MAX_PATH]; + char l_full_path[MAX_PATH]; snprintf(l_full_path, MAX_PATH, "%s/%"DAP_UINT64_FORMAT_x"."CELL_FILE_EXT, DAP_CHAIN_PVT(a_chain)->file_storage_dir, a_cell_id.uint64); pthread_rwlock_wrlock(&a_chain->cell_rwlock); int l_ret = s_cell_open(a_chain, l_full_path, a_cell_id, a_mode); -- GitLab