From d983e88168b3ee3001936005931dbce6088411fd Mon Sep 17 00:00:00 2001
From: "roman.padenkov" <roman.padenkov@demlabs.net>
Date: Tue, 11 Mar 2025 09:32:18 +0000
Subject: [PATCH] Feature 16131

---
 dap-sdk                                       |  2 +-
 modules/type/blocks/dap_chain_cs_blocks.c     | 85 ++++++++++++++-----
 .../blocks/include/dap_chain_block_cache.h    |  2 +-
 3 files changed, 64 insertions(+), 25 deletions(-)

diff --git a/dap-sdk b/dap-sdk
index d9b03ffb93..a7b6da64ee 160000
--- a/dap-sdk
+++ b/dap-sdk
@@ -1 +1 @@
-Subproject commit d9b03ffb93d4003cb1a33c6470612a7f88ad6005
+Subproject commit a7b6da64ee24a3aba64dcbbd5f3f356069d853ad
diff --git a/modules/type/blocks/dap_chain_cs_blocks.c b/modules/type/blocks/dap_chain_cs_blocks.c
index 52927f3c92..cc844a27f6 100644
--- a/modules/type/blocks/dap_chain_cs_blocks.c
+++ b/modules/type/blocks/dap_chain_cs_blocks.c
@@ -68,6 +68,7 @@ typedef struct dap_chain_cs_blocks_pvt {
 
     // All the blocks are here
     dap_chain_block_cache_t *blocks;
+    dap_chain_block_cache_t *blocks_num;
     _Atomic uint64_t blocks_count;
 
     // Brnches and forks
@@ -207,7 +208,7 @@ int dap_chain_cs_blocks_init()
                 "\t\tComplete the current new round, verify it and if everything is ok - publish new blocks in chain\n\n"
 
         "Blockchain explorer:\n"
-            "block -net <net_name> [-chain <chain_name>] dump -hash <block_hash>\n"
+            "block -net <net_name> [-chain <chain_name>] [-brief] dump {-hash <block_hash> | -num <block_number>}\n"
                 "\t\tDump block info\n\n"
 
             "block -net <net_name> [-chain <chain_name>] list [{signed | first_signed}] [-limit] [-offset] [-head]"
@@ -385,6 +386,21 @@ dap_chain_block_cache_t * dap_chain_block_cache_get_by_hash(dap_chain_cs_blocks_
     return l_ret;
 }
 
+/**
+ * @brief dap_chain_block_cache_get_by_number
+ * @param a_blocks
+ * @param a_block_number
+ * @return
+ */
+dap_chain_block_cache_t * dap_chain_block_cache_get_by_number(dap_chain_cs_blocks_t * a_blocks,  uint64_t a_block_number)
+{
+    dap_chain_block_cache_t * l_ret = NULL;
+    pthread_rwlock_rdlock(& PVT(a_blocks)->rwlock);
+    HASH_FIND_BYHASHVALUE(hh2, PVT(a_blocks)->blocks_num, &a_block_number, sizeof (a_block_number), a_block_number, l_ret);
+    pthread_rwlock_unlock(& PVT(a_blocks)->rwlock);
+    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)
@@ -760,7 +776,9 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply)
         case SUBCMD_DUMP:{
             const char *l_hash_out_type = NULL;
             const char *l_hash_str = NULL;
+            const char *l_num_str = NULL;
             dap_chain_hash_fast_t l_block_hash={0};
+            bool l_brief = (dap_cli_server_cmd_check_option(a_argv, arg_index, a_argc, "-brief") != -1) ? true : false;
             dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-H", &l_hash_out_type);
             if(!l_hash_out_type)
                 l_hash_out_type = "hex";
@@ -769,13 +787,21 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply)
                 return DAP_CHAIN_NODE_CLI_COM_BLOCK_PARAM_ERR;
             }           
             dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-hash", &l_hash_str);
-            if (!l_hash_str) {
-                dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_BLOCK_HASH_ERR, "Enter block hash ");
+            dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-num", &l_num_str);
+            if (!l_hash_str && !l_num_str) {
+                dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_BLOCK_HASH_ERR, "Enter block hash or block number");
                 return DAP_CHAIN_NODE_CLI_COM_BLOCK_HASH_ERR;
             }
 
             dap_chain_hash_fast_from_str(l_hash_str, &l_block_hash);
