diff --git a/dap_chain_net.c b/dap_chain_net.c index cd2df9fb4ea8b8cf39b11d9c13ed1e8af909b33f..733f8b778b1f32cbf59c828d960e748643a5fb89 100644 --- a/dap_chain_net.c +++ b/dap_chain_net.c @@ -30,11 +30,15 @@ #include "utlist.h" #include "dap_common.h" +#include "dap_string.h" #include "dap_strfuncs.h" #include "dap_config.h" #include "dap_chain_utxo.h" #include "dap_chain_net.h" #include "dap_chain_node_client.h" +#include "dap_chain_node_cli.h" +#include "dap_chain_node_cli_cmd.h" + #include "dap_module.h" #define _XOPEN_SOURCE 700 @@ -51,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; @@ -76,21 +81,25 @@ 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 size_t s_net_configs_count = 0; -static pthread_cond_t s_net_proc_loop_cond = PTHREAD_COND_INITIALIZER; -static pthread_mutex_t s_net_proc_loop_mutex = PTHREAD_MUTEX_INITIALIZER; - -int s_net_states_proc(dap_chain_net_t * l_net); 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", [NET_STATE_SYNC_CHAINS]= "NET_STATE_SYNC_CHAINS", - [NET_STATE_STAND_BY]= "NET_STATE_STAND_BY" + [NET_STATE_SYNC_ALL]= "NET_STATE_STAND_BY" }; +static dap_chain_net_t * s_net_new(const char * a_id, const char * a_name , const char * a_node_role); +inline static const char * s_net_state_to_str(dap_chain_net_state_t l_state); +static int s_net_states_proc(dap_chain_net_t * l_net); +static void * s_net_proc_thread ( void * a_net); +static void s_net_proc_thread_start( dap_chain_net_t * a_net ); +static void s_net_proc_kill( dap_chain_net_t * a_net ); + +static int s_cli_net(int argc, const char ** argv, char **str_reply); + /** * @brief s_net_state_to_str * @param l_state @@ -120,13 +129,14 @@ int dap_chain_net_state_go_to(dap_chain_net_t * a_net, dap_chain_net_state_t a_n * @brief s_net_states_proc * @param l_net */ -int s_net_states_proc(dap_chain_net_t * l_net) +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 ) - dap_chain_net_links_establish(l_net); + case NET_STATE_OFFLINE:{ + if ( PVT(l_net)->state_target != NET_STATE_OFFLINE ){ + + } }break; case NET_STATE_LINKS_CONNECTING:{ @@ -142,7 +152,7 @@ int s_net_states_proc(dap_chain_net_t * l_net) case NET_STATE_SYNC_CHAINS:{ }break; - case NET_STATE_STAND_BY:{ + case NET_STATE_SYNC_ALL:{ } break; } @@ -160,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; @@ -203,12 +214,13 @@ static void s_net_proc_kill( dap_chain_net_t * a_net ) * @param a_node_name * @return */ -dap_chain_net_t * dap_chain_net_new(const char * a_id, const char * a_name , +static dap_chain_net_t * s_net_new(const char * a_id, const char * a_name , const char * a_node_role) { 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; @@ -266,13 +278,98 @@ void dap_chain_net_delete( dap_chain_net_t * a_net ) * @return */ 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" + "net -net <chain net name> link < list | add | del | info | establish >\n" + "\tList,add,del, dump or establish links\n\n" + ); + +} + +/** + * @brief s_cli_net + * @param argc + * @param argv + * @param str_reply + * @return + */ +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; +} + + +int dap_chain_net_load(const char * a_net_name) { static dap_config_t *l_cfg=NULL; - if((l_cfg = dap_config_open( "network/default" ) ) == NULL) { + dap_string_t *l_cfg_path = dap_string_new("network/"); + dap_string_append(l_cfg_path,a_net_name); + + if( ( l_cfg = dap_config_open ( l_cfg_path->str ) ) == NULL ) { log_it(L_ERROR,"Can't open default network config"); + dap_string_free(l_cfg_path,true); return -1; - }else{ - dap_chain_net_t * l_net = dap_chain_net_new( + } else { + dap_string_free(l_cfg_path,true); + dap_chain_net_t * l_net = s_net_new( dap_config_get_item_str(l_cfg , "general" , "id" ), dap_config_get_item_str(l_cfg , "general" , "name" ), dap_config_get_item_str(l_cfg , "general" , "node-role" ) @@ -326,8 +423,11 @@ int dap_chain_net_init() // Create chain object dap_chain_t * l_chain = dap_chain_load_from_cfg(l_net->pub.name, l_net->pub.id, l_chains_path); - if(l_chain) + if(l_chain){ DL_APPEND( l_net->pub.chains, l_chain); + if(l_chain->callback_created) + l_chain->callback_created(l_chain,l_cfg); + } free(l_entry_name); } } diff --git a/dap_chain_net.h b/dap_chain_net.h index 276a09b08a0b73a7f49bade1f00a554b7846566e..042d13f77278c3629731ac6ef450ee0f810dd110 100644 --- a/dap_chain_net.h +++ b/dap_chain_net.h @@ -34,18 +34,19 @@ #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, NET_STATE_SYNC_CHAINS, - NET_STATE_STAND_BY, + NET_STATE_SYNC_ALL, } dap_chain_net_state_t; typedef struct dap_chain_net{ struct { dap_chain_net_id_t id; + dap_chain_cell_id_t cell_id; // Cell where the node is connected to. {{0}} if not celled(sharder) blockchain char * name; char * gdb_groups_prefix; dap_chain_t * chains; // double-linked list of chains @@ -53,17 +54,20 @@ typedef struct dap_chain_net{ uint8_t pvt[]; } dap_chain_net_t; + int dap_chain_net_init(void); void dap_chain_net_deinit(void); -dap_chain_net_t * dap_chain_net_new (const char * a_id, const char * a_name, - const char* a_node_role ); +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_STAND_BY); } -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_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_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); } +inline static int dap_chain_net_sync_all(dap_chain_net_t * a_net) { return dap_chain_net_state_go_to(a_net,NET_STATE_SYNC_ALL); } void dap_chain_net_delete( dap_chain_net_t * a_net); void dap_chain_net_proc_datapool (dap_chain_net_t * a_net); diff --git a/dap_chain_node_cli_cmd.c b/dap_chain_node_cli_cmd.c index 71e410f37c70783f6945edc58234562af1b7885d..2f29266b9ee84f2ced369d52151be93b9097f1f3 100644 --- a/dap_chain_node_cli_cmd.c +++ b/dap_chain_node_cli_cmd.c @@ -1432,37 +1432,40 @@ int com_tx_wallet(int argc, const char ** argv, char **str_reply) * @param l_net * @return */ -int s_values_parse_net_chain(int *a_arg_index,int argc, const char ** argv, char ** a_str_reply, +int dap_chain_node_cli_cmd_values_parse_net_chain(int *a_arg_index,int argc, const char ** argv, char ** a_str_reply, dap_chain_t ** a_chain, dap_chain_net_t ** a_net) { const char * l_chain_str = NULL; const char * l_net_str = NULL; - // Net name - dap_chain_node_cli_find_option_val(argv, *a_arg_index, argc, "-net", &l_net_str); - // Chain name - dap_chain_node_cli_find_option_val(argv, *a_arg_index, argc, "-chain", &l_chain_str); + // Net name + if ( a_net ) + dap_chain_node_cli_find_option_val(argv, *a_arg_index, argc, "-net", &l_net_str); + 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; - }else { - 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 -101; } - // Select chain - if(!l_chain_str) { - dap_chain_node_cli_set_reply_text(a_str_reply, "%s requires parameter 'chain'",argv[0]); - return -44; - }else { - 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; + 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 -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 -103; + } } } return 0; @@ -1492,7 +1495,7 @@ int com_token_decl_sign(int argc, const char ** argv, char ** a_str_reply) dap_chain_net_t * l_net = NULL; - if ( s_values_parse_net_chain(&arg_index,argc,argv,a_str_reply,&l_chain, &l_net) < 0 ) + if ( dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index,argc,argv,a_str_reply,&l_chain, &l_net) < 0 ) return -1; // Load certs lists @@ -1647,7 +1650,7 @@ int com_mempool_list(int argc, const char ** argv, char ** a_str_reply) dap_chain_t * l_chain; dap_chain_net_t * l_net = NULL; - if (s_values_parse_net_chain(&arg_index,argc,argv,a_str_reply,&l_chain, &l_net) < 0) + if (dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index,argc,argv,a_str_reply,&l_chain, &l_net) < 0) return -1; char * l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool(l_chain); @@ -1682,7 +1685,7 @@ int com_mempool_proc(int argc, const char ** argv, char ** a_str_reply) dap_chain_t * l_chain; dap_chain_net_t * l_net = NULL; - if (s_values_parse_net_chain(&arg_index,argc,argv,a_str_reply,&l_chain, &l_net) < 0) + if (dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index,argc,argv,a_str_reply,&l_chain, &l_net) < 0) return -1; char * l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool(l_chain); @@ -1752,7 +1755,7 @@ int com_token_decl(int argc, const char ** argv, char ** str_reply) dap_chain_t * l_chain; dap_chain_net_t * l_net = NULL; - if (s_values_parse_net_chain(&arg_index,argc,argv,str_reply,&l_chain, &l_net) < 0) + if (dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index,argc,argv,str_reply,&l_chain, &l_net) < 0) return -1; @@ -1906,8 +1909,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; @@ -1964,7 +1970,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'"); @@ -1976,19 +1981,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 @@ -2011,7 +2032,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 { @@ -2064,7 +2085,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); dap_chain_utxo_tx_add((dap_chain_datum_tx_t*) l_datum_tx->data); } diff --git a/dap_chain_node_cli_cmd.h b/dap_chain_node_cli_cmd.h index 47a195186f578d0fa889ad19660061c8783a983f..31eb7742a5cbe7f008e98b309a704c4ac1ae4476 100644 --- a/dap_chain_node_cli_cmd.h +++ b/dap_chain_node_cli_cmd.h @@ -24,6 +24,8 @@ #pragma once +#include "dap_chain.h" +#include "dap_chain_net.h" #include "dap_chain_node.h" #include "dap_chain_node_cli.h" @@ -35,6 +37,8 @@ dap_chain_node_addr_t* dap_chain_node_addr_get_by_alias(const char *alias); +int dap_chain_node_cli_cmd_values_parse_net_chain(int *a_arg_index,int argc, const char ** argv, char ** a_str_reply, + dap_chain_t ** a_chain, dap_chain_net_t ** a_net); /** * global_db command