From fc69de9b70c0752af1226c9ae60acd7b12612a50 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Al=D0=B5x=D0=B0nder=20Lysik=D0=BEv?=
 <alexander.lysikov@demlabs.net>
Date: Fri, 23 Aug 2019 11:23:16 +0500
Subject: [PATCH] added 'global_db cells' command fixed 'tx_history' command
 (added support plasma and zerochain)

---
 dap_chain_net.c             |  32 +++++++----
 dap_chain_net.h             |   2 +-
 dap_chain_node_cli.c        |  10 ++--
 dap_chain_node_cli_cmd.c    | 107 +++++++++++++++++++++++++++++++++---
 dap_chain_node_cli_cmd_tx.c |  22 +++-----
 5 files changed, 134 insertions(+), 39 deletions(-)

diff --git a/dap_chain_net.c b/dap_chain_net.c
index 728ca12304..17adfdd236 100644
--- a/dap_chain_net.c
+++ b/dap_chain_net.c
@@ -309,7 +309,6 @@ lb_proc_state:
                     if(!PVT(l_net)->links_addrs_count){
                         PVT(l_net)->links_addrs = DAP_NEW_Z_SIZE(dap_chain_node_addr_t,
                                 min(1, PVT(l_net)->seed_aliases_count) * sizeof(dap_chain_node_addr_t));
-
                         for(uint16_t i = 0; i < min(1, PVT(l_net)->seed_aliases_count); i++) {
                             dap_chain_node_addr_t * l_node_addr = dap_chain_node_alias_find(l_net, PVT(l_net)->seed_aliases[i]);
                             if(l_node_addr) {
@@ -756,7 +755,10 @@ static dap_chain_net_t *s_net_new(const char * a_id, const char * a_name ,
  */
 void dap_chain_net_delete( dap_chain_net_t * a_net )
 {
-    if (PVT(a_net)->seed_aliases)
+    if(PVT(a_net)->seed_aliases) {
+        DAP_DELETE(PVT(a_net)->seed_aliases);
+        PVT(a_net)->seed_aliases = NULL;
+    }
     DAP_DELETE( PVT(a_net) );
 }
 
@@ -809,6 +811,7 @@ void dap_chain_net_load_all()
                 *l_dot_pos = '\0';
             s_net_load(l_dir_entry->d_name );
         }
+        closedir(l_net_dir);
     }
     DAP_DELETE (l_net_dir_str);
 }
@@ -1064,10 +1067,15 @@ int s_net_load(const char * a_net_name)
         }
         // init LEDGER model
         l_net->pub.ledger = dap_chain_ledger_create(l_ledger_flags);
-
         // Check if seed nodes are present in local db alias
-        PVT(l_net)->seed_aliases = dap_config_get_array_str( l_cfg , "general" ,"seed_nodes_aliases"
+        char **l_seed_aliases = dap_config_get_array_str( l_cfg , "general" ,"seed_nodes_aliases"
                                                              ,&PVT(l_net)->seed_aliases_count);
+        PVT(l_net)->seed_aliases = PVT(l_net)->seed_aliases_count>0 ?
+                                   (char **)DAP_NEW_SIZE(char**, sizeof(char*)*PVT(l_net)->seed_aliases_count) : NULL;
+        for(size_t i = 0; i < PVT(l_net)->seed_aliases_count; i++) {
+            PVT(l_net)->seed_aliases[i] = dap_strdup(l_seed_aliases[i]);
+        }
+
         uint16_t l_seed_nodes_addrs_len =0;
         char ** l_seed_nodes_addrs = dap_config_get_array_str( l_cfg , "general" ,"seed_nodes_addrs"
                                                              ,&l_seed_nodes_addrs_len);
@@ -1079,7 +1087,6 @@ int s_net_load(const char * a_net_name)
         const char * l_node_ipv4_str = dap_config_get_item_str(l_cfg , "general" ,"node-ipv4");
         const char * l_node_addr_str = dap_config_get_item_str(l_cfg , "general" ,"node-addr");
         const char * l_node_alias_str = dap_config_get_item_str(l_cfg , "general" , "node-alias");
-
         log_it (L_DEBUG, "Read %u aliases, %u address and %u ipv4 addresses, check them",
                 PVT(l_net)->seed_aliases_count,l_seed_nodes_addrs_len, l_seed_nodes_ipv4_len );
         for ( size_t i = 0; i < PVT(l_net)->seed_aliases_count &&
@@ -1118,13 +1125,14 @@ int s_net_load(const char * a_net_name)
                 }else
                     log_it(L_WARNING,"No address for seed node, can't populate global_db with it");
                 DAP_DELETE( l_node_info);
-            }else
+            }else{
                 log_it(L_DEBUG,"Seed alias %s is present",PVT(l_net)->seed_aliases[i]);
+                DAP_DELETE( l_seed_node_addr);
+            }
 
          }