-            dap_chain_block_cache_t *l_block_cache = dap_chain_block_cache_get_by_hash(l_blocks, &l_block_hash);
+            dap_chain_block_cache_t *l_block_cache = NULL;
+            if (l_hash_str)
+                l_block_cache = dap_chain_block_cache_get_by_hash(l_blocks, &l_block_hash);
+            else {
+                uint16_t num = 0;
+                dap_digit_from_string(l_num_str, &num, sizeof(uint16_t));
+                l_block_cache = dap_chain_block_cache_get_by_number(l_blocks, num);
+            }
             if (!l_block_cache) {
                 dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_BLOCK_FIND_ERR, "Can't find block %s ", l_hash_str);
                 return DAP_CHAIN_NODE_CLI_COM_BLOCK_FIND_ERR;
@@ -786,7 +812,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_hash_str));
+            json_object_object_add(json_obj_inf, "hash", json_object_new_string(l_block_cache->block_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));
@@ -845,22 +871,30 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply)
                 json_object* json_obj_tx = json_object_new_object();
                 dap_chain_datum_t * l_datum = l_block_cache->datum[i];
                 size_t l_datum_size =  dap_chain_datum_size(l_datum);
-                json_object_object_add(json_obj_tx, "datum size ",json_object_new_uint64(l_datum_size));
-                if (l_datum_size < sizeof (l_datum->header) ){
-                    dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_BLOCK_DATUM_SIZE_ERR, "ERROR: datum size %zu is smaller than header size %zu \n",l_datum_size,
-                                            sizeof (l_datum->header));
-                    break;
-                }
-                // Nested datums
-                snprintf(l_hexbuf, sizeof(l_hexbuf), "0x%02X",l_datum->header.version_id);
-                json_object_object_add(json_obj_tx, "version",json_object_new_string(l_hexbuf));
-                const char * l_datum_type_str = "UNKNOWN";
-                DAP_DATUM_TYPE_STR(l_datum->header.type_id, l_datum_type_str);
-                json_object_object_add(json_obj_tx, "type_id",json_object_new_string(l_datum_type_str));
-                dap_time_to_str_rfc822(l_time_buf, DAP_TIME_STR_SIZE, l_datum->header.ts_create);
-                json_object_object_add(json_obj_tx, "ts_create",json_object_new_string(l_time_buf));
-                json_object_object_add(json_obj_tx, "data_size",json_object_new_int(l_datum->header.data_size));
-                dap_chain_datum_dump_json(*a_json_arr_reply, json_obj_tx,l_datum,l_hash_out_type,l_net->pub.id, true);
+                if (l_brief){
+                    const char *l_hash_str = dap_strcmp(l_hash_out_type, "hex")
+                            ? dap_enc_base58_encode_hash_to_str_static(&l_block_cache->datum_hash[i])
+                            : dap_chain_hash_fast_to_str_static(&l_block_cache->datum_hash[i]);
+                    json_object_object_add(json_obj_tx, "num",json_object_new_uint64(i));
+                    json_object_object_add(json_obj_tx, "hash",json_object_new_string(l_hash_str));
+                } else {
+                    json_object_object_add(json_obj_tx, "datum size ",json_object_new_uint64(l_datum_size));
+                    if (l_datum_size < sizeof (l_datum->header) ){
+                        dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_BLOCK_DATUM_SIZE_ERR, "ERROR: datum size %zu is smaller than header size %zu \n",l_datum_size,
+                                                sizeof (l_datum->header));
+                        break;
+                    }
+                    // Nested datums
+                    snprintf(l_hexbuf, sizeof(l_hexbuf), "0x%02X",l_datum->header.version_id);
+                    json_object_object_add(json_obj_tx, "version",json_object_new_string(l_hexbuf));
+                    const char * l_datum_type_str = "UNKNOWN";
+                    DAP_DATUM_TYPE_STR(l_datum->header.type_id, l_datum_type_str);
+                    json_object_object_add(json_obj_tx, "type_id",json_object_new_string(l_datum_type_str));
+                    dap_time_to_str_rfc822(l_time_buf, DAP_TIME_STR_SIZE, l_datum->header.ts_create);
+                    json_object_object_add(json_obj_tx, "ts_create",json_object_new_string(l_time_buf));
+                    json_object_object_add(json_obj_tx, "data_size",json_object_new_int(l_datum->header.data_size));
+                    dap_chain_datum_dump_json(*a_json_arr_reply, json_obj_tx,l_datum,l_hash_out_type,l_net->pub.id, true);
+                }                
                 json_object_array_add(json_arr_datum_out, json_obj_tx);
             }
             // Signatures
