From 4cf7b626592594f02d79592a204c29e063879f6c Mon Sep 17 00:00:00 2001 From: Roman Khlopkov <roman.khlopkov@demlabs.net> Date: Tue, 21 Feb 2023 09:53:10 +0000 Subject: [PATCH] features-7694 --- .../chain-voting/dap_stream_ch_chain_voting.c | 18 +- .../include/dap_stream_ch_chain_voting.h | 10 +- .../consensus/esbocs/dap_chain_cs_esbocs.c | 456 +++++++++++------- .../esbocs/include/dap_chain_cs_esbocs.h | 6 +- modules/type/blocks/dap_chain_cs_blocks.c | 2 +- 5 files changed, 318 insertions(+), 174 deletions(-) diff --git a/modules/channel/chain-voting/dap_stream_ch_chain_voting.c b/modules/channel/chain-voting/dap_stream_ch_chain_voting.c index ff82afac35..399f98c579 100644 --- a/modules/channel/chain-voting/dap_stream_ch_chain_voting.c +++ b/modules/channel/chain-voting/dap_stream_ch_chain_voting.c @@ -61,7 +61,7 @@ static bool s_callback_pkt_in_call_all(UNUSED_ARG dap_proc_thread_t *a_thread, v for (size_t i = 0; i < s_pkt_in_callback_count; i++) { struct voting_pkt_in_callback *l_callback = s_pkt_in_callback + i; if (l_callback->packet_in_callback) { - l_callback->packet_in_callback(l_callback->arg, &l_voting_pkt->hdr.sender_node_addr, + l_callback->packet_in_callback(l_callback->arg, &l_voting_pkt->hdr.sender_node_addr, &l_voting_pkt->hdr.receiver_node_addr, &l_voting_pkt->hdr.data_hash, l_voting_pkt->data, l_voting_pkt->hdr.data_size); } } @@ -93,6 +93,7 @@ void dap_stream_ch_chain_voting_message_write(dap_chain_net_t *a_net, dap_chain_ return; } l_node_client->client->connect_on_demand = true; + l_node_client->client->always_reconnect = true; l_node_client_item = DAP_NEW_Z(struct voting_node_client_list); l_node_client_item->node_addr = *a_remote_node_addr; @@ -153,13 +154,20 @@ static void s_stream_ch_packet_in(dap_stream_ch_t *a_ch, void *a_arg) l_voting_pkt->hdr.data_size, l_ch_chain_voting->callback_notify_arg); } -dap_stream_ch_chain_voting_pkt_t *dap_stream_ch_chain_voting_pkt_new(uint64_t a_net_id, const void *a_data, size_t a_data_size) +dap_stream_ch_chain_voting_pkt_t *dap_stream_ch_chain_voting_pkt_new(uint64_t a_net_id, + dap_chain_node_addr_t *a_sender_node_addr, + dap_chain_node_addr_t *a_receiver_node_addr, + const void *a_data, size_t a_data_size) { dap_stream_ch_chain_voting_pkt_t *l_voting_pkt = DAP_NEW_Z_SIZE(dap_stream_ch_chain_voting_pkt_t, sizeof(dap_stream_ch_chain_voting_pkt_t) + a_data_size); l_voting_pkt->hdr.data_size = a_data_size; l_voting_pkt->hdr.version = 1; l_voting_pkt->hdr.net_id.uint64 = a_net_id; + if (a_sender_node_addr) + l_voting_pkt->hdr.sender_node_addr = *a_sender_node_addr; + if (a_receiver_node_addr) + l_voting_pkt->hdr.receiver_node_addr = *a_receiver_node_addr; dap_hash_fast(a_data, a_data_size, &l_voting_pkt->hdr.data_hash); if (a_data_size && a_data) memcpy(l_voting_pkt->data, a_data, a_data_size); @@ -167,9 +175,13 @@ dap_stream_ch_chain_voting_pkt_t *dap_stream_ch_chain_voting_pkt_new(uint64_t a_ } size_t dap_stream_ch_chain_voting_pkt_write_unsafe(dap_stream_ch_t *a_ch, uint8_t a_type, uint64_t a_net_id, + dap_chain_node_addr_t *a_sender_node_addr, + dap_chain_node_addr_t *a_receiver_node_addr, const void * a_data, size_t a_data_size) { - dap_stream_ch_chain_voting_pkt_t *l_voting_pkt = dap_stream_ch_chain_voting_pkt_new(a_net_id, a_data, a_data_size); + dap_stream_ch_chain_voting_pkt_t *l_voting_pkt = dap_stream_ch_chain_voting_pkt_new(a_net_id, a_sender_node_addr, + a_receiver_node_addr, a_data, + a_data_size); size_t l_ret = dap_stream_ch_pkt_write_unsafe(a_ch, a_type, l_voting_pkt, sizeof(l_voting_pkt) + a_data_size); DAP_DELETE(l_voting_pkt); return l_ret; diff --git a/modules/channel/chain-voting/include/dap_stream_ch_chain_voting.h b/modules/channel/chain-voting/include/dap_stream_ch_chain_voting.h index 6c361312b6..530fbd064e 100644 --- a/modules/channel/chain-voting/include/dap_stream_ch_chain_voting.h +++ b/modules/channel/chain-voting/include/dap_stream_ch_chain_voting.h @@ -13,7 +13,8 @@ #define DAP_STREAM_CH_CHAIN_VOTING_PKT_TYPE_DATA 0x01 #define DAP_STREAM_CH_CHAIN_VOTING_PKT_TYPE_TEST 0x02 -typedef void (*dap_chain_voting_ch_callback_t)(void *a_arg, dap_chain_node_addr_t *a_addr, dap_chain_hash_fast_t *a_data_hash, uint8_t *a_data, size_t a_data_size); +typedef void (*dap_chain_voting_ch_callback_t)(void *a_arg, dap_chain_node_addr_t *a_sender_addr, dap_chain_node_addr_t *a_receiver_addr, + dap_chain_hash_fast_t *a_data_hash, uint8_t *a_data, size_t a_data_size); typedef struct dap_stream_ch_chain_voting_pkt_hdr { uint8_t version; @@ -51,9 +52,14 @@ void dap_stream_ch_chain_voting_in_callback_add(void* a_arg, dap_chain_voting_ch void dap_stream_ch_chain_voting_message_write(dap_chain_net_t * a_net, dap_chain_node_addr_t *a_remote_node_addr, dap_stream_ch_chain_voting_pkt_t *a_voting_pkt); -dap_stream_ch_chain_voting_pkt_t *dap_stream_ch_chain_voting_pkt_new(uint64_t a_net_id, const void *a_data, size_t a_data_size); +dap_stream_ch_chain_voting_pkt_t *dap_stream_ch_chain_voting_pkt_new(uint64_t a_net_id, + dap_chain_node_addr_t *a_sender_node_addr, + dap_chain_node_addr_t *a_receiver_node_addr, + const void *a_data, size_t a_data_size); size_t dap_stream_ch_chain_voting_pkt_write_unsafe(dap_stream_ch_t *a_ch, uint8_t a_type, uint64_t a_net_id, + dap_chain_node_addr_t *a_sender_node_addr, + dap_chain_node_addr_t *a_receiver_node_addr, const void * a_data, size_t a_data_size); int dap_stream_ch_chain_voting_init(); diff --git a/modules/consensus/esbocs/dap_chain_cs_esbocs.c b/modules/consensus/esbocs/dap_chain_cs_esbocs.c index b001d5c6bf..bce0e7dbba 100644 --- a/modules/consensus/esbocs/dap_chain_cs_esbocs.c +++ b/modules/consensus/esbocs/dap_chain_cs_esbocs.c @@ -1,3 +1,4 @@ +#include <pthread.h> #include "utlist.h" #include "dap_timerfd.h" #include "rand/dap_rand.h" @@ -23,7 +24,7 @@ enum s_esbocs_session_state { static dap_list_t *s_validator_check(dap_chain_addr_t *a_addr, dap_list_t *a_validators); static void s_get_last_block_hash(dap_chain_t *a_chain, dap_chain_hash_fast_t *a_last_hash_ptr); static void s_session_state_change(dap_chain_esbocs_session_t *a_session, enum s_esbocs_session_state a_new_state, dap_time_t a_time); -static void s_session_packet_in(void * a_arg, dap_chain_node_addr_t * a_sender_node_addr, +static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_node_addr, dap_chain_node_addr_t *a_receiver_node_addr, dap_chain_hash_fast_t *a_data_hash, uint8_t *a_data, size_t a_data_size); static void s_session_round_clear(dap_chain_esbocs_session_t *a_session); static void s_session_round_new(dap_chain_esbocs_session_t *a_session); @@ -37,8 +38,10 @@ static bool s_session_timer(void *a_arg); static void s_message_send(dap_chain_esbocs_session_t *a_session, uint8_t a_message_type, dap_hash_fast_t *a_block_hash, const void *a_data, size_t a_data_size, dap_list_t *a_validators); static void s_message_chain_add(dap_chain_esbocs_session_t * a_session, - dap_chain_esbocs_message_t * a_message, - size_t a_message_size, dap_chain_hash_fast_t *a_message_hash); + dap_chain_esbocs_message_t * a_message, + size_t a_message_size, + dap_chain_hash_fast_t *a_message_hash, + dap_chain_addr_t *a_signing_addr); static int s_callback_new(dap_chain_t *a_chain, dap_config_t *a_chain_cfg); static void s_callback_delete(dap_chain_cs_blocks_t *a_blocks); @@ -46,7 +49,7 @@ static int s_callback_created(dap_chain_t *a_chain, dap_config_t *a_chain_net_cf static size_t s_callback_block_sign(dap_chain_cs_blocks_t *a_blocks, dap_chain_block_t **a_block_ptr, size_t a_block_size); static int s_callback_block_verify(dap_chain_cs_blocks_t *a_blocks, dap_chain_block_t *a_block, size_t a_block_size); -DAP_STATIC_INLINE const char *s_VOTING_MSG_type_to_str(uint8_t a_type) +DAP_STATIC_INLINE const char *s_voting_msg_type_to_str(uint8_t a_type) { switch (a_type) { case DAP_STREAM_CH_VOTING_MSG_TYPE_START_SYNC: return "START_SYNC"; @@ -98,20 +101,27 @@ static int s_callback_new(dap_chain_t *a_chain, dap_config_t *a_chain_cfg) { dap_chain_cs_blocks_new(a_chain, a_chain_cfg); dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(a_chain); - dap_chain_esbocs_t *l_esbocs = DAP_NEW_Z(dap_chain_esbocs_t); - l_blocks->_inheritor = l_esbocs; l_blocks->callback_delete = s_callback_delete; l_blocks->callback_block_verify = s_callback_block_verify; l_blocks->callback_block_sign = s_callback_block_sign; - l_esbocs->_pvt = DAP_NEW_Z(dap_chain_esbocs_pvt_t); + dap_chain_esbocs_t *l_esbocs = DAP_NEW_Z(dap_chain_esbocs_t); + l_esbocs->chain = a_chain; + l_esbocs->blocks = l_blocks; + dap_chain_esbocs_session_t *l_session = DAP_NEW_Z(dap_chain_esbocs_session_t); + l_session->chain = a_chain; + l_session->esbocs = l_esbocs; + + l_esbocs->session = l_session; + l_blocks->_inheritor = l_esbocs; + l_esbocs->_pvt = DAP_NEW_Z(dap_chain_esbocs_pvt_t); dap_chain_esbocs_pvt_t *l_esbocs_pvt = PVT(l_esbocs); l_esbocs_pvt->debug = dap_config_get_item_bool_default(a_chain_cfg, "esbocs", "consensus_debug", false); l_esbocs_pvt->poa_mode = dap_config_get_item_bool_default(a_chain_cfg, "esbocs", "poa_mode", false); l_esbocs_pvt->round_start_sync_timeout = dap_config_get_item_uint16_default(a_chain_cfg, "esbocs", "round_start_sync_timeout", 15); - l_esbocs_pvt->new_round_delay = dap_config_get_item_uint16(a_chain_cfg, "esbocs", "new_round_delay"); + l_esbocs_pvt->new_round_delay = dap_config_get_item_uint16_default(a_chain_cfg, "esbocs", "new_round_delay", 10); l_esbocs_pvt->round_attempts_max = dap_config_get_item_uint16_default(a_chain_cfg, "esbocs", "round_attempts_max", 4); l_esbocs_pvt->round_attempt_timeout = dap_config_get_item_uint16_default(a_chain_cfg, "esbocs", "round_attempt_timeout", 10); @@ -173,16 +183,16 @@ lb_err: return l_ret; } -static void s_atom_notifier(void *a_arg, UNUSED_ARG dap_chain_t *a_chain, UNUSED_ARG dap_chain_cell_id_t a_id, +static void s_new_atom_notifier(void *a_arg, UNUSED_ARG dap_chain_t *a_chain, UNUSED_ARG dap_chain_cell_id_t a_id, UNUSED_ARG void* a_atom, UNUSED_ARG size_t a_atom_size) { dap_chain_esbocs_session_t *l_session = a_arg; - pthread_rwlock_wrlock(&l_session->rwlock); + pthread_mutex_lock(&l_session->mutex); dap_chain_hash_fast_t l_last_block_hash; s_get_last_block_hash(l_session->chain, &l_last_block_hash); if (!dap_hash_fast_compare(&l_last_block_hash, &l_session->cur_round.last_block_hash)) s_session_round_new(l_session); - pthread_rwlock_unlock(&l_session->rwlock); + pthread_mutex_unlock(&l_session->mutex); } static int s_callback_created(dap_chain_t *a_chain, dap_config_t *a_chain_net_cfg) { @@ -224,19 +234,22 @@ static int s_callback_created(dap_chain_t *a_chain, dap_config_t *a_chain_net_cf return 0; } } else { - if (s_validator_check(&l_my_signing_addr, l_esbocs_pvt->poa_validators)) { + if (!s_validator_check(&l_my_signing_addr, l_esbocs_pvt->poa_validators)) { log_it(L_WARNING, "Signing key is not present in PoA certs list. Switch off validator mode"); return 0; } } - dap_chain_esbocs_session_t *l_session = DAP_NEW_Z(dap_chain_esbocs_session_t); - l_session->chain = a_chain; - l_session->esbocs = l_esbocs; + dap_chain_esbocs_session_t *l_session = l_esbocs->session; l_session->my_addr.uint64 = dap_chain_net_get_cur_addr_int(l_net); - pthread_rwlock_init(&l_session->rwlock, NULL); + l_session->my_signing_addr = l_my_signing_addr; + pthread_mutexattr_t l_mutex_attr; + pthread_mutexattr_init(&l_mutex_attr); + pthread_mutexattr_settype(&l_mutex_attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&l_session->mutex, &l_mutex_attr); + pthread_mutexattr_destroy(&l_mutex_attr); dap_stream_ch_chain_voting_in_callback_add(l_session, s_session_packet_in); - dap_chain_add_callback_notify(a_chain, s_atom_notifier, l_session); + dap_chain_add_callback_notify(a_chain, s_new_atom_notifier, l_session); s_session_round_new(l_session); log_it(L_INFO, "ESBOCS: init session for net:%s, chain:%s", a_chain->net_name, a_chain->name); @@ -252,7 +265,7 @@ static void s_callback_delete(dap_chain_cs_blocks_t *a_blocks) { dap_chain_esbocs_t *l_esbocs = DAP_CHAIN_ESBOCS(a_blocks); dap_chain_esbocs_session_t *l_session = l_esbocs->session; - pthread_rwlock_wrlock(&l_session->rwlock); + pthread_mutex_lock(&l_session->mutex); DL_DELETE(s_session_items, l_session); if (!s_session_items) dap_timerfd_delete(s_session_cs_timer); @@ -263,7 +276,7 @@ static void s_callback_delete(dap_chain_cs_blocks_t *a_blocks) dap_list_free_full(l_item->messages, NULL); DAP_DELETE(l_item); } - pthread_rwlock_unlock(&l_session->rwlock); + pthread_mutex_unlock(&l_session->mutex); DAP_DELETE(l_session); if (l_esbocs->_pvt) DAP_DELETE(l_esbocs->_pvt); @@ -353,42 +366,45 @@ static void s_get_last_block_hash(dap_chain_t *a_chain, dap_chain_hash_fast_t *a dap_chain_atom_iter_t *l_iter = a_chain->callback_atom_iter_create(a_chain, c_dap_chain_cell_id_null, false); dap_chain_atom_ptr_t *l_ptr_list = a_chain->callback_atom_iter_get_lasts(l_iter, NULL, NULL); DAP_DEL_Z(l_ptr_list); - *a_last_hash_ptr = *l_iter->cur_hash; + *a_last_hash_ptr = l_iter->cur_hash ? *l_iter->cur_hash : (dap_hash_fast_t){0}; a_chain->callback_atom_iter_delete(l_iter); } -static int s_addr_compare(const void *a_list_data, const void *a_user_data) +static int s_callback_addr_compare(const void *a_list_data, const void *a_user_data) { - return dap_chain_addr_compare(&((dap_chain_esbocs_validator_t *)a_list_data)->signing_addr, - (dap_chain_addr_t *)a_user_data); + return memcmp(&((dap_chain_esbocs_validator_t *)a_list_data)->signing_addr, + (dap_chain_addr_t *)a_user_data, sizeof(dap_chain_addr_t)); } static dap_list_t *s_validator_check(dap_chain_addr_t *a_addr, dap_list_t *a_validators) { - return dap_list_find_custom(a_validators, a_addr, s_addr_compare); + return dap_list_find_custom(a_validators, a_addr, s_callback_addr_compare); } static void s_session_send_startsync(dap_chain_esbocs_session_t *a_session) { dap_chain_hash_fast_t l_last_block_hash; s_get_last_block_hash(a_session->chain, &l_last_block_hash); - a_session->ts_round_sync_start = dap_time_now(); + a_session->ts_round_sync_start = dap_time_now(); if (!dap_hash_fast_compare(&l_last_block_hash, &a_session->cur_round.last_block_hash)) return; // My last block hash is different, so skip this round if (!s_validator_check(&a_session->my_signing_addr, a_session->cur_round.validators_list)) return; // I'm not a selected validator, just skip sync message + debug_if(PVT(a_session->esbocs)->debug, L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U"." + " Sent START_SYNC pkt, attempt %"DAP_UINT64_FORMAT_U, + a_session->chain->net_name, a_session->chain->name, a_session->cur_round.id, a_session->cur_round.sync_attempt); s_message_send(a_session, DAP_STREAM_CH_VOTING_MSG_TYPE_START_SYNC, &l_last_block_hash, - NULL, 0, a_session->cur_round.validators_list); - debug_if(PVT(a_session->esbocs)->debug, L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U" Sent START_SYNC pkt", - a_session->chain->net_name, a_session->chain->name, a_session->cur_round.id); + &a_session->cur_round.sync_attempt, sizeof(uint64_t), + a_session->cur_round.validators_list); } static bool s_session_send_startsync_on_timer(void *a_arg) { dap_chain_esbocs_session_t *l_session = a_arg; - pthread_rwlock_wrlock(&l_session->rwlock); + pthread_mutex_lock(&l_session->mutex); s_session_send_startsync(l_session); - pthread_rwlock_unlock(&l_session->rwlock); + l_session->sync_timer = NULL; + pthread_mutex_unlock(&l_session->mutex); return false; } @@ -410,16 +426,24 @@ static void s_session_round_clear(dap_chain_esbocs_session_t *a_session) a_session->cur_round = (dap_chain_esbocs_round_t){ .id = a_session->cur_round.id, - .last_block_hash = a_session->cur_round.last_block_hash + .attempt_num = 1, + .last_block_hash = a_session->cur_round.last_block_hash, + .sync_attempt = a_session->cur_round.sync_attempt }; - dap_timerfd_delete(a_session->sync_timer); } static void s_session_round_new(dap_chain_esbocs_session_t *a_session) { s_session_round_clear(a_session); a_session->cur_round.id++; + a_session->cur_round.sync_attempt++; + + dap_timerfd_delete(a_session->sync_timer); + a_session->sync_timer = NULL; a_session->state = DAP_CHAIN_ESBOCS_SESSION_STATE_WAIT_START; + a_session->ts_round_sync_start = 0; + a_session->ts_attempt_start = 0; + dap_hash_fast_t *l_seed_hash = NULL; dap_hash_fast_t l_last_block_hash; s_get_last_block_hash(a_session->chain, &l_last_block_hash); @@ -427,25 +451,26 @@ static void s_session_round_new(dap_chain_esbocs_session_t *a_session) !dap_hash_fast_compare(&l_last_block_hash, &a_session->cur_round.last_block_hash)) { l_seed_hash = &l_last_block_hash; a_session->cur_round.last_block_hash = l_last_block_hash; + a_session->cur_round.sync_attempt = 1; } a_session->cur_round.validators_list = s_get_validators_list(a_session, l_seed_hash); + bool l_round_already_started = a_session->round_fast_forward; if (s_validator_check(&a_session->my_signing_addr, a_session->cur_round.validators_list)) { //I am a current round validator dap_chain_esbocs_sync_item_t *l_item, *l_tmp; - bool l_round_already_started = false; HASH_FIND(hh, a_session->sync_items, &a_session->cur_round.last_block_hash, sizeof(dap_hash_fast_t), l_item); if (l_item) { - debug_if(PVT(a_session->esbocs)->debug, L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U" already started. Process sync messages", - a_session->chain->net_name, a_session->chain->name, - a_session->cur_round.id); + debug_if(PVT(a_session->esbocs)->debug, + L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U" already started. Process sync messages", + a_session->chain->net_name, a_session->chain->name, a_session->cur_round.id); l_round_already_started = true; for (dap_list_t *it = l_item->messages; it; it = it->next) { dap_hash_fast_t l_msg_hash; dap_chain_esbocs_message_t *l_msg = it->data; size_t l_msg_size = sizeof(*l_msg) + l_msg->hdr.sign_size + l_msg->hdr.message_size; dap_hash_fast(l_msg, l_msg_size, &l_msg_hash); - s_session_packet_in(a_session, NULL, &l_msg_hash, (uint8_t *)l_msg, l_msg_size); + s_session_packet_in(a_session, NULL, NULL, &l_msg_hash, (uint8_t *)l_msg, l_msg_size); } } HASH_ITER(hh, a_session->sync_items, l_item, l_tmp) { @@ -453,26 +478,25 @@ static void s_session_round_new(dap_chain_esbocs_session_t *a_session) dap_list_free_full(l_item->messages, NULL); DAP_DELETE(l_item); } - if (l_round_already_started) { - s_session_send_startsync(a_session); - return; - } - debug_if(PVT(a_session->esbocs)->debug, L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U" start. Syncing validators in %u seconds", - a_session->chain->net_name, a_session->chain->name, - a_session->cur_round.id, PVT(a_session->esbocs)->new_round_delay); + debug_if(PVT(a_session->esbocs)->debug, L_MSG, + "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U" start. Syncing validators in %u seconds", + a_session->chain->net_name, a_session->chain->name, + a_session->cur_round.id, l_round_already_started ? 0 : PVT(a_session->esbocs)->new_round_delay); } - if (PVT(a_session->esbocs)->new_round_delay) - a_session->sync_timer = dap_timerfd_start(PVT(a_session->esbocs)->new_round_delay, s_session_send_startsync_on_timer, a_session); + if (PVT(a_session->esbocs)->new_round_delay && !l_round_already_started) + a_session->sync_timer = dap_timerfd_start(PVT(a_session->esbocs)->new_round_delay * 1000, + s_session_send_startsync_on_timer, a_session); else s_session_send_startsync(a_session); + a_session->round_fast_forward = false; } static void s_session_attempt_new(dap_chain_esbocs_session_t *a_session) { - if (++a_session->cur_round.attempt_num > PVT(a_session->esbocs)->round_attempts_max ) { + if (a_session->cur_round.attempt_num++ > PVT(a_session->esbocs)->round_attempts_max ) { debug_if(PVT(a_session->esbocs)->debug, L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U"." - " Round finish by reason: attempts is out", + " Round finished by reason: attempts is out", a_session->chain->net_name, a_session->chain->name, a_session->cur_round.id); s_session_round_new(a_session); @@ -482,14 +506,15 @@ static void s_session_attempt_new(dap_chain_esbocs_session_t *a_session) dap_chain_esbocs_validator_t *l_validator = it->data; if (l_validator->is_synced && !l_validator->is_chosen) { // We have synced validator with no submitted candidate - debug_if(PVT(a_session->esbocs)->debug, L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U". Attempt:%hu is started" " Round finish by reason: attempts is out", + debug_if(PVT(a_session->esbocs)->debug, L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U". Attempt:%hu is started", a_session->chain->net_name, a_session->chain->name, a_session->cur_round.id, a_session->cur_round.attempt_num); s_session_state_change(a_session, DAP_CHAIN_ESBOCS_SESSION_STATE_WAIT_PROC, dap_time_now()); + return; } } debug_if(PVT(a_session->esbocs)->debug, L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U"." - " Round finish by reason: all synced validators already tryed its attempt", + " Round finished by reason: all synced validators already tryed its attempt", a_session->chain->net_name, a_session->chain->name, a_session->cur_round.id); s_session_round_new(a_session); @@ -627,33 +652,38 @@ static void s_session_state_change(dap_chain_esbocs_session_t *a_session, enum s static void s_session_proc_state(dap_chain_esbocs_session_t *a_session) { - if (pthread_rwlock_trywrlock(&a_session->rwlock) != 0) + if (pthread_mutex_trylock(&a_session->mutex) != 0) return; // Session is busy bool l_cs_debug = PVT(a_session->esbocs)->debug; dap_time_t l_time = dap_time_now(); switch (a_session->state) { - case DAP_CHAIN_ESBOCS_SESSION_STATE_WAIT_START: - if (l_time - a_session->ts_round_sync_start >= PVT(a_session->esbocs)->round_start_sync_timeout) { + case DAP_CHAIN_ESBOCS_SESSION_STATE_WAIT_START: { + dap_time_t l_round_timeout = PVT(a_session->esbocs)->round_start_sync_timeout; + bool l_round_skip = !s_validator_check(&a_session->my_signing_addr, a_session->cur_round.validators_list); + if (l_round_skip) + l_round_timeout += PVT(a_session->esbocs)->round_attempt_timeout * PVT(a_session->esbocs)->round_attempts_max; + if (a_session->ts_round_sync_start && l_time - a_session->ts_round_sync_start >= l_round_timeout) { if (a_session->cur_round.validators_synced_count * 3 >= dap_list_length(a_session->cur_round.validators_list) * 2) { a_session->cur_round.id = s_session_calc_current_round_id(a_session); debug_if(l_cs_debug, L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu." - " More than 2/3 of the validators are synchronized, wait to submit candidate", + " Minimum count of validators are synchronized, wait to submit candidate", a_session->chain->net_name, a_session->chain->name, a_session->cur_round.id, a_session->cur_round.attempt_num); s_session_state_change(a_session, DAP_CHAIN_ESBOCS_SESSION_STATE_WAIT_PROC, l_time); } else { // timeout start sync debug_if(l_cs_debug, L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu." - " Round finish by reason: can't synchronize 2/3 of the validators", + " Round finished by reason: %s", a_session->chain->net_name, a_session->chain->name, - a_session->cur_round.id, a_session->cur_round.attempt_num); + a_session->cur_round.id, a_session->cur_round.attempt_num, + l_round_skip ? "skipped" : "can't synchronize minimum number of validators"); s_session_round_new(a_session); } } - break; + } break; case DAP_CHAIN_ESBOCS_SESSION_STATE_WAIT_PROC: if (l_time - a_session->ts_attempt_start >= PVT(a_session->esbocs)->round_attempt_timeout) { debug_if(l_cs_debug, L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu." - " Attempt finish by reason: haven't cantidate submitted", + " Attempt finished by reason: haven't cantidate submitted", a_session->chain->net_name, a_session->chain->name, a_session->cur_round.id, a_session->cur_round.attempt_num); s_session_attempt_new(a_session); @@ -672,7 +702,7 @@ static void s_session_proc_state(dap_chain_esbocs_session_t *a_session) if(l_cs_debug) { char *l_candidate_hash_str = dap_chain_hash_fast_to_str_new(&a_session->cur_round.attempt_candidate_hash); log_it(L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu" - " Candidate:%s collected sings of more than 2/3 of the validators, so to sent a PRE_COMMIT", + " Candidate:%s collected sings of minimum number of validators, so to sent PRE_COMMIT", a_session->chain->net_name, a_session->chain->name, a_session->cur_round.id, a_session->cur_round.attempt_num, l_candidate_hash_str); DAP_DELETE(l_candidate_hash_str); @@ -681,7 +711,7 @@ static void s_session_proc_state(dap_chain_esbocs_session_t *a_session) break; } debug_if(l_cs_debug, L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu." - " Attempt finish by reason: cant't collect 2/3 validator signs", + " Attempt finish by reason: cant't collect minimum number of validator's signs", a_session->chain->net_name, a_session->chain->name, a_session->cur_round.id, a_session->cur_round.attempt_num); s_session_attempt_new(a_session); @@ -690,7 +720,7 @@ static void s_session_proc_state(dap_chain_esbocs_session_t *a_session) case DAP_CHAIN_ESBOCS_SESSION_STATE_WAIT_FINISH: if (l_time - a_session->ts_attempt_start >= PVT(a_session->esbocs)->round_attempt_timeout) { debug_if(l_cs_debug, L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu." - " Attempt finish by reason: cant't collect 2/3 validator precommits with same final hash", + " Attempt finisedh by reason: cant't collect minimum number of validator's precommits with same final hash", a_session->chain->net_name, a_session->chain->name, a_session->cur_round.id, a_session->cur_round.attempt_num); s_session_attempt_new(a_session); @@ -700,7 +730,7 @@ static void s_session_proc_state(dap_chain_esbocs_session_t *a_session) break; } - pthread_rwlock_unlock(&a_session->rwlock); + pthread_mutex_unlock(&a_session->mutex); } static bool s_session_timer(void *a_arg) @@ -714,8 +744,10 @@ static bool s_session_timer(void *a_arg) } static void s_message_chain_add(dap_chain_esbocs_session_t *a_session, - dap_chain_esbocs_message_t *a_message, - size_t a_message_size, dap_chain_hash_fast_t *a_message_hash) + dap_chain_esbocs_message_t *a_message, + size_t a_message_size, + dap_chain_hash_fast_t *a_message_hash, + dap_chain_addr_t *a_signing_addr) { dap_chain_esbocs_round_t *l_round = &a_session->cur_round; dap_chain_esbocs_message_item_t *l_message_item = DAP_NEW_Z(dap_chain_esbocs_message_item_t); @@ -725,6 +757,7 @@ static void s_message_chain_add(dap_chain_esbocs_session_t *a_session, l_message_item->message_hash = l_message_hash; } else l_message_item->message_hash = *a_message_hash; + l_message_item->signing_addr = *a_signing_addr; l_message_item->message = DAP_DUP_SIZE(a_message, a_message_size); HASH_ADD(hh, l_round->message_items, message_hash, sizeof(l_message_item->message_hash), l_message_item); } @@ -742,16 +775,17 @@ static void s_session_candidate_submit(dap_chain_esbocs_session_t *a_session) dap_hash_fast(l_candidate, l_candidate_size, &l_candidate_hash); if (PVT(a_session->esbocs)->debug) { char *l_candidate_hash_str = dap_chain_hash_fast_to_str_new(&l_candidate_hash); - log_it(L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U" Submit my candidate:%s", + log_it(L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu. Submit my candidate:%s", a_session->chain->net_name, a_session->chain->name, - a_session->cur_round.id, l_candidate_hash_str); + a_session->cur_round.id, a_session->cur_round.attempt_num, l_candidate_hash_str); DAP_DELETE(l_candidate_hash_str); } } else { // there is no my candidate, send null hash if (PVT(a_session->esbocs)->debug) - log_it(L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu I don't have a candidate. I submit a null candidate.", - a_session->chain->net_name, a_session->chain->name, - a_session->cur_round.id, a_session->cur_round.attempt_num); + log_it(L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu." + " I don't have a candidate. I submit a null candidate.", + a_session->chain->net_name, a_session->chain->name, + a_session->cur_round.id, a_session->cur_round.attempt_num); } s_message_send(a_session, DAP_STREAM_CH_VOTING_MSG_TYPE_SUBMIT, &l_candidate_hash, l_candidate, l_candidate_size, a_session->cur_round.validators_list); @@ -760,6 +794,7 @@ static void s_session_candidate_submit(dap_chain_esbocs_session_t *a_session) static void s_session_candidate_verify(dap_chain_esbocs_session_t *a_session, dap_chain_block_t *a_candidate, size_t a_candidate_size, dap_hash_fast_t *a_candidate_hash) { + a_session->processing_candidate = a_candidate; dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(a_session->chain); if (l_blocks->chain->callback_atom_verify(l_blocks->chain, a_candidate, a_candidate_size) == ATOM_ACCEPT) { // validation - OK, gen event Approve @@ -784,6 +819,7 @@ static void s_session_candidate_verify(dap_chain_esbocs_session_t *a_session, da DAP_DELETE(l_candidate_hash_str); } } + a_session->processing_candidate = NULL; } static void s_session_candidate_to_chain(dap_chain_esbocs_session_t *a_session, dap_chain_hash_fast_t *a_candidate_hash, @@ -864,7 +900,7 @@ static void s_session_round_finish(dap_chain_esbocs_session_t *a_session, dap_ch if (l_cs_debug) { char *l_finish_candidate_hash_str = dap_chain_hash_fast_to_str_new(&l_store->candidate_hash); char *l_finish_block_hash_str = dap_chain_hash_fast_to_str_new(&l_store->precommit_candidate_hash); - log_it(L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu My candidate:%s passed the consensus!\n" + log_it(L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Candidate:%s passed the consensus!\n" "Move block %s to chains", a_session->chain->net_name, a_session->chain->name, a_session->cur_round.id, a_session->cur_round.attempt_num, l_finish_candidate_hash_str, l_finish_block_hash_str); @@ -874,6 +910,18 @@ static void s_session_round_finish(dap_chain_esbocs_session_t *a_session, dap_ch s_session_candidate_to_chain(a_session, &l_store->precommit_candidate_hash, l_store->candidate, l_store->candidate_size); } +void s_session_sync_queue_add(dap_chain_esbocs_session_t *a_session, dap_chain_esbocs_message_t *a_message, size_t a_message_size) +{ + dap_chain_esbocs_sync_item_t *l_sync_item; + HASH_FIND(hh, a_session->sync_items, &a_message->hdr.candidate_hash, sizeof(dap_hash_fast_t), l_sync_item); + if (!l_sync_item) { + l_sync_item = DAP_NEW_Z(dap_chain_esbocs_sync_item_t); + l_sync_item->last_block_hash = a_message->hdr.candidate_hash; + HASH_ADD(hh, a_session->sync_items, last_block_hash, sizeof(dap_hash_fast_t), l_sync_item); + } + l_sync_item->messages = dap_list_append(l_sync_item->messages, DAP_DUP_SIZE(a_message, a_message_size)); +} + /** * @brief s_session_packet_in * @param a_arg @@ -882,7 +930,7 @@ static void s_session_round_finish(dap_chain_esbocs_session_t *a_session, dap_ch * @param a_data * @param a_data_size */ -static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_node_addr, +static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_node_addr, dap_chain_node_addr_t *a_receiver_node_addr, dap_chain_hash_fast_t *a_data_hash, uint8_t *a_data, size_t a_data_size) { dap_chain_esbocs_session_t *l_session = a_arg; @@ -894,12 +942,17 @@ static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_nod dap_sign_t *l_sign = (dap_sign_t *)(l_message_data + l_message_data_size); size_t l_sign_size = l_message->hdr.sign_size; - pthread_rwlock_wrlock(&l_session->rwlock); if (a_sender_node_addr) { //Process network message - debug_if(l_cs_debug, L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Receive pkt type:%x from addr:"NODE_ADDR_FP_STR", my_addr:"NODE_ADDR_FP_STR"", - l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id, - l_session->cur_round.attempt_num, l_message->hdr.type, - NODE_ADDR_FP_ARGS(a_sender_node_addr), NODE_ADDR_FP_ARGS_S(l_session->my_addr)); + pthread_mutex_lock(&l_session->mutex); + debug_if(l_cs_debug, L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu." + " Receive pkt type:%x from addr:"NODE_ADDR_FP_STR", my_addr:"NODE_ADDR_FP_STR"", + l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id, + l_session->cur_round.attempt_num, l_message->hdr.type, + NODE_ADDR_FP_ARGS(a_sender_node_addr), NODE_ADDR_FP_ARGS_S(l_session->my_addr)); + if (a_receiver_node_addr->uint64 != l_session->my_addr.uint64) { + debug_if(l_cs_debug, L_MSG, "ESBOCS: Wrong packet destination address"); + goto session_unlock; + } if (sizeof(*l_message) + l_message->hdr.sign_size + l_message->hdr.message_size != a_data_size) { log_it(L_WARNING, "ESBOCS: incorrect message size in header is %zu when data size is only %zu and header size is %zu", @@ -915,18 +968,19 @@ static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_nod dap_chain_hash_fast_t l_data_hash = {}; dap_hash_fast(l_message, a_data_size, &l_data_hash); if (!dap_hash_fast_compare(a_data_hash, &l_data_hash)) { - debug_if(l_cs_debug, L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Message rejected: message hash does not match", - l_session->chain->net_name, l_session->chain->name, - l_session->cur_round.id, l_session->cur_round.attempt_num); + debug_if(l_cs_debug, L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu." + " Message rejected: message hash does not match", + l_session->chain->net_name, l_session->chain->name, + l_session->cur_round.id, l_session->cur_round.attempt_num); goto session_unlock; } l_message->hdr.sign_size = 0; // restore header on signing time - bool l_verify_passed = dap_sign_verify_all(l_sign, l_sign_size, l_message, l_message_data_size + sizeof(l_message->hdr)) == 1; - if (!l_verify_passed) { - debug_if(l_cs_debug, L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Message rejected from addr:"NODE_ADDR_FP_STR" not passed verification", - l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id, - l_session->cur_round.attempt_num, NODE_ADDR_FP_ARGS(a_sender_node_addr)); + if (dap_sign_verify_all(l_sign, l_sign_size, l_message, l_message_data_size + sizeof(l_message->hdr))) { + debug_if(l_cs_debug, L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu." + " Message rejected from addr:"NODE_ADDR_FP_STR" not passed verification", + l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id, + l_session->cur_round.attempt_num, NODE_ADDR_FP_ARGS(a_sender_node_addr)); goto session_unlock; } l_message->hdr.sign_size = l_sign_size; // restore original header @@ -934,21 +988,16 @@ static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_nod // consensus round start sync if (l_message->hdr.type == DAP_STREAM_CH_VOTING_MSG_TYPE_START_SYNC) { if (!dap_hash_fast_compare(&l_message->hdr.candidate_hash, &l_session->cur_round.last_block_hash)) { - dap_chain_esbocs_sync_item_t *l_sync_item; - HASH_FIND(hh, l_session->sync_items, &l_message->hdr.candidate_hash, sizeof(dap_hash_fast_t), l_sync_item); - if (!l_sync_item) { - l_sync_item = DAP_NEW(dap_chain_esbocs_sync_item_t); - l_sync_item->last_block_hash = l_message->hdr.candidate_hash; - } - l_sync_item->messages = dap_list_append(l_sync_item->messages, DAP_DUP(l_message)); + s_session_sync_queue_add(l_session, l_message, a_data_size); goto session_unlock; } } else if (l_message->hdr.round_id != l_session->cur_round.id || l_message->hdr.attempt_num < l_session->cur_round.attempt_num) { // round check - debug_if(l_cs_debug, L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Message rejected: round or attempt in message does not match", - l_session->chain->net_name, l_session->chain->name, - l_session->cur_round.id, l_session->cur_round.attempt_num); + debug_if(l_cs_debug, L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu." + " Message rejected: round or attempt in message does not match", + l_session->chain->net_name, l_session->chain->name, + l_session->cur_round.id, l_session->cur_round.attempt_num); goto session_unlock; } } @@ -959,9 +1008,10 @@ static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_nod if (l_cs_debug) l_validator_addr_str = dap_chain_addr_to_str(&l_signing_addr); if (!s_validator_check(&l_signing_addr, l_session->cur_round.validators_list)) { - debug_if(l_cs_debug, L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Message rejected: validator addr:%s not in the list.", - l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id, - l_session->cur_round.attempt_num, l_validator_addr_str); + debug_if(l_cs_debug, L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu." + " Message rejected: validator addr:%s not in the list.", + l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id, + l_session->cur_round.attempt_num, l_validator_addr_str); goto session_unlock; } @@ -971,9 +1021,10 @@ static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_nod dap_chain_esbocs_message_item_t *l_message_item_temp = NULL; HASH_FIND(hh, l_round->message_items, a_data_hash, sizeof(dap_chain_hash_fast_t), l_message_item_temp); if (l_message_item_temp) { - debug_if(l_cs_debug, L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Message rejected: message hash is exists in chain (duplicate?)", - l_session->chain->net_name, l_session->chain->name, - l_session->cur_round.id, l_session->cur_round.attempt_num); + debug_if(l_cs_debug, L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu." + " Message rejected: message hash is exists in chain (duplicate)", + l_session->chain->net_name, l_session->chain->name, + l_session->cur_round.id, l_session->cur_round.attempt_num); goto session_unlock; } @@ -987,21 +1038,58 @@ static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_nod l_message->hdr.type == DAP_STREAM_CH_VOTING_MSG_TYPE_APPROVE); if (l_same_type && dap_chain_addr_compare(&l_chain_message->signing_addr, &l_signing_addr) && dap_hash_fast_compare(&l_chain_message->message->hdr.candidate_hash, &l_message->hdr.candidate_hash)) { - debug_if(l_cs_debug, L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu. Message rejected: duplicate message %s", + debug_if(l_cs_debug, L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu." + " Message rejected: duplicate message %s", l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id, l_session->cur_round.attempt_num, - s_VOTING_MSG_type_to_str(l_message->hdr.type)); + s_voting_msg_type_to_str(l_message->hdr.type)); goto session_unlock; } } dap_chain_hash_fast_t *l_candidate_hash = &l_message->hdr.candidate_hash; switch (l_message->hdr.type) { - case DAP_STREAM_CH_VOTING_MSG_TYPE_START_SYNC: - debug_if(l_cs_debug, L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu. Receive START_SYNC: from validator:%s", - l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id, - l_session->cur_round.attempt_num, l_validator_addr_str); - s_message_chain_add(l_session, l_message, a_data_size, a_data_hash); + case DAP_STREAM_CH_VOTING_MSG_TYPE_START_SYNC: { + uint64_t l_sync_attempt = *(uint64_t *)l_message_data; + debug_if(l_cs_debug, L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U + " Receive START_SYNC: from validator:%s, sync attempt %"DAP_UINT64_FORMAT_U, + l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id, + l_validator_addr_str, l_sync_attempt); + if (l_sync_attempt != l_session->cur_round.sync_attempt) { + if (l_sync_attempt < l_session->cur_round.sync_attempt) { + debug_if(l_cs_debug, L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U + " SYNC message is rejected because current sync attempt %"DAP_UINT64_FORMAT_U + " is greater than meassage sync attempt %"DAP_UINT64_FORMAT_U, + l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id, + l_session->cur_round.sync_attempt, l_sync_attempt); + break; + } else { + uint64_t l_attempts_miss = l_sync_attempt - l_session->cur_round.sync_attempt; + if (l_attempts_miss > UINT16_MAX) { + debug_if(l_cs_debug, L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U + " SYNC message is rejected - too much sync attempt difference %"DAP_UINT64_FORMAT_U, + l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id, + l_attempts_miss); + break; + } + debug_if(l_cs_debug, L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U + " SYNC message sync attempt %"DAP_UINT64_FORMAT_U" is greater than" + " current round sync attempt %"DAP_UINT64_FORMAT_U" so fast-forward this round", + l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id, + l_sync_attempt, l_session->cur_round.sync_attempt); + for (uint64_t i = 0; i < l_attempts_miss - 1; i++) { + // Fast-forward current sync attempt + s_get_validators_list(l_session, NULL); + l_session->cur_round.sync_attempt++; + } + // Process this message in new round + s_session_sync_queue_add(l_session, l_message, a_data_size); + l_session->round_fast_forward = true; + s_session_round_new(l_session); + break; + } + } + s_message_chain_add(l_session, l_message, a_data_size, a_data_hash, &l_signing_addr); for (dap_list_t *it = l_session->cur_round.validators_list; it; it = it->next) { dap_chain_esbocs_validator_t *l_validator = it->data; if (dap_chain_addr_compare(&l_validator->signing_addr, &l_signing_addr)) @@ -1015,12 +1103,13 @@ static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_nod l_session->cur_round.id, l_session->cur_round.attempt_num); s_session_state_change(l_session, DAP_CHAIN_ESBOCS_SESSION_STATE_WAIT_PROC, dap_time_now()); } - break; + } break; case DAP_STREAM_CH_VOTING_MSG_TYPE_SUBMIT: { uint8_t *l_candidate = l_message->msg_n_sign; size_t l_candidate_size = l_message->hdr.message_size; if (!l_candidate_size || dap_hash_fast_is_blank(&l_message->hdr.candidate_hash)) { - debug_if(l_cs_debug, L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu. Receive SUBMIT candidate NULL", + debug_if(l_cs_debug, L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu." + " Receive SUBMIT candidate NULL", l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id, l_session->cur_round.attempt_num); if (dap_chain_addr_compare(&l_session->cur_round.attempt_submit_validator, &l_signing_addr)) @@ -1031,19 +1120,21 @@ static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_nod dap_chain_hash_fast_t l_check_hash; dap_hash_fast(l_candidate, l_candidate_size, &l_check_hash); if (!dap_hash_fast_compare(&l_check_hash, l_candidate_hash)) { - debug_if(l_cs_debug, L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu. Receive SUBMIT candidate hash broken", + debug_if(l_cs_debug, L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu." + " Receive SUBMIT candidate hash broken", l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id, l_session->cur_round.attempt_num); break; } - s_message_chain_add(l_session, l_message, a_data_size, a_data_hash); + s_message_chain_add(l_session, l_message, a_data_size, a_data_hash, &l_signing_addr); if (l_cs_debug) { char *l_candidate_hash_str = dap_chain_hash_fast_to_str_new(l_candidate_hash); - log_it(L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu. Receive SUBMIT candidate %s, size %zu", - l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id, - l_session->cur_round.attempt_num, l_candidate_hash_str, l_candidate_size); + log_it(L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu." + " Receive SUBMIT candidate %s, size %zu", + l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id, + l_session->cur_round.attempt_num, l_candidate_hash_str, l_candidate_size); DAP_DELETE(l_candidate_hash_str); } @@ -1078,27 +1169,29 @@ static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_nod HASH_FIND(hh, l_session->cur_round.store_items, l_candidate_hash, sizeof(dap_chain_hash_fast_t), l_store); if (!l_store) { l_candidate_hash_str = dap_chain_hash_fast_to_str_new(l_candidate_hash); - log_it(L_WARNING, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu, Receive REJECT message for unknown candidate:%s", - l_session->chain->net_name, l_session->chain->name, - l_session->cur_round.id, l_session->cur_round.attempt_num, - l_candidate_hash_str); + log_it(L_WARNING, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu." + " Receive REJECT message for unknown candidate:%s", + l_session->chain->net_name, l_session->chain->name, + l_session->cur_round.id, l_session->cur_round.attempt_num, + l_candidate_hash_str); DAP_DELETE(l_candidate_hash_str); break; } - s_message_chain_add(l_session, l_message, a_data_size, a_data_hash); + s_message_chain_add(l_session, l_message, a_data_size, a_data_hash, &l_signing_addr); if (l_cs_debug) { l_candidate_hash_str = dap_chain_hash_fast_to_str_new(l_candidate_hash); - log_it(L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Receive REJECT: candidate:%s", - l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id, - l_session->cur_round.attempt_num, l_candidate_hash_str); + log_it(L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu." + " Receive REJECT: candidate:%s", + l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id, + l_session->cur_round.attempt_num, l_candidate_hash_str); } if (++l_store->reject_count >= l_cs_level && !l_store->decide_reject && dap_hash_fast_compare(&l_session->cur_round.attempt_candidate_hash, l_candidate_hash)) { l_store->decide_reject = true; debug_if(l_cs_debug, L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu." - " Candidate:%s rejected by more than 2/3 of the validators", + " Candidate:%s rejected by minimum number of validators, attempt failed", l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id, l_session->cur_round.attempt_num, l_candidate_hash_str); s_session_attempt_new(l_session); @@ -1112,27 +1205,29 @@ static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_nod HASH_FIND(hh, l_session->cur_round.store_items, l_candidate_hash, sizeof(dap_chain_hash_fast_t), l_store); if (!l_store) { l_candidate_hash_str = dap_chain_hash_fast_to_str_new(l_candidate_hash); - log_it(L_WARNING, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu, Receive APPROVE message for unknown candidate:%s", - l_session->chain->net_name, l_session->chain->name, - l_session->cur_round.id, l_session->cur_round.attempt_num, - l_candidate_hash_str); + log_it(L_WARNING, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu." + " Receive APPROVE message for unknown candidate:%s", + l_session->chain->net_name, l_session->chain->name, + l_session->cur_round.id, l_session->cur_round.attempt_num, + l_candidate_hash_str); DAP_DELETE(l_candidate_hash_str); break; } - s_message_chain_add(l_session, l_message, a_data_size, a_data_hash); + s_message_chain_add(l_session, l_message, a_data_size, a_data_hash, &l_signing_addr); if (l_cs_debug) { l_candidate_hash_str = dap_chain_hash_fast_to_str_new(l_candidate_hash); - log_it(L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Receive APPROVE: candidate:%s", - l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id, - l_session->cur_round.attempt_num, l_candidate_hash_str); + log_it(L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu." + " Receive APPROVE: candidate:%s", + l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id, + l_session->cur_round.attempt_num, l_candidate_hash_str); } if (++l_store->approve_count >= l_cs_level && !l_store->decide_approve && dap_hash_fast_compare(&l_session->cur_round.attempt_candidate_hash, l_candidate_hash)) { l_store->decide_approve = true; debug_if(l_cs_debug, L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu." - " Candidate:%s approved by more than 2/3 of the validators, let's sign it", + " Candidate:%s approved by minimum number of validators, let's sign it", l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id, l_session->cur_round.attempt_num, l_candidate_hash_str); size_t l_offset = dap_chain_block_get_sign_offset(l_store->candidate, l_store->candidate_size); @@ -1150,8 +1245,9 @@ static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_nod dap_sign_t *l_candidate_sign = (dap_sign_t *)l_message_data; size_t l_candidate_sign_size = dap_sign_get_size(l_candidate_sign); if (l_candidate_sign_size != l_message_data_size) { - log_it(L_WARNING, "Wrong commit_sign message size, have %zu bytes for candidate sign section when requires %zu bytes", - l_candidate_sign_size, l_message_data_size); + log_it(L_WARNING, "Wrong commit_sign message size, have %zu bytes for candidate sign section" + " when requires %zu bytes", + l_candidate_sign_size, l_message_data_size); break; } @@ -1160,19 +1256,21 @@ static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_nod HASH_FIND(hh, l_session->cur_round.store_items, l_candidate_hash, sizeof(dap_chain_hash_fast_t), l_store); if (!l_store) { l_candidate_hash_str = dap_chain_hash_fast_to_str_new(l_candidate_hash); - log_it(L_WARNING, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu, Receive COMMIT_SIGN message for unknown candidate:%s", - l_session->chain->net_name, l_session->chain->name, - l_session->cur_round.id, l_session->cur_round.attempt_num, - l_candidate_hash_str); + log_it(L_WARNING, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu." + " Receive COMMIT_SIGN message for unknown candidate:%s", + l_session->chain->net_name, l_session->chain->name, + l_session->cur_round.id, l_session->cur_round.attempt_num, + l_candidate_hash_str); DAP_DELETE(l_candidate_hash_str); break; } if (l_cs_debug) { l_candidate_hash_str = dap_chain_hash_fast_to_str_new(l_candidate_hash); - log_it(L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Receive COMMIT_SIGN: candidate:%s", - l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id, - l_session->cur_round.attempt_num, l_candidate_hash_str); + log_it(L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu." + " Receive COMMIT_SIGN: candidate:%s", + l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id, + l_session->cur_round.attempt_num, l_candidate_hash_str); } size_t l_offset = dap_chain_block_get_sign_offset(l_store->candidate, l_store->candidate_size); @@ -1180,14 +1278,15 @@ static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_nod l_offset + sizeof(l_store->candidate->hdr)) == 1; // check candidate's sign if (l_sign_verified) { - s_message_chain_add(l_session, l_message, a_data_size, a_data_hash); + s_message_chain_add(l_session, l_message, a_data_size, a_data_hash, &l_signing_addr); l_store->candidate_signs = dap_list_append(l_store->candidate_signs, DAP_DUP_SIZE(l_candidate_sign, l_candidate_sign_size)); if (dap_list_length(l_store->candidate_signs) == l_round->validators_synced_count) { if (PVT(l_session->esbocs)->debug) - log_it(L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Candidate:%s collected signs of all synced validators", - l_session->chain->net_name, l_session->chain->name, l_round->id, - l_session->cur_round.attempt_num, l_candidate_hash_str); + log_it(L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu." + " Candidate:%s collected signs of all synced validators", + l_session->chain->net_name, l_session->chain->name, l_round->id, + l_session->cur_round.attempt_num, l_candidate_hash_str); s_session_state_change(l_session, DAP_CHAIN_ESBOCS_SESSION_STATE_WAIT_FINISH, dap_time_now()); } } else { @@ -1204,10 +1303,11 @@ static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_nod HASH_FIND(hh, l_session->cur_round.store_items, l_candidate_hash, sizeof(dap_chain_hash_fast_t), l_store); if (!l_store) { l_candidate_hash_str = dap_chain_hash_fast_to_str_new(l_candidate_hash); - log_it(L_WARNING, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu, Receive PRE_COMMIT message for unknown candidate:%s", - l_session->chain->net_name, l_session->chain->name, - l_session->cur_round.id, l_session->cur_round.attempt_num, - l_candidate_hash_str); + log_it(L_WARNING, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu." + " Receive PRE_COMMIT message for unknown candidate:%s", + l_session->chain->net_name, l_session->chain->name, + l_session->cur_round.id, l_session->cur_round.attempt_num, + l_candidate_hash_str); DAP_DELETE(l_candidate_hash_str); break; } @@ -1218,11 +1318,12 @@ static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_nod l_candidate_hash_str = dap_chain_hash_fast_to_str_new(l_candidate_hash); char *l_my_precommit_hash_str = dap_chain_hash_fast_to_str_new(&l_store->precommit_candidate_hash); char *l_remote_precommit_hash_str = dap_chain_hash_fast_to_str_new(l_precommit_hash); - log_it(L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Candidate:%s has different final hash of local and remote validators\n" - "(%s and %s)", - l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id, - l_session->cur_round.attempt_num, l_candidate_hash_str, - l_my_precommit_hash_str, l_remote_precommit_hash_str); + log_it(L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu." + " Candidate:%s has different final hash of local and remote validators\n" + "(%s and %s)", + l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id, + l_session->cur_round.attempt_num, l_candidate_hash_str, + l_my_precommit_hash_str, l_remote_precommit_hash_str); DAP_DELETE(l_candidate_hash_str); DAP_DELETE(l_my_precommit_hash_str); DAP_DELETE(l_remote_precommit_hash_str); @@ -1230,22 +1331,24 @@ static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_nod break; } - s_message_chain_add(l_session, l_message, a_data_size, a_data_hash); + s_message_chain_add(l_session, l_message, a_data_size, a_data_hash, &l_signing_addr); if (l_cs_debug) { l_candidate_hash_str = dap_chain_hash_fast_to_str_new(l_candidate_hash); - log_it(L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Receive PRE_COMMIT: candidate:%s", - l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id, - l_session->cur_round.attempt_num, l_candidate_hash_str); + log_it(L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu." + " Receive PRE_COMMIT: candidate:%s", + l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id, + l_session->cur_round.attempt_num, l_candidate_hash_str); } if (++l_store->precommit_count >= l_cs_level && !l_store->decide_commit && dap_hash_fast_compare(&l_session->cur_round.attempt_candidate_hash, l_candidate_hash)) { l_store->decide_commit = true; - debug_if(l_cs_debug, L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Candidate:%s rejected by more than 2/3 of the validators, remove it", - l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id, - l_session->cur_round.attempt_num, l_candidate_hash_str); + debug_if(l_cs_debug, L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu." + " Candidate:%s precommted by minimum number of validators, try to finish this round", + l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id, + l_session->cur_round.attempt_num, l_candidate_hash_str); s_session_round_finish(l_session, l_store); - s_session_round_new(l_session); + // ATTENTION: New round will be started by incoming atom notifier event } DAP_DEL_Z(l_candidate_hash_str); } break; @@ -1253,7 +1356,8 @@ static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_nod break; } session_unlock: - pthread_rwlock_unlock(&l_session->rwlock); + if (a_sender_node_addr) //Process network message + pthread_mutex_unlock(&l_session->mutex); } static void s_message_send(dap_chain_esbocs_session_t *a_session, uint8_t a_message_type, dap_hash_fast_t *a_block_hash, @@ -1282,13 +1386,17 @@ static void s_message_send(dap_chain_esbocs_session_t *a_session, uint8_t a_mess DAP_DELETE(l_sign); l_message->hdr.sign_size = l_sign_size; - dap_stream_ch_chain_voting_pkt_t *l_voting_pkt = dap_stream_ch_chain_voting_pkt_new(l_net->pub.id.uint64, l_message, l_message_size); + dap_stream_ch_chain_voting_pkt_t *l_voting_pkt = + dap_stream_ch_chain_voting_pkt_new(l_net->pub.id.uint64, &a_session->my_addr, + NULL, l_message, l_message_size); DAP_DELETE(l_message); for (dap_list_t *it = a_validators; it; it = it->next) { dap_chain_esbocs_validator_t *l_validator = it->data; - if (l_validator->is_synced) + if (l_validator->is_synced || a_message_type == DAP_STREAM_CH_VOTING_MSG_TYPE_START_SYNC) { + l_voting_pkt->hdr.receiver_node_addr = l_validator->node_addr; dap_stream_ch_chain_voting_message_write(l_net, &l_validator->node_addr, l_voting_pkt); + } } DAP_DELETE(l_voting_pkt); } @@ -1319,10 +1427,19 @@ static int s_callback_block_verify(dap_chain_cs_blocks_t *a_blocks, dap_chain_bl return -3; } if (sizeof(a_block->hdr) >= a_block_size) { - log_it(L_WARNING,"Incorrect size with block %p on chain %s", a_block, a_blocks->chain->name); + log_it(L_WARNING, "Incorrect header size with block %p on chain %s", a_block, a_blocks->chain->name); return -7; } + if (a_block->hdr.meta_n_datum_n_signs_size != a_block_size - sizeof(a_block->hdr)) { + log_it(L_WARNING, "Incorrect size with block %p on chain %s", a_block, a_blocks->chain->name); + return -8; + } + + if (l_esbocs->session->processing_candidate == a_block) + // It's a block candidate, don't check signs + return 0; + size_t l_offset = dap_chain_block_get_sign_offset(a_block, a_block_size); size_t l_signs_count = 0; dap_sign_t **l_signs = dap_sign_get_unique_signs(a_block->meta_n_datum_n_sign+l_offset, @@ -1342,7 +1459,9 @@ static int s_callback_block_verify(dap_chain_cs_blocks_t *a_blocks, dap_chain_bl // Parse the rest signs int l_ret = 0; uint16_t l_signs_verified_count = 0; - size_t l_block_excl_sign_size = dap_chain_block_get_sign_offset(a_block, a_block_size)+sizeof(a_block->hdr); + size_t l_block_excl_sign_size = dap_chain_block_get_sign_offset(a_block, a_block_size) + sizeof(a_block->hdr); + // Get the header on signing operation time + a_block->hdr.meta_n_datum_n_signs_size = l_block_excl_sign_size - sizeof(a_block->hdr); for (size_t i=0; i< l_signs_count; i++) { dap_sign_t *l_sign = (dap_sign_t *)l_signs[i]; if (!dap_sign_verify_size(l_sign, a_block_size - l_block_excl_sign_size + sizeof(a_block->hdr))) { @@ -1366,6 +1485,9 @@ static int s_callback_block_verify(dap_chain_cs_blocks_t *a_blocks, dap_chain_bl l_signs_verified_count++; } DAP_DELETE(l_signs); + // Restore the original header + a_block->hdr.meta_n_datum_n_signs_size = a_block_size - sizeof(a_block->hdr); + if ( l_ret != 0 ) { return l_ret; } diff --git a/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h b/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h index b0828c54b0..77778ec4b6 100644 --- a/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h +++ b/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h @@ -19,6 +19,7 @@ typedef struct dap_chain_esbocs_session dap_chain_esbocs_session_t; /* consensus messages +• Sync(round, last block, sync attempt) - try to synchronize validators before first round attempt start • Submit(round, candidate, body) — suggest a new block candidate *** candiate body in data section • Approve(round, candidate) — a block candidate has passed local validation • Reject(round, candidate) — a block candidate has failed local validation @@ -95,6 +96,7 @@ typedef struct dap_chain_esbocs_round { // Validators section uint16_t validators_synced_count; dap_list_t *validators_list; + uint64_t sync_attempt; } dap_chain_esbocs_round_t; typedef struct dap_chain_esbocs_validator { @@ -106,7 +108,8 @@ typedef struct dap_chain_esbocs_validator { } dap_chain_esbocs_validator_t; typedef struct dap_chain_esbocs_session { - pthread_rwlock_t rwlock; + pthread_mutex_t mutex; + dap_chain_block_t *processing_candidate; dap_chain_t *chain; dap_chain_esbocs_t *esbocs; @@ -114,6 +117,7 @@ typedef struct dap_chain_esbocs_session { dap_chain_node_addr_t my_addr; uint8_t state; // session state dap_chain_esbocs_round_t cur_round; + bool round_fast_forward; dap_time_t ts_round_sync_start; // time of start sync dap_time_t ts_attempt_start; // time of current attempt start diff --git a/modules/type/blocks/dap_chain_cs_blocks.c b/modules/type/blocks/dap_chain_cs_blocks.c index 6e2dca0267..05f962ea7d 100644 --- a/modules/type/blocks/dap_chain_cs_blocks.c +++ b/modules/type/blocks/dap_chain_cs_blocks.c @@ -158,7 +158,7 @@ int dap_chain_cs_blocks_init() "\t\tList block sections and show their datums hashes\n\n" "block -net <net_name> -chain <chain_name> new_datum\n\n" - "\t\tComplete the current new round, verify it and if everything is ok - publish new events in chain\n\n" + "\t\tComplete the current new round, verify it and if everything is ok - publish new blocks in chain\n\n" "Blockchain explorer:" "block -net <net_name> -chain <chain_name> dump <block_hash>\n" -- GitLab