From 74e0a8795a99412e2edd09ca5807078937e8c117 Mon Sep 17 00:00:00 2001 From: "roman.padenkov" <roman.padenkov@demlabs.net> Date: Mon, 12 Dec 2022 07:19:37 +0000 Subject: [PATCH] hotfix_7059_d --- modules/chain/dap_chain_ledger.c | 183 +++++++++++++++++++++++ modules/chain/include/dap_chain_ledger.h | 7 + modules/net/dap_chain_node_cli.c | 4 +- modules/net/dap_chain_node_cli_cmd_tx.c | 97 +++++------- 4 files changed, 226 insertions(+), 65 deletions(-) diff --git a/modules/chain/dap_chain_ledger.c b/modules/chain/dap_chain_ledger.c index 77b79789f4..8e0ccceda4 100644 --- a/modules/chain/dap_chain_ledger.c +++ b/modules/chain/dap_chain_ledger.c @@ -49,6 +49,7 @@ #include "dap_math_ops.h" #include "dap_list.h" #include "dap_hash.h" +#include "dap_enc_base58.h" #include "dap_string.h" #include "dap_strfuncs.h" #include "dap_config.h" @@ -557,6 +558,188 @@ dap_chain_datum_token_t *dap_chain_ledger_token_ticker_check(dap_ledger_t * a_le return l_token_item ? l_token_item->datum_token : NULL; } +/** + * @brief s_tx_header_print + * prepare data for print, add time + * + * return history string + * @param a_tx + * @param a_tx_hash + * @param a_hash_out_type + * @return a_str_out + */ + +static void s_tx_header_print(dap_string_t *a_str_out, dap_chain_datum_tx_t *a_tx, + const char *a_hash_out_type, dap_chain_hash_fast_t *a_tx_hash) +{ + // transaction time + char l_time_str[32] = "unknown"; + if (a_tx->header.ts_created) { + uint64_t l_ts = a_tx->header.ts_created; + dap_ctime_r(&l_ts, l_time_str); + } + char *l_tx_hash_str; + if (!dap_strcmp(a_hash_out_type, "hex")) { + l_tx_hash_str = dap_chain_hash_fast_to_str_new(a_tx_hash); + } else { + l_tx_hash_str = dap_enc_base58_encode_hash_to_str(a_tx_hash); + } + dap_string_append_printf(a_str_out, "TX hash %s \n\t%s",l_tx_hash_str, l_time_str); + DAP_DELETE(l_tx_hash_str); +} + +char * dap_ledger_token_tx_item_list(dap_ledger_t * a_ledger, dap_chain_addr_t *a_addr, const char *a_hash_out_type) +{ + dap_string_t *l_str_out =dap_string_new(NULL); + + //dap_chain_tx_hash_processed_ht_t *l_tx_data_ht = NULL; + dap_chain_ledger_tx_item_t *l_tx_item, *l_tx_tmp; + dap_ledger_private_t * l_ledger_pvt = PVT(a_ledger); + + pthread_rwlock_rdlock(&l_ledger_pvt->ledger_rwlock); + //unsigned test = dap_chain_ledger_count(a_ledger); + HASH_ITER(hh, l_ledger_pvt->ledger_items, l_tx_item, l_tx_tmp) { + + dap_chain_datum_tx_t *l_tx = l_tx_item->tx; + dap_chain_hash_fast_t *l_tx_hash = &l_tx_item->tx_hash_fast; + 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 + continue; + } + dap_chain_addr_t *l_src_addr = NULL; + bool l_base_tx = false; + const char *l_src_token = NULL; + int l_src_subtype = DAP_CHAIN_TX_OUT_COND_SUBTYPE_UNDEFINED; + for (dap_list_t *it = l_list_in_items; it; it = it->next) { + assert(it->data); + dap_chain_hash_fast_t *l_tx_prev_hash; + int l_tx_prev_out_idx; + dap_chain_datum_tx_t *l_tx_prev = NULL; + if (*(byte_t *)l_list_in_items->data == TX_ITEM_TYPE_IN) { + dap_chain_tx_in_t *l_tx_in = (dap_chain_tx_in_t *)l_list_in_items->data; + l_tx_prev_hash = &l_tx_in->header.tx_prev_hash; + l_tx_prev_out_idx = l_tx_in->header.tx_out_prev_idx; + } else { // TX_ITEM_TYPE_IN_COND + dap_chain_tx_in_cond_t *l_tx_in_cond = (dap_chain_tx_in_cond_t *)l_list_in_items->data; + 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; + } + if (dap_hash_fast_is_blank(l_tx_prev_hash)) { + l_base_tx = true; + dap_chain_tx_token_t *l_token = (dap_chain_tx_token_t *)dap_chain_datum_tx_item_get( + l_tx, NULL, TX_ITEM_TYPE_TOKEN, NULL); + if (l_token) + l_src_token = l_token->header.ticker; + break; + } + l_tx_prev = dap_chain_ledger_tx_find_by_hash (a_ledger,l_tx_prev_hash); + if (l_tx_prev) { + uint8_t *l_prev_out_union = dap_chain_datum_tx_item_get_nth(l_tx_prev, TX_ITEM_TYPE_OUT_ALL, l_tx_prev_out_idx); + if (!l_prev_out_union) + continue; + switch (*l_prev_out_union) { + case TX_ITEM_TYPE_OUT: + l_src_addr = &((dap_chain_tx_out_t *)l_prev_out_union)->addr; + break; + case TX_ITEM_TYPE_OUT_EXT: + l_src_addr = &((dap_chain_tx_out_ext_t *)l_prev_out_union)->addr; + l_src_token = (const char *)(((dap_chain_tx_out_ext_t *)l_prev_out_union)->token); + break; + case TX_ITEM_TYPE_OUT_COND: + l_src_subtype = ((dap_chain_tx_out_cond_t *)l_prev_out_union)->header.subtype; + default: + break; + } + } + else + { + continue; //temporary stub + } + if (!l_src_token){ + l_src_token = dap_chain_ledger_tx_get_token_ticker_by_hash(a_ledger, l_tx_prev_hash); + l_src_token = l_tx_item->cache_data.token_ticker; + } + if (l_src_addr && memcmp(l_src_addr, a_addr, sizeof(dap_chain_addr_t))) + break; //it's not our addr + } + dap_list_free(l_list_in_items); + + bool l_header_printed = false; + dap_list_t *l_list_out_items = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_OUT_ALL, NULL); + if(!l_list_out_items) + continue; + for(dap_list_t *l_list_out = l_list_out_items; l_list_out; l_list_out = dap_list_next(l_list_out)) { + assert(l_list_out->data); + dap_chain_addr_t *l_dst_addr = NULL; + dap_chain_tx_item_type_t l_type = *(uint8_t *)l_list_out->data; + uint256_t l_value; + switch (l_type) { + case TX_ITEM_TYPE_OUT: + l_dst_addr = &((dap_chain_tx_out_t *)l_list_out->data)->addr; + l_value = ((dap_chain_tx_out_t *)l_list_out->data)->header.value; + break; + case TX_ITEM_TYPE_OUT_EXT: + l_dst_addr = &((dap_chain_tx_out_ext_t *)l_list_out->data)->addr; + l_value = ((dap_chain_tx_out_ext_t *)l_list_out->data)->header.value; + break; + case TX_ITEM_TYPE_OUT_COND: + l_value = ((dap_chain_tx_out_cond_t *)l_list_out->data)->header.value; + default: + break; + } + if (l_src_addr && l_dst_addr && !memcmp(l_dst_addr, l_src_addr, sizeof(dap_chain_addr_t))) + continue; // send to self + if (l_src_addr && !memcmp(l_src_addr, a_addr, sizeof(dap_chain_addr_t))) { + if (!l_header_printed) { + s_tx_header_print(l_str_out, l_tx, a_hash_out_type, l_tx_hash); + l_header_printed = true; + } + //const char *l_token_ticker = dap_chain_ledger_tx_get_token_ticker_by_hash(l_ledger, &l_tx_hash); + const char *l_dst_addr_str = l_dst_addr ? dap_chain_addr_to_str(l_dst_addr) + : dap_chain_tx_out_cond_subtype_to_str( + ((dap_chain_tx_out_cond_t *)l_list_out->data)->header.subtype); + char *l_value_str = dap_chain_balance_print(l_value); + dap_string_append_printf(l_str_out, "\tsend %s %s to %s\n", + l_value_str, + l_src_token ? l_src_token : "UNKNOWN", + l_dst_addr_str); + if (l_dst_addr) + DAP_DELETE(l_dst_addr_str); + DAP_DELETE(l_value_str); + } + if (l_dst_addr && !memcmp(l_dst_addr, a_addr, sizeof(dap_chain_addr_t))) { + if (!l_header_printed) { + s_tx_header_print(l_str_out, l_tx, a_hash_out_type, l_tx_hash); + l_header_printed = true; + } + const char *l_dst_token = (l_type == TX_ITEM_TYPE_OUT_EXT) ? + (const char *)(((dap_chain_tx_out_ext_t *)l_list_out->data)->token) : NULL; + const char *l_src_addr_str = l_base_tx ? "emission" + : (l_src_addr ? dap_chain_addr_to_str(l_src_addr) + : dap_chain_tx_out_cond_subtype_to_str( + l_src_subtype)); + char *l_value_str = dap_chain_balance_print(l_value); + dap_string_append_printf(l_str_out, "\trecv %s %s from %s\n", + l_value_str, + l_dst_token ? l_dst_token : + (l_src_token ? l_src_token : "UNKNOWN"), + l_src_addr_str); + if (l_src_addr) + DAP_DELETE(l_src_addr_str); + DAP_DELETE(l_value_str); + } + } + dap_list_free(l_list_out_items); + } + pthread_rwlock_unlock(&l_ledger_pvt->ledger_rwlock); + + // if no history + if(!l_str_out->len) + dap_string_append(l_str_out, "\tempty"); + char *l_ret_str = l_str_out ? dap_string_free(l_str_out, false) : NULL; + return l_ret_str; +} + /** * @brief update current_supply in token cache * diff --git a/modules/chain/include/dap_chain_ledger.h b/modules/chain/include/dap_chain_ledger.h index 55b33eed08..340d5ba7a2 100644 --- a/modules/chain/include/dap_chain_ledger.h +++ b/modules/chain/include/dap_chain_ledger.h @@ -117,6 +117,13 @@ int dap_chain_ledger_tx_load(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, int dap_chain_ledger_tx_add_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx); +/** + * Print list transaction from ledger + * + */ + +char * dap_ledger_token_tx_item_list(dap_ledger_t * a_ledger, dap_chain_addr_t *a_addr, const char *a_hash_out_type); + /** * Check token ticker existance * diff --git a/modules/net/dap_chain_node_cli.c b/modules/net/dap_chain_node_cli.c index 80ce903c86..5dfec5e143 100644 --- a/modules/net/dap_chain_node_cli.c +++ b/modules/net/dap_chain_node_cli.c @@ -273,14 +273,14 @@ int dap_chain_node_cli_init(dap_config_t * g_config) dap_cli_server_cmd_add("tx_history", com_tx_history, "Transaction history (for address or by hash)", "tx_history {-addr <addr> | -w <wallet_name> | -tx <tx_hash>} -net <net_name> -chain <chain_name>\n"); - // Ledger info + // Ledger info dap_cli_server_cmd_add("ledger", com_ledger, "Ledger information", "ledger list coins -net <net_name>\n" "ledger list threshold [-hash <tx_treshold_hash>] -net <net_name>\n" "ledger list balance -net <net_name>\n" "ledger info -hash <tx_hash> -net <net_name> [-unspent]\n" "ledger tx -all -net <net_name>\n" - "ledger tx {-addr <addr> | -w <wallet_name> | -tx <tx_hash>} [-chain <chain_name>] -net <net_name>\n"); + "ledger tx {-addr <addr> | -w <wallet_name> | -tx <tx_hash>} -net <net_name>\n"); // Token info dap_cli_server_cmd_add("token", com_token, "Token info", diff --git a/modules/net/dap_chain_node_cli_cmd_tx.c b/modules/net/dap_chain_node_cli_cmd_tx.c index 0beb7fc6e0..bb5b7f5ccc 100644 --- a/modules/net/dap_chain_node_cli_cmd_tx.c +++ b/modules/net/dap_chain_node_cli_cmd_tx.c @@ -802,7 +802,7 @@ static char* dap_db_history_filter(dap_chain_t * a_chain, dap_ledger_t *a_ledger */ int com_ledger(int a_argc, char ** a_argv, char **a_str_reply) { - enum { CMD_NONE, CMD_LIST, CMD_TX_HISTORY, CMD_TX_INFO }; + enum { CMD_NONE, CMD_LIST, CMD_LEDGER_HISTORY, CMD_TX_INFO }; int arg_index = 1; const char *l_addr_base58 = NULL; const char *l_wallet_name = NULL; @@ -827,7 +827,7 @@ int com_ledger(int a_argc, char ** a_argv, char **a_str_reply) if (dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "list", NULL)){ l_cmd = CMD_LIST; } else if (dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "tx", NULL)){ - l_cmd = CMD_TX_HISTORY; + l_cmd = CMD_LEDGER_HISTORY; } else if (dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "info", NULL)) l_cmd = CMD_TX_INFO; @@ -836,11 +836,11 @@ int com_ledger(int a_argc, char ** a_argv, char **a_str_reply) arg_index++; // command tx_history - if(l_cmd == CMD_TX_HISTORY) { + if(l_cmd == CMD_LEDGER_HISTORY) { dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-addr", &l_addr_base58); dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-w", &l_wallet_name); dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-net", &l_net_str); - dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-chain", &l_chain_str); + // dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-chain", &l_chain_str); dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-tx", &l_tx_hash_str); dap_chain_tx_hash_processed_ht_t *l_list_tx_hash_processd = NULL; @@ -859,20 +859,7 @@ int com_ledger(int a_argc, char ** a_argv, char **a_str_reply) return -3; } } - //Select chain emission - if(!l_chain_str) { // chain may be null -> then all chain use - //dap_cli_server_cmd_set_reply_text(a_str_reply, "command requires parameter '-chain'"); - //return -4; - } else { - if((l_chain = dap_chain_net_get_chain_by_name(l_net, l_chain_str)) == NULL) { // Can't find such chain - dap_cli_server_cmd_set_reply_text(a_str_reply, - "command requires parameter '-chain' to be valid chain name in chain net %s", - l_net_str); - return -5; - } - } - //char *l_group_mempool = dap_chain_net_get_gdb_group_mempool(l_chain); - //const char *l_chain_group = dap_chain_gdb_get_group(l_chain); + dap_chain_hash_fast_t l_tx_hash; if(l_tx_hash_str) { if (dap_chain_hash_fast_from_str(l_tx_hash_str, &l_tx_hash)) { @@ -884,6 +871,7 @@ int com_ledger(int a_argc, char ** a_argv, char **a_str_reply) // dap_chain_hash_fast_to_str(&l_tx_hash, hash_str,99); // int gsdgsd=523; } + dap_chain_addr_t *l_addr = NULL; // if need addr if(l_wallet_name || l_addr_base58) { @@ -907,52 +895,35 @@ int com_ledger(int a_argc, char ** a_argv, char **a_str_reply) } } dap_string_t *l_str_ret = dap_string_new(NULL); //char *l_str_ret = NULL; - dap_chain_t *l_chain_cur; - int l_num = 0; - // only one chain - if (l_chain) - l_chain_cur = l_chain; - // all chain - else - l_chain_cur = l_net->pub.chains; - while (l_chain_cur) { - // only selected net - if(l_net->pub.id.uint64 == l_chain_cur->net_id.uint64) { - // separator between chains - if(l_num>0 && !l_chain) - dap_string_append(l_str_ret, "---------------\n"); - - char *l_str_out = NULL; - dap_string_append_printf(l_str_ret, "chain: %s\n", l_chain_cur->name); - dap_ledger_t *l_ledger = dap_chain_ledger_by_net_name(l_net_str); - if(l_is_all) { - // without filters - l_str_out = dap_db_history_filter(l_chain_cur, l_ledger, NULL, NULL, l_hash_out_type, -1, 0, NULL, l_list_tx_hash_processd); - dap_string_append_printf(l_str_ret, "all history:\n%s\n", l_str_out ? l_str_out : " empty"); - } - else { - l_str_out = l_tx_hash_str ? - dap_db_history_tx(&l_tx_hash, l_chain_cur, l_hash_out_type) : - dap_db_history_addr(l_addr, l_chain_cur, l_hash_out_type); - if(l_tx_hash_str) { - dap_string_append_printf(l_str_ret, "history for tx hash %s:\n%s\n", l_tx_hash_str, - l_str_out ? l_str_out : " empty"); - } - else if(l_addr) { - char *l_addr_str = dap_chain_addr_to_str(l_addr); - dap_string_append_printf(l_str_ret, "history for addr %s:\n%s\n", l_addr_str, - l_str_out ? l_str_out : " empty"); - DAP_DELETE(l_addr_str); - } - } - DAP_DELETE(l_str_out); - l_num++; + + char *l_str_out = NULL; + dap_ledger_t *l_ledger = dap_chain_ledger_by_net_name(l_net_str); + if(l_is_all) { + // without filters + //l_str_out = dap_db_history_filter(l_chain_cur, l_ledger, NULL, NULL, l_hash_out_type, -1, 0, NULL, l_list_tx_hash_processd); + dap_string_append_printf(l_str_ret, "all history:\n%s\n", l_str_out ? l_str_out : " empty"); + } + else {/* + l_str_out = l_tx_hash_str ? + dap_db_history_tx(&l_tx_hash, l_chain_cur, l_hash_out_type) : + dap_ledger_token_tx_item_list(l_ledger,l_addr,l_hash_out_type); + //dap_db_history_addr(l_addr, l_chain_cur, l_hash_out_type); + */ + l_str_out = dap_ledger_token_tx_item_list(l_ledger,l_addr,l_hash_out_type); + if(l_tx_hash_str) { + dap_string_append_printf(l_str_ret, "history for tx hash %s:\n%s\n", l_tx_hash_str, + l_str_out ? l_str_out : " empty"); + } + else if(l_addr) { + char *l_addr_str = dap_chain_addr_to_str(l_addr); + dap_string_append_printf(l_str_ret, "history for addr %s:\n%s\n", l_addr_str, + l_str_out ? l_str_out : " empty"); + DAP_DELETE(l_addr_str); } - // only one chain use - if(l_chain) - break; - l_chain_cur = l_chain_cur->next; } + DAP_DELETE(l_str_out); + + DAP_DELETE(l_addr); s_dap_chain_tx_hash_processed_ht_free(l_list_tx_hash_processd); // all chain @@ -960,7 +931,7 @@ int com_ledger(int a_argc, char ** a_argv, char **a_str_reply) dap_chain_enum_unlock(); dap_cli_server_cmd_set_reply_text(a_str_reply, l_str_ret->str); dap_string_free(l_str_ret, true); - return 0; + return 0; } else if(l_cmd == CMD_LIST){ enum {SUBCMD_NONE, SUBCMD_LIST_COIN, SUB_CMD_LIST_LEDGER_THRESHOLD, SUB_CMD_LIST_LEDGER_BALANCE, SUB_CMD_LIST_LEDGER_THRESHOLD_WITH_HASH}; -- GitLab