From a89d28d65a7e608b5ccb8e95616e27dea246ec93 Mon Sep 17 00:00:00 2001
From: Aleksey Feoktistov <aleksey@synestproject.com>
Date: Wed, 10 Nov 2021 23:45:25 +0500
Subject: [PATCH] features-3847

---
 modules/consensus/none/dap_chain_cs_none.c   |  4 +
 modules/net/dap_chain_net.c                  | 23 +++++
 modules/net/dap_chain_node_cli.c             |  9 +-
 modules/net/dap_chain_node_cli_cmd.c         | 96 ++++++++++++++++++++
 modules/net/include/dap_chain_net.h          |  1 +
 modules/net/include/dap_chain_node_cli_cmd.h |  3 +
 modules/type/dag/dap_chain_cs_dag.c          | 10 ++
 7 files changed, 145 insertions(+), 1 deletion(-)

diff --git a/modules/consensus/none/dap_chain_cs_none.c b/modules/consensus/none/dap_chain_cs_none.c
index 9f8939c1f3..caf9ab3ddb 100644
--- a/modules/consensus/none/dap_chain_cs_none.c
+++ b/modules/consensus/none/dap_chain_cs_none.c
@@ -332,6 +332,10 @@ static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_cha
             if(dap_chain_ledger_tx_load(a_chain->ledger, l_tx) != 1)
                 return ATOM_REJECT;
         }break;
+        case DAP_CHAIN_DATUM_CA:{
+            dap_cert_chain_file_save(l_datum, a_chain->net_name);
+            return ATOM_REJECT;
+        }break;
         default: return ATOM_REJECT;
     }
 
diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c
index 2658130cbc..b4a5144026 100644
--- a/modules/net/dap_chain_net.c
+++ b/modules/net/dap_chain_net.c
@@ -2963,3 +2963,26 @@ static uint8_t *dap_chain_net_set_acl(dap_chain_hash_fast_t *a_pkey_hash)
     }
     return NULL;
 }
+
+/**
+ * @brief dap_cert_chain_file_save
+ * @param datum
+ */
+int dap_cert_chain_file_save(dap_chain_datum_t * datum, char * net_name)
+{
+    const char * s_system_chain_ca_dir = dap_config_get_item_str(g_config, "resources", "chain_ca_folder");
+
+    dap_cert_t * cert = dap_cert_mem_load(datum->data, datum->header.data_size);
+    const char * cert_name = cert->name;
+
+    size_t cert_path_length = strlen(net_name)+strlen(cert_name)+9+strlen(s_system_chain_ca_dir);
+    char *cert_path = DAP_NEW_Z_SIZE(char,cert_path_length);
+
+    snprintf(cert_path,cert_path_length,"%s/%s/%s.dcert",s_system_chain_ca_dir,net_name,cert_name);
+
+//  if ( access( l_cert_path, F_OK ) != -1 ) {
+//      log_it (L_ERROR, "File %s is already exists.", l_cert_path);
+//      return -1;
+//  } else
+    return dap_cert_file_save(cert, cert_path);
+}
diff --git a/modules/net/dap_chain_node_cli.c b/modules/net/dap_chain_node_cli.c
index 45190dce94..09745c70f4 100644
--- a/modules/net/dap_chain_node_cli.c
+++ b/modules/net/dap_chain_node_cli.c
@@ -1071,6 +1071,13 @@ int dap_chain_node_cli_init(dap_config_t * g_config)
                                         "Add pubic certificate into the mempool to prepare its way to chains",
             "mempool_add_ca -net <net name> [-chain <chain name>] -ca_name <Certificate name>\n");
 
