diff --git a/dap-sdk b/dap-sdk index 1587a436ec9231ac3bb485e74cc5ec2a7534efd5..9e7565c9417bad979e90b83ccd537aecfe7c07f9 160000 --- a/dap-sdk +++ b/dap-sdk @@ -1 +1 @@ -Subproject commit 1587a436ec9231ac3bb485e74cc5ec2a7534efd5 +Subproject commit 9e7565c9417bad979e90b83ccd537aecfe7c07f9 diff --git a/modules/chain/include/dap_chain.h b/modules/chain/include/dap_chain.h index 63a772b325f40357bc4060cdf6ec4414b419bb81..7082039bcce764c727207eabe32cc5e78171a0c7 100644 --- a/modules/chain/include/dap_chain.h +++ b/modules/chain/include/dap_chain.h @@ -142,6 +142,14 @@ typedef enum dap_chain_type { CHAIN_TYPE_ANCHOR = 8 } dap_chain_type_t; +// not rotate, use in state machine +typedef enum dap_chain_sync_state { + CHAIN_SYNC_STATE_SYNCED = -1, // chain was synced + CHAIN_SYNC_STATE_IDLE = 0, // do nothink + CHAIN_SYNC_STATE_WAITING = 1, // wait packet in + CHAIN_SYNC_STATE_ERROR = 2 // have a error +} dap_chain_sync_state_t; + typedef struct dap_chain { pthread_rwlock_t rwlock; // Common rwlock for the whole structure @@ -166,6 +174,8 @@ typedef struct dap_chain { uint16_t *autoproc_datum_types; uint64_t atom_num_last; + dap_chain_sync_state_t state; + // To hold it in double-linked lists struct dap_chain * next; struct dap_chain * prev; diff --git a/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c b/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c index 0ac4c23414c1f025661d4d3d28db0c8051380c07..b708d9d05db22af9ce2f1acdcaaae2d72cd6f7dc 100644 --- a/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c +++ b/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c @@ -751,7 +751,7 @@ static int s_callback_created(dap_chain_t * a_chain, dap_config_t *a_chain_net_c assert(l_net); dap_global_db_cluster_t *l_dag_cluster = dap_global_db_cluster_add(dap_global_db_instance_get_default(), NULL, dap_guuid_compose(l_net->pub.id.uint64, DAP_CHAIN_CLUSTER_ID_DAG), - l_dag->gdb_group_events_round_new, 900, true, + l_dag->gdb_group_events_round_new, 1, true, DAP_GDB_MEMBER_ROLE_NOBODY, DAP_CLUSTER_TYPE_AUTONOMIC); dap_global_db_cluster_add_notify_callback(l_dag_cluster, s_round_changes_notify, l_dag); dap_chain_net_add_auth_nodes_to_cluster(l_net, l_dag_cluster); diff --git a/modules/consensus/esbocs/dap_chain_cs_esbocs.c b/modules/consensus/esbocs/dap_chain_cs_esbocs.c index 9b1e629107767a4294f513b3998a33875343a9ec..eaa405cd7fff060fb691a9ac78e475bdc861a140 100644 --- a/modules/consensus/esbocs/dap_chain_cs_esbocs.c +++ b/modules/consensus/esbocs/dap_chain_cs_esbocs.c @@ -539,7 +539,7 @@ static int s_callback_created(dap_chain_t *a_chain, dap_config_t *a_chain_net_cf char *l_sync_group = s_get_penalty_group(l_net->pub.id); l_session->db_cluster = dap_global_db_cluster_add(dap_global_db_instance_get_default(), NULL, dap_guuid_compose(l_net->pub.id.uint64, DAP_CHAIN_CLUSTER_ID_ESBOCS), - l_sync_group, 72 * 3600, true, + l_sync_group, 72, true, DAP_GDB_MEMBER_ROLE_NOBODY, DAP_CLUSTER_TYPE_AUTONOMIC); dap_link_manager_add_net_associate(l_net->pub.id.uint64, l_session->db_cluster->links_cluster); dap_global_db_erase_table_sync(l_sync_group); // Drop table on stratup @@ -729,6 +729,15 @@ int dap_chain_esbocs_set_min_validators_count(dap_chain_t *a_chain, uint16_t a_n return 0; } +int dap_chain_esbocs_get_min_validators_count(dap_chain_net_id_t a_net_id) +{ + dap_chain_esbocs_session_t *l_session; + DL_FOREACH(s_session_items, l_session) + if (l_session->chain->net_id.uint64 == a_net_id.uint64) + return PVT(l_session->esbocs)->min_validators_count; + return -1; +} + int dap_chain_esbocs_set_signs_struct_check(dap_chain_t *a_chain, bool a_enable) { dap_return_val_if_fail(a_chain && !strcmp(dap_chain_get_cs_type(a_chain), DAP_CHAIN_ESBOCS_CS_TYPE_STR), -1); @@ -873,7 +882,8 @@ static dap_list_t *s_get_validators_list(dap_chain_esbocs_t *a_esbocs, dap_hash_ for (size_t l_current_vld_cnt = 0; l_current_vld_cnt < l_need_vld_cnt; l_current_vld_cnt++) { uint256_t l_raw_result; uint256_t l_chosen_weight = dap_pseudo_random_get(l_total_weight, &l_raw_result); - if (false) { //PVT(a_session->esbocs)->debug) { +#if DAP_ESBOCS_PRNG_DEBUG + if (l_esbocs_pvt->debug) { unsigned l_strlen = 1024, l_off = 0; const char *l_chosen_weight_str, *l_total_weight_str, *l_raw_result_str; char l_str[l_strlen]; @@ -888,6 +898,7 @@ static dap_list_t *s_get_validators_list(dap_chain_esbocs_t *a_esbocs, dap_hash_ l_off += snprintf(l_str + l_off, l_strlen - l_off, "by number %s", l_raw_result_str); log_it(L_MSG, "%s", l_str); } +#endif dap_list_t *l_chosen = NULL; uint256_t l_cur_weight = uint256_0; for (dap_list_t *it = l_validators; it; it = it->next) { @@ -950,6 +961,9 @@ static dap_list_t *s_validator_check_synced(dap_chain_addr_t *a_addr, dap_list_t static void s_db_calc_sync_hash(dap_chain_esbocs_session_t *a_session) { + dap_chain_addr_t l_addr_blank = c_dap_chain_addr_blank; + l_addr_blank.net_id = a_session->chain->net_id; + dap_chain_net_srv_stake_mark_validator_active(&l_addr_blank, true); // Mark all validators active for now char *l_penalty_group = s_get_penalty_group(a_session->chain->net_id); size_t l_penalties_count = 0; dap_global_db_obj_t *l_objs = dap_global_db_get_all_sync(l_penalty_group, &l_penalties_count); diff --git a/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h b/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h index bd009e34b125c2eac26c81315a10a16800def6d7..5a99570e8ba8fcc13714422ddb36179ac177e934 100644 --- a/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h +++ b/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h @@ -268,5 +268,6 @@ bool dap_chain_esbocs_remove_validator_from_clusters(dap_chain_net_id_t a_net_id uint256_t dap_chain_esbocs_get_collecting_level(dap_chain_t *a_chain); dap_enc_key_t *dap_chain_esbocs_get_sign_key(dap_chain_t *a_chain); int dap_chain_esbocs_set_min_validators_count(dap_chain_t *a_chain, uint16_t a_new_value); +int dap_chain_esbocs_get_min_validators_count(dap_chain_net_id_t a_net_id); int dap_chain_esbocs_set_emergency_validator(dap_chain_t *a_chain, bool a_add, uint32_t a_sign_type, dap_hash_fast_t *a_validator_hash); int dap_chain_esbocs_set_signs_struct_check(dap_chain_t *a_chain, bool a_enable); diff --git a/modules/net/dap_chain_ledger.c b/modules/net/dap_chain_ledger.c index c24fe2c8ad288fddbea24f873bc7f4153f757d97..7c449e82744c8dbb0ccbd82c75f56f208253006e 100644 --- a/modules/net/dap_chain_ledger.c +++ b/modules/net/dap_chain_ledger.c @@ -3379,18 +3379,21 @@ static int s_tx_cache_check(dap_ledger_t *a_ledger, bool a_check_for_removing) { dap_return_val_if_fail(a_ledger && a_tx && a_tx_hash, DAP_LEDGER_CHECK_INVALID_ARGS); - if (!dap_chain_net_get_load_mode(a_ledger->net) && !a_from_threshold && !a_check_for_removing) { + if (!a_from_threshold) { dap_ledger_tx_item_t *l_ledger_item = NULL; pthread_rwlock_rdlock(&PVT(a_ledger)->ledger_rwlock); HASH_FIND(hh, PVT(a_ledger)->ledger_items, a_tx_hash, sizeof(dap_chain_hash_fast_t), l_ledger_item); pthread_rwlock_unlock(&PVT(a_ledger)->ledger_rwlock); - if (l_ledger_item) { // transaction already present in the cache list + if (l_ledger_item && !a_check_for_removing ) { // transaction already present in the cache list if (s_debug_more) { log_it(L_WARNING, "Transaction %s already present in the cache", dap_chain_hash_fast_to_str_static(a_tx_hash)); if (a_tag) *a_tag = l_ledger_item->cache_data.tag; if (a_action) *a_action = l_ledger_item->cache_data.action; } return DAP_LEDGER_CHECK_ALREADY_CACHED; + } else if (!l_ledger_item && a_check_for_removing) { // transaction already present in the cache list + debug_if(s_debug_more, L_WARNING, "Transaction %s not present in the cache. Can not delete it. Skip.", dap_chain_hash_fast_to_str_static(a_tx_hash)); + return DAP_LEDGER_TX_CHECK_FOR_REMOVING_CANT_FIND_TX; } } /* diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c index 7872b7ee40adf8c59700386e991a970df5fb22de..3df4dc5b0153a41fa91d1f8b924321195e279d06 100644 --- a/modules/net/dap_chain_net.c +++ b/modules/net/dap_chain_net.c @@ -117,6 +117,7 @@ #define F_DAP_CHAIN_NET_SYNC_FROM_ZERO ( 1 << 8 ) static bool s_debug_more = false; +static const int c_sync_timer_period = 5000; // msec struct request_link_info { char addr[DAP_HOSTADDR_STRLEN + 1]; @@ -129,23 +130,16 @@ struct block_reward { struct block_reward *prev, *next; }; -enum sync_state { - SYNC_STATE_IDLE, - SYNC_STATE_WAITING, - SYNC_STATE_SYNCED, - SYNC_STATE_ERROR -}; struct chain_sync_context { - enum sync_state state, - last_state; - dap_time_t stage_last_activity, - sync_idle_time; - dap_stream_node_addr_t current_link; - dap_chain_t *cur_chain; - dap_chain_cell_t *cur_cell; - dap_hash_fast_t requested_atom_hash; - uint64_t requested_atom_num; + dap_chain_sync_state_t state; + dap_time_t stage_last_activity, + sync_idle_time; + dap_stream_node_addr_t current_link; + dap_chain_t *cur_chain; + dap_chain_cell_t *cur_cell; + dap_hash_fast_t requested_atom_hash; + uint64_t requested_atom_num; }; /** @@ -156,7 +150,6 @@ typedef struct dap_chain_net_pvt{ pthread_t proc_tid; dap_chain_node_role_t node_role; uint32_t flags; - time_t last_sync; dap_chain_node_info_t *node_info; // Current node's info @@ -348,63 +341,10 @@ char *dap_chain_net_get_gdb_group_acl(dap_chain_net_t *a_net) return NULL; } -/** - * @brief set current network state to F_DAP_CHAIN_NET_GO_SYNC - * - * @param a_net dap_chain_net_t network object - * @param a_new_state dap_chain_net_state_t new network state - * @return int - */ -int dap_chain_net_state_go_to(dap_chain_net_t *a_net, dap_chain_net_state_t a_new_state) -{ - if (PVT(a_net)->load_mode) { - log_it(L_ERROR, "Can't change state of loading network '%s'", a_net->pub.name); - return -1; - } - if (PVT(a_net)->state_target == a_new_state) { - log_it(L_NOTICE, "Network %s already %s state %s", a_net->pub.name, - PVT(a_net)->state == a_new_state ? "have" : "going to", dap_chain_net_state_to_str(a_new_state)); - return 0; - } - //PVT(a_net)->flags |= F_DAP_CHAIN_NET_SYNC_FROM_ZERO; // TODO set this flag according to -mode argument from command line - PVT(a_net)->state_target = a_new_state; - if (a_new_state == NET_STATE_OFFLINE) { - char l_err_str[] = "ERROR_NET_IS_OFFLINE"; - size_t l_error_size = sizeof(dap_stream_ch_chain_net_pkt_t) + sizeof(l_err_str); - dap_stream_ch_chain_net_pkt_t *l_error = DAP_NEW_STACK_SIZE(dap_stream_ch_chain_net_pkt_t, l_error_size); - l_error->hdr.version = DAP_STREAM_CH_CHAIN_NET_PKT_VERSION; - l_error->hdr.net_id = a_net->pub.id; - l_error->hdr.data_size = sizeof(l_err_str); - memcpy(l_error->data, l_err_str, sizeof(l_err_str)); - dap_cluster_broadcast(PVT(a_net)->nodes_cluster->links_cluster, DAP_STREAM_CH_CHAIN_NET_ID, - DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_ERROR, l_error, l_error_size, NULL, 0); - dap_link_manager_set_net_condition(a_net->pub.id.uint64, false); - dap_chain_esbocs_stop_timer(a_net->pub.id); - } else if (PVT(a_net)->state == NET_STATE_OFFLINE) { - dap_link_manager_set_net_condition(a_net->pub.id.uint64, true); - for (uint16_t i = 0; i < PVT(a_net)->permanent_links_count; ++i) { - dap_link_info_t *l_permalink_info = PVT(a_net)->permanent_links[i]; - if (dap_chain_net_link_add(a_net, &l_permalink_info->node_addr, l_permalink_info->uplink_addr, l_permalink_info->uplink_port)) { - log_it(L_ERROR, "Can't create permanent link to addr " NODE_ADDR_FP_STR, NODE_ADDR_FP_ARGS_S(l_permalink_info->node_addr)); - continue; - } - PVT(a_net)->state = NET_STATE_LINKS_CONNECTING; - } - if (a_new_state == NET_STATE_ONLINE) - dap_chain_esbocs_start_timer(a_net->pub.id); - } - return dap_proc_thread_callback_add(NULL, s_net_states_proc, a_net); -} - -DAP_INLINE dap_chain_net_state_t dap_chain_net_get_target_state(dap_chain_net_t *a_net) -{ - return PVT(a_net)->state_target; -} - static struct request_link_info *s_balancer_link_from_cfg(dap_chain_net_t *a_net) { switch (PVT(a_net)->seed_nodes_count) { - case 0: return log_it(L_ERROR, "No available links! Add them in net config"), NULL; + case 0: return log_it(L_ERROR, "No available links in net %s! Add them in net config", a_net->pub.name), NULL; case 1: return PVT(a_net)->seed_nodes_info[0]; default: return PVT(a_net)->seed_nodes_info[dap_random_uint16() % PVT(a_net)->seed_nodes_count]; } @@ -556,7 +496,7 @@ int s_link_manager_link_request(uint64_t a_net_id) l_net_pvt->state = NET_STATE_LINKS_CONNECTING; struct request_link_info *l_balancer_link = s_balancer_link_from_cfg(l_net); if (!l_balancer_link) { - log_it(L_ERROR, "Can't process balancer link %s request", dap_chain_net_balancer_type_to_str(PVT(l_net)->balancer_type)); + log_it(L_ERROR, "Can't process balancer link %s request in nte %s", dap_chain_net_balancer_type_to_str(PVT(l_net)->balancer_type), l_net->pub.name); return -5; } return dap_chain_net_balancer_request(l_net, l_balancer_link->addr, l_balancer_link->port, PVT(l_net)->balancer_type); @@ -592,40 +532,32 @@ json_object *s_net_sync_status(dap_chain_net_t *a_net) json_object *l_jobj_chain = json_object_new_object(); json_object *l_jobj_chain_status = NULL; json_object *l_jobj_percent = NULL; - double l_percent = l_chain->callback_count_atom(l_chain) ? - (double) (l_chain->callback_count_atom(l_chain) * 100) / l_chain->atom_num_last : 0; - if (l_percent > 100) - l_percent = 100; - char *l_percent_str = dap_strdup_printf("%.3f", l_percent); - dap_chain_net_state_t l_state = PVT(a_net)->state; - switch (l_state) { - case NET_STATE_OFFLINE: - case NET_STATE_LINKS_PREPARE: - case NET_STATE_LINKS_ESTABLISHED: - case NET_STATE_LINKS_CONNECTING: - l_jobj_chain_status = json_object_new_string("not synced"); - l_jobj_percent = json_object_new_string(" - %"); + + switch (l_chain->state) { + case CHAIN_SYNC_STATE_ERROR: + l_jobj_chain_status = json_object_new_string("error"); + break; + case CHAIN_SYNC_STATE_IDLE: + l_jobj_chain_status = json_object_new_string("idle"); break; - case NET_STATE_ONLINE: + case CHAIN_SYNC_STATE_WAITING: + l_jobj_chain_status = json_object_new_string("sync in process"); + break; + case CHAIN_SYNC_STATE_SYNCED: l_jobj_chain_status = json_object_new_string("synced"); - l_jobj_percent = json_object_new_string(l_percent_str); break; - case NET_STATE_SYNC_CHAINS: - if (PVT(a_net)->sync_context.cur_chain && PVT(a_net)->sync_context.cur_chain->id.uint64 == l_chain->id.uint64) { - l_jobj_chain_status = json_object_new_string("sync in process"); - l_jobj_percent = json_object_new_string(l_percent_str); - } else { - if (l_chain->atom_num_last == l_chain->callback_count_atom(l_chain)) { - l_jobj_chain_status = json_object_new_string("synced"); - l_jobj_percent = json_object_new_string(l_percent_str); - } else { - l_jobj_chain_status = json_object_new_string("not synced"); - l_jobj_percent = json_object_new_string(" - %"); - } - } + default: + l_jobj_chain_status = json_object_new_string("unknown"); break; } - DAP_DELETE(l_percent_str); + if (l_chain->state == CHAIN_SYNC_STATE_IDLE) { + l_jobj_percent = json_object_new_string(" - %"); + } else { + double l_percent = dap_min((double)l_chain->callback_count_atom(l_chain) * 100 / l_chain->atom_num_last, 100.0); + char *l_percent_str = dap_strdup_printf("%.3f %c", l_percent, '%'); + l_jobj_percent = json_object_new_string(l_percent_str); + DAP_DELETE(l_percent_str); + } json_object *l_jobj_current = json_object_new_uint64(l_chain->callback_count_atom(l_chain)); json_object *l_jobj_total = json_object_new_uint64(l_chain->atom_num_last); json_object_object_add(l_jobj_chain, "status", l_jobj_chain_status); @@ -668,68 +600,6 @@ static void s_net_states_notify(dap_chain_net_t *a_net) json_object_put(l_json); } -/** - * @brief s_net_states_proc - * @param l_net - */ -static bool s_net_states_proc(void *a_arg) -{ - bool l_repeat_after_exit = false; // If true - repeat on next iteration of proc thread loop - dap_chain_net_t *l_net = (dap_chain_net_t *) a_arg; - assert(l_net); - dap_chain_net_pvt_t *l_net_pvt = PVT(l_net); - assert(l_net_pvt); - if (l_net_pvt->state_target == NET_STATE_OFFLINE) { - if(l_net_pvt->state == NET_STATE_SYNC_CHAINS) - dap_leger_load_end(l_net->pub.ledger); - l_net_pvt->state = NET_STATE_OFFLINE; - } - - switch ((dap_chain_net_state_t)l_net_pvt->state) { - // State OFFLINE where we don't do anything - case NET_STATE_OFFLINE: { - log_it(L_NOTICE,"%s.state: NET_STATE_OFFLINE", l_net->pub.name); - // delete all links - if ( l_net_pvt->state_target != NET_STATE_OFFLINE ){ - dap_chain_net_state_t l_prev_state = l_net_pvt->state; - l_net_pvt->state = NET_STATE_LINKS_PREPARE; - l_repeat_after_exit = true; - if(l_prev_state == NET_STATE_SYNC_CHAINS) - dap_leger_load_end(l_net->pub.ledger); - } - l_net_pvt->last_sync = 0; - } break; - - // Prepare links - case NET_STATE_LINKS_PREPARE: { - log_it(L_NOTICE,"%s.state: NET_STATE_LINKS_PREPARE", l_net->pub.name); - } break; - - case NET_STATE_LINKS_CONNECTING: { - log_it(L_INFO, "%s.state: NET_STATE_LINKS_CONNECTING",l_net->pub.name); - size_t l_used_links = 0; - } break; - - case NET_STATE_LINKS_ESTABLISHED: - log_it(L_INFO,"%s.state: NET_STATE_LINKS_ESTABLISHED", l_net->pub.name); - break; - - case NET_STATE_SYNC_CHAINS: - log_it(L_INFO,"%s.state: NET_STATE_SYNC_CHAINS", l_net->pub.name); - break; - - case NET_STATE_ONLINE: - log_it(L_NOTICE,"%s.state: NET_STATE_ONLINE", l_net->pub.name); - l_net_pvt->last_sync = dap_time_now(); - break; - - default: - log_it(L_DEBUG, "Unprocessed state"); - } - s_net_states_notify(l_net); - return l_repeat_after_exit; -} - /** * @brief dap_chain_net_get_role * @param a_net @@ -2326,7 +2196,7 @@ bool s_net_load(void *a_arg) l_gdb_groups_mask = dap_strdup_printf("%s.orders", l_net->pub.gdb_groups_prefix); l_net_pvt->common_orders = dap_global_db_cluster_add(dap_global_db_instance_get_default(), l_net->pub.name, dap_guuid_compose(l_net->pub.id.uint64, 0), - l_gdb_groups_mask, 72, true, + l_gdb_groups_mask, 336, true, DAP_GDB_MEMBER_ROLE_USER, DAP_CLUSTER_TYPE_EMBEDDED); if (!l_net_pvt->common_orders) { @@ -2337,12 +2207,11 @@ bool s_net_load(void *a_arg) DAP_DELETE(l_gdb_groups_mask); // Node states cluster l_gdb_groups_mask = dap_strdup_printf("%s.nodes.states", l_net->pub.gdb_groups_prefix); - l_net_pvt->nodes_states = dap_global_db_cluster_add( - dap_global_db_instance_get_default(), - l_net->pub.name, dap_guuid_compose(l_net->pub.id.uint64, 0), - l_gdb_groups_mask, 0, true, - DAP_GDB_MEMBER_ROLE_USER, - DAP_CLUSTER_TYPE_EMBEDDED); + l_net_pvt->nodes_states = dap_global_db_cluster_add(dap_global_db_instance_get_default(), + l_net->pub.name, dap_guuid_compose(l_net->pub.id.uint64, 0), + l_gdb_groups_mask, 6, true, + DAP_GDB_MEMBER_ROLE_USER, + DAP_CLUSTER_TYPE_EMBEDDED); DAP_DELETE(l_gdb_groups_mask); // Nodes and its aliases cluster l_net->pub.gdb_nodes = dap_strdup_printf("%s.nodes.list",l_net->pub.gdb_groups_prefix); @@ -2411,7 +2280,7 @@ bool s_net_load(void *a_arg) log_it(L_WARNING, "Unknown node address type will be defalted to 'auto'"); l_net_pvt->sync_context.sync_idle_time = dap_config_get_item_uint32_default(g_config, "chain", "sync_idle_time", 60); - dap_proc_thread_timer_add(NULL, s_sync_timer_callback, l_net, 1000); + dap_proc_thread_timer_add(NULL, s_sync_timer_callback, l_net, c_sync_timer_period); log_it(L_INFO, "Chain network \"%s\" initialized", l_net->pub.name); ret: @@ -2424,328 +2293,56 @@ ret: return false; } -static const uint64_t s_fork_sync_step = 20; // TODO get it from config - -static void s_ch_in_pkt_callback(dap_stream_ch_t *a_ch, uint8_t a_type, const void *a_data, size_t a_data_size, void *a_arg) +dap_global_db_cluster_t *dap_chain_net_get_mempool_cluster(dap_chain_t *a_chain) { - debug_if(s_debug_more, L_DEBUG, "Got IN sync packet type %hhu size %zu from addr " NODE_ADDR_FP_STR, - a_type, a_data_size, NODE_ADDR_FP_ARGS_S(a_ch->stream->node)); - dap_chain_net_t *l_net = a_arg; - dap_chain_net_pvt_t *l_net_pvt = PVT(l_net); - if (l_net_pvt->state == NET_STATE_LINKS_ESTABLISHED) - l_net_pvt->state = NET_STATE_SYNC_CHAINS; - - switch (a_type) { - case DAP_CHAIN_CH_PKT_TYPE_CHAIN_SUMMARY: - case DAP_CHAIN_CH_PKT_TYPE_CHAIN_MISS: - case DAP_CHAIN_CH_PKT_TYPE_CHAIN: - case DAP_CHAIN_CH_PKT_TYPE_SYNCED_CHAIN: - // TODO sync state & address checking - break; - default: - break; + dap_return_val_if_fail(a_chain, NULL); + dap_chain_net_t *l_net = dap_chain_net_by_id(a_chain->net_id); + if (!l_net) { + log_it(L_ERROR, "Invalid chain specified for mempool cluster search"); + return NULL; + } + dap_global_db_cluster_t *l_mempool = PVT(l_net)->mempool_clusters; + dap_chain_t *l_chain; + DL_FOREACH(l_net->pub.chains, l_chain) { + if (l_chain == a_chain) + return l_mempool; + assert(l_mempool); + l_mempool = l_mempool->next; } + log_it(L_ERROR, "No mempool cluster found for chain specified"); + return NULL; +} - switch (a_type) { - case DAP_CHAIN_CH_PKT_TYPE_ERROR: - l_net_pvt->sync_context.state = SYNC_STATE_ERROR; - return; +void dap_chain_add_mempool_notify_callback(dap_chain_t *a_chain, dap_store_obj_callback_notify_t a_callback, void *a_cb_arg) +{ + dap_global_db_cluster_add_notify_callback(dap_chain_net_get_mempool_cluster(a_chain), a_callback, a_cb_arg); +} - case DAP_CHAIN_CH_PKT_TYPE_SYNCED_CHAIN: - l_net_pvt->sync_context.state = SYNC_STATE_SYNCED; +static void s_nodelist_change_notify(dap_store_obj_t *a_obj, void *a_arg) +{ + dap_chain_net_t *l_net = a_arg; + dap_return_if_fail(a_obj->key && !dap_strcmp(l_net->pub.gdb_nodes, a_obj->group)); + char l_ts[DAP_TIME_STR_SIZE] = { '\0' }; + dap_nanotime_to_str_rfc822(l_ts, sizeof(l_ts), a_obj->timestamp); + if (dap_store_obj_get_type(a_obj) == DAP_GLOBAL_DB_OPTYPE_DEL) { + log_it(L_NOTICE, "Removed node %s from network %s at %s\n", + a_obj->key, l_net->pub.name, l_ts); return; - - case DAP_CHAIN_CH_PKT_TYPE_CHAIN_MISS: { - if (!l_net_pvt->sync_context.cur_chain) - return; - dap_chain_ch_miss_info_t *l_miss_info = (dap_chain_ch_miss_info_t *)(((dap_chain_ch_pkt_t *)(a_data))->data); - if (!dap_hash_fast_compare(&l_miss_info->missed_hash, &l_net_pvt->sync_context.requested_atom_hash)) { - char l_missed_hash_str[DAP_HASH_FAST_STR_SIZE]; - dap_hash_fast_to_str(&l_miss_info->missed_hash, l_missed_hash_str, DAP_HASH_FAST_STR_SIZE); - log_it(L_WARNING, "Get irrelevant chain sync MISSED packet with missed hash %s, but requested hash is %s", - l_missed_hash_str, - dap_hash_fast_to_str_static(&l_net_pvt->sync_context.requested_atom_hash)); - dap_stream_ch_write_error_unsafe(a_ch, l_net->pub.id, - l_net_pvt->sync_context.cur_chain->id, - l_net_pvt->sync_context.cur_cell - ? l_net_pvt->sync_context.cur_cell->id - : c_dap_chain_cell_id_null, - DAP_CHAIN_CH_ERROR_INCORRECT_SYNC_SEQUENCE); - return; - } - dap_chain_atom_iter_t *l_iter = l_net_pvt->sync_context.cur_chain->callback_atom_iter_create( - l_net_pvt->sync_context.cur_chain, - l_net_pvt->sync_context.cur_cell - ? l_net_pvt->sync_context.cur_cell->id - : c_dap_chain_cell_id_null, - NULL); - if (!l_iter) { - log_it(L_CRITICAL, "%s", c_error_memory_alloc); - dap_stream_ch_write_error_unsafe(a_ch, l_net->pub.id, - l_net_pvt->sync_context.cur_chain->id, - l_net_pvt->sync_context.cur_cell - ? l_net_pvt->sync_context.cur_cell->id - : c_dap_chain_cell_id_null, - DAP_CHAIN_CH_ERROR_OUT_OF_MEMORY); - return; - } - dap_chain_atom_ptr_t l_atom = l_net_pvt->sync_context.cur_chain->callback_atom_find_by_hash(l_iter, &l_miss_info->last_hash, NULL); - if (l_atom && l_iter->cur_num == l_miss_info->last_num) { // We already have this subchain in our chain - l_net_pvt->sync_context.state = SYNC_STATE_SYNCED; - return; - } - dap_chain_ch_sync_request_t l_request = {}; - l_request.num_from = l_net_pvt->sync_context.requested_atom_num > s_fork_sync_step - ? l_net_pvt->sync_context.requested_atom_num - s_fork_sync_step - : 0; - if (l_request.num_from) { - l_atom = l_net_pvt->sync_context.cur_chain->callback_atom_get_by_num(l_iter, l_request.num_from); - assert(l_atom); - l_request.hash_from = *l_iter->cur_hash; - } - l_net_pvt->sync_context.cur_chain->callback_atom_iter_delete(l_iter); - debug_if(s_debug_more, L_INFO, "Send sync request to node " NODE_ADDR_FP_STR - " for net %s and chain %s, hash from %s, num from %" DAP_UINT64_FORMAT_U, - NODE_ADDR_FP_ARGS_S(l_net_pvt->sync_context.current_link), - l_net->pub.name, l_net_pvt->sync_context.cur_chain->name, - dap_hash_fast_to_str_static(&l_request.hash_from), l_request.num_from); - dap_chain_ch_pkt_write_unsafe(a_ch, - DAP_CHAIN_CH_PKT_TYPE_CHAIN_REQ, - l_net->pub.id, - l_net_pvt->sync_context.cur_chain->id, - l_net_pvt->sync_context.cur_cell - ? l_net_pvt->sync_context.cur_cell->id - : c_dap_chain_cell_id_null, - &l_request, - sizeof(l_request), - DAP_CHAIN_CH_PKT_VERSION_CURRENT); - l_net_pvt->sync_context.requested_atom_hash = l_request.hash_from; - l_net_pvt->sync_context.requested_atom_num = l_request.num_from; - } - default: - break; } - l_net_pvt->sync_context.stage_last_activity = dap_time_now(); + dap_chain_node_info_t *l_node_info = (dap_chain_node_info_t *)a_obj->value; + assert(dap_chain_node_info_get_size(l_node_info) == a_obj->value_len); + log_it(L_NOTICE, "Added node "NODE_ADDR_FP_STR" [%s : %u] to network %s at %s\n", + NODE_ADDR_FP_ARGS_S(l_node_info->address), + l_node_info->ext_host, l_node_info->ext_port, + l_net->pub.name, l_ts); } -static void s_ch_out_pkt_callback(dap_stream_ch_t *a_ch, uint8_t a_type, const void *a_data, size_t a_data_size, void *a_arg) +void dap_chain_net_add_nodelist_notify_callback(dap_chain_net_t *a_net, dap_store_obj_callback_notify_t a_callback, void *a_cb_arg) { - debug_if(s_debug_more, L_DEBUG, "Sent OUT sync packet type %hhu size %zu to addr " NODE_ADDR_FP_STR, - a_type, a_data_size, NODE_ADDR_FP_ARGS_S(a_ch->stream->node)); - dap_chain_net_t *l_net = a_arg; - dap_chain_net_pvt_t *l_net_pvt = PVT(l_net); - switch (a_type) { - case DAP_CHAIN_CH_PKT_TYPE_ERROR: - l_net_pvt->sync_context.state = SYNC_STATE_ERROR; - break; - default: - break; - } - l_net_pvt->sync_context.stage_last_activity = dap_time_now(); + dap_global_db_cluster_add_notify_callback(PVT(a_net)->nodes_cluster, a_callback, a_cb_arg); } -static void s_sync_timer_callback(void *a_arg) -{ - dap_chain_net_t *l_net = a_arg; - dap_chain_net_pvt_t *l_net_pvt = PVT(l_net); - if (l_net_pvt->state_target == NET_STATE_OFFLINE) - return; - if (l_net_pvt->sync_context.last_state == SYNC_STATE_SYNCED || l_net_pvt->sync_context.last_state == SYNC_STATE_ERROR || - (l_net_pvt->sync_context.last_state == SYNC_STATE_IDLE && l_net_pvt->state != NET_STATE_ONLINE) || - dap_time_now() - l_net_pvt->sync_context.stage_last_activity > l_net_pvt->sync_context.sync_idle_time) { - if (!l_net_pvt->sync_context.cur_chain || l_net_pvt->sync_context.last_state == SYNC_STATE_ERROR) { - // Go no next link - dap_cluster_t *l_cluster = dap_cluster_by_mnemonim(l_net->pub.name); - if (!dap_stream_node_addr_is_blank(&l_net_pvt->sync_context.current_link)) { - dap_stream_ch_del_notifier(&l_net_pvt->sync_context.current_link, DAP_CHAIN_CH_ID, - DAP_STREAM_PKT_DIR_IN, s_ch_in_pkt_callback, l_net); - dap_stream_ch_del_notifier(&l_net_pvt->sync_context.current_link, DAP_CHAIN_CH_ID, - DAP_STREAM_PKT_DIR_OUT, s_ch_out_pkt_callback, l_net); - } - l_net_pvt->sync_context.current_link = dap_cluster_get_random_link(l_cluster); - if (dap_stream_node_addr_is_blank(&l_net_pvt->sync_context.current_link)) - return; // No links in cluster - l_net_pvt->sync_context.cur_chain = l_net->pub.chains; - if (!l_net_pvt->sync_context.cur_chain) { - log_it(L_ERROR, "No chains in net %s", l_net->pub.name); - return; - } - dap_stream_ch_add_notifier(&l_net_pvt->sync_context.current_link, DAP_CHAIN_CH_ID, - DAP_STREAM_PKT_DIR_IN, s_ch_in_pkt_callback, l_net); - dap_stream_ch_add_notifier(&l_net_pvt->sync_context.current_link, DAP_CHAIN_CH_ID, - DAP_STREAM_PKT_DIR_OUT, s_ch_out_pkt_callback, l_net); - l_net_pvt->sync_context.state = l_net_pvt->sync_context.last_state = SYNC_STATE_WAITING; - } else { - l_net_pvt->sync_context.cur_chain = l_net_pvt->sync_context.cur_chain->next; - if (l_net_pvt->sync_context.cur_chain) - log_it(L_DEBUG, "[%s:%d] Go to next chain \"%s\" for net %s", __FUNCTION__, __LINE__, - l_net_pvt->sync_context.cur_chain->name, l_net_pvt->sync_context.cur_chain->net_name); - else - log_it(L_DEBUG, "[%s:%d] Go to next chain: <NULL>", __FUNCTION__, __LINE__); - if (!l_net_pvt->sync_context.cur_chain) { - dap_chain_net_state_t l_prev_state = l_net_pvt->state; - if (l_net_pvt->sync_context.last_state == SYNC_STATE_SYNCED) { - l_net_pvt->state = NET_STATE_ONLINE; - l_net_pvt->sync_context.state = l_net_pvt->sync_context.last_state = SYNC_STATE_IDLE; - s_net_states_proc(l_net); - if(l_prev_state == NET_STATE_SYNC_CHAINS) - dap_leger_load_end(l_net->pub.ledger); - } else - l_net_pvt->sync_context.state = l_net_pvt->sync_context.last_state = SYNC_STATE_WAITING; - return; - } - } - // TODO make correct working with cells - assert(l_net_pvt->sync_context.cur_chain); - if (l_net_pvt->sync_context.cur_chain->callback_load_from_gdb) { - // This type of chain is GDB based and not synced by chains protocol - l_net_pvt->sync_context.cur_chain = l_net_pvt->sync_context.cur_chain->next; - if (l_net_pvt->sync_context.cur_chain) - log_it(L_DEBUG, "[%s:%d] Go to next chain \"%s\" for net %s", __FUNCTION__, __LINE__, - l_net_pvt->sync_context.cur_chain->name, l_net_pvt->sync_context.cur_chain->net_name); - else - log_it(L_DEBUG, "[%s:%d] Go to next chain: <NULL>", __FUNCTION__, __LINE__); - l_net_pvt->sync_context.last_state = SYNC_STATE_SYNCED; - return; - } - l_net_pvt->sync_context.cur_cell = l_net_pvt->sync_context.cur_chain->cells; - l_net_pvt->sync_context.state = l_net_pvt->sync_context.last_state = SYNC_STATE_WAITING; - dap_chain_ch_sync_request_t l_request = {}; - uint64_t l_last_num = 0; - if (!dap_chain_get_atom_last_hash_num(l_net_pvt->sync_context.cur_chain, - l_net_pvt->sync_context.cur_cell - ? l_net_pvt->sync_context.cur_cell->id - : c_dap_chain_cell_id_null, - &l_request.hash_from, - &l_last_num)) { - log_it(L_ERROR, "Can't get last atom hash and number for chain %s with net %s", l_net_pvt->sync_context.cur_chain->name, - l_net->pub.name); - return; - } - l_request.num_from = l_last_num; - dap_chain_ch_pkt_t *l_chain_pkt = dap_chain_ch_pkt_new(l_net->pub.id, l_net_pvt->sync_context.cur_chain->id, - l_net_pvt->sync_context.cur_cell ? l_net_pvt->sync_context.cur_cell->id : c_dap_chain_cell_id_null, - &l_request, sizeof(l_request), DAP_CHAIN_CH_PKT_VERSION_CURRENT); - if (!l_chain_pkt) { - log_it(L_CRITICAL, "%s", c_error_memory_alloc); - return; - } - log_it(L_INFO, "Start synchronization process with " NODE_ADDR_FP_STR - " for net %s and chain %s, last hash %s, last num %" DAP_UINT64_FORMAT_U, - NODE_ADDR_FP_ARGS_S(l_net_pvt->sync_context.current_link), - l_net->pub.name, l_net_pvt->sync_context.cur_chain->name, - dap_hash_fast_to_str_static(&l_request.hash_from), l_last_num); - dap_stream_ch_pkt_send_by_addr(&l_net_pvt->sync_context.current_link, DAP_CHAIN_CH_ID, - DAP_CHAIN_CH_PKT_TYPE_CHAIN_REQ, l_chain_pkt, - dap_chain_ch_pkt_get_size(l_chain_pkt)); - l_net_pvt->sync_context.requested_atom_hash = l_request.hash_from; - l_net_pvt->sync_context.requested_atom_num = l_request.num_from; - DAP_DELETE(l_chain_pkt); - } - if (l_net_pvt->sync_context.last_state != SYNC_STATE_IDLE && - l_net_pvt->sync_context.last_state != l_net_pvt->sync_context.state) - l_net_pvt->sync_context.last_state = l_net_pvt->sync_context.state; -} - -/** - * @brief try net to go online - * - * @param a_net dap_chain_net_t *: network - * @return int - * - **/ -static int s_net_try_online(dap_chain_net_t *a_net) -{ - - dap_chain_net_t *l_net = a_net; - - dap_chain_net_pvt_t * l_net_pvt = PVT(l_net); - dap_chain_net_state_t l_target_state = NET_STATE_OFFLINE; - - if (dap_config_get_item_bool_default(g_config ,"general", "auto_online", false)) - { - l_target_state = NET_STATE_ONLINE; - } - - if (l_target_state != l_net_pvt->state_target) - { - dap_chain_net_state_go_to(l_net, l_target_state); - log_it(L_INFO, "Network \"%s\" goes online",l_net->pub.name); - } - - return 0; -} - -/** - * @brief - * change all network states according to auto-online settings - */ -void dap_chain_net_try_online_all() { - int32_t l_ret = 0; - - if(!HASH_COUNT(s_net_items)){ - log_it(L_ERROR, "Can't find any nets"); - return; - } - dap_chain_net_item_t *l_net_items_current = NULL, *l_net_items_tmp = NULL; - HASH_ITER(hh, s_net_items, l_net_items_current, l_net_items_tmp) { - if( (l_ret = s_net_try_online(l_net_items_current->chain_net)) ) { - log_it(L_ERROR, "Can't try online state for net %s. Finished with (%d) error code.", l_net_items_current->name, l_ret); - } - } -} - - -dap_global_db_cluster_t *dap_chain_net_get_mempool_cluster(dap_chain_t *a_chain) -{ - dap_return_val_if_fail(a_chain, NULL); - dap_chain_net_t *l_net = dap_chain_net_by_id(a_chain->net_id); - if (!l_net) { - log_it(L_ERROR, "Invalid chain specified for mempool cluster search"); - return NULL; - } - dap_global_db_cluster_t *l_mempool = PVT(l_net)->mempool_clusters; - dap_chain_t *l_chain; - DL_FOREACH(l_net->pub.chains, l_chain) { - if (l_chain == a_chain) - return l_mempool; - assert(l_mempool); - l_mempool = l_mempool->next; - } - log_it(L_ERROR, "No mempool cluster found for chain specified"); - return NULL; -} - -void dap_chain_add_mempool_notify_callback(dap_chain_t *a_chain, dap_store_obj_callback_notify_t a_callback, void *a_cb_arg) -{ - dap_global_db_cluster_add_notify_callback(dap_chain_net_get_mempool_cluster(a_chain), a_callback, a_cb_arg); -} - -static void s_nodelist_change_notify(dap_store_obj_t *a_obj, void *a_arg) -{ - dap_chain_net_t *l_net = a_arg; - dap_return_if_fail(a_obj->key && !dap_strcmp(l_net->pub.gdb_nodes, a_obj->group)); - char l_ts[DAP_TIME_STR_SIZE] = { '\0' }; - dap_nanotime_to_str_rfc822(l_ts, sizeof(l_ts), a_obj->timestamp); - if (dap_store_obj_get_type(a_obj) == DAP_GLOBAL_DB_OPTYPE_DEL) { - log_it(L_NOTICE, "Removed node %s from network %s at %s\n", - a_obj->key, l_net->pub.name, l_ts); - return; - } - dap_chain_node_info_t *l_node_info = (dap_chain_node_info_t *)a_obj->value; - assert(dap_chain_node_info_get_size(l_node_info) == a_obj->value_len); - log_it(L_NOTICE, "Added node "NODE_ADDR_FP_STR" [%s : %u] to network %s at %s\n", - NODE_ADDR_FP_ARGS_S(l_node_info->address), - l_node_info->ext_host, l_node_info->ext_port, - l_net->pub.name, l_ts); -} - -void dap_chain_net_add_nodelist_notify_callback(dap_chain_net_t *a_net, dap_store_obj_callback_notify_t a_callback, void *a_cb_arg) -{ - dap_global_db_cluster_add_notify_callback(PVT(a_net)->nodes_cluster, a_callback, a_cb_arg); -} - -void dap_chain_net_srv_order_add_notify_callback(dap_chain_net_t *a_net, dap_store_obj_callback_notify_t a_callback, void *a_cb_arg) +void dap_chain_net_srv_order_add_notify_callback(dap_chain_net_t *a_net, dap_store_obj_callback_notify_t a_callback, void *a_cb_arg) { dap_global_db_cluster_add_notify_callback(PVT(a_net)->orders_cluster, a_callback, a_cb_arg); } @@ -2958,24 +2555,6 @@ dap_chain_net_state_t dap_chain_net_get_state (dap_chain_net_t * l_net) return PVT(l_net)->state; } -/** - * @brief dap_chain_net_set_state - * @param l_net - * @param a_state - */ -void dap_chain_net_set_state(dap_chain_net_t *l_net, dap_chain_net_state_t a_state) -{ - assert(l_net); - log_it(L_DEBUG,"%s set state %s", l_net->pub.name, dap_chain_net_state_to_str(a_state)); - if(a_state == PVT(l_net)->state){ - return; - } - if(PVT(l_net)->state == NET_STATE_SYNC_CHAINS) - dap_leger_load_end(l_net->pub.ledger); - PVT(l_net)->state = a_state; - dap_proc_thread_callback_add(NULL, s_net_states_proc, l_net); -} - dap_chain_cell_id_t * dap_chain_net_get_cur_cell( dap_chain_net_t * l_net) { return PVT(l_net)->node_info ? &PVT(l_net)->node_info->cell_id: 0; @@ -3407,3 +2986,419 @@ decree_table_t **dap_chain_net_get_decrees(dap_chain_net_t *a_net) { anchor_table_t **dap_chain_net_get_anchors(dap_chain_net_t *a_net) { return a_net ? &(PVT(a_net)->anchors) : NULL; } + +/*------------------------------------State machine block------------------------------------*/ + +/** + * @brief try net to go online + * @param a_net dap_chain_net_t *: network + * @return 0 if ok + **/ +static int s_net_try_online(dap_chain_net_t *a_net) +{ +// sanity check + dap_return_val_if_pass(!a_net || !PVT(a_net), -1); +// func work + dap_chain_net_t *l_net = a_net; + dap_chain_net_pvt_t * l_net_pvt = PVT(l_net); + dap_chain_net_state_go_to(l_net, NET_STATE_ONLINE); + log_it(L_INFO, "Network \"%s\" goes online",l_net->pub.name); + return 0; +} + +/** + * @brief + * change all network states according to auto-online settings + */ +void dap_chain_net_try_online_all() { + int32_t l_ret = 0; + + if(!HASH_COUNT(s_net_items)){ + log_it(L_ERROR, "Can't find any nets"); + return; + } + if (!dap_config_get_item_bool_default(g_config ,"general", "auto_online", false)) { + log_it(L_DEBUG, "Auto online is off in config"); + return; + } + dap_chain_net_item_t *l_net_items_current = NULL, *l_net_items_tmp = NULL; + HASH_ITER(hh, s_net_items, l_net_items_current, l_net_items_tmp) { + if( (l_ret = s_net_try_online(l_net_items_current->chain_net)) ) { + log_it(L_ERROR, "Can't try online state for net %s. Finished with (%d) error code.", l_net_items_current->name, l_ret); + } + } +} + +static const uint64_t s_fork_sync_step = 20; // TODO get it from config + +static void s_ch_in_pkt_callback(dap_stream_ch_t *a_ch, uint8_t a_type, const void *a_data, size_t a_data_size, void *a_arg) +{ + debug_if(s_debug_more, L_DEBUG, "Got IN sync packet type %hhu size %zu from addr " NODE_ADDR_FP_STR, + a_type, a_data_size, NODE_ADDR_FP_ARGS_S(a_ch->stream->node)); + dap_chain_net_t *l_net = a_arg; + dap_chain_net_pvt_t *l_net_pvt = PVT(l_net); + if (l_net_pvt->state == NET_STATE_LINKS_ESTABLISHED) + l_net_pvt->state = NET_STATE_SYNC_CHAINS; + + switch (a_type) { + case DAP_CHAIN_CH_PKT_TYPE_CHAIN_SUMMARY: + case DAP_CHAIN_CH_PKT_TYPE_CHAIN_MISS: + case DAP_CHAIN_CH_PKT_TYPE_CHAIN: + case DAP_CHAIN_CH_PKT_TYPE_SYNCED_CHAIN: + // TODO sync state & address checking + break; + default: + break; + } + + switch (a_type) { + case DAP_CHAIN_CH_PKT_TYPE_ERROR: + if (!l_net_pvt->sync_context.cur_chain) { + log_it(L_DEBUG, "Got ERROR paket with NO chain net %s", l_net->pub.name); + return; + } + log_it(L_DEBUG, "Got ERROR paket to %s chain in net %s", l_net_pvt->sync_context.cur_chain->name, l_net->pub.name); + l_net_pvt->sync_context.cur_chain->state = CHAIN_SYNC_STATE_ERROR; + return; + + case DAP_CHAIN_CH_PKT_TYPE_SYNCED_CHAIN: + if (!l_net_pvt->sync_context.cur_chain) { + log_it(L_DEBUG, "Got SYNCED_CHAIN paket with NO chain net %s", l_net->pub.name); + return; + } + log_it(L_DEBUG, "Got SYNCED_CHAIN paket to %s chain net %s", l_net_pvt->sync_context.cur_chain->name, l_net->pub.name); + l_net_pvt->sync_context.cur_chain->state = CHAIN_SYNC_STATE_SYNCED; + l_net_pvt->sync_context.cur_chain->atom_num_last = l_net_pvt->sync_context.cur_chain->callback_count_atom(l_net_pvt->sync_context.cur_chain); + return; + + case DAP_CHAIN_CH_PKT_TYPE_CHAIN_MISS: { + if (!l_net_pvt->sync_context.cur_chain) + return; + dap_chain_ch_miss_info_t *l_miss_info = (dap_chain_ch_miss_info_t *)(((dap_chain_ch_pkt_t *)(a_data))->data); + if (!dap_hash_fast_compare(&l_miss_info->missed_hash, &l_net_pvt->sync_context.requested_atom_hash)) { + char l_missed_hash_str[DAP_HASH_FAST_STR_SIZE]; + dap_hash_fast_to_str(&l_miss_info->missed_hash, l_missed_hash_str, DAP_HASH_FAST_STR_SIZE); + log_it(L_WARNING, "Get irrelevant chain sync MISSED packet with missed hash %s, but requested hash is %s", + l_missed_hash_str, + dap_hash_fast_to_str_static(&l_net_pvt->sync_context.requested_atom_hash)); + dap_stream_ch_write_error_unsafe(a_ch, l_net->pub.id, + l_net_pvt->sync_context.cur_chain->id, + l_net_pvt->sync_context.cur_cell + ? l_net_pvt->sync_context.cur_cell->id + : c_dap_chain_cell_id_null, + DAP_CHAIN_CH_ERROR_INCORRECT_SYNC_SEQUENCE); + return; + } + dap_chain_atom_iter_t *l_iter = l_net_pvt->sync_context.cur_chain->callback_atom_iter_create( + l_net_pvt->sync_context.cur_chain, + l_net_pvt->sync_context.cur_cell + ? l_net_pvt->sync_context.cur_cell->id + : c_dap_chain_cell_id_null, + NULL); + if (!l_iter) { + log_it(L_CRITICAL, "%s", c_error_memory_alloc); + dap_stream_ch_write_error_unsafe(a_ch, l_net->pub.id, + l_net_pvt->sync_context.cur_chain->id, + l_net_pvt->sync_context.cur_cell + ? l_net_pvt->sync_context.cur_cell->id + : c_dap_chain_cell_id_null, + DAP_CHAIN_CH_ERROR_OUT_OF_MEMORY); + return; + } + dap_chain_atom_ptr_t l_atom = l_net_pvt->sync_context.cur_chain->callback_atom_find_by_hash(l_iter, &l_miss_info->last_hash, NULL); + if (l_atom && l_iter->cur_num == l_miss_info->last_num) { // We already have this subchain in our chain + l_net_pvt->sync_context.cur_chain->state = CHAIN_SYNC_STATE_SYNCED; + l_net_pvt->sync_context.cur_chain->atom_num_last = l_miss_info->last_num; + return; + } + dap_chain_ch_sync_request_t l_request = {}; + l_request.num_from = l_net_pvt->sync_context.requested_atom_num > s_fork_sync_step + ? l_net_pvt->sync_context.requested_atom_num - s_fork_sync_step + : 0; + if (l_request.num_from) { + l_atom = l_net_pvt->sync_context.cur_chain->callback_atom_get_by_num(l_iter, l_request.num_from); + assert(l_atom); + l_request.hash_from = *l_iter->cur_hash; + } + l_net_pvt->sync_context.cur_chain->callback_atom_iter_delete(l_iter); + debug_if(s_debug_more, L_INFO, "Send sync request to node " NODE_ADDR_FP_STR + " for net %s and chain %s, hash from %s, num from %" DAP_UINT64_FORMAT_U, + NODE_ADDR_FP_ARGS_S(l_net_pvt->sync_context.current_link), + l_net->pub.name, l_net_pvt->sync_context.cur_chain->name, + dap_hash_fast_to_str_static(&l_request.hash_from), l_request.num_from); + dap_chain_ch_pkt_write_unsafe(a_ch, + DAP_CHAIN_CH_PKT_TYPE_CHAIN_REQ, + l_net->pub.id, + l_net_pvt->sync_context.cur_chain->id, + l_net_pvt->sync_context.cur_cell + ? l_net_pvt->sync_context.cur_cell->id + : c_dap_chain_cell_id_null, + &l_request, + sizeof(l_request), + DAP_CHAIN_CH_PKT_VERSION_CURRENT); + l_net_pvt->sync_context.requested_atom_hash = l_request.hash_from; + l_net_pvt->sync_context.requested_atom_num = l_request.num_from; + } + default: + break; + } + l_net_pvt->sync_context.stage_last_activity = dap_time_now(); +} + +static void s_ch_out_pkt_callback(dap_stream_ch_t *a_ch, uint8_t a_type, const void *a_data, size_t a_data_size, void *a_arg) +{ + debug_if(s_debug_more, L_DEBUG, "Sent OUT sync packet type %hhu size %zu to addr " NODE_ADDR_FP_STR, + a_type, a_data_size, NODE_ADDR_FP_ARGS_S(a_ch->stream->node)); + dap_chain_net_t *l_net = a_arg; + dap_chain_net_pvt_t *l_net_pvt = PVT(l_net); + switch (a_type) { + case DAP_CHAIN_CH_PKT_TYPE_ERROR: + l_net_pvt->sync_context.cur_chain->state = CHAIN_SYNC_STATE_ERROR; + break; + default: + break; + } + l_net_pvt->sync_context.stage_last_activity = dap_time_now(); +} + + +static int s_restart_sync_chains(dap_chain_net_t *a_net) +{ + // sanity check + dap_return_val_if_pass(!a_net || !PVT(a_net), -1); + dap_chain_net_pvt_t *l_net_pvt = PVT(a_net); + + dap_cluster_t *l_cluster = dap_cluster_by_mnemonim(a_net->pub.name); + if (!dap_stream_node_addr_is_blank(&l_net_pvt->sync_context.current_link)) { + dap_stream_ch_del_notifier(&l_net_pvt->sync_context.current_link, DAP_CHAIN_CH_ID, + DAP_STREAM_PKT_DIR_IN, s_ch_in_pkt_callback, a_net); + dap_stream_ch_del_notifier(&l_net_pvt->sync_context.current_link, DAP_CHAIN_CH_ID, + DAP_STREAM_PKT_DIR_OUT, s_ch_out_pkt_callback, a_net); + } + l_net_pvt->sync_context.current_link = dap_cluster_get_random_link(l_cluster); + if (dap_stream_node_addr_is_blank(&l_net_pvt->sync_context.current_link)) { + log_it(L_DEBUG, "No links in net %s cluster", a_net->pub.name); + return -2; // No links in cluster + } + l_net_pvt->sync_context.cur_chain = a_net->pub.chains; + if (!l_net_pvt->sync_context.cur_chain) { + log_it(L_ERROR, "No chains in net %s", a_net->pub.name); + return -3; + } + dap_stream_ch_add_notifier(&l_net_pvt->sync_context.current_link, DAP_CHAIN_CH_ID, + DAP_STREAM_PKT_DIR_IN, s_ch_in_pkt_callback, a_net); + dap_stream_ch_add_notifier(&l_net_pvt->sync_context.current_link, DAP_CHAIN_CH_ID, + DAP_STREAM_PKT_DIR_OUT, s_ch_out_pkt_callback, a_net); + dap_chain_t *l_chain = NULL; + DL_FOREACH(a_net->pub.chains, l_chain) { + l_chain->state = CHAIN_SYNC_STATE_IDLE; + } + l_net_pvt->sync_context.stage_last_activity = dap_time_now(); + return 0; +} + +static dap_chain_t *s_switch_sync_chain(dap_chain_net_t *a_net) +{ +// sanity check + dap_return_val_if_pass(!a_net || !PVT(a_net), NULL); + dap_chain_net_pvt_t *l_net_pvt = PVT(a_net); +// func work + dap_chain_t *l_curr_chain = NULL; + for (l_curr_chain = a_net->pub.chains; l_curr_chain && l_curr_chain->state == CHAIN_SYNC_STATE_SYNCED; l_curr_chain = l_curr_chain->next) { + // find last not synced chain + } + l_net_pvt->sync_context.cur_chain = l_curr_chain; + if (l_curr_chain) { + log_it(L_DEBUG, "Go to chain \"%s\" for net %s", l_curr_chain->name, l_curr_chain->net_name); + return l_curr_chain; + } + log_it(L_DEBUG, "Go to next chain: <NULL>"); + if (l_net_pvt->state_target != NET_STATE_ONLINE) { + dap_chain_net_state_go_to(a_net, NET_STATE_OFFLINE); + return NULL; + } + dap_chain_net_state_t l_prev_state = l_net_pvt->state; + l_net_pvt->state = NET_STATE_ONLINE; + s_net_states_proc(a_net); + if(l_prev_state == NET_STATE_SYNC_CHAINS) + dap_leger_load_end(a_net->pub.ledger); + return NULL; +} + +static dap_chain_sync_state_t s_sync_context_state_forming(dap_chain_t *a_chains) +{ + dap_chain_sync_state_t l_ret = CHAIN_SYNC_STATE_SYNCED; + dap_chain_t *l_chain = NULL; + DL_FOREACH(a_chains, l_chain) { + l_ret = dap_max(l_ret, l_chain->state); + } + return l_ret; +} + +static void s_sync_timer_callback(void *a_arg) +{ + dap_chain_net_t *l_net = a_arg; + dap_chain_net_pvt_t *l_net_pvt = PVT(l_net); + if (l_net_pvt->state_target == NET_STATE_OFFLINE) // if offline no need sync + return; + l_net_pvt->sync_context.state = s_sync_context_state_forming(l_net->pub.chains); + if ( // check if need restart sync chains + l_net_pvt->sync_context.state == CHAIN_SYNC_STATE_ERROR || + dap_time_now() - l_net_pvt->sync_context.stage_last_activity > l_net_pvt->sync_context.sync_idle_time + ) { + if (s_restart_sync_chains(l_net)) { + log_it(L_INFO, "Can't start sync chains in net %s, wait seccond attempt", l_net->pub.name); + return; + } + } else if (l_net_pvt->state == NET_STATE_ONLINE && l_net_pvt->sync_context.state == CHAIN_SYNC_STATE_SYNCED) { + return; + } + if (!s_switch_sync_chain(l_net)) { // return if all chans synced + log_it(L_DEBUG, "All chains in net %s synced, no need new sync request", l_net->pub.name); + return; + } + if (l_net_pvt->sync_context.cur_chain->state == CHAIN_SYNC_STATE_WAITING) { + return; + } + if (l_net_pvt->sync_context.cur_chain->callback_load_from_gdb) { + // This type of chain is GDB based and not synced by chains protocol + log_it(L_DEBUG, "Chain %s in net %s will sync from gdb", l_net_pvt->sync_context.cur_chain->name, l_net->pub.name); + l_net_pvt->sync_context.cur_chain->state = CHAIN_SYNC_STATE_SYNCED; + return; + } + + l_net_pvt->sync_context.cur_cell = l_net_pvt->sync_context.cur_chain->cells; + l_net_pvt->sync_context.cur_chain->state = CHAIN_SYNC_STATE_WAITING; + dap_chain_ch_sync_request_t l_request = {}; + uint64_t l_last_num = l_request.num_from; + if (!dap_chain_get_atom_last_hash_num(l_net_pvt->sync_context.cur_chain, + l_net_pvt->sync_context.cur_cell + ? l_net_pvt->sync_context.cur_cell->id + : c_dap_chain_cell_id_null, + &l_request.hash_from, + &l_last_num)) { + log_it(L_ERROR, "Can't get last atom hash and number for chain %s with net %s", l_net_pvt->sync_context.cur_chain->name, + l_net->pub.name); + return; + } + + dap_chain_ch_pkt_t *l_chain_pkt = dap_chain_ch_pkt_new(l_net->pub.id, l_net_pvt->sync_context.cur_chain->id, + l_net_pvt->sync_context.cur_cell ? l_net_pvt->sync_context.cur_cell->id : c_dap_chain_cell_id_null, + &l_request, sizeof(l_request), DAP_CHAIN_CH_PKT_VERSION_CURRENT); + if (!l_chain_pkt) { + log_it(L_CRITICAL, "%s", c_error_memory_alloc); + return; + } + log_it(L_INFO, "Start synchronization process with " NODE_ADDR_FP_STR + " for net %s and chain %s, last hash %s, last num %" DAP_UINT64_FORMAT_U, + NODE_ADDR_FP_ARGS_S(l_net_pvt->sync_context.current_link), + l_net->pub.name, l_net_pvt->sync_context.cur_chain->name, + dap_hash_fast_to_str_static(&l_request.hash_from), l_last_num); + dap_stream_ch_pkt_send_by_addr(&l_net_pvt->sync_context.current_link, DAP_CHAIN_CH_ID, + DAP_CHAIN_CH_PKT_TYPE_CHAIN_REQ, l_chain_pkt, + dap_chain_ch_pkt_get_size(l_chain_pkt)); + l_net_pvt->sync_context.requested_atom_hash = l_request.hash_from; + l_net_pvt->sync_context.requested_atom_num = l_last_num; + DAP_DELETE(l_chain_pkt); +} + +/** + * @brief s_net_states_proc + * @param l_net + */ +static bool s_net_states_proc(void *a_arg) +{ + bool l_repeat_after_exit = false; // If true - repeat on next iteration of proc thread loop + dap_chain_net_t *l_net = (dap_chain_net_t *) a_arg; + assert(l_net); + dap_chain_net_pvt_t *l_net_pvt = PVT(l_net); + assert(l_net_pvt); + if (l_net_pvt->state_target == NET_STATE_OFFLINE) { + if(l_net_pvt->state == NET_STATE_SYNC_CHAINS) + dap_leger_load_end(l_net->pub.ledger); + l_net_pvt->state = NET_STATE_OFFLINE; + } + + switch ((dap_chain_net_state_t)l_net_pvt->state) { + // State OFFLINE where we don't do anything + case NET_STATE_OFFLINE: { + log_it(L_NOTICE,"%s.state: %s", l_net->pub.name, c_net_states[l_net_pvt->state]); + // delete all links + if ( l_net_pvt->state_target != NET_STATE_OFFLINE ){ + l_net_pvt->state = NET_STATE_LINKS_PREPARE; + l_repeat_after_exit = true; + } + } break; + + case NET_STATE_LINKS_PREPARE: + case NET_STATE_LINKS_CONNECTING: + case NET_STATE_LINKS_ESTABLISHED: + case NET_STATE_SYNC_CHAINS: + case NET_STATE_ONLINE: + log_it(L_INFO,"%s.state: %s", l_net->pub.name, c_net_states[l_net_pvt->state]); + break; + default: + log_it(L_DEBUG, "Unprocessed state"); + } + s_net_states_notify(l_net); + return l_repeat_after_exit; +} + +/** + * @brief set current network state to F_DAP_CHAIN_NET_GO_SYNC + * + * @param a_net dap_chain_net_t network object + * @param a_new_state dap_chain_net_state_t new network state + * @return int + */ +int dap_chain_net_state_go_to(dap_chain_net_t *a_net, dap_chain_net_state_t a_new_state) +{ + if (PVT(a_net)->load_mode) { + log_it(L_ERROR, "Can't change state of loading network '%s'", a_net->pub.name); + return -1; + } + if (PVT(a_net)->state_target == a_new_state) { + log_it(L_NOTICE, "Network %s already %s state %s", a_net->pub.name, + PVT(a_net)->state == a_new_state ? "have" : "going to", dap_chain_net_state_to_str(a_new_state)); + return 0; + } + //PVT(a_net)->flags |= F_DAP_CHAIN_NET_SYNC_FROM_ZERO; // TODO set this flag according to -mode argument from command line + PVT(a_net)->state_target = a_new_state; + if (a_new_state == NET_STATE_OFFLINE) { + char l_err_str[] = "ERROR_NET_IS_OFFLINE"; + size_t l_error_size = sizeof(dap_stream_ch_chain_net_pkt_t) + sizeof(l_err_str); + dap_stream_ch_chain_net_pkt_t *l_error = DAP_NEW_STACK_SIZE(dap_stream_ch_chain_net_pkt_t, l_error_size); + l_error->hdr.version = DAP_STREAM_CH_CHAIN_NET_PKT_VERSION; + l_error->hdr.net_id = a_net->pub.id; + l_error->hdr.data_size = sizeof(l_err_str); + memcpy(l_error->data, l_err_str, sizeof(l_err_str)); + dap_cluster_broadcast(PVT(a_net)->nodes_cluster->links_cluster, DAP_STREAM_CH_CHAIN_NET_ID, + DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_ERROR, l_error, l_error_size, NULL, 0); + dap_link_manager_set_net_condition(a_net->pub.id.uint64, false); + dap_chain_esbocs_stop_timer(a_net->pub.id); + } else if (PVT(a_net)->state == NET_STATE_OFFLINE) { + dap_link_manager_set_net_condition(a_net->pub.id.uint64, true); + for (uint16_t i = 0; i < PVT(a_net)->permanent_links_count; ++i) { + dap_link_info_t *l_permalink_info = PVT(a_net)->permanent_links[i]; + if (dap_chain_net_link_add(a_net, &l_permalink_info->node_addr, l_permalink_info->uplink_addr, l_permalink_info->uplink_port)) { + log_it(L_ERROR, "Can't create permanent link to addr " NODE_ADDR_FP_STR, NODE_ADDR_FP_ARGS_S(l_permalink_info->node_addr)); + continue; + } + PVT(a_net)->state = NET_STATE_LINKS_CONNECTING; + } + if (a_new_state == NET_STATE_ONLINE) { + dap_chain_esbocs_start_timer(a_net->pub.id); + PVT(a_net)->sync_context.current_link.uint64 = 0; + PVT(a_net)->sync_context.cur_chain = NULL; + PVT(a_net)->sync_context.cur_cell = NULL; + } + } + return dap_proc_thread_callback_add(NULL, s_net_states_proc, a_net); +} + +DAP_INLINE dap_chain_net_state_t dap_chain_net_get_target_state(dap_chain_net_t *a_net) +{ + return PVT(a_net)->state_target; +} + +/*------------------------------------State machine block end---------------------------------*/ \ No newline at end of file diff --git a/modules/net/dap_chain_net_decree.c b/modules/net/dap_chain_net_decree.c index 616e9558aadd0334dd93347c079ea3752bd3c8c8..c96ccaf73e8625175509fc78fc8e77fa90a68d44 100644 --- a/modules/net/dap_chain_net_decree.c +++ b/modules/net/dap_chain_net_decree.c @@ -445,15 +445,23 @@ static int s_common_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain break; dap_chain_net_srv_stake_key_delegate(a_net, &l_addr, &l_hash, l_value, &l_node_addr); break; - case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_INVALIDATE: + case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_INVALIDATE: { if (dap_chain_datum_decree_get_stake_signing_addr(a_decree, &l_addr)){ log_it(L_WARNING,"Can't get signing address from decree."); return -105; } + + uint16_t l_current_count = dap_chain_net_srv_stake_get_total_keys(a_net->pub.id, NULL); + uint16_t l_min_count = dap_chain_esbocs_get_min_validators_count(a_net->pub.id); + if (l_current_count == l_min_count) { + log_it(L_WARNING, "Can't invalidate validator cause min validators count %hu will become less than total count for net %s", + l_current_count, a_net->pub.name); + return -116; + } if (!a_apply) break; dap_chain_net_srv_stake_key_invalidate(&l_addr); - break; + } break; case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_MIN_VALUE: if (dap_chain_datum_decree_get_stake_min_value(a_decree, &l_value)){ log_it(L_WARNING,"Can't get min stake value from decree."); @@ -463,7 +471,7 @@ static int s_common_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain break; dap_chain_net_srv_stake_set_allowed_min_value(a_net->pub.id, l_value); break; - case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_MIN_VALIDATORS_COUNT: + case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_MIN_VALIDATORS_COUNT: { if (dap_chain_datum_decree_get_stake_min_signers_count(a_decree, &l_value)){ log_it(L_WARNING,"Can't get min stake value from decree."); return -105; @@ -477,10 +485,17 @@ static int s_common_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain log_it(L_WARNING, "Can't apply this decree to specified chain"); return -115; } + uint16_t l_decree_count = (uint16_t)dap_chain_uint256_to(l_value); + uint16_t l_current_count = dap_chain_net_srv_stake_get_total_keys(a_net->pub.id, NULL); + if (l_decree_count > l_current_count) { + log_it(L_WARNING, "Minimum validators count by decree %hu is greater than total validators count %hu in network %s", + l_decree_count, l_current_count, a_net->pub.name); + return -116; + } if (!a_apply) break; - dap_chain_esbocs_set_min_validators_count(l_chain, (uint16_t)dap_chain_uint256_to(l_value)); - break; + dap_chain_esbocs_set_min_validators_count(l_chain, l_decree_count); + } break; case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_BAN: { if (dap_chain_datum_decree_get_ban_addr(a_decree, &l_ban_addr)) { log_it(L_WARNING, "Can't get ban address from decree."); diff --git a/modules/net/include/dap_chain_ledger.h b/modules/net/include/dap_chain_ledger.h index 2993133a1dd253fb7e99d9e1a8f1ac5959d1568b..b7e2418cf9a8f599215455b7aa07f4e667af957e 100644 --- a/modules/net/include/dap_chain_ledger.h +++ b/modules/net/include/dap_chain_ledger.h @@ -89,6 +89,7 @@ typedef enum dap_ledger_check_error { DAP_LEDGER_TX_CHECK_UNEXPECTED_TOKENIZED_OUT, DAP_LEDGER_TX_CHECK_NOT_ENOUGH_FEE, DAP_LEDGER_TX_CHECK_NOT_ENOUGH_TAX, + DAP_LEDGER_TX_CHECK_FOR_REMOVING_CANT_FIND_TX, /* Emisssion check return codes */ DAP_LEDGER_EMISSION_CHECK_VALUE_EXCEEDS_CURRENT_SUPPLY, DAP_LEDGER_EMISSION_CHECK_LEGACY_FORBIDDEN, @@ -145,6 +146,7 @@ DAP_STATIC_INLINE const char *dap_ledger_check_error_str(dap_ledger_check_error_ case DAP_LEDGER_TX_CHECK_UNEXPECTED_TOKENIZED_OUT: return "Tokenized out is forbidden for single-channel trandactions"; case DAP_LEDGER_TX_CHECK_NOT_ENOUGH_FEE: return "Not enough network fee for transaction processing"; case DAP_LEDGER_TX_CHECK_NOT_ENOUGH_TAX: return "Not enough sovereign tax provided with current transaction"; + case DAP_LEDGER_TX_CHECK_FOR_REMOVING_CANT_FIND_TX: return "Can't find tx in ledger for removing."; /* Emisssion check return codes */ case DAP_LEDGER_EMISSION_CHECK_VALUE_EXCEEDS_CURRENT_SUPPLY: return "Value of emission execeeds current token supply"; case DAP_LEDGER_EMISSION_CHECK_LEGACY_FORBIDDEN: return "Legacy type of emissions are present for old chains comliance only"; diff --git a/modules/net/include/dap_chain_net.h b/modules/net/include/dap_chain_net.h index 720f6cb5f4c9be689c1ba86943b2fc6227b16198..904ea35a28d734a9b545c4aa082e4f6dd1292c26 100644 --- a/modules/net/include/dap_chain_net.h +++ b/modules/net/include/dap_chain_net.h @@ -101,7 +101,6 @@ void dap_chain_net_try_online_all(); int dap_chain_net_state_go_to(dap_chain_net_t * a_net, dap_chain_net_state_t a_new_state); dap_chain_net_state_t dap_chain_net_get_target_state(dap_chain_net_t *a_net); -void dap_chain_net_set_state ( dap_chain_net_t * l_net, dap_chain_net_state_t a_state); dap_chain_net_state_t dap_chain_net_get_state ( dap_chain_net_t * l_net); inline static int dap_chain_net_start(dap_chain_net_t * a_net){ return dap_chain_net_state_go_to(a_net,NET_STATE_ONLINE); } diff --git a/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c b/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c index 494ae6cd9eab56720468c56ea16bdb808b801a69..2efa8490bfb650e3268f9e8e8e4595c6a79d508c 100644 --- a/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c +++ b/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c @@ -505,13 +505,17 @@ int dap_chain_net_srv_stake_mark_validator_active(dap_chain_addr_t *a_signing_ad dap_return_val_if_fail(a_signing_addr, -1); dap_chain_net_srv_stake_t *l_srv_stake = s_srv_stake_by_net_id(a_signing_addr->net_id); dap_return_val_if_fail(l_srv_stake, -3); - dap_chain_net_srv_stake_item_t *l_stake = NULL; - HASH_FIND(hh, l_srv_stake->itemlist, &a_signing_addr->data.hash_fast, sizeof(dap_hash_fast_t), l_stake); - if (l_stake) { // public key delegated for this network + dap_chain_net_srv_stake_item_t *l_stake = NULL, *l_tmp; + if (!dap_hash_fast_is_blank(&a_signing_addr->data.hash_fast)) { + // Mark a single validator + HASH_FIND(hh, l_srv_stake->itemlist, &a_signing_addr->data.hash_fast, sizeof(dap_hash_fast_t), l_stake); + if (!l_stake) // public key isn't delegated for this network + return -2; l_stake->is_active = a_on_off; - return 0; - } - return -2; + } else // Mark all validators + HASH_ITER(hh, l_srv_stake->itemlist, l_stake, l_tmp) + l_stake->is_active = a_on_off; + return 0; } int dap_chain_net_srv_stake_verify_key_and_node(dap_chain_addr_t *a_signing_addr, dap_chain_node_addr_t *a_node_addr) @@ -2721,7 +2725,7 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, void **a_str_reply) l_arg_index++; dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-net", &l_net_str); if (!l_net_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'min_value' requires parameter -net"); + dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'max_weight' requires parameter -net"); return -3; } dap_chain_net_t *l_net = dap_chain_net_by_name(l_net_str); @@ -2738,7 +2742,7 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, void **a_str_reply) } dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-poa_cert", &l_cert_str); if (!l_cert_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'min_value' requires parameter -poa_cert"); + dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'max_weight' requires parameter -poa_cert"); return -3; } dap_cert_t *l_poa_cert = dap_cert_find_by_name(l_cert_str); @@ -2753,10 +2757,10 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, void **a_str_reply) dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-percent", &l_value_str); if (!l_value_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'min_value' requires parameter -percent"); + dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'max_weight' requires parameter -percent"); return -9; } - uint256_t l_value = dap_chain_balance_scan(l_value_str); + uint256_t l_value = dap_chain_coins_to_balance(l_value_str); if (IS_ZERO_256(l_value)) { dap_cli_server_cmd_set_reply_text(a_str_reply, "Unrecognized number in '-percent' param"); return -10; @@ -2944,7 +2948,8 @@ dap_chain_net_srv_stake_item_t *dap_chain_net_srv_stake_check_pkey_hash(dap_chai return NULL; } -size_t dap_chain_net_srv_stake_get_total_keys(dap_chain_net_id_t a_net_id, size_t *a_in_active_count){ +size_t dap_chain_net_srv_stake_get_total_keys(dap_chain_net_id_t a_net_id, size_t *a_in_active_count) +{ dap_chain_net_srv_stake_t *l_stake_rec = s_srv_stake_by_net_id(a_net_id); if (!l_stake_rec) return 0; diff --git a/modules/service/voting/dap_chain_net_srv_voting.c b/modules/service/voting/dap_chain_net_srv_voting.c index 84b2689868d76f591cbbc8a314f57e4d8f11ce93..7583bc2f1bd431cdeb18f5731eba9e8d42dd6b71 100644 --- a/modules/service/voting/dap_chain_net_srv_voting.c +++ b/modules/service/voting/dap_chain_net_srv_voting.c @@ -671,7 +671,7 @@ static int s_cli_voting(int a_argc, char **a_argv, void **a_str_reply) dap_time_t l_time_expire = 0; if (l_voting_expire_str) l_time_expire = dap_time_from_str_rfc822(l_voting_expire_str); - if(!l_time_expire){ + if(l_voting_expire_str && !l_time_expire){ dap_cli_server_cmd_set_reply_text(a_str_reply, "Wrong time format. -expire parameter must be in format \"Day Month Year HH:MM:SS Timezone\" e.g. \"19 August 2024 22:00:00 +00\""); return -104; } diff --git a/modules/type/blocks/dap_chain_cs_blocks.c b/modules/type/blocks/dap_chain_cs_blocks.c index e23d1a1e11164fa471818b7ba42bf1fe11c56a45..295b2e4b287ef4e73df3a1da72309ec2780da6e0 100644 --- a/modules/type/blocks/dap_chain_cs_blocks.c +++ b/modules/type/blocks/dap_chain_cs_blocks.c @@ -1758,8 +1758,7 @@ static dap_chain_atom_verify_res_t s_callback_atom_add(dap_chain_t * a_chain, da } debug_if(s_debug_more, L_DEBUG, "... new block %s", l_block_cache->block_hash_str); dap_chain_block_cache_t *l_prev_bcache = NULL, *l_tmp = NULL; - pthread_rwlock_wrlock(& PVT(l_blocks)->rwlock); - log_it(L_INFO, "New fork. Previous block hash %s, current block hash %s", dap_chain_hash_fast_to_str_static(&l_block_prev_hash), + pthread_rwlock_wrlock(& PVT(l_blocks)->rwlock); log_it(L_INFO, "New fork. Previous block hash %s, current block hash %s", dap_chain_hash_fast_to_str_static(&l_block_prev_hash), l_block_cache->block_hash_str); HASH_FIND(hh, PVT(l_blocks)->blocks, &l_block_prev_hash, sizeof(dap_hash_fast_t), l_prev_bcache); if (l_prev_bcache){