-         DAP_DELETE( l_seed_nodes_ipv4);
-         DAP_DELETE(l_seed_nodes_addrs);
-
+         //DAP_DELETE( l_seed_nodes_ipv4);
+         //DAP_DELETE(l_seed_nodes_addrs);
         if ( l_node_addr_str || l_node_alias_str ){
             dap_chain_node_addr_t * l_node_addr;
             if ( l_node_addr_str == NULL)
@@ -1167,7 +1175,6 @@ int s_net_load(const char * a_net_name)
 
 
          }
-
         // Init chains
         //size_t l_chains_path_size =strlen(dap_config_path())+1+strlen(l_net->pub.name)+1+strlen("network")+1;
         //char * l_chains_path = DAP_NEW_Z_SIZE (char,l_chains_path_size);
@@ -1199,13 +1206,13 @@ int s_net_load(const char * a_net_name)
                 }
                 DAP_DELETE (l_entry_name);
             }
+            closedir(l_chains_dir);
         } else {
             log_it(L_ERROR,"Can't any chains for network %s",l_net->pub.name);
             PVT(l_net)->load_mode = false;
 
             return -2;
         }
-
         // Do specific role actions post-chain created
         switch ( PVT( l_net )->node_role.enums ) {
             case NODE_ROLE_ROOT_MASTER:{
@@ -1251,8 +1258,9 @@ int s_net_load(const char * a_net_name)
         // Start the proc thread
         s_net_proc_thread_start(l_net);
         log_it(L_NOTICE, "Сhain network \"%s\" initialized",l_net_item->name);
-        return 0;
+        dap_config_close(l_cfg);
     }
+    return 0;
 }
 
 /**
diff --git a/dap_chain_net.h b/dap_chain_net.h
index 5a5a5bbeb6..c757b610c4 100644
--- a/dap_chain_net.h
+++ b/dap_chain_net.h
@@ -102,7 +102,7 @@ void dap_chain_net_links_connect(dap_chain_net_t * a_net);
  */
 DAP_STATIC_INLINE char * dap_chain_net_get_gdb_group_mempool(dap_chain_t * l_chain)
 {
-    dap_chain_net_t * l_net = dap_chain_net_by_id(l_chain->net_id);
+    dap_chain_net_t * l_net = l_chain ? dap_chain_net_by_id(l_chain->net_id) : NULL;
     if ( l_net ) {
         const char c_mempool_group_str[]="mempool";
 		return dap_strdup_printf("%s.chain-%s.%s",l_net->pub.gdb_groups_prefix,l_chain->name,c_mempool_group_str);
diff --git a/dap_chain_node_cli.c b/dap_chain_node_cli.c
index 25ad232e87..d2d6537a2e 100644
--- a/dap_chain_node_cli.c
+++ b/dap_chain_node_cli.c
@@ -305,8 +305,10 @@ static void* thread_one_client_func(void *args)
                 char *str_reply = NULL;
                 if(l_cmd){
                     while(list) {
+                        char *str_cmd_prev = str_cmd;
                         str_cmd = dap_strdup_printf("%s;%s", str_cmd, list->data);
                         list = dap_list_next(list);
+                        DAP_DELETE(str_cmd_prev);
                     }
                     log_it(L_INFO, "execute command=%s", str_cmd);
                     // exec command
@@ -770,10 +772,10 @@ int dap_chain_node_cli_init(dap_config_t * g_config)
         return 0;
     }
 
-/*    dap_chain_node_cli_cmd_item_create("global_db", com_global_db, "Work with global database",
-                    "global_db cells add -cell <cell id> \n\n"
-            "global_db wallet_info set -addr <wallet address> -cell <cell id> \n\n"
-            );*/
+    dap_chain_node_cli_cmd_item_create("global_db", com_global_db, "Work with global database",
+            "global_db cells add -cell <cell id> \n\n"
+//                    "global_db wallet_info set -addr <wallet address> -cell <cell id> \n\n"
+            );
 
     dap_chain_node_cli_cmd_item_create("node", com_node, "Work with node",
             "node add  -net <net name> -addr {<node address> | -alias <node alias>} -cell <cell id>  {-ipv4 <ipv4 external address> | -ipv6 <ipv6 external address>}\n\n"
diff --git a/dap_chain_node_cli_cmd.c b/dap_chain_node_cli_cmd.c
index d394c6d86a..c1e9ca1012 100644
--- a/dap_chain_node_cli_cmd.c
+++ b/dap_chain_node_cli_cmd.c
@@ -632,8 +632,84 @@ static int node_info_dump_with_reply(dap_chain_net_t * a_net, dap_chain_node_add
  *
  * return 0 OK, -1 Err
  */
-/*
+
 int com_global_db(int a_argc, char ** a_argv, char **a_str_reply)
+{
+    enum {
+        CMD_NONE, CMD_NAME_CELL, CMD_ADD };
+    int arg_index = 1;
+    int cmd_name =  CMD_NONE;
+    // find 'cells' as first parameter only
+    arg_index = dap_chain_node_cli_find_option_val(a_argv, arg_index, min(a_argc, arg_index + 1), "cells", NULL);
+    if(arg_index)
+        cmd_name = CMD_NAME_CELL;
+    if(!arg_index || a_argc < 3) {
+        dap_chain_node_cli_set_reply_text(a_str_reply, "parameters are not valid");
+        return -1;
+    }
+    dap_chain_t * l_chain = NULL;
+    dap_chain_net_t * l_net = NULL;
+
+    if(dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index, a_argc, a_argv, a_str_reply, &l_chain, &l_net) < 0)
+        return -11;
+
+    const char *l_cell_str = NULL, *l_chain_str = NULL;
+    // find cell and chain
+    dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "-cell", &l_cell_str);
+    dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "-chain", &l_chain_str);
+
+    // Check for chain
+    if(!l_chain_str) {
+        dap_chain_node_cli_set_reply_text(a_str_reply, "%s requires parameter 'chain' to be valid");
+        return -12;
+    }
+
+    int arg_index_n = ++arg_index;
+    // find command (add, delete, etc) as second parameter only
+    int cmd_num = CMD_NONE;
+    switch (cmd_name) {
+    case CMD_NAME_CELL:
+        if((arg_index_n = dap_chain_node_cli_find_option_val(a_argv, arg_index, min(a_argc, arg_index + 1), "add", NULL))
+                != 0) {
+            cmd_num = CMD_ADD;
+        }
+        dap_chain_cell_id_t l_cell_id = { 0 };
+        if(l_cell_str) {
+            dap_digit_from_string(l_cell_str, (uint8_t*) &l_cell_id.raw, sizeof(l_cell_id.raw)); //DAP_CHAIN_CELL_ID_SIZE);
+        }
+
+        switch (cmd_num)
+        {
+        // add new node to global_db
+        case CMD_ADD:
+            if(!arg_index || a_argc < 7) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "invalid parameters");
+                return -1;
+            }
+            dap_chain_cell_t *l_cell = dap_chain_cell_create();
+            l_cell->chain = l_chain;
+            l_cell->id.uint64 = l_cell_id.uint64;
+            l_cell->file_storage_path = dap_strdup_printf("%0llx.dchaincell",l_cell->id.uint64);
+            int l_ret = dap_chain_cell_file_update(l_cell);
+            if(!l_ret)
+                dap_chain_node_cli_set_reply_text(a_str_reply, "cell added successfully");
+            else
+                dap_chain_node_cli_set_reply_text(a_str_reply, "can't create file for cell 0x%016X ( %s )",
+                        l_cell->id.uint64,l_cell->file_storage_path);
+            dap_chain_cell_delete(l_cell);
+            return l_ret;
+
+        //case CMD_NONE:
+        default:
+            dap_chain_node_cli_set_reply_text(a_str_reply, "command %s not recognized", a_argv[1]);
+            return -1;
+        }
+
+    }
+}
+
+/*
+int com_global_db_prev(int a_argc, char ** a_argv, char **a_str_reply)
 {
     enum {
         CMD_NONE, CMD_NAME_NODE, CMD_NAME_CELL, CMD_ADD, CMD_DEL, CMD_LINK    };
@@ -773,7 +849,8 @@ int com_global_db(int a_argc, char ** a_argv, char **a_str_reply)
         dap_chain_node_cli_set_reply_text(a_str_reply, "command %s not recognized", a_argv[1]);
         return -1;
     }
-}*/
+}
+ */
 
 /**
  * Node command
@@ -1558,11 +1635,16 @@ int dap_chain_node_cli_cmd_values_parse_net_chain(int *a_arg_index, int argc, ch
         if(l_chain_str) {
             if((*a_chain = dap_chain_net_get_chain_by_name(*a_net, l_chain_str)) == NULL) { // Can't find such chain
                 dap_chain_node_cli_set_reply_text(a_str_reply,
-                        "%s requires parameter 'chain' to be valid chain name in chain net %s",
+                        "%s requires parameter '-chain' to be valid chain name in chain net %s",
                         argv[0], l_net_str);
                 return -103;
             }
         }
+        else {
+            dap_chain_node_cli_set_reply_text(a_str_reply,
+                    "%s requires parameter '-chain'", argv[0]);
+            return -104;
+        }
     }
     return 0;
 
@@ -1788,6 +1870,8 @@ int com_mempool_list(int argc, char ** argv, char ** a_str_reply)
         for(dap_chain_type_t i = CHAIN_TYPE_FIRST+1; i < CHAIN_TYPE_LAST; i++) {
             if(!l_gdb_group_mempool){
                 l_chain = dap_chain_net_get_chain_by_chain_type(l_net, i);
+                if(!l_chain)
+                    continue;
                 l_gdb_group_mempool_tmp = dap_chain_net_get_gdb_group_mempool(l_chain);
             }
             size_t l_objs_size = 0;
@@ -1796,7 +1880,7 @@ int com_mempool_list(int argc, char ** argv, char ** a_str_reply)
                 dap_string_append_printf(l_str_tmp, "%s.%s: Found %u records :\n", l_net->pub.name, l_chain->name,
                         l_objs_size);
             else
-                dap_string_append_printf(l_str_tmp, "%s.%s: Found %u records\n", l_net->pub.name, l_chain->name);
+                dap_string_append_printf(l_str_tmp, "%s.%s: Not found records\n", l_net->pub.name, l_chain->name);
             for(size_t i = 0; i < l_objs_size; i++) {
                 dap_chain_datum_t * l_datum = (dap_chain_datum_t*) l_objs[i].value;
                 char buf[50];
@@ -1903,8 +1987,8 @@ int com_mempool_proc(int argc, char ** argv, char ** a_str_reply)
         size_t l_objs_size = 0;
         dap_global_db_obj_t * l_objs = dap_chain_global_db_gr_load(l_gdb_group_mempool_tmp, &l_objs_size);
         if(l_objs_size) {
-            dap_string_append_printf(l_str_tmp, "%s.%s: Found %u records :\n", l_net->pub.name, l_chain->name);
-
+            dap_string_append_printf(l_str_tmp, "%s.%s: Found %u records :\n", l_net->pub.name, l_chain->name,
+                    l_objs_size);
             size_t l_datums_size = l_objs_size;
             dap_chain_datum_t ** l_datums = DAP_NEW_Z_SIZE(dap_chain_datum_t*,
                     sizeof(dap_chain_datum_t*) * l_datums_size);
@@ -1947,7 +2031,7 @@ int com_mempool_proc(int argc, char ** argv, char ** a_str_reply)
             break;
     }
     dap_chain_node_cli_set_reply_text(a_str_reply, l_str_tmp->str);
-    dap_string_free(l_str_tmp, false);
+    dap_string_free(l_str_tmp, true);
     return 0;
 }
 
@@ -2212,11 +2296,13 @@ int com_token_emit(int argc, char ** argv, char ** str_reply)
     // Select chain network
     if(!l_net_str) {
         dap_chain_node_cli_set_reply_text(str_reply, "token_create requires parameter 'net'");
+        DAP_DELETE(l_addr);
         return -42;
     } else {
         if((l_net = dap_chain_net_by_name(l_net_str)) == NULL) { // Can't find such network
             dap_chain_node_cli_set_reply_text(str_reply,
                     "token_create requires parameter '-net' to be valid chain network name");
+            DAP_DELETE(l_addr);
             return -43;
         }
     }
@@ -2234,6 +2320,7 @@ int com_token_emit(int argc, char ** argv, char ** str_reply)
             dap_chain_node_cli_set_reply_text(str_reply,
                     "token_create requires parameter 'chain_emission' to be valid chain name in chain net %s",
                     l_net_str);
+            DAP_DELETE(l_addr);
             return -45;
         }
     }
@@ -2248,6 +2335,7 @@ int com_token_emit(int argc, char ** argv, char ** str_reply)
             dap_chain_node_cli_set_reply_text(str_reply,
                     "token_create requires parameter 'chain_emission' to be valid chain name in chain net %s",
                     l_net_str);
+            DAP_DELETE(l_addr);
             return -47;
         }
     }
@@ -2316,6 +2404,7 @@ int com_token_emit(int argc, char ** argv, char ** str_reply)
         return -1;
     }
     DAP_DELETE(l_key_str);
+    DAP_DELETE(l_datum_emission);
 
     // create first transaction (with tx_token)
     dap_chain_datum_tx_t *l_tx = DAP_NEW_Z_SIZE(dap_chain_datum_tx_t, sizeof(dap_chain_datum_tx_t));
@@ -2335,6 +2424,7 @@ int com_token_emit(int argc, char ** argv, char ** str_reply)
         if(dap_chain_datum_tx_add_sign_item(&l_tx, l_certs[i]->enc_key) < 0) {
             dap_chain_node_cli_set_reply_text(str_reply, "No private key for certificate=%s",
                     l_certs[i]->name);
+            DAP_DELETE(l_addr);
             return -3;
         }
     }
@@ -2371,7 +2461,8 @@ int com_token_emit(int argc, char ** argv, char ** str_reply)
     }
     DAP_DELETE(str_reply_tmp);
     DAP_DELETE(l_key_str);
-
+    DAP_DELETE(l_datum_tx);
+    DAP_DELETE(l_addr);
     return 0;
 }
 
diff --git a/dap_chain_node_cli_cmd_tx.c b/dap_chain_node_cli_cmd_tx.c
index dc4c118103..dee80f84b2 100644
--- a/dap_chain_node_cli_cmd_tx.c
+++ b/dap_chain_node_cli_cmd_tx.c
@@ -51,7 +51,7 @@ typedef struct dap_tx_data {
     UT_hash_handle hh;
 } dap_tx_data_t;
 
-static char* dap_db_new_history_timestamp()
+/*static char* dap_db_new_history_timestamp()
 {
     static pthread_mutex_t s_mutex = PTHREAD_MUTEX_INITIALIZER;
     // get unique key
@@ -68,7 +68,7 @@ static char* dap_db_new_history_timestamp()
     char *l_str = dap_strdup_printf("%lld_%lld", (uint64_t) l_cur_time, s_suffix);
     pthread_mutex_unlock(&s_mutex);
     return l_str;
-}
+}*/
 
 // for dap_db_history_tx & dap_db_history_addr()
 static dap_chain_datum_t* get_prev_tx(dap_tx_data_t *a_tx_data)
@@ -134,7 +134,6 @@ char* dap_db_history_tx(dap_chain_hash_fast_t* a_tx_hash, dap_chain_t * a_chain)
                 // save token name
                 if(l_list_tx_token) {
                     dap_chain_tx_token_t *tk = l_list_tx_token->data;
-                    int d = sizeof(l_tx_data->token_ticker);
                     memcpy(l_tx_data->token_ticker, tk->header.ticker, sizeof(l_tx_data->token_ticker));
                 }
                 // take token from prev out item
@@ -187,14 +186,11 @@ char* dap_db_history_tx(dap_chain_hash_fast_t* a_tx_hash, dap_chain_t * a_chain)
         // found a_tx_hash now
 
         // transaction time
-        char *l_time_str = NULL;
         if(l_tx->header.ts_created > 0) {
             time_t rawtime = (time_t) l_tx->header.ts_created;
-            struct tm * timeinfo;
-            timeinfo = localtime(&rawtime);
-            if(timeinfo) {
-                dap_string_append_printf(l_str_out, " %s", asctime(timeinfo));
-            }
+            struct tm l_timeinfo = {0};
+            localtime_r(&rawtime, &l_timeinfo);
+            dap_string_append_printf(l_str_out, " %s", asctime(&l_timeinfo));
         }
 
         // find all OUT items in transaction
@@ -301,7 +297,6 @@ char* dap_db_history_addr(dap_chain_addr_t * a_addr, dap_chain_t * a_chain)
 {
     dap_string_t *l_str_out = dap_string_new(NULL);
 
-    bool l_tx_hash_found = false;
     dap_tx_data_t *l_tx_data_hash = NULL;
     // load transactions
     dap_chain_atom_iter_t *l_atom_iter = a_chain->callback_atom_iter_create(a_chain);
@@ -309,15 +304,15 @@ char* dap_db_history_addr(dap_chain_addr_t * a_addr, dap_chain_t * a_chain)
     size_t l_atom_size = a_chain->callback_atom_get_size(l_atom);
 
     while(l_atom && l_atom_size) {
-        dap_chain_datum_t *l_datum = (dap_chain_datum_t*) l_atom;
-        if(!l_datum && l_datum->header.type_id != DAP_CHAIN_DATUM_TX) {
+        dap_chain_datum_t *l_datum = a_chain->callback_atom_get_datum ? a_chain->callback_atom_get_datum(l_atom) : (dap_chain_datum_t*)l_atom;
+        if(!l_datum || l_datum->header.type_id != DAP_CHAIN_DATUM_TX) {
             // go to next transaction
             l_atom = a_chain->callback_atom_iter_get_next(l_atom_iter);
             l_atom_size = a_chain->callback_atom_get_size(l_atom);
             continue;
         }
-        dap_tx_data_t *l_tx_data = NULL;
 
+        dap_tx_data_t *l_tx_data = NULL;
         // transaction
         dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t*) l_datum->data;
         dap_list_t *l_records_out = NULL;
@@ -360,7 +355,6 @@ char* dap_db_history_addr(dap_chain_addr_t * a_addr, dap_chain_t * a_chain)
                 // save token name
                 if(l_tx_data && l_list_tx_token) {
                     dap_chain_tx_token_t *tk = l_list_tx_token->data;
-                    int d = sizeof(l_tx_data->token_ticker);
                     memcpy(l_tx_data->token_ticker, tk->header.ticker, sizeof(l_tx_data->token_ticker));
                 }
                 HASH_ADD(hh, l_tx_data_hash, tx_hash, sizeof(dap_chain_hash_fast_t), l_tx_data);
-- 
GitLab