+    dap_chain_node_cli_cmd_item_create ("chain_ca_pub", com_chain_ca_pub,
+                                        "Add pubic certificate into the mempool to prepare its way to chains",
+            "chain_ca -net <net name> [-chain <chain name>] -ca_name <Certificate name>\n");
+
+    dap_chain_node_cli_cmd_item_create ("chain_ca_copy", com_chain_ca_copy,
+                                        "Copy pubic certificate into the mempool to prepare its way to chains",
+            "chain_ca -net <net name> [-chain <chain name>] -ca_name <Public certificate name>\n");
 
     // Transaction commands
     dap_chain_node_cli_cmd_item_create ("tx_create", com_tx_create, "Make transaction",
@@ -1135,7 +1142,7 @@ int dap_chain_node_cli_init(dap_config_t * g_config)
     if ( l_listen_unix_socket_path && l_listen_unix_socket_permissions ) {
         if ( l_listen_unix_socket_permissions_str ) {
             uint16_t l_perms;
-            dap_sscanf(l_listen_unix_socket_permissions_str,"%hu", &l_perms);
+            dap_sscanf(l_listen_unix_socket_permissions_str,"%ho", &l_perms);
             l_listen_unix_socket_permissions = l_perms;
         }
         log_it( L_INFO, "Console interace on path %s (%04o) ", l_listen_unix_socket_path, l_listen_unix_socket_permissions );
diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c
index 815826f3db..ff4ca0d020 100644
--- a/modules/net/dap_chain_node_cli_cmd.c
+++ b/modules/net/dap_chain_node_cli_cmd.c
@@ -3703,6 +3703,102 @@ int com_mempool_add_ca(int a_argc,  char ** a_argv, char ** a_str_reply)
     }
 }
 
+/**
+ * @brief com_chain_ca_copy
+ * @details copy public CA into the mempool
+ * @param a_argc
+ * @param a_argv
+ * @param a_arg_func
+ * @param a_str_reply
+ * @return
+ */
+int com_chain_ca_copy( int a_argc,  char ** a_argv, char ** a_str_reply)
+{
+    return com_mempool_add_ca(a_argc, a_argv, a_str_reply);
+}
+
+
+/**
+ * @brief com_chain_ca_pub
+ * @details place public CA into the mempool
+ * @param a_argc
+ * @param a_argv
+ * @param a_arg_func
+ * @param a_str_reply
+ * @return
+ */
+int com_chain_ca_pub( int a_argc,  char ** a_argv, char ** a_str_reply)
+{
+    int arg_index = 1;
+    // Read params
+    const char * l_ca_name = NULL;
+    dap_chain_net_t * l_net = NULL;
+    dap_chain_t * l_chain = NULL;
+
+    dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "-ca_name", &l_ca_name);
+    dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index,a_argc, a_argv, a_str_reply, &l_chain, &l_net);
+
+    dap_cert_t * l_cert = dap_cert_find_by_name( l_ca_name );
+    if( l_cert == NULL ){
+        dap_chain_node_cli_set_reply_text(a_str_reply,
+                "Can't find \"%s\" certificate", l_ca_name );
+        return -4;
+    }
+
+
+    if( l_cert->enc_key == NULL ){
+        dap_chain_node_cli_set_reply_text(a_str_reply,
+                "Corrupted certificate \"%s\" without keys certificate", l_ca_name );
+        return -5;
+    }
+
+    // Create empty new cert
+    dap_cert_t * l_cert_new = dap_cert_new(l_ca_name);
+    l_cert_new->enc_key = dap_enc_key_new( l_cert->enc_key->type);
+
+    // Copy only public key
+    l_cert_new->enc_key->pub_key_data = DAP_NEW_Z_SIZE(uint8_t,
+                                                      l_cert_new->enc_key->pub_key_data_size =
+                                                      l_cert->enc_key->pub_key_data_size );
+    memcpy(l_cert_new->enc_key->pub_key_data, l_cert->enc_key->pub_key_data,l_cert->enc_key->pub_key_data_size);
+
+    // Serialize certificate into memory
+    uint32_t l_cert_serialized_size = 0;
+    byte_t * l_cert_serialized = dap_cert_mem_save( l_cert_new, &l_cert_serialized_size );
+    if( l_cert_serialized == NULL){
+        dap_chain_node_cli_set_reply_text(a_str_reply,
+                "Can't serialize in memory certificate" );
+        return -7;
+    }
+    if( l_cert_serialized == NULL){
+        dap_chain_node_cli_set_reply_text(a_str_reply,
+                "Can't serialize in memory certificate");
+        return -7;
+    }
+    // Now all the chechs passed, forming datum for mempool
+    dap_chain_datum_t * l_datum = dap_chain_datum_create( DAP_CHAIN_DATUM_CA, l_cert_serialized , l_cert_serialized_size);
+    DAP_DELETE( l_cert_serialized);
+    if( l_datum == NULL){
+        dap_chain_node_cli_set_reply_text(a_str_reply,
+                "Can't produce datum from certificate");
+        return -7;
+    }
+
+    // Finaly add datum to mempool
+    char *l_hash_str = dap_chain_mempool_datum_add(l_datum,l_chain);
+    if (l_hash_str) {
+        dap_chain_node_cli_set_reply_text(a_str_reply,
+                "Datum %s was successfully placed to mempool", l_hash_str);
+        DAP_DELETE(l_hash_str);
+        return 0;
+    } else {
+        dap_chain_node_cli_set_reply_text(a_str_reply,
+                "Can't place certificate \"%s\" to mempool", l_ca_name);
+        DAP_DELETE( l_datum );
+        return -8;
+    }
+}
+
 
 /**
  * @brief Create transaction
diff --git a/modules/net/include/dap_chain_net.h b/modules/net/include/dap_chain_net.h
index bb7fe912de..98e6ceb072 100644
--- a/modules/net/include/dap_chain_net.h
+++ b/modules/net/include/dap_chain_net.h
@@ -181,3 +181,4 @@ void dap_chain_net_sync_gdb_broadcast(void *a_arg, const char a_op_code, const c
 struct dap_chain_node_client * dap_chain_net_client_create_n_connect( dap_chain_net_t * a_net, struct dap_chain_node_info *a_link_info);
 struct dap_chain_node_client * dap_chain_net_client_create_n_connect_channels( dap_chain_net_t * a_net,struct dap_chain_node_info *a_link_info,
                                                                                const char * a_channels);
+int dap_cert_chain_file_save(dap_chain_datum_t * l_datum, char * net_name);
diff --git a/modules/net/include/dap_chain_node_cli_cmd.h b/modules/net/include/dap_chain_node_cli_cmd.h
index 3c50d18e3c..0a35ddba34 100644
--- a/modules/net/include/dap_chain_node_cli_cmd.h
+++ b/modules/net/include/dap_chain_node_cli_cmd.h
@@ -144,3 +144,6 @@ int com_mempool_proc(int argc, char ** argv, char ** a_str_reply);
  * Place public CA into the mempool
  */
 int com_mempool_add_ca( int a_argc,  char ** a_argv, char ** a_str_reply);
