diff --git a/dap-sdk b/dap-sdk index 0d12538f93d71775dbcece9c65a2fdb65702b595..0bc8b39bb03244c4f9d25c0b1228848bf27c9fe8 160000 --- a/dap-sdk +++ b/dap-sdk @@ -1 +1 @@ -Subproject commit 0d12538f93d71775dbcece9c65a2fdb65702b595 +Subproject commit 0bc8b39bb03244c4f9d25c0b1228848bf27c9fe8 diff --git a/modules/chain/include/dap_chain.h b/modules/chain/include/dap_chain.h index 5d10ba584ffbc32504e9d0f4650ba5155edbbc99..825915ef413d48c1164fdd736560f5526b7f34f0 100644 --- a/modules/chain/include/dap_chain.h +++ b/modules/chain/include/dap_chain.h @@ -98,7 +98,10 @@ typedef void (*dap_chain_callback_atom_iter_delete_t)(dap_chain_atom_iter_t *); typedef dap_chain_datum_iter_t * (*dap_chain_datum_callback_iter_create_t)(dap_chain_t *); typedef dap_chain_datum_t * (*dap_chain_datum_callback_iter_get_first_t)(dap_chain_datum_iter_t *); +typedef dap_chain_datum_t * (*dap_chain_datum_callback_iter_get_last_t)(dap_chain_datum_iter_t *); typedef dap_chain_datum_t * (*dap_chain_datum_callback_iter_get_next_t)(dap_chain_datum_iter_t *); +typedef dap_chain_datum_t * (*dap_chain_datum_callback_iter_get_prev_t)(dap_chain_datum_iter_t *); +typedef dap_chain_datum_t * (*dap_chain_datum_callback_iters)(dap_chain_datum_iter_t *); typedef void (*dap_chain_datum_callback_iter_delete_t)(dap_chain_datum_iter_t *); typedef dap_chain_datum_t** (*dap_chain_callback_atom_get_datum_t)(dap_chain_atom_ptr_t, size_t, size_t * ); @@ -199,7 +202,9 @@ typedef struct dap_chain { // Iterator callbacks dap_chain_datum_callback_iter_create_t callback_datum_iter_create; dap_chain_datum_callback_iter_get_first_t callback_datum_iter_get_first; + dap_chain_datum_callback_iter_get_last_t callback_datum_iter_get_last; dap_chain_datum_callback_iter_get_next_t callback_datum_iter_get_next; + dap_chain_datum_callback_iter_get_prev_t callback_datum_iter_get_prev; dap_chain_datum_callback_iter_delete_t callback_datum_iter_delete; dap_list_t *atom_notifiers; diff --git a/modules/common/dap_chain_common.c b/modules/common/dap_chain_common.c index e9d3f1919dc86d9b948bbeb092b7c590a5b8ce57..b9d0400a7aab2abbfe4003814ba4cc7b97a3f98a 100644 --- a/modules/common/dap_chain_common.c +++ b/modules/common/dap_chain_common.c @@ -217,3 +217,21 @@ int dap_chain_addr_check_sum(const dap_chain_addr_t *a_addr) dap_hash_fast(a_addr, sizeof(dap_chain_addr_t) - sizeof(dap_chain_hash_fast_t), &l_checksum); return memcmp(a_addr->checksum.raw, l_checksum.raw, sizeof(l_checksum.raw)); } + +void s_set_offset_limit_json(json_object * a_json_obj_out, size_t *a_start, size_t *a_and, size_t a_limit, size_t a_offset, size_t a_and_count) +{ + json_object* json_obj_lim = json_object_new_object(); + if (a_offset > 0) { + *a_start = a_offset; + json_object_object_add(json_obj_lim, "offset", json_object_new_int(*a_start)); + } + *a_and = a_and_count; + if (a_limit > 0) { + *a_and = *a_start + a_limit; + json_object_object_add(json_obj_lim, "limit", json_object_new_int(*a_and - *a_start)); + } + else + json_object_object_add(json_obj_lim, "limit", json_object_new_string("unlimit")); + json_object_array_add(a_json_obj_out, json_obj_lim); +} + diff --git a/modules/common/include/dap_chain_common.h b/modules/common/include/dap_chain_common.h index 6a3449ba911400ce8568eb9ef56a0fe859821961..3ae8e849771803033be56fcf2e743d3f1c36b8aa 100644 --- a/modules/common/include/dap_chain_common.h +++ b/modules/common/include/dap_chain_common.h @@ -209,6 +209,7 @@ int dap_chain_addr_fill_from_key(dap_chain_addr_t *a_addr, dap_enc_key_t *a_key, int dap_chain_addr_fill_from_sign(dap_chain_addr_t *a_addr, dap_sign_t *a_sign, dap_chain_net_id_t a_net_id); int dap_chain_addr_check_sum(const dap_chain_addr_t *a_addr); +void s_set_offset_limit_json(json_object * a_json_obj_out, size_t *a_start, size_t *a_and, size_t a_limit, size_t a_offset, size_t a_and_count); DAP_STATIC_INLINE bool dap_chain_addr_compare(const dap_chain_addr_t *a_addr1, const dap_chain_addr_t *a_addr2) { diff --git a/modules/net/dap_chain_ledger.c b/modules/net/dap_chain_ledger.c index ff1c0b6459a8ac0258f3d080bb05e76da98b6bfd..2b6e49df66c572470ad1d2c1185fa581d01eb2fb 100644 --- a/modules/net/dap_chain_ledger.c +++ b/modules/net/dap_chain_ledger.c @@ -1983,7 +1983,33 @@ json_object *dap_ledger_token_tx_item_list(dap_ledger_t * a_ledger, dap_chain_ad return json_arr_out; } -json_object *dap_ledger_threshold_info(dap_ledger_t *a_ledger, size_t a_limit, size_t a_offset, dap_chain_hash_fast_t *a_threshold_hash) +static bool s_pack_ledger_threshold_info_json (json_object *a_json_arr_out, dap_ledger_tx_item_t *a_tx_item) +{ + json_object *json_obj_tx = json_object_new_object(); + if (!json_obj_tx) + return 1; + char l_tx_prev_hash_str[DAP_HASH_FAST_STR_SIZE]={0}; + char l_time[DAP_TIME_STR_SIZE] = {0}; + dap_chain_hash_fast_to_str(&a_tx_item->tx_hash_fast,l_tx_prev_hash_str,sizeof(l_tx_prev_hash_str)); + dap_time_to_str_rfc822(l_time, sizeof(l_time), a_tx_item->cache_data.ts_created); + json_object_object_add(json_obj_tx, "Ledger thresholded tx_hash_fast", json_object_new_string(l_tx_prev_hash_str)); + json_object_object_add(json_obj_tx, "time_created", json_object_new_string(l_time)); + json_object_object_add(json_obj_tx, "tx_item_size", json_object_new_int(a_tx_item->tx->header.tx_items_size)); + json_object_array_add(a_json_arr_out, json_obj_tx); + return 0; +} +static bool s_pack_ledger_balance_info_json (json_object *a_json_arr_out, dap_ledger_wallet_balance_t *a_balance_item) +{ + json_object* json_obj_tx = json_object_new_object(); + + json_object_object_add(json_obj_tx, "Ledger balance key", json_object_new_string(a_balance_item->key)); + json_object_object_add(json_obj_tx, "token_ticker", json_object_new_string(a_balance_item->token_ticker)); + json_object_object_add(json_obj_tx, "balance", json_object_new_string(dap_uint256_to_char(a_balance_item->balance, NULL))); + json_object_array_add(a_json_arr_out, json_obj_tx); + return 0; +} + +json_object *dap_ledger_threshold_info(dap_ledger_t *a_ledger, size_t a_limit, size_t a_offset, dap_chain_hash_fast_t *a_threshold_hash, bool a_head) { dap_ledger_private_t *l_ledger_pvt = PVT(a_ledger); dap_ledger_tx_item_t *l_tx_item = NULL, *l_tx_tmp; @@ -1992,31 +2018,10 @@ json_object *dap_ledger_threshold_info(dap_ledger_t *a_ledger, size_t a_limit, s return NULL; uint32_t l_counter = 0; size_t l_arr_start = 0; - if (a_offset > 0) { - l_arr_start = a_offset; - json_object *json_obj_tx = json_object_new_object(); - if (!json_obj_tx) { - json_object_put(json_arr_out); - return NULL; - } - json_object_object_add(json_obj_tx, "offset", json_object_new_int(l_arr_start)); - json_object_array_add(json_arr_out, json_obj_tx); - } + size_t l_arr_end = 0; + s_set_offset_limit_json(json_arr_out, &l_arr_start, &l_arr_end, a_limit, a_offset, HASH_COUNT(l_ledger_pvt->threshold_txs)); + pthread_rwlock_rdlock(&l_ledger_pvt->threshold_txs_rwlock); - size_t l_arr_end = l_arr_start + a_limit; - if (a_limit) { - json_object *json_obj_tx = json_object_new_object(); - if (!json_obj_tx) { - pthread_rwlock_unlock(&l_ledger_pvt->threshold_txs_rwlock); - json_object_put(json_arr_out); - return NULL; - } - json_object_object_add(json_obj_tx, "limit", json_object_new_int(a_limit)); - json_object_array_add(json_arr_out, json_obj_tx); - } - if (l_arr_end > HASH_COUNT(l_ledger_pvt->threshold_txs)) { - l_arr_end = HASH_COUNT(l_ledger_pvt->threshold_txs); - } if (a_threshold_hash) { json_object *json_obj_tx = json_object_new_object(); if (!json_obj_tx) { @@ -2034,25 +2039,35 @@ json_object *dap_ledger_threshold_info(dap_ledger_t *a_ledger, size_t a_limit, s } } else { size_t i_tmp = 0; + if (a_head) HASH_ITER(hh, l_ledger_pvt->threshold_txs, l_tx_item, l_tx_tmp) { - if (i_tmp < l_arr_start || i_tmp++ >= l_arr_end) + if (i_tmp < l_arr_start || i_tmp >= l_arr_end) + { + i_tmp++; continue; - json_object *json_obj_tx = json_object_new_object(); - if (!json_obj_tx) { + } + i_tmp++; + if (s_pack_ledger_threshold_info_json(json_arr_out, l_tx_item)) { pthread_rwlock_unlock(&l_ledger_pvt->threshold_txs_rwlock); json_object_put(json_arr_out); return NULL; - } - char l_tx_prev_hash_str[DAP_HASH_FAST_STR_SIZE]={0}; - char l_time[DAP_TIME_STR_SIZE] = {0}; - dap_chain_hash_fast_to_str(&l_tx_item->tx_hash_fast,l_tx_prev_hash_str,sizeof(l_tx_prev_hash_str)); - dap_time_to_str_rfc822(l_time, sizeof(l_time), l_tx_item->cache_data.ts_created); - json_object_object_add(json_obj_tx, "Ledger thresholded tx_hash_fast", json_object_new_string(l_tx_prev_hash_str)); - json_object_object_add(json_obj_tx, "time_created", json_object_new_string(l_time)); - json_object_object_add(json_obj_tx, "tx_item_size", json_object_new_int(l_tx_item->tx->header.tx_items_size)); - json_object_array_add(json_arr_out, json_obj_tx); + } l_counter++; } + else + { + l_tx_item = HASH_LAST(l_ledger_pvt->threshold_txs); + for(; l_tx_item; l_tx_item = l_tx_item->hh.prev, i_tmp++){ + if (i_tmp < l_arr_start || i_tmp >= l_arr_end) + continue; + if (s_pack_ledger_threshold_info_json(json_arr_out, l_tx_item)) { + pthread_rwlock_unlock(&l_ledger_pvt->threshold_txs_rwlock); + json_object_put(json_arr_out); + return NULL; + } + l_counter++; + } + } if (!l_counter) { json_object* json_obj_tx = json_object_new_object(); json_object_object_add(json_obj_tx, "status", json_object_new_string("0 items in ledger tx threshold")); @@ -2064,7 +2079,7 @@ json_object *dap_ledger_threshold_info(dap_ledger_t *a_ledger, size_t a_limit, s return json_arr_out; } -json_object *dap_ledger_balance_info(dap_ledger_t *a_ledger, size_t a_limit, size_t a_offset) +json_object *dap_ledger_balance_info(dap_ledger_t *a_ledger, size_t a_limit, size_t a_offset, bool a_head) { dap_ledger_private_t *l_ledger_pvt = PVT(a_ledger); json_object * json_arr_out = json_object_new_array(); @@ -2072,37 +2087,28 @@ json_object *dap_ledger_balance_info(dap_ledger_t *a_ledger, size_t a_limit, siz uint32_t l_counter = 0; dap_ledger_wallet_balance_t *l_balance_item, *l_balance_tmp; size_t l_arr_start = 0; - if (a_offset > 1) { - l_arr_start = a_offset; - json_object* json_obj_tx = json_object_new_object(); - json_object_object_add(json_obj_tx, "offset", json_object_new_int(l_arr_start)); - json_object_array_add(json_arr_out, json_obj_tx); - } - size_t l_arr_end = HASH_COUNT(l_ledger_pvt->balance_accounts); - if (a_limit) { - json_object* json_obj_tx = json_object_new_object(); - json_object_object_add(json_obj_tx, "limit", json_object_new_int(l_arr_start)); - json_object_array_add(json_arr_out, json_obj_tx); - l_arr_end = l_arr_start + a_limit; - if (l_arr_end > HASH_COUNT(l_ledger_pvt->balance_accounts)) { - l_arr_end = HASH_COUNT(l_ledger_pvt->balance_accounts); - } - } + size_t l_arr_end = 0; + s_set_offset_limit_json(json_arr_out, &l_arr_start, &l_arr_end, a_limit, a_offset, HASH_COUNT(l_ledger_pvt->balance_accounts)); + size_t i_tmp = 0; - HASH_ITER(hh, l_ledger_pvt->balance_accounts, l_balance_item, l_balance_tmp) { - if (i_tmp < l_arr_start || i_tmp >= l_arr_end) { + if (a_head) + HASH_ITER(hh, l_ledger_pvt->balance_accounts, l_balance_item, l_balance_tmp) { + if (i_tmp < l_arr_start || i_tmp >= l_arr_end) { + i_tmp++; + continue; + } i_tmp++; - continue; + s_pack_ledger_balance_info_json(json_arr_out, l_balance_item); + l_counter +=1; } - i_tmp++; - json_object* json_obj_tx = json_object_new_object(); - //log_it(L_DEBUG,"Ledger balance key %s, token_ticker: %s, balance: %s", l_balance_key, l_balance_item->token_ticker, - // dap_chain_balance_print(l_balance_item->balance)); - json_object_object_add(json_obj_tx, "Ledger balance key", json_object_new_string(l_balance_item->key)); - json_object_object_add(json_obj_tx, "token_ticker", json_object_new_string(l_balance_item->token_ticker)); - json_object_object_add(json_obj_tx, "balance", json_object_new_string(dap_uint256_to_char(l_balance_item->balance, NULL))); - json_object_array_add(json_arr_out, json_obj_tx); - l_counter +=1; + else { + l_balance_item = HASH_LAST(l_ledger_pvt->balance_accounts); + for(; l_balance_item; l_balance_item = l_balance_item->hh.prev, i_tmp++){ + if (i_tmp < l_arr_start || i_tmp >= l_arr_end) + continue; + s_pack_ledger_balance_info_json(json_arr_out, l_balance_item); + l_counter++; + } } if (!l_counter){ json_object* json_obj_tx = json_object_new_object(); diff --git a/modules/net/dap_chain_node_cli.c b/modules/net/dap_chain_node_cli.c index 3e472f4d4e1fc0a20a18abeda98c8ee41c805107..95620a0b29061ed7bdfdb3839f3a806ae19f4baa 100644 --- a/modules/net/dap_chain_node_cli.c +++ b/modules/net/dap_chain_node_cli.c @@ -291,8 +291,8 @@ int dap_chain_node_cli_init(dap_config_t * g_config) // Ledger info dap_cli_server_cmd_add("ledger", com_ledger, "Ledger information", "ledger list coins -net <net_name> [-limit] [-offset]\n" - "ledger list threshold [-hash <tx_treshold_hash>] -net <net_name> [-limit] [-offset]\n" - "ledger list balance -net <net_name> [-limit] [-offset]\n" + "ledger list threshold [-hash <tx_treshold_hash>] -net <net_name> [-limit] [-offset] [-head]\n" + "ledger list balance -net <net_name> [-limit] [-offset] [-head]\n" "ledger info -hash <tx_hash> -net <net_name> [-unspent]\n"); // Token info diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c index 0bd77659346871b0291c30fce7ad44fe31e26fa6..09cd68230f0593ca54de0c2ecb13771885f2eb73 100644 --- a/modules/net/dap_chain_node_cli_cmd.c +++ b/modules/net/dap_chain_node_cli_cmd.c @@ -7234,6 +7234,7 @@ int com_tx_history(int a_argc, char ** a_argv, void **a_str_reply) const char *l_tx_act_str = NULL; const char *l_limit_str = NULL; const char *l_offset_str = NULL; + const char *l_head_str = NULL; dap_chain_t * l_chain = NULL; dap_chain_net_t * l_net = NULL; @@ -7259,7 +7260,8 @@ int com_tx_history(int a_argc, char ** a_argv, void **a_str_reply) dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-limit", &l_limit_str); dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-offset", &l_offset_str); - size_t l_limit = l_limit_str ? strtoul(l_limit_str, NULL, 10) : 1000; + bool l_head = dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-head", &l_head_str) ? true : false; + size_t l_limit = l_limit_str ? strtoul(l_limit_str, NULL, 10) : 0; size_t l_offset = l_offset_str ? strtoul(l_offset_str, NULL, 10) : 0; //default is ALL/ANY @@ -7381,7 +7383,7 @@ int com_tx_history(int a_argc, char ** a_argv, void **a_str_reply) if (!json_obj_summary) { return DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_MEMORY_ERR; } - json_obj_out = dap_db_history_addr(l_addr, l_chain, l_hash_out_type, dap_chain_addr_to_str_static(l_addr), json_obj_summary, l_limit, l_offset, l_brief, l_tx_srv_str, l_action); + json_obj_out = dap_db_history_addr(l_addr, l_chain, l_hash_out_type, dap_chain_addr_to_str_static(l_addr), json_obj_summary, l_limit, l_offset, l_brief, l_tx_srv_str, l_action, l_head); if (!json_obj_out) { dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_DAP_DB_HISTORY_ADDR_ERR, "something went wrong in tx_history"); @@ -7399,7 +7401,7 @@ int com_tx_history(int a_argc, char ** a_argv, void **a_str_reply) } json_object* json_arr_history_all = dap_db_history_tx_all(l_chain, l_net, l_hash_out_type, json_obj_summary, - l_limit, l_offset, l_brief, l_tx_srv_str, l_action); + l_limit, l_offset, l_brief, l_tx_srv_str, l_action, l_head); if (!json_arr_history_all) { dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_DAP_DB_HISTORY_ALL_ERR, "something went wrong in tx_history"); diff --git a/modules/net/dap_chain_node_cli_cmd_tx.c b/modules/net/dap_chain_node_cli_cmd_tx.c index df1ac92b19193450127ebd2385fb6fdf01e7aa07..b28680716f06337311dc487d48782957194cb17c 100644 --- a/modules/net/dap_chain_node_cli_cmd_tx.c +++ b/modules/net/dap_chain_node_cli_cmd_tx.c @@ -302,7 +302,6 @@ static void s_tx_header_print(json_object* json_obj_datum, dap_chain_tx_hash_pro DAP_DELETE(l_atom_hash_str); } - /** * @brief dap_db_history_addr * Get data according the history log @@ -315,7 +314,7 @@ static void s_tx_header_print(json_object* json_obj_datum, dap_chain_tx_hash_pro */ json_object* dap_db_history_addr(dap_chain_addr_t *a_addr, dap_chain_t *a_chain, const char *a_hash_out_type, const char * l_addr_str, json_object *json_obj_summary, - size_t a_limit, size_t a_offset, bool a_brief, const char *a_srv, dap_chain_tx_tag_action_type_t a_action) + size_t a_limit, size_t a_offset, bool a_brief, const char *a_srv, dap_chain_tx_tag_action_type_t a_action, bool a_head) { json_object* json_obj_datum = json_object_new_array(); if (!json_obj_datum){ @@ -349,36 +348,34 @@ json_object* dap_db_history_addr(dap_chain_addr_t *a_addr, dap_chain_t *a_chain, dap_chain_addr_t l_net_fee_addr = {}; bool l_net_fee_used = dap_chain_net_tx_get_fee(l_net->pub.id, NULL, &l_net_fee_addr); bool l_is_need_correction = false; + bool l_continue = false; uint256_t l_corr_value = {}, l_unstake_value = {}; bool look_for_unknown_service = (a_srv && strcmp(a_srv,"unknown") == 0); - - json_object* json_obj_lim = json_object_new_object(); size_t l_arr_start = 0; - if (a_offset){ - l_arr_start = a_offset; - json_object_object_add(json_obj_lim, "offset", json_object_new_int(l_arr_start)); - } - size_t l_arr_end = a_chain->callback_count_atom(a_chain); - if (a_limit) { - json_object_object_add(json_obj_lim, "limit", json_object_new_int(a_limit)); - l_arr_end = l_arr_start + a_limit; - size_t l_length = a_chain->callback_count_atom(a_chain); - if (l_arr_end > l_length) - l_arr_end = l_length; - } - json_object_array_add(json_obj_datum, json_obj_lim); + size_t l_arr_end = 0; + s_set_offset_limit_json(json_obj_datum, &l_arr_start, &l_arr_end, a_limit, a_offset, a_chain->callback_count_atom(a_chain)); + size_t i_tmp = 0; size_t + l_count = 0, l_tx_ledger_accepted = 0, l_tx_ledger_rejected = 0; // load transactions dap_chain_datum_iter_t *l_datum_iter = a_chain->callback_datum_iter_create(a_chain); -size_t datums = 0; - for (dap_chain_datum_t *l_datum = a_chain->callback_datum_iter_get_first(l_datum_iter); + + dap_chain_datum_callback_iters iter_begin; + dap_chain_datum_callback_iters iter_direc; + iter_begin = a_head ? a_chain->callback_datum_iter_get_first + : a_chain->callback_datum_iter_get_last; + iter_direc = a_head ? a_chain->callback_datum_iter_get_next + : a_chain->callback_datum_iter_get_prev; + + for (dap_chain_datum_t *l_datum = iter_begin(l_datum_iter); l_datum; - l_datum = a_chain->callback_datum_iter_get_next(l_datum_iter)) + l_datum = iter_direc(l_datum_iter)) { - datums++; + if (i_tmp >= l_arr_end) + break; json_object *l_corr_object = NULL; if (l_datum->header.type_id != DAP_CHAIN_DATUM_TX) // go to next datum @@ -561,11 +558,19 @@ size_t datums = 0; } } - if (l_dst_addr && dap_chain_addr_compare(l_dst_addr, a_addr)) { - if (!l_header_printed) { + if (l_dst_addr && dap_chain_addr_compare(l_dst_addr, a_addr)) { + if (i_tmp < l_arr_start) { + i_tmp++; + l_continue = true; + break; + } + if (!l_header_printed) { s_tx_header_print(j_obj_tx, &l_tx_data_ht, l_tx, l_datum_iter->cur_atom_hash, a_hash_out_type, l_ledger, &l_tx_hash, l_datum_iter->ret_code); l_header_printed = true; + l_count++; + i_tmp++; + l_src_token ? l_tx_ledger_accepted++ : l_tx_ledger_rejected++; } const char *l_src_str = NULL; if (l_base_tx) @@ -580,21 +585,15 @@ size_t datums = 0; l_is_need_correction = true; l_corr_value = l_value; } - const char *l_coins_str, *l_value_str = dap_uint256_to_char(l_value, &l_coins_str); - if (i_tmp >= l_arr_end || i_tmp < l_arr_start) { - i_tmp++; - continue; - } - i_tmp++; - - json_object *j_obj_data = json_object_new_object(); + const char *l_coins_str, *l_value_str = dap_uint256_to_char(l_value, &l_coins_str); + + json_object * j_obj_data = json_object_new_object(); if (!j_obj_data) { dap_json_rpc_allocation_error; json_object_put(j_obj_tx); json_object_put(j_arr_data); return NULL; - } - l_src_token ? l_tx_ledger_accepted++ : l_tx_ledger_rejected++; + } json_object_object_add(j_obj_data, "tx_type", json_object_new_string("recv")); json_object_object_add(j_obj_data, "recv_coins", json_object_new_string(l_coins_str)); json_object_object_add(j_obj_data, "recv_datoshi", json_object_new_string(l_value_str)); @@ -610,30 +609,33 @@ size_t datums = 0; if (!l_dst_addr && ((dap_chain_tx_out_cond_t *)it->data)->header.subtype == l_src_subtype && l_src_subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE) continue; if (!l_src_addr && l_dst_addr && !dap_chain_addr_compare(l_dst_addr, &l_net_fee_addr)) - continue; - if (!l_header_printed) { + continue; + if (i_tmp < l_arr_start) { + i_tmp++; + l_continue = true; + break; + } + if (!l_header_printed) { s_tx_header_print(j_obj_tx, &l_tx_data_ht, l_tx, l_datum_iter->cur_atom_hash, a_hash_out_type, l_ledger, &l_tx_hash, l_datum_iter->ret_code); l_header_printed = true; + l_count++; + i_tmp++; + l_src_token ? l_tx_ledger_accepted++ : l_tx_ledger_rejected++; } const char *l_dst_addr_str = l_dst_addr ? dap_chain_addr_to_str_static(l_dst_addr) : dap_chain_tx_out_cond_subtype_to_str( ((dap_chain_tx_out_cond_t *)it->data)->header.subtype); const char *l_coins_str, *l_value_str = dap_uint256_to_char(l_value, &l_coins_str); - if (i_tmp >= l_arr_end || i_tmp < l_arr_start) { - i_tmp++; - continue; - } - i_tmp++; + json_object * j_obj_data = json_object_new_object(); if (!j_obj_data) { dap_json_rpc_allocation_error; json_object_put(j_obj_tx); json_object_put(j_arr_data); return NULL; - } - l_src_token ? l_tx_ledger_accepted++ : l_tx_ledger_rejected++; + } json_object_object_add(j_obj_data, "tx_type", json_object_new_string("send")); json_object_object_add(j_obj_data, "send_coins", json_object_new_string(l_coins_str)); json_object_object_add(j_obj_data, "send_datoshi", json_object_new_string(l_value_str)); @@ -642,12 +644,18 @@ size_t datums = 0; json_object_object_add(j_obj_data, "destination_address", json_object_new_string(l_dst_addr_str)); json_object_array_add(j_arr_data, j_obj_data); } + } + if (l_continue){ + l_continue = false; + continue; } + if (json_object_array_length(j_arr_data) > 0) { json_object_object_add(j_obj_tx, "data", j_arr_data); json_object_array_add(json_obj_datum, j_obj_tx); } else { json_object_put(j_arr_data); + j_arr_data = NULL; json_object_put(j_obj_tx); } dap_list_free(l_list_out_items); @@ -655,11 +663,10 @@ size_t datums = 0; SUM_256_256(l_corr_value, l_fee_sum, &l_corr_value); const char *l_coins_str, *l_value_str = dap_uint256_to_char(l_corr_value, &l_coins_str); json_object_object_add(l_corr_object, "recv_coins", json_object_new_string(l_coins_str)); - json_object_object_add(l_corr_object, "recv_datoshi", json_object_new_string(l_value_str)); - if (!j_arr_data) { - j_arr_data = json_object_new_array(); - } - json_object_array_add(j_arr_data, l_corr_object); + json_object_object_add(l_corr_object, "recv_datoshi", json_object_new_string(l_value_str)); + json_object * j_arr_correct = json_object_new_object(); + json_object_object_add(j_arr_correct, "correction", l_corr_object); + json_object_array_add(json_obj_datum, j_arr_correct); l_is_need_correction = false; } } @@ -668,7 +675,7 @@ size_t datums = 0; s_dap_chain_tx_hash_processed_ht_free(&l_tx_data_ht); // if no history - if (json_object_array_length(json_obj_datum) == 1) { + if (json_object_array_length(json_obj_datum) == 2) { json_object * json_empty_tx = json_object_new_object(); if (!json_empty_tx) { dap_json_rpc_allocation_error; @@ -680,17 +687,65 @@ size_t datums = 0; } json_object_object_add(json_obj_summary, "network", json_object_new_string(l_net->pub.name)); json_object_object_add(json_obj_summary, "chain", json_object_new_string(a_chain->name)); - json_object_object_add(json_obj_summary, "tx_sum", json_object_new_int(i_tmp)); + json_object_object_add(json_obj_summary, "tx_sum", json_object_new_int(l_count)); json_object_object_add(json_obj_summary, "accepted_tx", json_object_new_int(l_tx_ledger_accepted)); json_object_object_add(json_obj_summary, "rejected_tx", json_object_new_int(l_tx_ledger_rejected)); return json_obj_datum; } -json_object *dap_db_history_tx_all(dap_chain_t *l_chain, dap_chain_net_t *l_net, - const char *l_hash_out_type, json_object *json_obj_summary, +static int s_json_tx_history_pack(json_object** a_json_obj_datum, dap_chain_datum_t * a_datum, dap_chain_net_t *a_net, + dap_chain_t *a_chain, dap_chain_tx_tag_action_type_t a_action, + const char *a_hash_out_type, bool a_out_brief, size_t* a_accepted, + size_t* a_rejected, bool a_look_for_unknown_service, const char *a_srv) +{ + dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t*)a_datum->data; + dap_hash_fast_t l_ttx_hash = {0}; + dap_hash_fast(l_tx, a_datum->header.data_size, &l_ttx_hash); + + char *service_name = NULL; + dap_chain_tx_tag_action_type_t l_action = DAP_CHAIN_TX_TAG_ACTION_UNKNOWN; + + dap_ledger_t *l_ledger = a_net->pub.ledger; + bool srv_found = dap_ledger_tx_service_info(l_ledger, &l_ttx_hash, NULL, &service_name, &l_action); + + if (!(l_action & a_action)) + return 1; + + if (a_srv) + { + char *service_name = NULL; + bool srv_found = dap_ledger_tx_service_info(l_ledger, &l_ttx_hash, NULL, &service_name, NULL); + //skip if looking for UNKNOWN + it is known + if (a_look_for_unknown_service && srv_found) { + return 1; + } + + //skip if search condition provided, it not UNKNOWN and found name not match + if (!a_look_for_unknown_service && (!srv_found || strcmp(service_name, a_srv) != 0)) + { + return 1; + } + } + + bool accepted_tx; + *a_json_obj_datum = dap_db_tx_history_to_json(&l_ttx_hash, NULL, l_tx, a_chain, a_hash_out_type, a_net, 0, &accepted_tx, a_out_brief); + if (!*a_json_obj_datum) { + log_it(L_CRITICAL, "%s", c_error_memory_alloc); + return 2; + } + if (accepted_tx) { + ++*a_accepted; + } else { + ++*a_rejected; + } + return 0; + +} + +json_object *dap_db_history_tx_all(dap_chain_t *a_chain, dap_chain_net_t *a_net, + const char *a_hash_out_type, json_object *json_obj_summary, size_t a_limit, size_t a_offset, bool out_brief, - const char *a_srv, - dap_chain_tx_tag_action_type_t a_action) + const char *a_srv, dap_chain_tx_tag_action_type_t a_action, bool a_head) { log_it(L_DEBUG, "Start getting tx from chain"); size_t @@ -698,94 +753,96 @@ json_object *dap_db_history_tx_all(dap_chain_t *l_chain, dap_chain_net_t *l_net, l_tx_ledger_rejected = 0, l_count = 0, l_count_tx = 0; + int res = 0; dap_chain_cell_t *l_cell = NULL, *l_cell_tmp = NULL; dap_chain_atom_iter_t *l_iter = NULL; json_object * json_arr_out = json_object_new_array(); - json_object* json_obj_lim = json_object_new_object(); + json_object * json_tx_history = NULL; size_t l_arr_start = 0; - if (a_offset) { - l_arr_start = a_offset; - json_object_object_add(json_obj_lim, "offset", json_object_new_int(l_arr_start)); - } - size_t l_arr_end = l_chain->callback_count_atom(l_chain); - l_arr_end = a_limit ? l_arr_start + a_limit : 0; - l_arr_end ? json_object_object_add(json_obj_lim, "limit", json_object_new_int(l_arr_end - l_arr_start)): - json_object_object_add(json_obj_lim, "limit", json_object_new_string("unlimit")); - json_object_array_add(json_arr_out, json_obj_lim); - + size_t l_arr_end = 0; + s_set_offset_limit_json(json_arr_out, &l_arr_start, &l_arr_end, a_limit, a_offset, a_chain->callback_count_atom(a_chain)); bool look_for_unknown_service = (a_srv && strcmp(a_srv,"unknown") == 0); - HASH_ITER(hh, l_chain->cells, l_cell, l_cell_tmp) { - if ((l_count_tx >= l_arr_end)&&(l_arr_end)) - break; - l_iter = l_chain->callback_atom_iter_create(l_chain, l_cell->id, NULL); - size_t l_atom_size = 0; - dap_chain_atom_ptr_t l_ptr = l_chain->callback_atom_iter_get(l_iter, DAP_CHAIN_ITER_OP_FIRST, &l_atom_size); - while (l_ptr && l_atom_size && ((l_count_tx < l_arr_end)||(!l_arr_end))) { - size_t l_datums_count = 0; - dap_chain_datum_t **l_datums = l_cell->chain->callback_atom_get_datums(l_ptr, l_atom_size, &l_datums_count); - for (size_t i = 0; i < l_datums_count && ((l_count_tx < l_arr_end)||(!l_arr_end)); i++) { - if (l_datums[i]->header.type_id == DAP_CHAIN_DATUM_TX) { - if (l_count_tx < l_arr_start) { - l_count_tx++; - continue; - } - dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t*)l_datums[i]->data; - dap_hash_fast_t l_ttx_hash = {0}; - dap_hash_fast(l_tx, l_datums[i]->header.data_size, &l_ttx_hash); - - char *service_name = NULL; - dap_chain_tx_tag_action_type_t l_action = DAP_CHAIN_TX_TAG_ACTION_UNKNOWN; - - dap_ledger_t *l_ledger = l_net->pub.ledger; - bool srv_found = dap_ledger_tx_service_info(l_ledger, &l_ttx_hash, NULL, &service_name, &l_action); - - if (!(l_action & a_action)) - continue; - - if (a_srv) - { - char *service_name = NULL; - bool srv_found = dap_ledger_tx_service_info(l_ledger, &l_ttx_hash, NULL, &service_name, NULL); - //skip if looking for UNKNOWN + it is known - if (look_for_unknown_service && srv_found) { + if(a_head) + HASH_ITER(hh, a_chain->cells, l_cell, l_cell_tmp) { + if ((l_count_tx >= l_arr_end)&&(l_arr_end)) + break; + l_iter = a_chain->callback_atom_iter_create(a_chain, l_cell->id, NULL); + size_t l_atom_size = 0; + dap_chain_atom_ptr_t l_ptr = a_chain->callback_atom_iter_get(l_iter, DAP_CHAIN_ITER_OP_FIRST, &l_atom_size); + while (l_ptr && l_atom_size && ((l_count_tx < l_arr_end)||(!l_arr_end))) { + size_t l_datums_count = 0; + dap_chain_datum_t **l_datums = l_cell->chain->callback_atom_get_datums(l_ptr, l_atom_size, &l_datums_count); + for (size_t i = 0; i < l_datums_count && ((l_count_tx < l_arr_end)||(!l_arr_end)); i++) { + if (l_datums[i]->header.type_id == DAP_CHAIN_DATUM_TX) { + if (l_count_tx < l_arr_start) { + l_count_tx++; continue; } - - //skip if search condition provided, it not UNKNOWN and found name not match - if (!look_for_unknown_service && (!srv_found || strcmp(service_name, a_srv) != 0)) - { + res = s_json_tx_history_pack(&json_tx_history, l_datums[i], a_net, a_chain, a_action, a_hash_out_type, out_brief, + &l_tx_ledger_accepted, &l_tx_ledger_rejected, look_for_unknown_service, a_srv); + if (res == 1) continue; + else if (res == 2) + { + json_object_put(json_arr_out); + return NULL; } - } - - bool accepted_tx; - json_object* json_obj_datum = dap_db_tx_history_to_json(&l_ttx_hash, NULL, l_tx, l_chain, l_hash_out_type, l_net, 0, &accepted_tx, out_brief); - if (!json_obj_datum) { - log_it(L_CRITICAL, "%s", c_error_memory_alloc); - return NULL; + json_object_object_add(json_tx_history, "tx number", json_object_new_uint64(l_count+1)); + json_object_array_add(json_arr_out, json_tx_history); + ++l_count_tx; + l_count++; } - if (accepted_tx) { - ++l_tx_ledger_accepted; - } else { - ++l_tx_ledger_rejected; + } + DAP_DEL_Z(l_datums); + l_ptr = a_chain->callback_atom_iter_get(l_iter, DAP_CHAIN_ITER_OP_NEXT, &l_atom_size); + } + l_cell->chain->callback_atom_iter_delete(l_iter); + } + else + { + l_cell_tmp = HASH_LAST(a_chain->cells); + for(; l_cell_tmp; l_cell_tmp = l_cell_tmp->hh.prev){ + if ((l_count_tx >= l_arr_end)&&(l_arr_end)) + break; + l_iter = a_chain->callback_atom_iter_create(a_chain, l_cell_tmp->id, NULL); + size_t l_atom_size = 0; + dap_chain_atom_ptr_t l_ptr = a_chain->callback_atom_iter_get(l_iter, DAP_CHAIN_ITER_OP_LAST, &l_atom_size); + while (l_ptr && l_atom_size && ((l_count_tx < l_arr_end)||(!l_arr_end))) { + size_t l_datums_count = 0; + dap_chain_datum_t **l_datums = l_cell_tmp->chain->callback_atom_get_datums(l_ptr, l_atom_size, &l_datums_count); + for (size_t i = l_datums_count; i && ((l_count_tx < l_arr_end)||(!l_arr_end)); i--) { + if (l_datums[i-1]->header.type_id == DAP_CHAIN_DATUM_TX) { + if (l_count_tx < l_arr_start) { + l_count_tx++; + continue; + } + res = s_json_tx_history_pack(&json_tx_history, l_datums[i-1], a_net, a_chain, a_action, a_hash_out_type, out_brief, + &l_tx_ledger_accepted, &l_tx_ledger_rejected, look_for_unknown_service, a_srv); + if (res == 1) + continue; + else if (res == 2) + { + json_object_put(json_arr_out); + return NULL; + } + json_object_object_add(json_tx_history, "tx number", json_object_new_uint64(l_count+1)); + json_object_array_add(json_arr_out, json_tx_history); + ++l_count_tx; + l_count++; } - json_object_array_add(json_arr_out, json_obj_datum); - //const char * debug_json_string = json_object_to_json_string(json_obj_datum); - ++l_count_tx; - l_count++; } + DAP_DEL_Z(l_datums); + l_ptr = a_chain->callback_atom_iter_get(l_iter, DAP_CHAIN_ITER_OP_PREV, &l_atom_size); } - DAP_DEL_Z(l_datums); - l_ptr = l_chain->callback_atom_iter_get(l_iter, DAP_CHAIN_ITER_OP_NEXT, &l_atom_size); + l_cell_tmp->chain->callback_atom_iter_delete(l_iter); } - l_cell->chain->callback_atom_iter_delete(l_iter); } log_it(L_DEBUG, "END getting tx from chain"); - json_object_object_add(json_obj_summary, "network", json_object_new_string(l_net->pub.name)); - json_object_object_add(json_obj_summary, "chain", json_object_new_string(l_chain->name)); + json_object_object_add(json_obj_summary, "network", json_object_new_string(a_net->pub.name)); + json_object_object_add(json_obj_summary, "chain", json_object_new_string(a_chain->name)); json_object_object_add(json_obj_summary, "tx_sum", json_object_new_int(l_count)); json_object_object_add(json_obj_summary, "accepted_tx", json_object_new_int(l_tx_ledger_accepted)); json_object_object_add(json_obj_summary, "rejected_tx", json_object_new_int(l_tx_ledger_rejected)); @@ -946,6 +1003,7 @@ int com_ledger(int a_argc, char ** a_argv, void **reply) dap_chain_hash_fast_t l_tx_threshold_hash = {}; const char *l_limit_str = NULL; const char *l_offset_str = NULL; + const char *l_head_str = NULL; if (dap_cli_server_cmd_find_option_val(a_argv, 2, 3, "coins", NULL )) l_sub_cmd = SUBCMD_LIST_COIN; if (dap_cli_server_cmd_find_option_val(a_argv, 2, 3, "balance", NULL )) @@ -970,7 +1028,8 @@ int com_ledger(int a_argc, char ** a_argv, void **reply) 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, arg_index, a_argc, "-limit", &l_limit_str); dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-offset", &l_offset_str); - size_t l_limit = l_limit_str ? strtoul(l_limit_str, NULL, 10) : 1000; + bool l_head = dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-head", &l_head_str) ? true : false; + size_t l_limit = l_limit_str ? strtoul(l_limit_str, NULL, 10) : 0; size_t l_offset = l_offset_str ? strtoul(l_offset_str, NULL, 10) : 0; if (l_net_str == NULL){ dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_LEDGER_NET_PARAM_ERR, "Command 'list' requires key -net"); @@ -982,21 +1041,21 @@ int com_ledger(int a_argc, char ** a_argv, void **reply) return DAP_CHAIN_NODE_CLI_COM_LEDGER_LACK_ERR; } if (l_sub_cmd == SUB_CMD_LIST_LEDGER_THRESHOLD) { - json_object* json_obj_out = dap_ledger_threshold_info(l_ledger, l_limit, l_offset, NULL); + json_object* json_obj_out = dap_ledger_threshold_info(l_ledger, l_limit, l_offset, NULL, l_head); if (json_obj_out){ json_object_array_add(*json_arr_reply, json_obj_out); } return 0; } if (l_sub_cmd == SUB_CMD_LIST_LEDGER_THRESHOLD_WITH_HASH) { - json_object *json_obj_out = dap_ledger_threshold_info(l_ledger, 0, 0, &l_tx_threshold_hash); + json_object *json_obj_out = dap_ledger_threshold_info(l_ledger, 0, 0, &l_tx_threshold_hash, l_head); if (json_obj_out){ json_object_array_add(*json_arr_reply, json_obj_out); } return 0; } if (l_sub_cmd == SUB_CMD_LIST_LEDGER_BALANCE) { - json_object *json_obj_out = dap_ledger_balance_info(l_ledger, l_limit, l_offset); + json_object *json_obj_out = dap_ledger_balance_info(l_ledger, l_limit, l_offset, l_head); if (json_obj_out){ json_object_array_add(*json_arr_reply, json_obj_out); } diff --git a/modules/net/include/dap_chain_ledger.h b/modules/net/include/dap_chain_ledger.h index c81920485e18d0e532892cdea39838a4c28adf9e..b536f7572f8d4c928eec6138f2d95aef8a2fcedd 100644 --- a/modules/net/include/dap_chain_ledger.h +++ b/modules/net/include/dap_chain_ledger.h @@ -301,8 +301,8 @@ json_object *dap_ledger_token_info_by_name(dap_ledger_t *a_ledger, const char *a // Get all token-declarations dap_list_t* dap_ledger_token_decl_all(dap_ledger_t *a_ledger); -json_object *dap_ledger_threshold_info(dap_ledger_t *a_ledger, size_t a_limit, size_t a_offset, dap_hash_fast_t *a_threshold_hash); -json_object *dap_ledger_balance_info(dap_ledger_t *a_ledger, size_t a_limit, size_t a_offset); +json_object *dap_ledger_threshold_info(dap_ledger_t *a_ledger, size_t a_limit, size_t a_offset, dap_hash_fast_t *a_threshold_hash, bool a_head); +json_object *dap_ledger_balance_info(dap_ledger_t *a_ledger, size_t a_limit, size_t a_offset, bool a_head); size_t dap_ledger_token_get_auth_signs_valid(dap_ledger_t *a_ledger, const char *a_token_ticker); size_t dap_ledger_token_get_auth_signs_total(dap_ledger_t *a_ledger, const char *a_token_ticker); diff --git a/modules/net/include/dap_chain_node_cli_cmd_tx.h b/modules/net/include/dap_chain_node_cli_cmd_tx.h index 0402711b9dc95d821e6ecfe6a55cd91e6a6cbe66..be6bb5f251298dcc803e00ba26fad4233f23be79 100644 --- a/modules/net/include/dap_chain_node_cli_cmd_tx.h +++ b/modules/net/include/dap_chain_node_cli_cmd_tx.h @@ -44,7 +44,7 @@ json_object * dap_db_history_tx(dap_chain_hash_fast_t* a_tx_hash, dap_chain_t * json_object * dap_db_history_addr(dap_chain_addr_t * a_addr, dap_chain_t * a_chain, const char *a_hash_out_type, const char * l_addr_str, json_object *json_obj_summary, size_t a_limit, size_t a_offset, bool a_brief, const char *a_srv, -dap_chain_tx_tag_action_type_t a_action); +dap_chain_tx_tag_action_type_t a_action, bool a_head); json_object * dap_db_tx_history_to_json(dap_chain_hash_fast_t* a_tx_hash, dap_hash_fast_t * l_atom_hash, dap_chain_datum_tx_t * l_tx, @@ -59,7 +59,7 @@ json_object *dap_db_history_tx_all(dap_chain_t *l_chain, dap_chain_net_t *l_net, const char *l_hash_out_type, json_object *json_obj_summary, size_t a_limit, size_t a_offset, bool out_brief, const char *a_srv, - dap_chain_tx_tag_action_type_t a_action); + dap_chain_tx_tag_action_type_t a_action, bool a_head); bool s_dap_chain_datum_tx_out_data(dap_chain_datum_tx_t *a_datum, dap_ledger_t *a_ledger, diff --git a/modules/type/blocks/dap_chain_cs_blocks.c b/modules/type/blocks/dap_chain_cs_blocks.c index ea48d44a6ae9abfa95c2a993ff7cf133baf866c2..86937703bd001d40952a72f444ab4f9b25b1bc94 100644 --- a/modules/type/blocks/dap_chain_cs_blocks.c +++ b/modules/type/blocks/dap_chain_cs_blocks.c @@ -143,7 +143,9 @@ static void s_callback_atom_iter_delete(dap_chain_atom_iter_t * a_atom_iter ); static dap_chain_datum_iter_t *s_chain_callback_datum_iter_create(dap_chain_t *a_chain); static void s_chain_callback_datum_iter_delete(dap_chain_datum_iter_t *a_datum_iter); static dap_chain_datum_t *s_chain_callback_datum_iter_get_first(dap_chain_datum_iter_t *a_datum_iter); // Get the fisrt datum from blocks +static dap_chain_datum_t *s_chain_callback_datum_iter_get_last(dap_chain_datum_iter_t *a_datum_iter); // Get the last datum from blocks static dap_chain_datum_t *s_chain_callback_datum_iter_get_next(dap_chain_datum_iter_t *a_datum_iter); // Get the next datum from blocks +static dap_chain_datum_t *s_chain_callback_datum_iter_get_prev(dap_chain_datum_iter_t *a_datum_iter); // Get the prev datum from blocks static size_t s_callback_add_datums(dap_chain_t * a_chain, dap_chain_datum_t ** a_datums, size_t a_datums_count); @@ -280,7 +282,9 @@ static int s_chain_cs_blocks_new(dap_chain_t *a_chain, dap_config_t *a_chain_con a_chain->callback_datum_iter_create = s_chain_callback_datum_iter_create; // Datum iterator create a_chain->callback_datum_iter_delete = s_chain_callback_datum_iter_delete; // Datum iterator delete a_chain->callback_datum_iter_get_first = s_chain_callback_datum_iter_get_first; // Get the fisrt datum from chain + a_chain->callback_datum_iter_get_last = s_chain_callback_datum_iter_get_last; // Get the last datum from chain a_chain->callback_datum_iter_get_next = s_chain_callback_datum_iter_get_next; // Get the next datum from chain from the current one + a_chain->callback_datum_iter_get_prev = s_chain_callback_datum_iter_get_prev; // Get the next datum from chain from the current one a_chain->callback_atom_get_datums = s_callback_atom_get_datums; a_chain->callback_atom_get_timestamp = s_chain_callback_atom_get_timestamp; @@ -820,7 +824,7 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply) } break; case SUBCMD_LIST:{ - const char *l_cert_name = NULL, *l_from_hash_str = NULL, *l_to_hash_str = NULL, + const char *l_cert_name = NULL, *l_from_hash_str = NULL, *l_to_hash_str = NULL, *l_head_str = NULL, *l_from_date_str = NULL, *l_to_date_str = NULL, *l_pkey_hash_str = NULL, *l_limit_str = NULL, *l_offset_str = NULL; bool l_unspent_flag = false, l_first_signed_flag = false, l_signed_flag = false, l_hash_flag = false; dap_pkey_t * l_pub_key = NULL; @@ -839,8 +843,9 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply) dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-to_dt", &l_to_date_str); dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-limit", &l_limit_str); dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-offset", &l_offset_str); + bool l_head = dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-head", &l_head_str) ? true : false; size_t l_offset = l_offset_str ? strtoul(l_offset_str, NULL, 10) : 0; - size_t l_limit = l_limit_str ? strtoul(l_limit_str, NULL, 10) : 1000; + size_t l_limit = l_limit_str ? strtoul(l_limit_str, NULL, 10) : 0; if (l_signed_flag && l_first_signed_flag) { dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_PARAM_ERR, "Choose only one option from 'singed' and 'first_signed'"); @@ -906,22 +911,15 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply) pthread_rwlock_rdlock(&PVT(l_blocks)->rwlock); json_object* json_arr_bl_cache_out = json_object_new_array(); - json_object* json_obj_lim = json_object_new_object(); size_t l_start_arr = 0; - if(l_offset > 0) { - l_start_arr = l_offset; - json_object_object_add(json_obj_lim, "offset",json_object_new_uint64(l_start_arr)); - } - size_t l_arr_end = PVT(l_blocks)->blocks_count; - if (l_limit) { - json_object_object_add(json_obj_lim, "limit",json_object_new_uint64(l_limit)); - l_arr_end = l_start_arr + l_limit; - if (l_arr_end > PVT(l_blocks)->blocks_count) - l_arr_end = PVT(l_blocks)->blocks_count; - } - json_object_array_add(json_arr_bl_cache_out, json_obj_lim); + size_t l_arr_end = 0; + s_set_offset_limit_json(json_arr_bl_cache_out, &l_start_arr, &l_arr_end, l_limit, l_offset, PVT(l_blocks)->blocks_count); + size_t i_tmp = 0; - for (dap_chain_block_cache_t *l_block_cache = PVT(l_blocks)->blocks; l_block_cache; l_block_cache = l_block_cache->hh.next) { + dap_chain_block_cache_t *l_block_cache = PVT(l_blocks)->blocks; + if (!l_head) + l_block_cache = HASH_LAST(l_block_cache); + for ( ; l_block_cache; l_block_cache = l_head ? l_block_cache->hh.next : l_block_cache->hh.prev) { dap_time_t l_ts = l_block_cache->block->hdr.ts_created; if (l_from_time && l_ts < l_from_time) continue; @@ -2210,6 +2208,17 @@ static dap_chain_datum_t *s_chain_callback_datum_iter_get_first(dap_chain_datum_ return a_datum_iter->cur; } +static dap_chain_datum_t *s_chain_callback_datum_iter_get_last(dap_chain_datum_iter_t *a_datum_iter) +{ + dap_chain_cs_blocks_t * l_cs_blocks = DAP_CHAIN_CS_BLOCKS(a_datum_iter->chain); + pthread_rwlock_rdlock(&PVT(l_cs_blocks)->datums_rwlock); + //dap_chain_block_datum_index_t *l_datum_index = PVT(l_cs_blocks)->datum_index; + dap_chain_block_datum_index_t *l_datum_index = HASH_LAST(PVT(l_cs_blocks)->datum_index); + s_datum_iter_fill(a_datum_iter, l_datum_index); + pthread_rwlock_unlock(&PVT(l_cs_blocks)->datums_rwlock); + return a_datum_iter->cur; +} + static dap_chain_datum_t *s_chain_callback_datum_iter_get_next(dap_chain_datum_iter_t *a_datum_iter) { dap_chain_cs_blocks_t * l_cs_blocks = DAP_CHAIN_CS_BLOCKS(a_datum_iter->chain); @@ -2222,6 +2231,18 @@ static dap_chain_datum_t *s_chain_callback_datum_iter_get_next(dap_chain_datum_i return a_datum_iter->cur; } +static dap_chain_datum_t *s_chain_callback_datum_iter_get_prev(dap_chain_datum_iter_t *a_datum_iter) +{ + dap_chain_cs_blocks_t * l_cs_blocks = DAP_CHAIN_CS_BLOCKS(a_datum_iter->chain); + pthread_rwlock_rdlock(&PVT(l_cs_blocks)->datums_rwlock); + dap_chain_block_datum_index_t *l_datum_index = a_datum_iter->cur_item; + if (l_datum_index) + l_datum_index = l_datum_index->hh.prev; + s_datum_iter_fill(a_datum_iter, l_datum_index); + pthread_rwlock_unlock(&PVT(l_cs_blocks)->datums_rwlock); + return a_datum_iter->cur; +} + static dap_chain_block_t *s_new_block_move(dap_chain_cs_blocks_t *a_blocks, size_t *a_new_block_size) { diff --git a/modules/type/dag/dap_chain_cs_dag.c b/modules/type/dag/dap_chain_cs_dag.c index 200cbbbe141ea45d8652c72a26cc02b815bf70a2..e91572b1dd5346a4441fe60200c37e219cf21909 100644 --- a/modules/type/dag/dap_chain_cs_dag.c +++ b/modules/type/dag/dap_chain_cs_dag.c @@ -157,7 +157,7 @@ int dap_chain_cs_dag_init() "\tdoesn't changes after sign add to event. \n\n" "dag event dump -net <net_name> [-chain <chain_name>] -event <event_hash> -from {events | events_lasts | threshold | round.new | round.<Round_id_in_hex>} [-H {hex | base58(default)}]\n" "\tDump event info\n\n" - "dag event list -net <net_name> [-chain <chain_name>] -from {events | events_lasts | threshold | round.new | round.<Round_id_in_hex>} [-limit] [-offset]\n\n" + "dag event list -net <net_name> [-chain <chain_name>] -from {events | events_lasts | threshold | round.new | round.<Round_id_in_hex>} [-limit] [-offset] [-head]\n\n" "\tShow event list \n\n" "dag event count -net <net_name> [-chain <chain_name>]\n" "\tShow count event \n\n" @@ -1285,6 +1285,34 @@ static dap_chain_datum_t *s_chain_callback_datum_iter_get_next(dap_chain_datum_i return a_datum_iter->cur; } +static bool s_json_dag_pack_round(json_object * a_json_out, dap_global_db_obj_t * a_objs, int i){ + json_object * json_obj_event_i = json_object_new_object(); + if (!strcmp(DAG_ROUND_CURRENT_KEY, a_objs[i].key)) { + json_object_object_add(json_obj_event_i, a_objs[i].key, json_object_new_uint64(*(uint64_t *)a_objs[i].value)); + json_object_array_add(a_json_out, json_obj_event_i); + return true; + } + dap_chain_cs_dag_event_t * l_event = (dap_chain_cs_dag_event_t *) + ((dap_chain_cs_dag_event_round_item_t *)a_objs[i].value)->event_n_signs; + char buf[DAP_TIME_STR_SIZE]; + dap_time_to_str_rfc822(buf, DAP_TIME_STR_SIZE, l_event->header.ts_created); + json_object_object_add(json_obj_event_i, "event", json_object_new_string(dap_itoa(i-1))); + json_object_object_add(json_obj_event_i, "obj key", json_object_new_string(a_objs[i].key)); + json_object_object_add(json_obj_event_i, "ts_create", json_object_new_string(buf)); + json_object_array_add(a_json_out, json_obj_event_i); + return false; +} + +static void s_json_dag_pack_event(json_object * a_json_out, dap_chain_cs_dag_event_item_t * a_event_item, size_t i){ + json_object * json_obj_event_i = json_object_new_object(); + char buf[DAP_TIME_STR_SIZE]; + dap_time_to_str_rfc822(buf, DAP_TIME_STR_SIZE, a_event_item->event->header.ts_created); + json_object_object_add(json_obj_event_i, "event", json_object_new_string(dap_itoa(i))); + json_object_object_add(json_obj_event_i, "hash", json_object_new_string(dap_chain_hash_fast_to_str_static(&a_event_item->hash))); + json_object_object_add(json_obj_event_i, "ts_create", json_object_new_string(buf)); + json_object_array_add(a_json_out, json_obj_event_i); +} + /** * @brief s_cli_dag * @param argc @@ -1661,16 +1689,13 @@ static int s_cli_dag(int argc, char ** argv, void **a_str_reply) case SUBCMD_EVENT_LIST: { json_object * json_obj_event_list = json_object_new_object(); json_object * json_arr_obj_event = json_object_new_array(); - const char *l_limit_str = NULL, *l_offset_str = NULL; + const char *l_limit_str = NULL, *l_offset_str = NULL, *l_head_str = NULL; dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-limit", &l_limit_str); dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-offset", &l_offset_str); + bool l_head = dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-head", &l_head_str) ? true : false; char *ptr; - size_t l_limit = l_limit_str ? strtoull(l_limit_str, &ptr, 10) : 1000; - size_t l_offset = l_offset_str ? strtoull(l_offset_str, &ptr, 10) : 0; - if (l_offset) - json_object_object_add(json_obj_event_list,"offset", json_object_new_uint64(l_offset)); - if (l_limit) - json_object_object_add(json_obj_event_list,"limit", json_object_new_uint64(l_limit)); + size_t l_limit = l_limit_str ? strtoull(l_limit_str, &ptr, 10) : 0; + size_t l_offset = l_offset_str ? strtoull(l_offset_str, &ptr, 10) : 0; if (l_from_events_str && strcmp(l_from_events_str,"round.new") == 0) { char * l_gdb_group_events = DAP_CHAIN_CS_DAG(l_chain)->gdb_group_events_round_new; @@ -1679,35 +1704,19 @@ static int s_cli_dag(int argc, char ** argv, void **a_str_reply) size_t l_objs_count = 0; l_objs = dap_global_db_get_all_sync(l_gdb_group_events,&l_objs_count); size_t l_arr_start = 0; - if (l_offset) { - l_arr_start = l_offset; - } - size_t l_arr_end = l_objs_count; - if (l_limit) { - l_arr_end = l_arr_start + l_limit; - if (l_arr_end > l_objs_count) - l_arr_end = l_objs_count; - } + size_t l_arr_end = 0; + s_set_offset_limit_json(json_arr_obj_event, &l_arr_start, &l_arr_end, l_limit, l_offset, l_objs_count); + json_object_object_add(json_obj_event_list,"net name", json_object_new_string(l_net->pub.name)); json_object_object_add(json_obj_event_list,"chain", json_object_new_string(l_chain->name)); json_object_object_add(json_obj_event_list,"obj count", json_object_new_uint64(l_objs_count)); - for (size_t i = l_arr_start; i < l_arr_end; i++) { - json_object * json_obj_event_i = json_object_new_object(); - if (!strcmp(DAG_ROUND_CURRENT_KEY, l_objs[i].key)) { - json_object_object_add(json_obj_event_i, l_objs[i].key, json_object_new_uint64(*(uint64_t *)l_objs[i].value)); - json_object_array_add(json_arr_obj_event, json_obj_event_i); - continue; - } - dap_chain_cs_dag_event_t * l_event = (dap_chain_cs_dag_event_t *) - ((dap_chain_cs_dag_event_round_item_t *)l_objs[i].value)->event_n_signs; - char buf[DAP_TIME_STR_SIZE]; - dap_time_to_str_rfc822(buf, DAP_TIME_STR_SIZE, l_event->header.ts_created); - json_object_object_add(json_obj_event_i, "#", json_object_new_string(dap_itoa(i-1))); - json_object_object_add(json_obj_event_i, "obj key", json_object_new_string(l_objs[i].key)); - json_object_object_add(json_obj_event_i, "ts_create", json_object_new_string(buf)); - json_object_array_add(json_arr_obj_event, json_obj_event_i); - } + if (l_head) + for (size_t i = l_arr_start; i < l_arr_end; i++) + s_json_dag_pack_round(json_arr_obj_event, l_objs, i); + else + for (size_t i = l_objs_count - l_arr_start; i > l_objs_count - l_arr_end; i--) + s_json_dag_pack_round(json_arr_obj_event, l_objs, i); json_object_object_add(json_obj_event_list, "OBJ", json_arr_obj_event); if (l_objs && l_objs_count ) dap_global_db_objs_delete(l_objs, l_objs_count); @@ -1715,37 +1724,38 @@ static int s_cli_dag(int argc, char ** argv, void **a_str_reply) } else { dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_DAG_GLOBALDB_ERR, "%s.%s: Error! No GlobalDB group!\n", l_net->pub.name, l_chain->name); ret = -2; - } json_object_array_add(*json_arr_reply, json_obj_event_list); } else if (!l_from_events_str || (strcmp(l_from_events_str,"events") == 0)) { pthread_mutex_lock(&PVT(l_dag)->events_mutex); size_t l_arr_start = 0; - if (l_offset > 0) { - l_arr_start = l_offset; - } - size_t l_arr_end = HASH_COUNT(PVT(l_dag)->events); - if (l_limit) { - l_arr_end = l_arr_start + l_limit; - if (l_arr_end > HASH_COUNT(PVT(l_dag)->events)) - l_arr_end = HASH_COUNT(PVT(l_dag)->events); - } + size_t l_arr_end = 0; + s_set_offset_limit_json(json_arr_obj_event, &l_arr_start, &l_arr_end, l_limit, l_offset, HASH_COUNT(PVT(l_dag)->events)); + size_t i_tmp = 0; dap_chain_cs_dag_event_item_t * l_event_item = NULL,*l_event_item_tmp = NULL; - HASH_ITER(hh,PVT(l_dag)->events,l_event_item, l_event_item_tmp ) { - if (i_tmp < l_arr_start || i_tmp >= l_arr_end) { - i_tmp++; - } else { - json_object * json_obj_event_i = json_object_new_object(); - i_tmp++; - char buf[DAP_TIME_STR_SIZE]; - dap_time_to_str_rfc822(buf, DAP_TIME_STR_SIZE, l_event_item->ts_created); - json_object_object_add(json_obj_event_i, "#", json_object_new_string(dap_itoa(i_tmp))); - json_object_object_add(json_obj_event_i, "hash", json_object_new_string(dap_chain_hash_fast_to_str_static(&l_event_item->hash))); - json_object_object_add(json_obj_event_i, "ts_create", json_object_new_string(buf)); - json_object_array_add(json_arr_obj_event, json_obj_event_i); + if (l_head){ + HASH_ITER(hh, PVT(l_dag)->events, l_event_item, l_event_item_tmp) { + if (i_tmp < l_arr_start || i_tmp >= l_arr_end) { + i_tmp++; + } else { + i_tmp++; + s_json_dag_pack_event(json_arr_obj_event, l_event_item, i_tmp); + } } } + else { + l_event_item = HASH_LAST(PVT(l_dag)->events); + for(; l_event_item; l_event_item = l_event_item->hh.prev){ + if (i_tmp < l_arr_start || i_tmp >= l_arr_end) { + i_tmp++; + } else { + i_tmp++; + s_json_dag_pack_event(json_arr_obj_event, l_event_item, i_tmp); + } + } + } + json_object_object_add(json_obj_event_list, "EVENTS", json_arr_obj_event); size_t l_events_count = HASH_COUNT(PVT(l_dag)->events); pthread_mutex_unlock(&PVT(l_dag)->events_mutex); @@ -1759,29 +1769,30 @@ static int s_cli_dag(int argc, char ** argv, void **a_str_reply) pthread_mutex_lock(&PVT(l_dag)->events_mutex); dap_chain_cs_dag_event_item_t * l_event_item = NULL,*l_event_item_tmp = NULL; size_t l_arr_start = 0; - if (l_offset) { - l_arr_start = l_offset; - } - size_t l_arr_end = HASH_COUNT(PVT(l_dag)->events_treshold); - if (l_limit) { - l_arr_end = l_arr_start + l_limit; - if (l_arr_end > HASH_COUNT(PVT(l_dag)->events_treshold)) - l_arr_end = HASH_COUNT(PVT(l_dag)->events_treshold); - } + size_t l_arr_end = 0; + s_set_offset_limit_json(json_arr_obj_event, &l_arr_start, &l_arr_end, l_limit, l_offset, HASH_COUNT(PVT(l_dag)->events_treshold)); + size_t i_tmp = 0; - HASH_ITER(hh,PVT(l_dag)->events_treshold,l_event_item, l_event_item_tmp ) { - if (i_tmp < l_arr_start || i_tmp > l_arr_end) { - i_tmp++; - continue; + if (l_head){ + HASH_ITER(hh, PVT(l_dag)->events_treshold, l_event_item, l_event_item_tmp) { + if (i_tmp < l_arr_start || i_tmp >= l_arr_end) { + i_tmp++; + } else { + i_tmp++; + s_json_dag_pack_event(json_arr_obj_event, l_event_item, i_tmp); + } + } + } + else { + l_event_item = HASH_LAST(PVT(l_dag)->events); + for(; l_event_item; l_event_item = l_event_item->hh.prev){ + if (i_tmp < l_arr_start || i_tmp >= l_arr_end) { + i_tmp++; + } else { + i_tmp++; + s_json_dag_pack_event(json_arr_obj_event, l_event_item, i_tmp); + } } - i_tmp++; - json_object * json_obj_event_i = json_object_new_object(); - char buf[DAP_TIME_STR_SIZE]; - dap_time_to_str_rfc822(buf, DAP_TIME_STR_SIZE, l_event_item->ts_created); - json_object_object_add(json_obj_event_i, "#", json_object_new_string(dap_itoa(i_tmp))); - json_object_object_add(json_obj_event_i, "hash", json_object_new_string(dap_chain_hash_fast_to_str_static(&l_event_item->hash))); - json_object_object_add(json_obj_event_i, "ts_create", json_object_new_string(buf)); - json_object_array_add(json_arr_obj_event, json_obj_event_i); } json_object_object_add(json_obj_event_list, "TRESHOLD", json_arr_obj_event); size_t l_events_count = HASH_COUNT(PVT(l_dag)->events_treshold); @@ -1849,10 +1860,13 @@ static int s_cli_dag(int argc, char ** argv, void **a_str_reply) // dap_chain_cs_dag_event_item_t *l_curr_event = PVT(l_dag)->events; dap_chain_cs_dag_event_item_t *l_curr_event = NULL, *l_temp; json_object* json_arr_bl_cache_out = json_object_new_array(); + json_object* json_obj_event = NULL; // for (;l_curr_event;l_curr_event = l_curr_event->hh.next) - HASH_ITER(hh, PVT(l_dag)->events, l_curr_event, l_temp){ + HASH_ITER(hh, PVT(l_dag)->events, l_curr_event, l_temp){ if (l_curr_event && dap_hash_fast_compare(&l_datum_hash, &l_curr_event->datum_hash)){ - json_object_array_add(json_arr_bl_cache_out, json_object_new_string(dap_hash_fast_to_str_static(&l_curr_event->hash))); + json_obj_event = json_object_new_object(); + json_object_object_add(json_obj_event, "event hash", json_object_new_string(dap_hash_fast_to_str_static(&l_curr_event->hash))); + json_object_array_add(json_arr_bl_cache_out, json_obj_event); l_atoms_cnt++; } }