From 46a382ad02a711b3c10bafcdf8039c56d3b5b602 Mon Sep 17 00:00:00 2001
From: Dmitriy Gerasimov <naeper@demlabs.net>
Date: Sun, 12 May 2019 20:33:46 +0700
Subject: [PATCH] [*] Fixed token_emission command

---
 dap_chain_net.c          | 84 ++++++++++++++++++++++++++++++++++------
 dap_chain_net.h          |  4 +-
 dap_chain_node_cli_cmd.c | 65 ++++++++++++++++++++-----------
 3 files changed, 116 insertions(+), 37 deletions(-)

diff --git a/dap_chain_net.c b/dap_chain_net.c
index 47b5f527bf..ca6cf96f5c 100644
--- a/dap_chain_net.c
+++ b/dap_chain_net.c
@@ -55,10 +55,11 @@
 typedef struct dap_chain_net_pvt{
     pthread_t proc_tid;
     pthread_cond_t proc_cond;
+    pthread_mutex_t proc_mutex;
     dap_chain_node_role_t node_role;
     uint8_t padding[4];
 
-    dap_chain_node_client_t * clients_by_node_addr;
+    dap_chain_node_client_t * links_by_node_addr;
     dap_chain_node_client_t * clients_by_ipv4;
     dap_chain_node_client_t * clients_by_ipv6;
     size_t clients_count;
@@ -80,11 +81,9 @@ typedef struct dap_chain_net_item{
 static dap_chain_net_item_t * s_net_items = NULL;
 static dap_chain_net_item_t * s_net_items_ids = NULL;
 
-static pthread_cond_t    s_net_proc_loop_cond = PTHREAD_COND_INITIALIZER;
-static pthread_mutex_t    s_net_proc_loop_mutex = PTHREAD_MUTEX_INITIALIZER;
 
 static const char * c_net_states[]={
-    [NET_STATE_BEGIN] = "NET_STATE_BEGIN",
+    [NET_STATE_OFFLINE] = "NET_STATE_OFFLINE",
     [NET_STATE_LINKS_CONNECTING] = "NET_STATE_LINKS_CONNECTING",
     [NET_STATE_LINKS_ESTABLISHED]= "NET_STATE_LINKS_ESTABLISHED",
     [NET_STATE_SYNC_GDB]= "NET_STATE_SYNC_GDB",
@@ -134,8 +133,8 @@ static int s_net_states_proc(dap_chain_net_t * l_net)
 {
     int ret=0;
     switch ( PVT(l_net)->state ){
-        case NET_STATE_BEGIN:{
-            if ( PVT(l_net)->state_target != NET_STATE_BEGIN ){
+        case NET_STATE_OFFLINE:{
+            if ( PVT(l_net)->state_target != NET_STATE_OFFLINE ){
 
             }
         }break;
@@ -171,10 +170,11 @@ static void * s_net_proc_thread ( void * a_net)
     dap_chain_net_t * l_net = (dap_chain_net_t *) a_net;
     bool is_looping = true ;
     while( is_looping ) {
-        pthread_mutex_lock(&s_net_proc_loop_mutex);
-        pthread_cond_wait(&s_net_proc_loop_cond,&s_net_proc_loop_mutex);
-        pthread_mutex_unlock(&s_net_proc_loop_mutex);
+        pthread_mutex_lock( &PVT(l_net)->proc_mutex );
+        pthread_cond_wait(&PVT(l_net)->proc_cond,&PVT(l_net)->proc_mutex);
+        pthread_mutex_unlock( &PVT(l_net)->proc_mutex );
         log_it( L_DEBUG, "Waked up net proc thread");
+
         s_net_states_proc(l_net);
     }
     return NULL;
@@ -219,7 +219,8 @@ static dap_chain_net_t * s_net_new(const char * a_id, const char * a_name ,
 {
     dap_chain_net_t * ret = DAP_NEW_Z_SIZE (dap_chain_net_t, sizeof (ret->pub)+ sizeof (dap_chain_net_pvt_t) );
     ret->pub.name = strdup( a_name );
-
+    pthread_mutex_init( &PVT(ret)->proc_mutex, NULL);
+    pthread_cond_init( &PVT(ret)->proc_cond, NULL);
     if ( sscanf(a_id,"0x%016lx", &ret->pub.id.uint64 ) == 1 ){
         if (strcmp (a_node_role, "root_master")==0){
             PVT(ret)->node_role.enums = NODE_ROLE_ROOT_MASTER;
@@ -280,7 +281,10 @@ int dap_chain_net_init()
 {
     dap_chain_node_cli_cmd_item_create ("net", s_cli_net, "Network commands",
         "net -net <chain net name> sync < all | gdb | chains >\n"
-            "\tSyncronyze gdb, chains or everything\n\n" );
+            "\tSyncronyze gdb, chains or everything\n\n"
+        "net -net <chain net name> link < list | add | del | info | establish >\n"
+            "\tList,add,del, dump or establish links\n\n"
+                                        );
 
 }
 
@@ -291,9 +295,65 @@ int dap_chain_net_init()
  * @param str_reply
  * @return
  */
-static int s_cli_net(int argc, const char ** argv, char **str_reply)
+static int s_cli_net(int argc, const char ** argv, char **a_str_reply)
 {
+    int arg_index=1;
+    dap_chain_net_t * l_net;
+    int ret = dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index,argc,argv,a_str_reply,NULL,&l_net);
+    if ( l_net ){
+        const char * l_sync_str = NULL;
+        const char * l_links_str = NULL;
+        dap_chain_node_cli_find_option_val(argv, arg_index, argc, "sync", &l_sync_str);
+        dap_chain_node_cli_find_option_val(argv, arg_index, argc, "link", &l_links_str);
+
+        if ( l_links_str ){
+            if ( strcmp(l_links_str,"list") == 0 ) {
+
+            } else if ( strcmp(l_links_str,"add") == 0 ) {
+
+            } else if ( strcmp(l_links_str,"del") == 0 ) {
+
+            }  else if ( strcmp(l_links_str,"info") == 0 ) {
+
+            } else if ( strcmp (l_links_str,"disconnect_all") == 0 ){
+                ret = 0;
+                dap_chain_net_stop(l_net);
+            }else {
+                dap_chain_node_cli_set_reply_text(a_str_reply,
+                                                  "Subcommand \"link\" requires one of parameter: list\n");
+                ret = -3;
+            }
+
+        } else if( l_sync_str) {
+            if ( strcmp(l_sync_str,"all") == 0 ) {
+                dap_chain_node_cli_set_reply_text(a_str_reply,
+                                                  "SYNC_ALL state requested to state machine. Current state: %s\n",
+                                                  c_net_states[ PVT(l_net)->state] );
+                dap_chain_net_sync_all(l_net);
+            } else if ( strcmp(l_sync_str,"gdb") == 0) {
+                dap_chain_node_cli_set_reply_text(a_str_reply,
+                                                  "SYNC_GDB state requested to state machine. Current state: %s\n",
+                                                  c_net_states[ PVT(l_net)->state] );
+                dap_chain_net_sync_gdb(l_net);
+
+            }  else if ( strcmp(l_sync_str,"chains") == 0) {
+                dap_chain_node_cli_set_reply_text(a_str_reply,
+                                                  "SYNC_CHAINS state requested to state machine. Current state: %s\n",
+                                                  c_net_states[ PVT(l_net)->state] );
+                dap_chain_net_sync_chains(l_net);
+
+            } else {
+                dap_chain_node_cli_set_reply_text(a_str_reply,
+                                                  "Subcommand \"sync\" requires one of parameter: all,gdb,chains\n");
+                ret = -2;
+            }
+        } else {
+            dap_chain_node_cli_set_reply_text(a_str_reply,"Command requires one of subcomand: sync, links\n");
+            ret = -1;
+        }
 
+    }
+    return  ret;
 }
 
 
diff --git a/dap_chain_net.h b/dap_chain_net.h
index ab49382ae0..042d13f772 100644
--- a/dap_chain_net.h
+++ b/dap_chain_net.h
@@ -34,7 +34,7 @@
 #define DAP_CHAIN_NET_NAME_MAX 32
 
 typedef  enum dap_chain_net_state{
-    NET_STATE_BEGIN = 0,
+    NET_STATE_OFFLINE = 0,
     NET_STATE_LINKS_CONNECTING,
     NET_STATE_LINKS_ESTABLISHED,
     NET_STATE_SYNC_GDB,
@@ -63,7 +63,7 @@ int dap_chain_net_load(const char * a_net_name);
 int dap_chain_net_state_go_to(dap_chain_net_t * a_net, dap_chain_net_state_t a_new_state);
 
 inline static int dap_chain_net_start(dap_chain_net_t * a_net){ return dap_chain_net_state_go_to(a_net,NET_STATE_SYNC_ALL); }
-inline static int dap_chain_net_stop(dap_chain_net_t * a_net) { return dap_chain_net_state_go_to(a_net,NET_STATE_BEGIN); }
+inline static int dap_chain_net_stop(dap_chain_net_t * a_net) { return dap_chain_net_state_go_to(a_net,NET_STATE_OFFLINE); }
 inline static int dap_chain_net_links_establish(dap_chain_net_t * a_net) { return dap_chain_net_state_go_to(a_net,NET_STATE_LINKS_ESTABLISHED); }
 inline static int dap_chain_net_sync_chains(dap_chain_net_t * a_net) { return dap_chain_net_state_go_to(a_net,NET_STATE_SYNC_CHAINS); }
 inline static int dap_chain_net_sync_gdb(dap_chain_net_t * a_net) { return dap_chain_net_state_go_to(a_net,NET_STATE_SYNC_GDB); }
diff --git a/dap_chain_node_cli_cmd.c b/dap_chain_node_cli_cmd.c
index 79a686eef4..386b921553 100644
--- a/dap_chain_node_cli_cmd.c
+++ b/dap_chain_node_cli_cmd.c
@@ -1394,27 +1394,28 @@ int dap_chain_node_cli_cmd_values_parse_net_chain(int *a_arg_index,int argc, con
     else
        return -100;
 
-    // Select chain network
+    // Select network
     if(!l_net_str) {
         dap_chain_node_cli_set_reply_text(a_str_reply, "%s requires parameter 'net'",argv[0]);
-        return -42;
+        return -101;
     }
-    // Chain name
-    if ( a_chain )
-        dap_chain_node_cli_find_option_val(argv, *a_arg_index, argc, "-chain", &l_chain_str);
 
     if ( ( *a_net  = dap_chain_net_by_name(l_net_str) ) == NULL ){ // Can't find such network
         dap_chain_node_cli_set_reply_text(a_str_reply, "%s cand find network \"%s\"",argv[0],l_net_str);
-        return -43;
+        return -102;
     }
 
+    // Chain name
+    if ( a_chain ){
+        dap_chain_node_cli_find_option_val(argv, *a_arg_index, argc, "-chain", &l_chain_str);
 
-    // Select chain
-    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",
-                                              argv[0] , l_net_str);
-            return -45;
+        // Select chain
+        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",
+                                                  argv[0] , l_net_str);
+                return -103;
+            }
         }
     }
     return  0;
@@ -1858,8 +1859,11 @@ int com_token_emit(int argc, const char ** argv, char ** str_reply)
     dap_chain_cert_t ** l_certs = NULL;
     size_t l_certs_size = 0;
 
-    const char * l_chain_str = NULL;
-    dap_chain_t * l_chain;
+    const char * l_chain_emission_str = NULL;
+    dap_chain_t * l_chain_emission = NULL;
+
+    const char * l_chain_base_tx_str = NULL;
+    dap_chain_t * l_chain_base_tx = NULL;
 
     const char * l_net_str = NULL;
     dap_chain_net_t * l_net = NULL;
@@ -1916,7 +1920,6 @@ int com_token_emit(int argc, const char ** argv, char ** str_reply)
         return -4;
     }
 
-
     // Select chain network
     if(!l_net_str) {
         dap_chain_node_cli_set_reply_text(str_reply, "token_create requires parameter 'net'");
@@ -1928,19 +1931,35 @@ int com_token_emit(int argc, const char ** argv, char ** str_reply)
         }
     }
 
-    // Select chain
-    if(!l_chain_str) {
-        dap_chain_node_cli_set_reply_text(str_reply, "token_create requires parameter 'chain'");
+
+    dap_chain_node_cli_find_option_val(argv, arg_index, argc, "chain_emission", &l_chain_emission_str);
+    dap_chain_node_cli_find_option_val(argv, arg_index, argc, "chain_base_tx", &l_chain_base_tx_str);
+
+    // Select chain emission
+    if(!l_chain_emission_str) {
+        dap_chain_node_cli_set_reply_text(str_reply, "token_create requires parameter 'chain_emission'");
         return -44;
     }else {
-        if ( ( l_chain  = dap_chain_net_get_chain_by_name(l_net, l_chain_str ) ) == NULL ){ // Can't find such chain
-            dap_chain_node_cli_set_reply_text(str_reply, "token_create requires parameter 'chain' to be valid chain name in chain net %s",l_net_str);
+        if ( ( l_chain_emission  = dap_chain_net_get_chain_by_name(l_net, l_chain_emission_str ) ) == NULL ){ // Can't find such chain
+            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);
             return -45;
         }
     }
 
+    // Select chain emission
+    if(!l_chain_base_tx_str) {
+        dap_chain_node_cli_set_reply_text(str_reply, "token_create requires parameter 'chain_base_tx'");
+        return -46;
+    }else {
+        if ( ( l_chain_base_tx  = dap_chain_net_get_chain_by_name(l_net, l_chain_base_tx_str ) ) == NULL ){ // Can't find such chain
+            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);
+            return -47;
+        }
+    }
+
     // Get mempool group for this chain
-    char * l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool(l_chain);
+    char * l_gdb_group_mempool_emission = dap_chain_net_get_gdb_group_mempool(l_chain_emission);
+    char * l_gdb_group_mempool_base_tx = dap_chain_net_get_gdb_group_mempool(l_chain_base_tx);
 
 
     // Create emission datum
@@ -1963,7 +1982,7 @@ int com_token_emit(int argc, const char ** argv, char ** str_reply)
 
     // Add to mempool emission token
     if(dap_chain_global_db_gr_set(l_key_str, (uint8_t *) l_datum_emission, l_datum_emission_size
-            , l_gdb_group_mempool)) {
+            , l_gdb_group_mempool_emission)) {
         str_reply_tmp = dap_strdup_printf("datum emission %s is placed in datum pool ", l_key_str);
     }
     else{
@@ -2009,7 +2028,7 @@ int com_token_emit(int argc, const char ** argv, char ** str_reply)
 
     // Add to mempool tx token
     if(dap_chain_global_db_gr_set(l_key_str, (uint8_t *) l_datum_tx, l_datum_tx_size
-            , l_gdb_group_mempool)) {
+            , l_gdb_group_mempool_base_tx)) {
         dap_chain_node_cli_set_reply_text(str_reply, "%s\ndatum tx %s is placed in datum pool ", str_reply_tmp, l_key_str);
     }
     else{
-- 
GitLab