+int com_chain_ca_pub( int a_argc,  char ** a_argv, char ** a_str_reply);
+int com_chain_ca_copy( int a_argc,  char ** a_argv, char ** a_str_reply);
+
diff --git a/modules/type/dag/dap_chain_cs_dag.c b/modules/type/dag/dap_chain_cs_dag.c
index 04436de8ec..4241cba8a7 100644
--- a/modules/type/dag/dap_chain_cs_dag.c
+++ b/modules/type/dag/dap_chain_cs_dag.c
@@ -327,6 +327,11 @@ static int s_dap_chain_add_atom_to_ledger(dap_chain_cs_dag_t * a_dag, dap_ledger
             }
         }
         break;
+        case DAP_CHAIN_DATUM_CA: {
+            dap_cert_chain_file_save(l_datum, a_dag->chain->net_name);
+            return DAP_CHAIN_DATUM_CA;
+        }
+        break;
         default:
             return -1;
     }
@@ -434,6 +439,11 @@ static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_cha
                 log_it(L_DEBUG, "... tresholded");
             ret = ATOM_MOVE_TO_THRESHOLD;
             break;
+        case DAP_CHAIN_DATUM_CA:
+            ret = ATOM_ACCEPT;
+            if(s_debug_more)
+                log_it(L_DEBUG, "... DATUM_CA");
+            break;
         default:
             if (s_debug_more) {
                 l_event_hash_str = dap_chain_hash_fast_to_str_new(&l_event_item->hash);
-- 
GitLab