@@ -1526,6 +1560,7 @@ static void s_callback_cs_blocks_purge(dap_chain_t *a_chain)
         dap_chain_block_cache_delete(l_block);
     }
     PVT(l_blocks)->blocks_count = 0;
+    HASH_CLEAR(hh2, PVT(l_blocks)->blocks_num);
     pthread_rwlock_unlock(&PVT(l_blocks)->rwlock);
     
     dap_chain_block_datum_index_t *l_datum_index = NULL, *l_datum_index_tmp = NULL;
@@ -1704,7 +1739,8 @@ static bool s_select_longest_branch(dap_chain_cs_blocks_t * a_blocks, dap_chain_
         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){
             s_delete_atom_datums(l_blocks, l_last_new_forked_item->block_cache);
             --PVT(l_blocks)->blocks_count;
-            HASH_DEL(PVT(l_blocks)->blocks, l_last_new_forked_item->block_cache);
+            HASH_DEL(PVT(l_blocks)->blocks_num, l_last_new_forked_item->block_cache);
+            HASH_DELETE(hh2, PVT(l_blocks)->blocks, l_last_new_forked_item->block_cache);            
         }
 
         // Next we add all atoms from new main branch into blockchain 
@@ -1716,6 +1752,7 @@ static bool s_select_longest_branch(dap_chain_cs_blocks_t * a_blocks, dap_chain_
             dap_chain_block_cache_t *l_curr_atom = l_item->block_cache;
             ++PVT(l_blocks)->blocks_count;
             HASH_ADD(hh, PVT(l_blocks)->blocks, block_hash, sizeof(l_curr_atom->block_hash), l_curr_atom);
+            HASH_ADD_BYHASHVALUE(hh2, PVT(l_blocks)->blocks_num, block_number, sizeof(l_curr_atom->block_number), l_curr_atom->block_number, l_curr_atom);
             debug_if(s_debug_more, L_DEBUG, "Verified atom %p: ACCEPTED", l_curr_atom);
             s_add_atom_datums(l_blocks, l_curr_atom);
             dap_chain_atom_notify(a_cell, &l_curr_atom->block_hash, (byte_t*)l_curr_atom->block, l_curr_atom->block_size);
@@ -1785,6 +1822,7 @@ static dap_chain_atom_verify_res_t s_callback_atom_add(dap_chain_t * a_chain, da
             if (l_last_block && dap_hash_fast_compare(&l_last_block->block_hash, &l_block_prev_hash)){
                 ++PVT(l_blocks)->blocks_count;
                 HASH_ADD(hh, PVT(l_blocks)->blocks, block_hash, sizeof(l_block_cache->block_hash), l_block_cache);
+                HASH_ADD_BYHASHVALUE(hh2, PVT(l_blocks)->blocks_num, block_number, sizeof(l_block_cache->block_number), l_block_cache->block_number, l_block_cache);
                 debug_if(s_debug_more, L_DEBUG, "Verified atom %p: ACCEPTED", a_atom);
                 s_add_atom_datums(l_blocks, l_block_cache);
                 dap_chain_atom_notify(l_cell, &l_block_cache->block_hash, (byte_t*)l_block, a_atom_size);
@@ -1851,8 +1889,9 @@ static dap_chain_atom_verify_res_t s_callback_atom_add(dap_chain_t * a_chain, da
                 }
             }
 
-        } else {
+        } else {            
             HASH_ADD(hh, PVT(l_blocks)->blocks, block_hash, sizeof(l_block_cache->block_hash), l_block_cache);
+            HASH_ADD_BYHASHVALUE(hh2, PVT(l_blocks)->blocks_num, block_number, sizeof(l_block_cache->block_number), l_block_cache->block_number, l_block_cache);
             ++PVT(l_blocks)->blocks_count;
             debug_if(s_debug_more, L_DEBUG, "Verified atom %p: ACCEPTED", a_atom);
             s_add_atom_datums(l_blocks, l_block_cache);
diff --git a/modules/type/blocks/include/dap_chain_block_cache.h b/modules/type/blocks/include/dap_chain_block_cache.h
index 2a622f0a0a..3581489318 100644
--- a/modules/type/blocks/include/dap_chain_block_cache.h
+++ b/modules/type/blocks/include/dap_chain_block_cache.h
@@ -68,7 +68,7 @@ typedef struct dap_chain_block_cache {
     struct dap_chain_block_cache * next;
 
     // uthash handle
-    UT_hash_handle hh;
+    UT_hash_handle hh, hh2;
 } dap_chain_block_cache_t;
 
 typedef struct dap_chain_block_forked_branch_atoms_table{
-- 
GitLab