diff --git a/CMakeLists.txt b/CMakeLists.txt index c3113a99696a3bdf36037847a2453a6e0ffc7bda..74b876a7d093222a9cfea8084edce25b35c53961 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,7 @@ set(DAPSDK_MODULES "") if(NOT DEFINED CELLFRAME_MODULES) include (cmake/OS_Detection.cmake) - set(CELLFRAME_MODULES "core chains mining network srv cs-dag-poa cs-block-poa cs-dag-pos cs-block-pos cs-block-ton cs-none srv-app srv-app-db srv-datum srv-stake-pos-delegate srv-stake-lock srv-xchange") + set(CELLFRAME_MODULES "core chains mining network srv cs-dag-poa cs-block-poa cs-dag-pos cs-block-pos cs-esbocs cs-none srv-app srv-app-db srv-datum srv-stake-pos-delegate srv-stake-lock srv-xchange") if(LINUX OR DARWIN) set(CELLFRAME_MODULES "${CELLFRAME_MODULES} srv-vpn") @@ -144,8 +144,8 @@ if (CELLFRAME_MODULES MATCHES "cs-dag-pos") endif() # Blocks based consensus(es) -if (CELLFRAME_MODULES MATCHES "cs-block-" ) - set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_chain_cs_dag) +if (CELLFRAME_MODULES MATCHES "cs-block-" OR CELLFRAME_MODULES MATCHES "cs-esbocs") + set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_chain_cs_blocks) endif() # PoA consensus for blocks @@ -161,9 +161,9 @@ if (CELLFRAME_MODULES MATCHES "cs-block-pos") endif() # TON consensus for blocks -if (CELLFRAME_MODULES MATCHES "cs-block-ton") - message("[+] Module 'cs-block-ton'") - set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_chain_cs_block_ton) +if (CELLFRAME_MODULES MATCHES "cs-esbocs") + message("[+] Module 'cs-esbocs'") + set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_chain_cs_esbocs) endif() # PoW consensus for blocks diff --git a/dap-sdk b/dap-sdk index 6551148098209cc9237f67453205271a74802d06..2fa175608533db70a74d61ab1ed57edd85a01607 160000 --- a/dap-sdk +++ b/dap-sdk @@ -1 +1 @@ -Subproject commit 6551148098209cc9237f67453205271a74802d06 +Subproject commit 2fa175608533db70a74d61ab1ed57edd85a01607 diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt index 5b2c9751855e2352bf26fe28f0ef0a2926c16a69..66cf900cedd7d54bc315393c4e688bf87bab22a4 100644 --- a/modules/CMakeLists.txt +++ b/modules/CMakeLists.txt @@ -67,8 +67,8 @@ if (CELLFRAME_MODULES MATCHES "cs-block-pos") endif() # Block TON -if (CELLFRAME_MODULES MATCHES "cs-block-ton") - add_subdirectory(consensus/block-ton) +if (CELLFRAME_MODULES MATCHES "cs-esbocs") + add_subdirectory(consensus/esbocs) endif() # Block PoW diff --git a/modules/chain/dap_chain.c b/modules/chain/dap_chain.c index 27dd828169b151dd3dd2227f95182c1f1d71096c..760e8acb6bebb635c7d3b138dfcb10c5ad099ad5 100644 --- a/modules/chain/dap_chain.c +++ b/modules/chain/dap_chain.c @@ -411,8 +411,8 @@ dap_chain_t * dap_chain_load_from_cfg(dap_ledger_t* a_ledger, const char * a_cha } l_chain = dap_chain_create(a_ledger,a_chain_net_name,l_chain_name, a_chain_net_id,l_chain_id); - if ( dap_chain_cs_create(l_chain, l_cfg) == 0 ) - { + if ( dap_chain_cs_create(l_chain, l_cfg) == 0 ) { + log_it (L_NOTICE, "Consensus initialized for chain id 0x%016"DAP_UINT64_FORMAT_x, l_chain_id.uint64); if ( dap_config_get_item_path_default(l_cfg , "files","storage_dir",NULL ) ) diff --git a/modules/chain/dap_chain_ledger.c b/modules/chain/dap_chain_ledger.c index eaec9d67130994307fd2d8b0d2f9d4fa1d87568c..67df1a73f05bb5cce3e1b75e88ae3b79800935b0 100644 --- a/modules/chain/dap_chain_ledger.c +++ b/modules/chain/dap_chain_ledger.c @@ -55,7 +55,7 @@ #include "dap_config.h" #include "dap_cert.h" #include "dap_timerfd.h" -#include "dap_chain_datum_tx_token.h" +#include "dap_chain_datum_tx_in_ems.h" #include "dap_chain_datum_token.h" #include "dap_chain_mempool.h" #include "dap_global_db.h" @@ -148,9 +148,9 @@ typedef struct dap_chain_ledger_tx_item { uint32_t n_outs; uint32_t n_outs_used; char token_ticker[DAP_CHAIN_TICKER_SIZE_MAX]; - char padding[6]; + byte_t padding[6]; byte_t multichannel; - char pad[15]; + byte_t pad[15]; // TODO dynamically allocates the memory in order not to limit the number of outputs in transaction dap_chain_hash_fast_t tx_hash_spent_fast[MAX_OUT_ITEMS]; // spent outs list } DAP_ALIGN_PACKED cache_data; diff --git a/modules/chain/include/dap_chain.h b/modules/chain/include/dap_chain.h index 70dbf5096e3298494db617e3704414ca9210c5e7..9dd0602837a6bcf97a4c029cbe1653cfc20b5c01 100644 --- a/modules/chain/include/dap_chain.h +++ b/modules/chain/include/dap_chain.h @@ -46,15 +46,14 @@ typedef const void * dap_chain_atom_ptr_t; // Atomic element iterator typedef struct dap_chain_atom_iter{ - dap_chain_t * chain; + dap_chain_t *chain; dap_chain_atom_ptr_t cur; dap_chain_hash_fast_t *cur_hash; dap_chain_cell_id_t cell_id; bool with_treshold; bool found_in_treshold; size_t cur_size; - void * cur_item; - void * _inheritor; + void *cur_item; } dap_chain_atom_iter_t; @@ -90,7 +89,7 @@ typedef dap_chain_atom_ptr_t * (*dap_chain_callback_atom_iter_get_atoms_t)(dap_c typedef size_t (*dap_chain_callback_add_datums_t)(dap_chain_t * , dap_chain_datum_t **, size_t ); typedef dap_chain_atom_ptr_t (*dap_chain_callback_atom_iter_get_next_t)(dap_chain_atom_iter_t * ,size_t*); -typedef void (*dap_chain_callback_atom_iter_delete_t)(dap_chain_atom_iter_t * ); +typedef void (*dap_chain_callback_atom_iter_delete_t)(dap_chain_atom_iter_t *); typedef void (*dap_chain_callback_notify_t)(void * a_arg, dap_chain_t *a_chain, dap_chain_cell_id_t a_id, void* a_atom, size_t a_atom_size); //change in chain happened diff --git a/modules/chain/include/dap_chain_ledger.h b/modules/chain/include/dap_chain_ledger.h index 340d5ba7a218db675d44c4cacc23fb08f9ff1d07..486450c5748ca22d8310bc9bd18dc563f62c850e 100644 --- a/modules/chain/include/dap_chain_ledger.h +++ b/modules/chain/include/dap_chain_ledger.h @@ -33,7 +33,7 @@ #include "dap_chain_common.h" #include "dap_chain_datum_token.h" #include "dap_chain_datum_tx.h" -#include "dap_chain_datum_tx_token.h" +#include "dap_chain_datum_tx_in_ems.h" #include "dap_chain_datum_tx_items.h" typedef struct dap_ledger { diff --git a/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.c b/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.c index 554f953ab4ac7f04eb42a87c3d2c9838eb8937cc..0d3229773f508e2e0ef155fb06d05d00832d4ca3 100644 --- a/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.c +++ b/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.c @@ -370,8 +370,8 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg) typedef dap_stream_ch_chain_net_srv_pkt_test_t pkt_test_t; pkt_test_t *l_request = (pkt_test_t*)l_ch_pkt->data; size_t l_request_size = l_request->data_size + sizeof(pkt_test_t); - if (l_ch_pkt->hdr.size != l_request_size) { - log_it(L_WARNING, "Wrong request size %u, must be %zu [pkt seq %"DAP_UINT64_FORMAT_U"]", l_ch_pkt->hdr.size, l_request_size, l_ch_pkt->hdr.seq_id); + if (l_ch_pkt->hdr.data_size != l_request_size) { + log_it(L_WARNING, "Wrong request size %u, must be %zu [pkt seq %"DAP_UINT64_FORMAT_U"]", l_ch_pkt->hdr.data_size, l_request_size, l_ch_pkt->hdr.seq_id); l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_WRONG_SIZE; dap_stream_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof(l_err)); break; @@ -406,29 +406,29 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg) } break; /* DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_CHECK_REQUEST */ case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_REQUEST: { - if (l_ch_pkt->hdr.size < sizeof(dap_stream_ch_chain_net_srv_pkt_request_hdr_t) ){ + if (l_ch_pkt->hdr.data_size < sizeof(dap_stream_ch_chain_net_srv_pkt_request_hdr_t) ){ log_it( L_WARNING, "Wrong request size, less than minimum"); break; } dap_chain_net_srv_grace_t *l_grace = DAP_NEW_Z(dap_chain_net_srv_grace_t); // Parse the request - l_grace->request = DAP_NEW_Z_SIZE(dap_stream_ch_chain_net_srv_pkt_request_t, l_ch_pkt->hdr.size); - memcpy(l_grace->request, l_ch_pkt->data, l_ch_pkt->hdr.size); + l_grace->request = DAP_NEW_Z_SIZE(dap_stream_ch_chain_net_srv_pkt_request_t, l_ch_pkt->hdr.data_size); + memcpy(l_grace->request, l_ch_pkt->data, l_ch_pkt->hdr.data_size); l_ch_chain_net_srv->srv_uid.uint64 = l_grace->request->hdr.srv_uid.uint64; - l_grace->request_size = l_ch_pkt->hdr.size; + l_grace->request_size = l_ch_pkt->hdr.data_size; l_grace->ch_uuid = a_ch->uuid; l_grace->stream_worker = a_ch->stream_worker; s_grace_period_control(l_grace); } break; /* DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_REQUEST */ case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_SIGN_RESPONSE: { - if (l_ch_pkt->hdr.size < sizeof(dap_chain_receipt_info_t)) { - log_it(L_ERROR, "Wrong sign response size, %u when expected at least %zu with smth", l_ch_pkt->hdr.size, + if (l_ch_pkt->hdr.data_size < sizeof(dap_chain_receipt_info_t)) { + log_it(L_ERROR, "Wrong sign response size, %u when expected at least %zu with smth", l_ch_pkt->hdr.data_size, sizeof(dap_chain_receipt_info_t)); break; } dap_chain_datum_tx_receipt_t * l_receipt = (dap_chain_datum_tx_receipt_t *) l_ch_pkt->data; - size_t l_receipt_size = l_ch_pkt->hdr.size; + size_t l_receipt_size = l_ch_pkt->hdr.data_size; dap_chain_net_srv_usage_t * l_usage= NULL, *l_tmp= NULL; bool l_is_found = false; pthread_mutex_lock(& l_srv_session->parent->mutex ); // TODO rework it with packet usage_id @@ -593,13 +593,13 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg) } break; case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_DATA: { - if (l_ch_pkt->hdr.size < sizeof(dap_stream_ch_chain_net_srv_pkt_data_hdr_t) ){ + if (l_ch_pkt->hdr.data_size < sizeof(dap_stream_ch_chain_net_srv_pkt_data_hdr_t) ){ log_it( L_WARNING, "Wrong request size, less than minimum"); break; } typedef dap_stream_ch_chain_net_srv_pkt_data_t pkt_t; pkt_t * l_pkt =(pkt_t *) l_ch_pkt->data; - size_t l_pkt_size = l_ch_pkt->hdr.size - sizeof(pkt_t); + size_t l_pkt_size = l_ch_pkt->hdr.data_size - sizeof(pkt_t); dap_chain_net_srv_t * l_srv = dap_chain_net_srv_get( l_pkt->hdr.srv_uid); dap_chain_net_srv_usage_t * l_usage = dap_chain_net_srv_usage_find_unsafe( l_srv_session, l_pkt->hdr.usage_id ); // If service not found @@ -625,12 +625,12 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg) } break; case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR:{ - if ( l_ch_pkt->hdr.size == sizeof (dap_stream_ch_chain_net_srv_pkt_error_t) ){ + if ( l_ch_pkt->hdr.data_size == sizeof (dap_stream_ch_chain_net_srv_pkt_error_t) ){ dap_stream_ch_chain_net_srv_pkt_error_t * l_err = (dap_stream_ch_chain_net_srv_pkt_error_t *) l_ch_pkt->data; log_it( L_NOTICE, "Remote responsed with error code 0x%08X", l_err->code ); // TODO code for service client mode }else{ - log_it(L_ERROR, "Wrong error response size, %u when expected %zu", l_ch_pkt->hdr.size, + log_it(L_ERROR, "Wrong error response size, %u when expected %zu", l_ch_pkt->hdr.data_size, sizeof ( dap_stream_ch_chain_net_srv_pkt_error_t) ); } } break; diff --git a/modules/channel/chain-net/dap_stream_ch_chain_net.c b/modules/channel/chain-net/dap_stream_ch_chain_net.c index a2994fe2d2ab42b5338d62105d1a70d4aed69755..a05b21284956e9c176313df51091e61b66335e85 100644 --- a/modules/channel/chain-net/dap_stream_ch_chain_net.c +++ b/modules/channel/chain-net/dap_stream_ch_chain_net.c @@ -226,9 +226,8 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) l_ch_chain_net_pkt->hdr.net_id, l_err_str, strlen(l_err_str) + 1); dap_stream_ch_set_ready_to_write_unsafe(a_ch, true); } - //size_t l_ch_chain_net_pkt_data_size = (size_t) l_ch_pkt->hdr.size - sizeof (l_ch_chain_net_pkt->hdr); if (!l_error && l_ch_chain_net_pkt) { - size_t l_ch_chain_net_pkt_data_size = l_ch_pkt->hdr.size - sizeof(dap_stream_ch_chain_net_pkt_hdr_t); + size_t l_ch_chain_net_pkt_data_size = l_ch_pkt->hdr.data_size - sizeof(dap_stream_ch_chain_net_pkt_hdr_t); switch (l_ch_pkt->hdr.type) { case DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_DBG: { dap_stream_ch_chain_net_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_PING, diff --git a/modules/channel/chain-voting/CMakeLists.txt b/modules/channel/chain-voting/CMakeLists.txt index 5c12a8e74d9b9c40fdadc2bc2508292125aae3c4..39d888157b65eb06e7e4a7629ca0a7025aa585fd 100644 --- a/modules/channel/chain-voting/CMakeLists.txt +++ b/modules/channel/chain-voting/CMakeLists.txt @@ -6,7 +6,7 @@ file(GLOB DAP_STREAM_CH_CHAIN_VOTING_HDRS include/*.h) add_library(${PROJECT_NAME} STATIC ${DAP_STREAM_CH_CHAIN_VOTING_SRCS} ${DAP_STREAM_CH_CHAIN_VOTING_HDRS}) -target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_stream dap_stream_ch dap_stream_ch_chain dap_chain_net) +target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_stream dap_stream_ch dap_chain_net) target_include_directories(${PROJECT_NAME} INTERFACE .) 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 22542e7b20ce4c3c5ba611f7be65afe3cc47cec3..ff82afac35a96cc372f94498bc101ab1a16ad911 100644 --- a/modules/channel/chain-voting/dap_stream_ch_chain_voting.c +++ b/modules/channel/chain-voting/dap_stream_ch_chain_voting.c @@ -8,85 +8,46 @@ #include "dap_stream_ch_chain_voting.h" #include "dap_chain_net.h" #include "dap_client_pvt.h" - +#include "dap_proc_queue.h" #include "dap_chain_node_cli.h" #define LOG_TAG "dap_stream_ch_chain_voting" -typedef struct voting_pkt_in_callback{ +struct voting_pkt_in_callback { void * arg; - voting_ch_callback_t packet_in_callback; -} voting_pkt_in_callback_t; - -typedef struct voting_pkt_addr { - dap_chain_node_addr_t node_addr; - dap_stream_ch_chain_voting_pkt_t *voting_pkt; -} voting_pkt_addr_t; + dap_chain_voting_ch_callback_t packet_in_callback; +}; -typedef struct voting_pkt_items { - pthread_rwlock_t rwlock_out; - pthread_rwlock_t rwlock_in; - dap_list_t * pkts_out; // voting_pkt_addr_t - dap_list_t * pkts_in; // dap_stream_ch_chain_voting_pkt_t -} voting_pkt_items_t; - -typedef struct voting_node_client_list { +struct voting_node_client_list { + dap_chain_node_addr_t node_addr; // HT key dap_chain_node_info_t *node_info; dap_chain_node_client_t *node_client; - dap_chain_node_addr_t node_addr; UT_hash_handle hh; -} voting_node_client_list_t; - -static size_t s_pkt_in_callback_count = 0; -static voting_pkt_in_callback_t s_pkt_in_callback[256]={{0}}; -static voting_pkt_items_t *s_pkt_items = NULL; -static voting_node_client_list_t *s_node_client_list = NULL; - -static void s_callback_send_all_loopback(uint64_t a_node_addr); -static void s_callback_send_all_unsafe(dap_client_t *a_client, void *a_arg); - -static void s_callback_send_all_unsafe(dap_client_t *a_client, void *a_arg); -static void s_stream_ch_new(dap_stream_ch_t* a_ch, void* a_arg); -static void s_stream_ch_delete(dap_stream_ch_t* a_ch, void* a_arg); +}; -static void s_packet_in_callback_handler(void * a_arg); -static void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg); -static void s_stream_ch_packet_out(dap_stream_ch_t* a_ch, void* a_arg); +static struct voting_node_client_list *s_node_client_list = NULL; -static dap_interval_timer_t *s_packet_in_callback_timer = NULL; -static bool s_is_inited = false; +static size_t s_pkt_in_callback_count = 0; +static struct voting_pkt_in_callback s_pkt_in_callback[16] = {}; -//static int s_cli_voting(int argc, char ** argv, char **a_str_reply); +static void s_stream_ch_new(dap_stream_ch_t *a_ch, void *a_arg); +static void s_stream_ch_delete(dap_stream_ch_t *a_ch, void *a_arg); +static void s_stream_ch_packet_in(dap_stream_ch_t *a_ch, void *a_arg); -int dap_stream_ch_chain_voting_init() { +int dap_stream_ch_chain_voting_init() +{ log_it(L_NOTICE, "Chains voting channel initialized"); - if (s_is_inited) { - return 0; - } - - if (!s_pkt_items) { - s_pkt_items = DAP_NEW_Z(voting_pkt_items_t); - s_pkt_items->pkts_out = NULL; - s_pkt_items->pkts_in = NULL; - pthread_rwlock_init(&s_pkt_items->rwlock_out, NULL); - pthread_rwlock_init(&s_pkt_items->rwlock_in, NULL); - } dap_stream_ch_proc_add(dap_stream_ch_chain_voting_get_id(), s_stream_ch_new, s_stream_ch_delete, s_stream_ch_packet_in, - s_stream_ch_packet_out); + NULL); - if (!s_packet_in_callback_timer) { - s_packet_in_callback_timer = dap_interval_timer_create(1000, s_packet_in_callback_handler, NULL); - } - s_is_inited = true; - // s_packet_in_callback_handler(); return 0; } -void dap_stream_ch_chain_voting_in_callback_add(void* a_arg, voting_ch_callback_t packet_in_callback) +void dap_stream_ch_chain_voting_in_callback_add(void* a_arg, dap_chain_voting_ch_callback_t packet_in_callback) { size_t i = s_pkt_in_callback_count; s_pkt_in_callback[i].arg = a_arg; @@ -94,250 +55,122 @@ void dap_stream_ch_chain_voting_in_callback_add(void* a_arg, voting_ch_callback_ s_pkt_in_callback_count++; } -void dap_stream_ch_chain_voting_message_write(dap_chain_net_t * a_net, dap_list_t *a_sendto_nodes, - dap_chain_hash_fast_t * a_data_hash, - const void * a_data, size_t a_data_size) +static bool s_callback_pkt_in_call_all(UNUSED_ARG dap_proc_thread_t *a_thread, void *a_arg) { - dap_stream_ch_chain_voting_pkt_t * l_voting_pkt; - size_t l_voting_pkt_size = sizeof(l_voting_pkt->hdr) + a_data_size; - l_voting_pkt = DAP_NEW_SIZE(dap_stream_ch_chain_voting_pkt_t, l_voting_pkt_size ); - l_voting_pkt->hdr.data_size = a_data_size; - memcpy( &l_voting_pkt->hdr.data_hash, a_data_hash, sizeof(dap_chain_hash_fast_t)); - l_voting_pkt->hdr.pkt_type = DAP_STREAM_CH_CHAIN_VOTING_PKT_TYPE_TEST; - l_voting_pkt->hdr.version = 1; - l_voting_pkt->hdr.net_id.uint64 = a_net->pub.id.uint64; - if (a_data_size && a_data) { - memcpy( l_voting_pkt->data, a_data, a_data_size); + dap_stream_ch_chain_voting_pkt_t *l_voting_pkt = a_arg; + 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_voting_pkt->hdr.data_hash, l_voting_pkt->data, l_voting_pkt->hdr.data_size); + } } - voting_pkt_addr_t * l_pkt_addr = DAP_NEW_Z(voting_pkt_addr_t); - l_pkt_addr->node_addr.uint64 = 0; - l_pkt_addr->voting_pkt = l_voting_pkt; - pthread_rwlock_wrlock(&s_pkt_items->rwlock_out); - s_pkt_items->pkts_out = dap_list_append(s_pkt_items->pkts_out, l_pkt_addr); - pthread_rwlock_unlock(&s_pkt_items->rwlock_out); - - dap_stream_ch_chain_voting_pkt_broadcast(a_net, a_sendto_nodes); + return true; } -static void s_callback_send_all_unsafe_on_worker(dap_worker_t *a_worker, void *a_arg) +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) { - UNUSED(a_worker); - s_callback_send_all_unsafe((dap_client_t *)a_arg, NULL); -} - -void dap_stream_ch_chain_voting_pkt_broadcast(dap_chain_net_t *a_net, dap_list_t *a_sendto_nodes) -{ - bool l_send_loop = false; - dap_list_t *l_nodes_list_temp = dap_list_first(a_sendto_nodes); - while(l_nodes_list_temp) { - dap_list_t *l_nodes_list = l_nodes_list_temp; - l_nodes_list_temp = l_nodes_list_temp->next; - dap_chain_node_addr_t *l_remote_node_addr = (dap_chain_node_addr_t *)l_nodes_list->data; - - voting_node_client_list_t *l_node_item = NULL; - if ( l_remote_node_addr->uint64 != dap_chain_net_get_cur_addr_int(a_net) ) { - HASH_FIND(hh, s_node_client_list, l_remote_node_addr, sizeof(dap_chain_node_addr_t), l_node_item); - if (l_node_item) { - if (!dap_client_get_stream(l_node_item->node_client->client)) - dap_chain_node_client_close_mt(l_node_item->node_client); - } else { - size_t node_info_size = 0; - char *l_key = dap_chain_node_addr_to_hash_str(l_remote_node_addr); - dap_chain_node_info_t *l_node_info = - (dap_chain_node_info_t *)dap_global_db_get_sync(a_net->pub.gdb_nodes, l_key, - &node_info_size, NULL, NULL); - DAP_DELETE(l_key); - if (!l_node_info) { - continue; - } - char l_channels[] = {dap_stream_ch_chain_voting_get_id(),0}; - dap_chain_node_client_t *l_node_client = dap_chain_node_client_connect_channels(a_net, l_node_info, l_channels); - if (!l_node_client) { - continue; - } - voting_node_client_list_t *l_node_client_item = DAP_NEW_Z(voting_node_client_list_t); - l_node_client_item->node_addr = *l_remote_node_addr; - l_node_client_item->node_info = l_node_info; - l_node_client_item->node_client = l_node_client; - HASH_ADD(hh, s_node_client_list, node_addr, sizeof(dap_chain_node_addr_t), l_node_client_item); - l_node_item = l_node_client_item; + size_t l_voting_pkt_size = sizeof(*a_voting_pkt) + a_voting_pkt->hdr.data_size; + struct voting_node_client_list *l_node_client_item = NULL; + if (a_remote_node_addr->uint64 != dap_chain_net_get_cur_addr_int(a_net)) { + HASH_FIND(hh, s_node_client_list, a_remote_node_addr, sizeof(dap_chain_node_addr_t), l_node_client_item); + if (!l_node_client_item) { + size_t node_info_size = 0; + char *l_key = dap_chain_node_addr_to_hash_str(a_remote_node_addr); + dap_chain_node_info_t *l_node_info = + (dap_chain_node_info_t *)dap_global_db_get_sync(a_net->pub.gdb_nodes, l_key, + &node_info_size, NULL, NULL); + DAP_DELETE(l_key); + if (!l_node_info) { + log_it(L_WARNING, "Can't find validator's addr "NODE_ADDR_FP_STR" in database", NODE_ADDR_FP_ARGS(a_remote_node_addr)); + return; } - if ( !l_node_item || !l_node_item->node_client ) { - continue; + char l_channels[] = {dap_stream_ch_chain_voting_get_id(),0}; + dap_chain_node_client_t *l_node_client = dap_chain_node_client_connect_channels(a_net, l_node_info, l_channels); + if (!l_node_client || !l_node_client->client) { + log_it(L_ERROR, "Can't connect to remote node "NODE_ADDR_FP_STR, NODE_ADDR_FP_ARGS(a_remote_node_addr)); + return; } - pthread_rwlock_wrlock(&s_pkt_items->rwlock_out); - dap_list_t* l_pkts_list_temp = s_pkt_items->pkts_out; - while(l_pkts_list_temp) { - dap_list_t *l_pkts_list = l_pkts_list_temp; - l_pkts_list_temp = l_pkts_list_temp->next; - voting_pkt_addr_t * l_pkt_addr = (voting_pkt_addr_t *)l_pkts_list->data; - if (!l_pkt_addr->node_addr.uint64) { - voting_pkt_addr_t * l_pkt_addr_new = DAP_NEW(voting_pkt_addr_t); - l_pkt_addr_new->node_addr.uint64 = l_remote_node_addr->uint64; - l_pkt_addr_new->voting_pkt = DAP_DUP_SIZE(l_pkt_addr->voting_pkt, - l_pkt_addr->voting_pkt->hdr.data_size+sizeof(dap_stream_ch_chain_voting_pkt_hdr_t)); - l_pkt_addr_new->voting_pkt->hdr.sender_node_addr.uint64 = dap_chain_net_get_cur_addr_int(a_net); - l_pkt_addr_new->voting_pkt->hdr.recipient_node_addr.uint64 = l_remote_node_addr->uint64; - s_pkt_items->pkts_out = dap_list_append(s_pkt_items->pkts_out, l_pkt_addr_new); - } - } - pthread_rwlock_unlock(&s_pkt_items->rwlock_out); - - if (dap_client_get_stage(l_node_item->node_client->client) != STAGE_STREAM_STREAMING) - dap_client_go_stage(l_node_item->node_client->client, STAGE_STREAM_STREAMING, s_callback_send_all_unsafe); - else { - dap_stream_t *l_stream = dap_client_get_stream(l_node_item->node_client->client); - dap_worker_exec_callback_on(l_stream->stream_worker->worker, s_callback_send_all_unsafe_on_worker, - l_node_item->node_client->client); - } - } else - l_send_loop = true; - } - s_callback_send_all_loopback(l_send_loop ? dap_chain_net_get_cur_addr_int(a_net) : 0); -} + l_node_client->client->connect_on_demand = true; -static void s_callback_send_all_loopback(uint64_t a_node_addr) -{ - pthread_rwlock_wrlock(&s_pkt_items->rwlock_out); - dap_list_t* l_pkts_list = s_pkt_items->pkts_out; - while (l_pkts_list) { - dap_list_t *l_pkts_list_next = l_pkts_list->next; - voting_pkt_addr_t *l_pkt_addr = (voting_pkt_addr_t *)l_pkts_list->data; - if (l_pkt_addr->node_addr.uint64 == 0) { - if (a_node_addr) { - l_pkt_addr->voting_pkt->hdr.sender_node_addr.uint64 = - l_pkt_addr->voting_pkt->hdr.recipient_node_addr.uint64 = - a_node_addr; - pthread_rwlock_wrlock(&s_pkt_items->rwlock_in); - s_pkt_items->pkts_in = dap_list_append(s_pkt_items->pkts_in, l_pkt_addr->voting_pkt); - pthread_rwlock_unlock(&s_pkt_items->rwlock_in); - } else - DAP_DELETE(l_pkt_addr->voting_pkt); - DAP_DELETE(l_pkt_addr); - s_pkt_items->pkts_out = dap_list_delete_link(s_pkt_items->pkts_out, l_pkts_list); + l_node_client_item = DAP_NEW_Z(struct voting_node_client_list); + l_node_client_item->node_addr = *a_remote_node_addr; + l_node_client_item->node_info = l_node_info; + l_node_client_item->node_client = l_node_client; + HASH_ADD(hh, s_node_client_list, node_addr, sizeof(dap_chain_node_addr_t), l_node_client_item); } - l_pkts_list = l_pkts_list_next; - } - pthread_rwlock_unlock(&s_pkt_items->rwlock_out); -} - -static void s_callback_send_all_unsafe(dap_client_t *a_client, void *a_arg) -{ - UNUSED(a_arg); - pthread_rwlock_wrlock(&s_pkt_items->rwlock_out); - dap_chain_node_client_t *l_node_client = DAP_CHAIN_NODE_CLIENT(a_client); - if (l_node_client) { - dap_stream_ch_t * l_ch = dap_client_get_stream_ch_unsafe(a_client, dap_stream_ch_chain_voting_get_id() ); - if (l_ch) { - dap_list_t* l_pkts_list = s_pkt_items->pkts_out; - while(l_pkts_list) { - dap_list_t *l_pkts_list_next = l_pkts_list->next; - voting_pkt_addr_t *l_pkt_addr = (voting_pkt_addr_t *)l_pkts_list->data; - dap_stream_ch_chain_voting_pkt_t * l_voting_pkt = l_pkt_addr->voting_pkt; - size_t l_voting_pkt_size = sizeof(l_voting_pkt->hdr) + l_voting_pkt->hdr.data_size; - if ( l_pkt_addr->node_addr.uint64 == l_node_client->remote_node_addr.uint64 ) { - if (l_ch) { - dap_stream_ch_pkt_write_unsafe(l_ch, - l_voting_pkt->hdr.pkt_type, l_voting_pkt, l_voting_pkt_size); - log_it(L_DEBUG, "Sent pkt size %zu to addr "NODE_ADDR_FP_STR, l_voting_pkt_size, - NODE_ADDR_FP_ARGS_S(l_node_client->remote_node_addr)); - } - DAP_DELETE(l_voting_pkt); - DAP_DELETE(l_pkt_addr); - s_pkt_items->pkts_out = dap_list_delete_link(s_pkt_items->pkts_out, l_pkts_list); - } - l_pkts_list = l_pkts_list_next; - } + if (!l_node_client_item->node_client) { + log_it(L_ERROR, "NULL node_client in item of voting channel"); + return; } - } - pthread_rwlock_unlock(&s_pkt_items->rwlock_out); + dap_chain_node_client_write_mt(l_node_client_item->node_client, dap_stream_ch_chain_voting_get_id(), + DAP_STREAM_CH_CHAIN_VOTING_PKT_TYPE_DATA, a_voting_pkt, + l_voting_pkt_size); + } else + dap_proc_queue_add_callback(dap_events_worker_get_auto(), s_callback_pkt_in_call_all, + DAP_DUP_SIZE(a_voting_pkt, l_voting_pkt_size)); } - void dap_stream_ch_chain_voting_deinit() { - voting_node_client_list_t *l_node_info_item=NULL, *l_node_info_tmp=NULL; + struct voting_node_client_list *l_node_info_item, *l_node_info_tmp; HASH_ITER(hh, s_node_client_list, l_node_info_item, l_node_info_tmp) { // Clang bug at this, l_node_info_item should change at every loop cycle HASH_DEL(s_node_client_list, l_node_info_item); - DAP_DELETE(l_node_info_item->node_client); + dap_chain_node_client_close_mt(l_node_info_item->node_client); DAP_DELETE(l_node_info_item); } } -static void s_stream_ch_new(dap_stream_ch_t* a_ch, void* a_arg) { +static void s_stream_ch_new(dap_stream_ch_t *a_ch, void *a_arg) { UNUSED(a_arg); a_ch->internal = DAP_NEW_Z(dap_stream_ch_chain_voting_t); - dap_stream_ch_chain_voting_t * l_ch_chain_voting = DAP_STREAM_CH_CHAIN_VOTING(a_ch); - l_ch_chain_voting->ch = a_ch; + dap_stream_ch_chain_voting_t *l_ch_chain_voting = DAP_STREAM_CH_CHAIN_VOTING(a_ch); + l_ch_chain_voting->_inheritor = a_ch; } -static void s_stream_ch_delete(dap_stream_ch_t* a_ch, void* a_arg) +static void s_stream_ch_delete(dap_stream_ch_t *a_ch, UNUSED_ARG void *a_arg) { DAP_DEL_Z(a_ch->internal); } -static void s_packet_in_callback_handler(void *a_arg) +static void s_stream_ch_packet_in(dap_stream_ch_t *a_ch, void *a_arg) { - UNUSED(a_arg); - pthread_rwlock_wrlock(&s_pkt_items->rwlock_in); - if (s_pkt_items->pkts_in) { - dap_list_t* l_list_pkts = dap_list_copy(s_pkt_items->pkts_in); - dap_list_free(s_pkt_items->pkts_in); - s_pkt_items->pkts_in = NULL; - pthread_rwlock_unlock(&s_pkt_items->rwlock_in); - while(l_list_pkts) { - dap_stream_ch_chain_voting_pkt_t * l_voting_pkt = (dap_stream_ch_chain_voting_pkt_t *)l_list_pkts->data; - for (size_t i=0; i<s_pkt_in_callback_count; i++) { - voting_pkt_in_callback_t * 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_voting_pkt->hdr.data_hash, l_voting_pkt->data, l_voting_pkt->hdr.data_size); - } - } - DAP_DELETE(l_voting_pkt); - l_list_pkts = l_list_pkts->next; - } - dap_list_free(l_list_pkts); - } else { - pthread_rwlock_unlock(&s_pkt_items->rwlock_in); - } -} - - -static void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) -{ - dap_stream_ch_pkt_t * l_ch_pkt = (dap_stream_ch_pkt_t *) a_arg; + dap_stream_ch_pkt_t *l_ch_pkt = (dap_stream_ch_pkt_t *) a_arg; if (!l_ch_pkt) return; - pthread_rwlock_wrlock(&s_pkt_items->rwlock_in); - size_t l_voting_pkt_size = l_ch_pkt->hdr.size; + + size_t l_voting_pkt_size = l_ch_pkt->hdr.data_size; if (!l_voting_pkt_size || l_voting_pkt_size > UINT16_MAX) return; - dap_stream_ch_chain_voting_pkt_t *l_voting_pkt = DAP_DUP_SIZE(&l_ch_pkt->data, l_voting_pkt_size); - s_pkt_items->pkts_in = dap_list_append(s_pkt_items->pkts_in, l_voting_pkt); - pthread_rwlock_unlock(&s_pkt_items->rwlock_in); -} -static void s_stream_ch_packet_out(dap_stream_ch_t* a_ch, void* a_arg) { - UNUSED(a_arg); + dap_stream_ch_chain_voting_pkt_t *l_voting_pkt = (dap_stream_ch_chain_voting_pkt_t *)l_ch_pkt->data; + dap_proc_queue_add_callback(a_ch->stream_worker->worker, s_callback_pkt_in_call_all, + DAP_DUP_SIZE(l_voting_pkt, l_voting_pkt_size)); + dap_stream_ch_chain_voting_t *l_ch_chain_voting = DAP_STREAM_CH_CHAIN_VOTING(a_ch); + if (l_ch_chain_voting->callback_notify) + l_ch_chain_voting->callback_notify(l_ch_chain_voting, l_ch_pkt->hdr.type, l_voting_pkt, + 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 *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; + 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); + return l_voting_pkt; +} 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, const void * a_data, size_t a_data_size) { - dap_stream_ch_chain_voting_pkt_t * l_chain_pkt; - size_t l_chain_pkt_size = sizeof (l_chain_pkt->hdr) + a_data_size; - l_chain_pkt = DAP_NEW_Z_SIZE(dap_stream_ch_chain_voting_pkt_t, l_chain_pkt_size ); - l_chain_pkt->hdr.data_size = a_data_size; - l_chain_pkt->hdr.pkt_type = a_type; - l_chain_pkt->hdr.version = 1; - l_chain_pkt->hdr.net_id.uint64 = a_net_id; - - if (a_data_size && a_data) - memcpy( &l_chain_pkt->data, a_data, a_data_size); - - size_t l_ret = dap_stream_ch_pkt_write_unsafe(a_ch, a_type , l_chain_pkt, l_chain_pkt_size); - DAP_DELETE(l_chain_pkt); + 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); + 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 30163c46ae8e9c0ee07fcc2e6ad90efab7018075..6c361312b6eb348fe43cab46798ebbd8f9930e67 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 @@ -10,40 +10,19 @@ // #include "dap_stream_ch_chain_pkt.h" #include "uthash.h" -#define DAP_STREAM_CH_CHAIN_VOTING_PKT_TYPE_TEST 0x01 -#define DAP_STREAM_CH_CHAIN_VOTING_PKT_TYPE_TEST_RES 0x02 - -typedef void (*voting_ch_callback_t) (void*,dap_chain_node_addr_t*,dap_chain_hash_fast_t*,uint8_t*,size_t); - -// typedef struct dap_stream_ch_chain_pkt_hdr{ -// union{ -// struct{ -// uint8_t version; -// uint8_t padding[7]; -// } DAP_ALIGN_PACKED; -// uint64_t ext_id; -// }DAP_ALIGN_PACKED; -// dap_chain_net_id_t net_id; -// dap_chain_id_t chain_id; -// dap_chain_cell_id_t cell_id; -// } DAP_ALIGN_PACKED dap_stream_ch_chain_pkt_hdr_t; +#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 struct dap_stream_ch_chain_voting_pkt_hdr { - uint8_t pkt_type; - union{ - struct{ - uint8_t version; - uint8_t padding[7]; - } DAP_ALIGN_PACKED; - uint64_t ext_id; - }DAP_ALIGN_PACKED; - size_t data_size; + uint8_t version; + uint8_t padding[7]; + uint64_t data_size; dap_chain_hash_fast_t data_hash; dap_chain_net_id_t net_id; dap_chain_node_addr_t sender_node_addr; - dap_chain_node_addr_t recipient_node_addr; - // dap_chain_id_t chain_id; - // dap_chain_cell_id_t cell_id; + dap_chain_node_addr_t receiver_node_addr; } DAP_ALIGN_PACKED dap_stream_ch_chain_voting_pkt_hdr_t; typedef struct dap_stream_ch_chain_voting_pkt { @@ -53,24 +32,12 @@ typedef struct dap_stream_ch_chain_voting_pkt { typedef struct dap_stream_ch_chain_voting dap_stream_ch_chain_voting_t; -typedef void (*dap_stream_ch_chain_voting_callback_packet_t)(dap_stream_ch_chain_voting_t*, uint8_t a_pkt_type, +typedef void (*dap_stream_ch_chain_voting_callback_packet_t)(dap_stream_ch_chain_voting_t *a_ch_voting, uint8_t a_pkt_type, dap_stream_ch_chain_voting_pkt_t *a_pkt, size_t a_pkt_data_size, void * a_arg); typedef struct dap_stream_ch_chain_voting { - //void *_inheritor; - dap_stream_ch_t * ch; - //dap_stream_ch_chain_state_t state; - dap_chain_node_client_t * node_client; // Node client associated with stream - - // request section - //dap_stream_ch_chain_sync_request_t request; - //dap_stream_ch_chain_pkt_hdr_t request_hdr; - //dap_list_t *request_db_iter; - - //bool was_active; - - //dap_stream_ch_chain_voting_callback_packet_t callback_notify_packet_out; + void *_inheritor; // parent stream ch dap_stream_ch_chain_voting_callback_packet_t callback_notify; void *callback_notify_arg; } dap_stream_ch_chain_voting_t; @@ -79,16 +46,12 @@ typedef struct dap_stream_ch_chain_voting { inline static uint8_t dap_stream_ch_chain_voting_get_id(void) { return (uint8_t) 'V'; } -void dap_stream_ch_chain_voting_in_callback_add(void* a_arg, voting_ch_callback_t packet_in_callback); +void dap_stream_ch_chain_voting_in_callback_add(void* a_arg, dap_chain_voting_ch_callback_t packet_in_callback); -void dap_stream_ch_chain_voting_message_write(dap_chain_net_t * a_net, dap_list_t *a_sendto_nodes, - dap_chain_hash_fast_t * a_data_hash, - const void * a_data, size_t a_data_size); -void dap_stream_ch_chain_voting_pkt_broadcast(dap_chain_net_t * a_net, dap_list_t *a_sendto_nodes); +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); -// size_t dap_stream_ch_chain_voting_pkt_write_mt(dap_stream_worker_t *a_worker, dap_stream_ch_uuid_t a_ch_uuid, -// uint8_t a_type,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, 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, const void * a_data, size_t a_data_size); diff --git a/modules/channel/chain/dap_stream_ch_chain.c b/modules/channel/chain/dap_stream_ch_chain.c index 83926112676f0ea1f812857fca17a36e30f6ed80..f33e764cc55a236e6edc4c2e763b5e6a8f843e8f 100644 --- a/modules/channel/chain/dap_stream_ch_chain.c +++ b/modules/channel/chain/dap_stream_ch_chain.c @@ -1023,12 +1023,12 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) log_it(L_ERROR, "No chain packet in channel packet, returning"); return; } - if (l_ch_pkt->hdr.size < sizeof (l_chain_pkt->hdr)){ - log_it(L_ERROR, "Corrupted packet: too small size %u, smaller then header size %zu", l_ch_pkt->hdr.size, + if (l_ch_pkt->hdr.data_size < sizeof (l_chain_pkt->hdr)){ + log_it(L_ERROR, "Corrupted packet: too small size %u, smaller then header size %zu", l_ch_pkt->hdr.data_size, sizeof(l_chain_pkt->hdr)); return; } - size_t l_chain_pkt_data_size = l_ch_pkt->hdr.size-sizeof (l_chain_pkt->hdr); + size_t l_chain_pkt_data_size = l_ch_pkt->hdr.data_size - sizeof(l_chain_pkt->hdr); dap_chain_net_t *l_net = dap_chain_net_by_id(l_chain_pkt->hdr.net_id); if (!l_net) { if (l_ch_pkt->hdr.type == DAP_STREAM_CH_CHAIN_PKT_TYPE_ERROR) { diff --git a/modules/common/dap_chain_common.c b/modules/common/dap_chain_common.c index 19e23fc6d378b40917f78703fe0c06788969d264..a2a8f77dd28ba8f538d6cbc569703c82dccbe08d 100644 --- a/modules/common/dap_chain_common.c +++ b/modules/common/dap_chain_common.c @@ -38,6 +38,7 @@ #define LOG_TAG "dap_chain_common" const dap_chain_net_srv_uid_t c_dap_chain_net_srv_uid_null = {0}; +const dap_chain_cell_id_t c_dap_chain_cell_id_null = {0}; /* * Forward declarations @@ -173,19 +174,30 @@ dap_chain_net_srv_uid_t dap_chain_net_srv_uid_from_str( const char * a_net_srv_u * @param a_net_id * @return */ -void dap_chain_addr_fill_from_key(dap_chain_addr_t *a_addr, dap_enc_key_t *a_key, dap_chain_net_id_t a_net_id) { +int dap_chain_addr_fill_from_key(dap_chain_addr_t *a_addr, dap_enc_key_t *a_key, dap_chain_net_id_t a_net_id) +{ dap_sign_type_t l_type = dap_sign_type_from_key_type(a_key->type); size_t l_pub_key_data_size; uint8_t *l_pub_key_data = dap_enc_key_serealize_pub_key(a_key, &l_pub_key_data_size); if (!l_pub_key_data) { log_it(L_ERROR,"Can't fill address from key, its empty"); - return; + return -1; } dap_chain_hash_fast_t l_hash_public_key; // serialized key -> key hash dap_hash_fast(l_pub_key_data, l_pub_key_data_size, &l_hash_public_key); dap_chain_addr_fill(a_addr, l_type, &l_hash_public_key, a_net_id); DAP_DELETE(l_pub_key_data); + return 0; +} + +int dap_chain_addr_fill_from_sign(dap_chain_addr_t *a_addr, dap_sign_t *a_sign, dap_chain_net_id_t a_net_id) +{ + dap_hash_fast_t l_sign_pkey_hash; + if (!dap_sign_get_pkey_hash(a_sign, &l_sign_pkey_hash)) + return -1; + dap_chain_addr_fill(a_addr, a_sign->header.type, &l_sign_pkey_hash, a_net_id); + return 0; } /** @@ -226,6 +238,8 @@ int dap_chain_addr_check_sum(const dap_chain_addr_t *a_addr) return -1; } + + uint64_t dap_chain_uint128_to(uint128_t a_from) { #ifdef DAP_GLOBAL_IS_INT128 diff --git a/modules/common/dap_chain_datum.c b/modules/common/dap_chain_datum.c index 9ddec492ea931de34d216b0a82887baf15e85b37..bdac29630bd4ed27dd8065b49ad796c8b706393b 100644 --- a/modules/common/dap_chain_datum.c +++ b/modules/common/dap_chain_datum.c @@ -292,7 +292,7 @@ bool dap_chain_datum_dump_tx(dap_chain_datum_tx_t *a_datum, DAP_DELETE(l_hash_str); } break; case TX_ITEM_TYPE_IN_EMS_EXT: { - l_hash_tmp = &((dap_chain_tx_token_ext_t*)item)->header.ext_tx_hash; + l_hash_tmp = &((dap_chain_tx_in_ems_ext_t*)item)->header.ext_tx_hash; if (!dap_strcmp(a_hash_out_type, "hex")) l_hash_str = dap_chain_hash_fast_to_str_new(l_hash_tmp); else @@ -304,12 +304,12 @@ bool dap_chain_datum_dump_tx(dap_chain_datum_tx_t *a_datum, "\t\t Ext net id: 0x%016"DAP_UINT64_FORMAT_x"\n" "\t\t Ext tx hash: %s\n" "\t\t Ext tx out idx: %u\n", - ((dap_chain_tx_token_ext_t*)item)->header.version, - ((dap_chain_tx_token_ext_t*)item)->header.ticker, - ((dap_chain_tx_token_ext_t*)item)->header.ext_chain_id.uint64, - ((dap_chain_tx_token_ext_t*)item)->header.ext_net_id.uint64, + ((dap_chain_tx_in_ems_ext_t*)item)->header.version, + ((dap_chain_tx_in_ems_ext_t*)item)->header.ticker, + ((dap_chain_tx_in_ems_ext_t*)item)->header.ext_chain_id.uint64, + ((dap_chain_tx_in_ems_ext_t*)item)->header.ext_net_id.uint64, l_hash_str, - ((dap_chain_tx_token_ext_t*)item)->header.ext_tx_out_idx); + ((dap_chain_tx_in_ems_ext_t*)item)->header.ext_tx_out_idx); DAP_DELETE(l_hash_str); } break; case TX_ITEM_TYPE_SIG: { diff --git a/modules/common/dap_chain_datum_tx_token.c b/modules/common/dap_chain_datum_tx_token.c deleted file mode 100644 index 0379c5ae4640d3faf766f20becfde6e5139dd81a..0000000000000000000000000000000000000000 --- a/modules/common/dap_chain_datum_tx_token.c +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Authors: - * Dmitriy A. Gearasimov <kahovski@gmail.com> - * DeM Labs Inc. https://demlabs.net - * DeM Labs Open source community https://github.com/demlabsinc - * Copyright (c) 2017-2019 - * All rights reserved. - - This file is part of DAP (Deus Applications Prototypes) the open source project - - DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - DAP is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with any DAP based project. If not, see <http://www.gnu.org/licenses/>. -*/ -#include <dap_chain_datum_tx_token.h> diff --git a/modules/common/include/dap_chain_common.h b/modules/common/include/dap_chain_common.h index e17af915462c1d1f6ec167f13ba2a40a8816f647..49d7febfbc31cb0265fa528e14b25b3404785ae5 100644 --- a/modules/common/include/dap_chain_common.h +++ b/modules/common/include/dap_chain_common.h @@ -38,7 +38,7 @@ #define DAP_CHAIN_ID_SIZE 8 #define DAP_CHAIN_SHARD_ID_SIZE 8 #define DAP_CHAIN_NET_ID_SIZE 8 -#define DAP_CHAIN_NODE_ROLE_SIZE 2 +#define DAP_CHAIN_NODE_ROLE_SIZE 4 #define DAP_CHAIN_HASH_SLOW_SIZE 32 #define DAP_CHAIN_TIMESTAMP_SIZE 8 #define DAP_CHAIN_TICKER_SIZE_MAX 10 @@ -83,7 +83,6 @@ typedef union dap_chain_node_addr { #define NODE_ADDR_FPS_ARGS(a) &a->words[3],&a->words[2],&a->words[1],&a->words[0] #define NODE_ADDR_FP_ARGS_S(a) a.words[3],a.words[2],a.words[1],a.words[0] #define NODE_ADDR_FPS_ARGS_S(a) &a.words[3],&a.words[2],&a.words[1],&a.words[0] - #endif inline static int dap_chain_node_addr_from_str( dap_chain_node_addr_t * a_addr, const char * a_addr_str){ @@ -99,15 +98,17 @@ inline static bool dap_chain_node_addr_not_null(dap_chain_node_addr_t * a_addr){ * * */ +enum { + NODE_ROLE_ROOT_MASTER=0x00, + NODE_ROLE_ROOT=0x01, + NODE_ROLE_ARCHIVE=0x02, + NODE_ROLE_CELL_MASTER=0x10, + NODE_ROLE_MASTER = 0x20, + NODE_ROLE_FULL=0xf0, + NODE_ROLE_LIGHT=0xff +}; typedef union dap_chain_node_role{ - enum { - NODE_ROLE_ROOT_MASTER=0x00, - NODE_ROLE_ROOT=0x01, - NODE_ROLE_ARCHIVE=0x02, - NODE_ROLE_CELL_MASTER=0x10, - NODE_ROLE_MASTER = 0x20, - NODE_ROLE_FULL=0xf0, - NODE_ROLE_LIGHT=0xff } enums; + uint32_t enums; uint8_t raw[DAP_CHAIN_NODE_ROLE_SIZE]; } DAP_ALIGN_PACKED dap_chain_node_role_t; @@ -132,16 +133,16 @@ typedef struct dap_chain_addr{ uint8_t addr_ver; // 0 for default dap_chain_net_id_t net_id; // Testnet, mainnet or alternet dap_sign_type_t sig_type; - union{ + union { //dap_chain_hash_fast_t hash; struct { uint8_t key_spend[sizeof(dap_chain_hash_fast_t)/2]; uint8_t key_view[sizeof(dap_chain_hash_fast_t)/2]; - } key_sv; + } DAP_ALIGN_PACKED key_sv; uint8_t key[sizeof(dap_chain_hash_fast_t)]; uint8_t hash[sizeof(dap_chain_hash_fast_t)]; dap_chain_hash_fast_t hash_fast; - } data; + } DAP_ALIGN_PACKED data; dap_chain_hash_fast_t checksum; } DAP_ALIGN_PACKED dap_chain_addr_t; @@ -159,8 +160,9 @@ typedef union { } dap_chain_net_srv_uid_t; extern const dap_chain_net_srv_uid_t c_dap_chain_net_srv_uid_null; +extern const dap_chain_cell_id_t c_dap_chain_cell_id_null; -typedef enum { +enum serv_unit_enum { SERV_UNIT_UNDEFINED = 0 , SERV_UNIT_MB = 0x00000001, // megabytes SERV_UNIT_SEC = 0x00000002, // seconds @@ -168,7 +170,8 @@ typedef enum { SERV_UNIT_KB = 0x00000010, // kilobytes SERV_UNIT_B = 0x00000011, // bytes SERV_UNIT_PCS = 0x00000022 // pieces -} serv_unit_enum_t; +}; +typedef uint32_t serv_unit_enum_t; DAP_STATIC_INLINE const char *serv_unit_enum_to_str(serv_unit_enum_t *unit_enum){ switch (*unit_enum) { @@ -180,20 +183,14 @@ DAP_STATIC_INLINE const char *serv_unit_enum_to_str(serv_unit_enum_t *unit_enum) case SERV_UNIT_B: return "SERV_UNIT_B"; case SERV_UNIT_PCS: return "SERV_UNIT_PCS"; default: return "UNDEFINED"; - } -// switch (unit_enum){ -// case SERV -// } -// return "SERV_UNIT_UNDEFINED"; } typedef union { uint8_t raw[4]; - uint32_t raw_ui32[1]; uint32_t uint32; serv_unit_enum_t enm; -} dap_chain_net_srv_price_unit_uid_t; +} DAP_ALIGN_PACKED dap_chain_net_srv_price_unit_uid_t; enum dap_chain_tx_item_type { TX_ITEM_TYPE_IN = 0x00, /// @brief Transaction: inputs @@ -249,15 +246,21 @@ bool dap_chain_addr_is_blank(const dap_chain_addr_t *a_addr); dap_chain_net_srv_uid_t dap_chain_net_srv_uid_from_str(const char* a_str); void dap_chain_addr_fill(dap_chain_addr_t *a_addr, dap_sign_type_t a_type, dap_chain_hash_fast_t *a_pkey_hash, dap_chain_net_id_t a_net_id); -void dap_chain_addr_fill_from_key(dap_chain_addr_t *a_addr, dap_enc_key_t *a_key, dap_chain_net_id_t a_net_id); +int dap_chain_addr_fill_from_key(dap_chain_addr_t *a_addr, dap_enc_key_t *a_key, dap_chain_net_id_t a_net_id); +int dap_chain_addr_fill_from_sign(dap_chain_addr_t *a_addr, dap_sign_t *a_sign, dap_chain_net_id_t a_net_id); int dap_chain_addr_check_sum(const dap_chain_addr_t *a_addr); +DAP_STATIC_INLINE bool dap_chain_addr_compare(dap_chain_addr_t *a_addr1, dap_chain_addr_t *a_addr2) +{ + return !memcmp(a_addr1, a_addr2, sizeof(dap_chain_addr_t)); +} +// Deprecated DAP_STATIC_INLINE long double dap_chain_datoshi_to_coins(uint64_t a_count) { return (double)a_count / DATOSHI_LD; } - +// Deprecated DAP_STATIC_INLINE uint64_t dap_chain_coins_to_datoshi(long double a_count) { return (uint64_t)(a_count * DATOSHI_LD); diff --git a/modules/common/include/dap_chain_datum_tx_token.h b/modules/common/include/dap_chain_datum_tx_in_ems.h similarity index 94% rename from modules/common/include/dap_chain_datum_tx_token.h rename to modules/common/include/dap_chain_datum_tx_in_ems.h index 63a86c6f1a4d541cf1674c2263e7b907dabd8e27..c0f46fbeecf0e6011e5ec50ab534996ce84b2f34 100644 --- a/modules/common/include/dap_chain_datum_tx_token.h +++ b/modules/common/include/dap_chain_datum_tx_in_ems.h @@ -32,7 +32,7 @@ * @struct dap_chain_tx_token * @brief Token item */ -typedef struct dap_chain_tx_token{ +typedef struct dap_chain_tx_in_ems { struct { dap_chain_tx_item_type_t type; char ticker[DAP_CHAIN_TICKER_SIZE_MAX]; @@ -47,7 +47,7 @@ typedef struct dap_chain_tx_token{ * @struct dap_chain_tx_token_ext * @brief External token swap */ -typedef struct dap_chain_tx_token_ext{ +typedef struct dap_chain_tx_in_ems_ext{ struct { dap_chain_tx_item_type_t type; uint8_t version; @@ -59,4 +59,4 @@ typedef struct dap_chain_tx_token_ext{ uint16_t padding2; uint16_t ext_tx_out_idx; // Output index } header; /// Only header's hash is used for verification -} DAP_ALIGN_PACKED dap_chain_tx_token_ext_t; +} DAP_ALIGN_PACKED dap_chain_tx_in_ems_ext_t; diff --git a/modules/common/include/dap_chain_datum_tx_items.h b/modules/common/include/dap_chain_datum_tx_items.h index 8e83de002985ad6fa77e858d75ae3ddf85cf5a4e..050909ccd2bda840e6d62292163d7238f756186c 100644 --- a/modules/common/include/dap_chain_datum_tx_items.h +++ b/modules/common/include/dap_chain_datum_tx_items.h @@ -39,7 +39,7 @@ #include "dap_chain_datum_tx_out_cond.h" #include "dap_chain_datum_tx_sig.h" #include "dap_chain_datum_tx_pkey.h" -#include "dap_chain_datum_tx_token.h" +#include "dap_chain_datum_tx_in_ems.h" #include "dap_chain_datum_tx_receipt.h" #include "dap_chain_datum_tx_tsd.h" diff --git a/modules/consensus/block-ton/dap_chain_cs_block_ton.c b/modules/consensus/block-ton/dap_chain_cs_block_ton.c deleted file mode 100644 index 688c50eea641cbf5e57eed211bbd060a283a7555..0000000000000000000000000000000000000000 --- a/modules/consensus/block-ton/dap_chain_cs_block_ton.c +++ /dev/null @@ -1,2347 +0,0 @@ - -#include "dap_timerfd.h" -#include "utlist.h" -#include "dap_chain_net.h" -#include "dap_chain_common.h" -#include "dap_chain_cell.h" -#include "dap_chain_cs.h" -#include "dap_chain_cs_blocks.h" -#include "dap_chain_cs_block_ton.h" -#include "dap_stream_ch_chain_voting.h" -#include "dap_chain_net_srv_stake_pos_delegate.h" -#include "dap_chain_ledger.h" - -#define LOG_TAG "dap_chain_cs_blocks_ton" - -static int s_callback_new(dap_chain_t *a_chain, dap_config_t *a_chain_cfg); -static void s_session_packet_in(void * a_arg, dap_chain_node_addr_t * a_sender_node_addr, - dap_chain_hash_fast_t *a_data_hash, uint8_t *a_data, size_t a_data_size); -static void s_session_candidate_to_chain( - dap_chain_cs_block_ton_session_t *a_session, dap_chain_hash_fast_t *a_candidate_hash, - dap_chain_block_t *a_candidate, size_t a_candidate_size); -static void s_session_candidate_submit(dap_chain_cs_block_ton_session_t *a_session); -static void s_session_timer(void *a_arg); -static int s_session_atom_validation(dap_chain_cs_blocks_t *a_blocks, dap_chain_block_t *a_block, size_t a_block_size); -static uint8_t *s_message_data_sign(dap_chain_cs_block_ton_session_t *a_session, - dap_chain_cs_block_ton_message_t *a_message, size_t *a_sign_size); -static void s_message_send(dap_chain_cs_block_ton_session_t *a_session, uint8_t a_message_type, - uint8_t *a_data, size_t a_data_size, dap_list_t *a_validators); -static void s_message_chain_add(dap_chain_cs_block_ton_session_t * a_session, dap_chain_node_addr_t * a_sender_node_addr, - dap_chain_cs_block_ton_message_t * a_message, - size_t a_message_size, dap_chain_hash_fast_t *a_message_hash); -static void s_session_round_clear(dap_chain_cs_block_ton_session_t *a_session); -static bool s_session_send_startsync(dap_chain_cs_block_ton_session_t *a_session); -static void s_session_my_candidate_delete(dap_chain_cs_block_ton_session_t *a_session); -static void s_session_round_finish(dap_chain_cs_block_ton_session_t *a_session, bool a_failed); -static dap_chain_node_addr_t *s_session_get_validator( - dap_chain_cs_block_ton_session_t *a_session, dap_chain_node_addr_t *a_addr, - dap_list_t *a_validators); -static uint16_t s_session_message_count(dap_chain_cs_block_ton_session_t *a_session, uint8_t a_type, - dap_chain_hash_fast_t *a_candidate_hash, uint16_t *a_attempt_number); -static void s_callback_delete(dap_chain_cs_blocks_t *a_blocks); -static int s_callback_created(dap_chain_t *a_chain, dap_config_t *a_chain_net_cfg); -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); - -static int s_compare_validators_list_stake(const void * a_item1, const void * a_item2, void *a_unused); -static int s_compare_validators_list_addr(const void * a_item1, const void * a_item2, void *a_unused); -static dap_list_t *s_get_validators_addr_list(dap_chain_cs_block_ton_session_t *a_session); //(dap_chain_t *a_chain); - -static dap_chain_cs_block_ton_session_t * s_session_items; -static dap_interval_timer_t s_session_cs_timer = NULL; - -typedef struct dap_chain_cs_block_ton_pvt -{ - dap_enc_key_t *blocks_sign_key; - char **tokens_hold; - uint64_t *tokens_hold_value; - dap_config_t *chain_cfg; - size_t tokens_hold_size; - // uint16_t confirmations_minimum; - dap_chain_callback_new_cfg_t prev_callback_created; - - uint16_t poa_validators_count; - bool flag_sign_verify; - - bool debug; - bool validators_list_by_stake; - uint16_t round_start_sync_timeout; - uint16_t round_start_multiple_of; - uint32_t allowed_clock_offset; - uint32_t session_idle_min; - uint16_t round_candidates_max; - uint16_t next_candidate_delay; - uint16_t round_attempts_max; - uint16_t round_attempt_duration; - uint16_t first_message_delay; - uint16_t my_candidate_attempts_max; - - dap_list_t *ton_nodes_addrs; // dap_chain_node_addr_t - - uint16_t auth_certs_count; - char *auth_certs_prefix; - dap_cert_t ** auth_certs; -} dap_chain_cs_block_ton_pvt_t; - -#define PVT(a) ((dap_chain_cs_block_ton_pvt_t *)a->_pvt) - -int dap_chain_cs_block_ton_init() { - dap_stream_ch_chain_voting_init(); - dap_chain_cs_add("block_ton", s_callback_new); - return 0; -} - -void dap_chain_cs_block_ton_deinit(void) { - -} - -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_cs_block_ton_t *l_ton = DAP_NEW_Z(dap_chain_cs_block_ton_t); - l_blocks->_inheritor = l_ton; - 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_ton->_pvt = DAP_NEW_Z(dap_chain_cs_block_ton_pvt_t); - - dap_chain_cs_block_ton_pvt_t *l_ton_pvt = PVT(l_ton); - - char ** l_tokens_hold = NULL; - char ** l_tokens_hold_value_str = NULL; - uint16_t l_tokens_hold_size = 0; - uint16_t l_tokens_hold_value_size = 0; - - l_tokens_hold = dap_config_get_array_str(a_chain_cfg, "block-ton", "stake_tokens", &l_tokens_hold_size); - l_tokens_hold_value_str = dap_config_get_array_str(a_chain_cfg, "block-ton", "stake_tokens_value", &l_tokens_hold_value_size); - - if (l_tokens_hold_size != l_tokens_hold_value_size){ - log_it(L_CRITICAL, "Entries tokens_hold and tokens_hold_value are different size!"); - goto lb_err; - } - //l_ton_pvt->confirmations_minimum = dap_config_get_item_uint16_default(a_chain_cfg, "block-ton", "verifications_minimum", 1); - l_ton_pvt->flag_sign_verify = true; - l_ton_pvt->tokens_hold_size = l_tokens_hold_size; - l_ton_pvt->tokens_hold = DAP_NEW_Z_SIZE(char *, sizeof(char *) * l_tokens_hold_size); - l_ton_pvt->tokens_hold_value = DAP_NEW_Z_SIZE(uint64_t, l_tokens_hold_value_size * sizeof(uint64_t)); - l_ton_pvt->debug = dap_config_get_item_bool_default(a_chain_cfg,"block-ton","consensus_debug", true); - - l_ton_pvt->validators_list_by_stake = dap_config_get_item_bool_default(a_chain_cfg,"block-ton","validators_list_by_stake", false); - l_ton_pvt->round_start_sync_timeout = dap_config_get_item_uint16_default(a_chain_cfg,"block-ton", "round_start_sync_timeout", 10); - l_ton_pvt->round_start_multiple_of = dap_config_get_item_uint16_default(a_chain_cfg,"block-ton", "round_start_multiple_of", 30); - l_ton_pvt->allowed_clock_offset = dap_config_get_item_uint32_default(a_chain_cfg,"block-ton", "allowed_clock_offset", 5); - l_ton_pvt->session_idle_min = dap_config_get_item_uint32_default(a_chain_cfg,"block-ton", "session_idle_min", 15); - l_ton_pvt->round_candidates_max = dap_config_get_item_uint16_default(a_chain_cfg,"block-ton", "round_candidates_max", 3); - l_ton_pvt->next_candidate_delay = dap_config_get_item_uint16_default(a_chain_cfg,"block-ton", "next_candidate_delay", 2); - l_ton_pvt->round_attempts_max = dap_config_get_item_uint16_default(a_chain_cfg,"block-ton", "round_attempts_max", 4); - l_ton_pvt->round_attempt_duration = dap_config_get_item_uint16_default(a_chain_cfg,"block-ton", "round_attempt_duration", 60); - l_ton_pvt->first_message_delay = dap_config_get_item_uint16_default(a_chain_cfg,"block-ton", "first_message_delay", 3); - l_ton_pvt->my_candidate_attempts_max = dap_config_get_item_uint16_default(a_chain_cfg,"block-ton", "my_candidate_attempts_max", 2); - - l_ton_pvt->ton_nodes_addrs = NULL; - l_ton_pvt->auth_certs_prefix = strdup( dap_config_get_item_str_default(a_chain_cfg,"block-ton","auth_certs_prefix", "ton") ); - l_ton_pvt->auth_certs_count = dap_config_get_item_uint16_default(a_chain_cfg,"block-ton","auth_certs_number", 0); - if ( !l_ton_pvt->validators_list_by_stake ) { // auth by cert for PoA mode - if (l_ton_pvt->auth_certs_count) { - l_ton_pvt->auth_certs = DAP_NEW_Z_SIZE(dap_cert_t *, l_ton_pvt->auth_certs_count * sizeof(dap_cert_t*)); - char l_cert_name[512]; - for (size_t i = 0; i < l_ton_pvt->auth_certs_count; i++ ){ - dap_snprintf(l_cert_name, sizeof(l_cert_name), "%s.%zu", l_ton_pvt->auth_certs_prefix, i); - if ((l_ton_pvt->auth_certs[i] = dap_cert_find_by_name( l_cert_name)) == NULL) { - dap_snprintf(l_cert_name, sizeof(l_cert_name), "%s.%zu.pub", l_ton_pvt->auth_certs_prefix, i); - if ((l_ton_pvt->auth_certs[i] = dap_cert_find_by_name(l_cert_name)) == NULL) { - log_it(L_ERROR, "TON: Can't find cert \"%s\"", l_cert_name); - return -1; - } - } - log_it(L_NOTICE, "TON: Initialized auth cert \"%s\"", l_cert_name); - } - } - - uint16_t l_node_addrs_count; - char **l_addrs = dap_config_get_array_str(a_chain_cfg, "block-ton", "ton_nodes_addrs", &l_node_addrs_count); - l_ton_pvt->poa_validators_count = l_node_addrs_count; - for(size_t i = 0; i < l_node_addrs_count; i++) { - dap_chain_node_addr_t *l_node_addr = DAP_NEW_Z(dap_chain_node_addr_t); - if (dap_sscanf(l_addrs[i],NODE_ADDR_FP_STR, NODE_ADDR_FPS_ARGS(l_node_addr) ) != 4 ){ - log_it(L_ERROR,"TON: Wrong address format, should be like 0123::4567::890AB::CDEF"); - DAP_DELETE(l_node_addr); - //DAP_DELETE(l_node_info); - l_node_addr = NULL; - continue; - } - if (l_node_addr) { - log_it(L_MSG, "TON: add validator addr:"NODE_ADDR_FP_STR"", NODE_ADDR_FP_ARGS(l_node_addr)); - l_ton_pvt->ton_nodes_addrs = dap_list_append(l_ton_pvt->ton_nodes_addrs, l_node_addr); - } - } - - } - else { // stake - for (size_t i = 0; i < l_tokens_hold_value_size; i++) { - l_ton_pvt->tokens_hold[i] = dap_strdup(l_tokens_hold[i]); - if ((l_ton_pvt->tokens_hold_value[i] = - strtoull(l_tokens_hold_value_str[i],NULL,10)) == 0) { - log_it(L_CRITICAL, "Token %s has inproper hold value %s", - l_ton_pvt->tokens_hold[i], l_tokens_hold_value_str[i]); - goto lb_err; - } - } - } - - - // Save old callback if present and set the call of its own (chain callbacks) - l_ton_pvt->prev_callback_created = l_blocks->chain->callback_created; - l_blocks->chain->callback_created = s_callback_created; - return 0; - -lb_err: - for (int i = 0; i < l_tokens_hold_size; i++) - DAP_DELETE(l_tokens_hold[i]); - DAP_DELETE(l_tokens_hold); - DAP_DELETE(l_ton_pvt->tokens_hold_value); - DAP_DELETE(l_ton_pvt); - DAP_DELETE(l_ton ); - l_blocks->_inheritor = NULL; - l_blocks->callback_delete = NULL; - l_blocks->callback_block_verify = NULL; - return -1; - -} - -static void s_callback_delete(dap_chain_cs_blocks_t *a_blocks) { - dap_interval_timer_delete(s_session_cs_timer); - dap_chain_cs_block_ton_t *l_ton = DAP_CHAIN_CS_BLOCK_TON(a_blocks); - if (l_ton->_pvt) - DAP_DELETE(l_ton->_pvt); -} - - -static int s_compare_validators_list_stake(const void * a_item1, const void * a_item2, void *a_unused) -{ - UNUSED(a_unused); - dap_chain_net_srv_stake_item_t *l_item1 = (dap_chain_net_srv_stake_item_t *)a_item1; - dap_chain_net_srv_stake_item_t *l_item2 = (dap_chain_net_srv_stake_item_t *)a_item2; - return compare256(l_item1->value, l_item2->value)*-1; -} - -static int s_compare_validators_list_addr(const void * a_item1, const void * a_item2, void *a_unused) -{ - UNUSED(a_unused); - dap_chain_node_addr_t *l_item1 = (dap_chain_node_addr_t *)a_item1; - dap_chain_node_addr_t *l_item2 = (dap_chain_node_addr_t *)a_item2; - if(!l_item1 || !l_item2 || l_item1->uint64 == l_item2->uint64) - return 0; - if(l_item1->uint64 > l_item2->uint64) - return 1; - return -1; -} - -static dap_list_t *s_get_validators_addr_list(dap_chain_cs_block_ton_session_t *a_session) {//(dap_chain_t *a_chain) { - - dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(a_session->chain); - dap_chain_cs_block_ton_t *l_ton = DAP_CHAIN_CS_BLOCK_TON(l_blocks); - dap_chain_cs_block_ton_pvt_t *l_ton_pvt = PVT(l_ton); - dap_list_t *l_ret = NULL; - - if ( l_ton_pvt->validators_list_by_stake) { - dap_list_t *l_validators = dap_chain_net_srv_stake_get_validators(); - l_validators = dap_list_sort(l_validators, s_compare_validators_list_stake); - dap_list_t *l_list = dap_list_first(l_validators); - while (l_list){ - dap_list_t *l_next = l_list->next; - dap_chain_node_addr_t *l_addr = - (dap_chain_node_addr_t *)DAP_DUP_SIZE( - &((dap_chain_net_srv_stake_item_t * )l_list->data)->node_addr, - sizeof(dap_chain_node_addr_t)); - DAP_DELETE(l_list->data); - l_ret = dap_list_append(l_ret, l_addr); - l_list = l_next; - } - dap_list_free(l_list); - } - else { - // dap_chain_net_t *l_net = dap_chain_net_by_id(a_session->chain->net_id); - dap_list_t *l_list = dap_list_first(PVT(a_session->ton)->ton_nodes_addrs); - while (l_list) { - dap_chain_node_addr_t *l_addr = - (dap_chain_node_addr_t *)DAP_DUP_SIZE( - l_list->data, sizeof(dap_chain_node_addr_t)); - l_ret = dap_list_append(l_ret, l_addr); - l_list = l_list->next; - } - l_ret = dap_list_sort(l_ret, s_compare_validators_list_addr); - } - return l_ret; -} - -static int s_callback_created(dap_chain_t *a_chain, dap_config_t *a_chain_net_cfg) { - - dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(a_chain); - dap_chain_cs_block_ton_t *l_ton = DAP_CHAIN_CS_BLOCK_TON(l_blocks); - dap_chain_cs_block_ton_pvt_t *l_ton_pvt = PVT(l_ton); - - const char *l_sign_cert_str = NULL; - if ((l_sign_cert_str = dap_config_get_item_str(a_chain_net_cfg,"block-ton","blocks-sign-cert")) != NULL) { - dap_cert_t *l_sign_cert = dap_cert_find_by_name(l_sign_cert_str); - if (l_sign_cert == NULL) { - log_it(L_ERROR, "Can't load sign certificate, name \"%s\" is wrong", l_sign_cert_str); - } else if (l_sign_cert->enc_key->priv_key_data) { - l_ton_pvt->blocks_sign_key = l_sign_cert->enc_key; - log_it(L_INFO, "Loaded \"%s\" certificate to sign TON blocks", l_sign_cert_str); - } else { - log_it(L_ERROR, "Certificate \"%s\" has no private key", l_sign_cert_str); - } - } else { - log_it(L_ERROR, "No sign certificate provided, can't sign any blocks"); - } - - dap_chain_net_t *l_net = dap_chain_net_by_id(a_chain->net_id); - dap_chain_cs_block_ton_session_t *l_session = DAP_NEW_Z(dap_chain_cs_block_ton_session_t); - l_session->chain = a_chain; - l_session->ton = l_ton; - - l_session->my_candidate = NULL; - l_session->my_candidate_size = 0; - l_session->my_candidate_attempts_count = 0; - - l_session->cur_round.validators_list = s_get_validators_addr_list(l_session); - l_session->cur_round.validators_count = dap_list_length(l_session->cur_round.validators_list); - - l_session->my_addr = DAP_NEW(dap_chain_node_addr_t); - l_session->my_addr->uint64 = dap_chain_net_get_cur_addr_int(l_net); - - l_session->cur_round.id.uint64 = 1000; - pthread_rwlock_init(&l_session->cur_round.messages_rwlock, NULL); - l_session->gdb_group_store = dap_strdup_printf("local.ton.%s.%s.store", - a_chain->net_name, a_chain->name); - l_session->gdb_group_message = dap_strdup_printf("local.ton.%s.%s.message", - a_chain->net_name, a_chain->name); - l_session->state = DAP_STREAM_CH_CHAIN_SESSION_STATE_IDLE; - - dap_time_t l_time = dap_time_now(); - while (true) { - l_time++; - if ( (l_time % l_ton_pvt->round_start_multiple_of) == 0) { - l_session->ts_round_sync_start = l_time; - break; - } - } - pthread_rwlock_init(&l_session->rwlock, NULL); - - log_it(L_INFO, "TON: init session for net:%s, chain:%s", a_chain->net_name, a_chain->name); - DL_APPEND(s_session_items, l_session); - dap_chain_node_role_t l_role = dap_chain_net_get_role(l_net); - if (l_ton_pvt->validators_list_by_stake || - (l_role.enums == NODE_ROLE_MASTER || l_role.enums == NODE_ROLE_ROOT) ) { - if ( s_session_get_validator(l_session, l_session->my_addr, l_session->cur_round.validators_list) ) { - if (!s_session_cs_timer) { - s_session_cs_timer = dap_interval_timer_create(1000, s_session_timer, NULL); - if (l_ton_pvt->debug) - log_it(L_MSG, "TON: Consensus main timer is started"); - } - dap_stream_ch_chain_voting_in_callback_add(l_session, s_session_packet_in); - } - } - return 0; -} - -/** - * @brief s_session_send_startsync - * @param a_session - * @return - */ -static bool s_session_send_startsync(dap_chain_cs_block_ton_session_t *a_session) -{ - dap_chain_cs_block_ton_message_startsync_t *l_startsync = - DAP_NEW_Z(dap_chain_cs_block_ton_message_startsync_t); - l_startsync->ts = a_session->ts_round_sync_start; - l_startsync->round_id.uint64 = a_session->cur_round.id.uint64; - s_message_send(a_session, DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_START_SYNC, - (uint8_t*)l_startsync, sizeof(dap_chain_cs_block_ton_message_startsync_t), - a_session->cur_round.validators_list); - if (PVT(a_session->ton)->debug) - log_it(L_MSG, "TON: 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.uint64); - - DAP_DELETE(l_startsync); - return false; -} - -typedef struct s_session_send_votefor_data { - dap_chain_cs_block_ton_message_votefor_t *votefor; - dap_chain_cs_block_ton_session_t *session; -} DAP_ALIGN_PACKED s_session_send_votefor_data_t; - -static bool s_session_send_votefor(s_session_send_votefor_data_t *a_data){ - dap_chain_cs_block_ton_message_votefor_t *l_votefor = a_data->votefor; - dap_chain_cs_block_ton_session_t *l_session = a_data->session; - l_votefor->round_id.uint64 = l_session->cur_round.id.uint64; - s_message_send(l_session, DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE_FOR, - (uint8_t*)l_votefor, sizeof(dap_chain_cs_block_ton_message_votefor_t), - l_session->cur_round.validators_start); - DAP_DELETE(l_votefor); - DAP_DELETE(a_data); - return false; -} - -/** - * @brief s_session_round_start_callback_load_session_store_coordinator_state_proc - * @param a_global_db_context - * @param a_rc - * @param a_group - * @param a_key - * @param a_values_total - * @param a_values_shift - * @param a_values_count - * @param a_values - * @param a_arg - */ -static void s_session_round_start_callback_load_session_store_coordinator_state_proc(dap_global_db_context_t *a_global_db_context, - int a_rc, const char *a_group, - const size_t a_values_total, const size_t a_values_count, - dap_global_db_obj_t *a_values, void *a_arg) -{ - dap_chain_cs_block_ton_session_t * l_session = (dap_chain_cs_block_ton_session_t *) a_arg; - pthread_rwlock_wrlock(&l_session->rwlock); - dap_list_t *l_list_candidate = NULL; - // I am a coordinator :-) select candidate - - if (a_values_count) { - for (size_t i = 0; i < a_values_count; i++) { - if (!a_values[i].value_len) - continue; - - dap_chain_cs_block_ton_store_t *l_store = - (dap_chain_cs_block_ton_store_t *)a_values[i].value; - if ( l_store->hdr.round_id.uint64 != l_session->cur_round.id.uint64 ) - continue; - - // add candidate in list if it has 2/3 approve - if ( l_store->hdr.approve_collected ) { - dap_chain_hash_fast_t * l_hash = DAP_NEW(dap_chain_hash_fast_t); - dap_chain_hash_fast_from_str(a_values[i].key, l_hash); - l_list_candidate = dap_list_append(l_list_candidate, l_hash); - } - } - } - - size_t l_list_candidate_size = (size_t)dap_list_length(l_list_candidate); - dap_chain_cs_block_ton_message_votefor_t *l_votefor = - DAP_NEW_Z(dap_chain_cs_block_ton_message_votefor_t); - if (l_list_candidate) { - dap_chain_hash_fast_t *l_candidate_hash = dap_list_nth_data(l_list_candidate, (rand()%l_list_candidate_size)); - l_votefor->candidate_hash = *l_candidate_hash; - dap_list_free_full(l_list_candidate, NULL); - } else { - l_votefor->candidate_hash = (dap_chain_hash_fast_t){ }; - } - l_votefor->attempt_number = l_session->attempt_current_number; - s_session_send_votefor_data_t *l_data = DAP_NEW_Z(s_session_send_votefor_data_t); - l_data->votefor = l_votefor; - l_data->session = l_session; - dap_timerfd_start(PVT(l_session->ton)->first_message_delay*1000, // pause before send votefor - (dap_timerfd_callback_t)s_session_send_votefor, - l_data); - if (PVT(l_session->ton)->debug) { - char *l_hash_str = dap_chain_hash_fast_to_str_new(&l_votefor->candidate_hash); - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu I coordinator :-) Sent VoteFor candidate:%s", - l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, - l_session->attempt_current_number, l_hash_str); - DAP_DELETE(l_hash_str); - } - pthread_rwlock_unlock(&l_session->rwlock); -} - -/** - * @brief s_session_proc_state - * @param l_session - */ -static void s_session_proc_state( dap_chain_cs_block_ton_session_t * a_session) -{ - dap_time_t l_time = dap_time_now(); - // Mostly we're writting in session on the next operations, at least we do it with state - if (pthread_rwlock_trywrlock(&a_session->rwlock) != 0) // Session is busy - return; - switch (a_session->state) { - case DAP_STREAM_CH_CHAIN_SESSION_STATE_IDLE: { - if ( (((l_time/10)*10) % PVT(a_session->ton)->round_start_multiple_of) == 0 - && (l_time - ((l_time/10)*10)) <= 3 - && l_time > a_session->ts_round_finish - && (l_time-a_session->ts_round_finish) >= PVT(a_session->ton)->session_idle_min) { - - // round start - s_session_round_clear(a_session); - a_session->cur_round.id.uint64++; - a_session->state = DAP_STREAM_CH_CHAIN_SESSION_STATE_WAIT_START; - a_session->ts_round_start = 0; - a_session->ts_round_state_commit = 0; - a_session->attempt_current_number = 1; - a_session->ts_round_sync_start = dap_time_now(); - dap_chain_node_mempool_process_all(a_session->chain); - dap_list_free_full(a_session->cur_round.validators_list, free); - a_session->cur_round.validators_list = s_get_validators_addr_list(a_session); - a_session->cur_round.validators_count = dap_list_length(a_session->cur_round.validators_list); - dap_timerfd_start(PVT(a_session->ton)->first_message_delay*1000, - (dap_timerfd_callback_t)s_session_send_startsync, a_session); - if (PVT(a_session->ton)->debug) - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Start syncing validators ", - a_session->chain->net_name, a_session->chain->name, - a_session->cur_round.id.uint64, a_session->attempt_current_number); - } else - break; - } - case DAP_STREAM_CH_CHAIN_SESSION_STATE_WAIT_START: { - if ( (l_time - a_session->ts_round_sync_start) < PVT(a_session->ton)->round_start_sync_timeout ) - break; // timeout start sync - uint16_t l_startsync_count = a_session->cur_round.validators_start_count; - if (l_startsync_count * 3 >= a_session->cur_round.validators_count * 2) { - // if sync more 2/3 validators then start round and submit candidate - if (PVT(a_session->ton)->debug) - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu More than 2/3 of the validators are synchronized, so starting the round and send the candidate", - a_session->chain->net_name, a_session->chain->name, - a_session->cur_round.id.uint64, a_session->attempt_current_number); - - a_session->ts_round_start = l_time; - a_session->state = DAP_STREAM_CH_CHAIN_SESSION_STATE_CS_PROC; - - // sort validators list - dap_list_t *l_validators_start = a_session->cur_round.validators_start; - a_session->cur_round.validators_start = NULL; - dap_list_t *l_validators_list_temp = dap_list_first(a_session->cur_round.validators_list); - while (l_validators_list_temp) { - dap_chain_node_addr_t *l_validator_1 = (dap_chain_node_addr_t *)l_validators_list_temp->data; - l_validators_list_temp = l_validators_list_temp->next; - dap_list_t *l_validators_start_temp = dap_list_first(l_validators_start); - while (l_validators_start_temp) { - dap_chain_node_addr_t *l_validator_2 = (dap_chain_node_addr_t *)l_validators_start_temp->data; - l_validators_start_temp = l_validators_start_temp->next; - if ( l_validator_1->uint64 == l_validator_2->uint64 ) { - a_session->cur_round.validators_start = - dap_list_append(a_session->cur_round.validators_start, l_validator_1); - } - } - } - - // first coordinator - a_session->attempt_coordinator = - (dap_chain_node_addr_t *)(dap_list_first(a_session->cur_round.validators_start)->data); - } else { - s_session_round_finish(a_session, true); - if (PVT(a_session->ton)->debug) - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Round finish by reason: can't synchronized 2/3 of the validators", - a_session->chain->net_name, a_session->chain->name, - a_session->cur_round.id.uint64, a_session->attempt_current_number); - break; - } - } - case DAP_STREAM_CH_CHAIN_SESSION_STATE_WAIT_SIGNS: - case DAP_STREAM_CH_CHAIN_SESSION_STATE_CS_PROC: { - if ( !a_session->cur_round.submit && a_session->attempt_current_number == 1 ) { - dap_list_t *l_validators_list = dap_list_first(a_session->cur_round.validators_start); - int l_my_number = -1; - int i = 0; - while(l_validators_list) { - if( ((dap_chain_node_addr_t*)l_validators_list->data)->uint64 == a_session->my_addr->uint64) { - l_my_number = i; - break; - } - i++; - l_validators_list = l_validators_list->next; - } - if ( l_my_number != -1 ) { - l_my_number++; - if ( (l_time-a_session->ts_round_start) >= - (dap_time_t)((PVT(a_session->ton)->next_candidate_delay*l_my_number)+PVT(a_session->ton)->first_message_delay) ) { - a_session->cur_round.submit = true; - s_session_candidate_submit(a_session); - } - } - } - - if ( (l_time - a_session->ts_round_start) >= - (dap_time_t)(PVT(a_session->ton)->round_attempt_duration * a_session->attempt_current_number) ) { - - a_session->attempt_current_number++; - if ( a_session->attempt_current_number > PVT(a_session->ton)->round_attempts_max ) { - s_session_round_finish(a_session,true); // attempts is out - if (PVT(a_session->ton)->debug) - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Round finish by reason: attempts is out", - a_session->chain->net_name, a_session->chain->name, - a_session->cur_round.id.uint64, a_session->attempt_current_number); - break; - } - if ( a_session->cur_round.candidates_count == 0 ) { // no candidates - s_session_round_finish(a_session,true); - if (PVT(a_session->ton)->debug) - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Round finish by reason: no block candidates", - a_session->chain->net_name, a_session->chain->name, - a_session->cur_round.id.uint64, a_session->attempt_current_number); - break; - } - if ( a_session->state == DAP_STREAM_CH_CHAIN_SESSION_STATE_WAIT_SIGNS ) { - break; - } - - uint16_t l_validators_count = a_session->cur_round.validators_start_count; - uint64_t l_mod = 0; - if (!PVT(a_session->ton)->validators_list_by_stake) { - // rotate validatir list in non-stake mode - l_mod = a_session->cur_round.id.uint64; - } - uint16_t l_validators_index = - ( (a_session->attempt_current_number-2+l_mod) - - (l_validators_count - *((a_session->attempt_current_number-2+l_mod)/l_validators_count))); - - a_session->attempt_coordinator = (dap_chain_node_addr_t *) - (dap_list_nth(a_session->cur_round.validators_start, - l_validators_index)->data); - if (PVT(a_session->ton)->debug) - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Start attempt: selected coordinator "NODE_ADDR_FP_STR"(index:%u)", - a_session->chain->net_name, a_session->chain->name, a_session->cur_round.id.uint64, - a_session->attempt_current_number, NODE_ADDR_FP_ARGS(a_session->attempt_coordinator), - l_validators_index); - - if ( a_session->my_addr->uint64 == a_session->attempt_coordinator->uint64 ) { - // I am coordinator :-) select candidate - dap_global_db_get_all(a_session->gdb_group_store,0,s_session_round_start_callback_load_session_store_coordinator_state_proc, a_session); - break; // Unlock in its callback - } - } - } - } - pthread_rwlock_unlock(&a_session->rwlock); -} - -/** - * @brief s_session_timer - * @return - */ -static void s_session_timer(void *a_arg) -{ - UNUSED(a_arg); - dap_chain_cs_block_ton_session_t *l_session = NULL; - DL_FOREACH(s_session_items, l_session) { - s_session_proc_state(l_session); - } -} - -/** - * @brief s_session_candidate_to_chain - * @param a_session - * @param a_candidate_hash - * @param a_candidate - * @param a_candidate_size - */ -static void s_session_candidate_to_chain( - dap_chain_cs_block_ton_session_t *a_session, dap_chain_hash_fast_t *a_candidate_hash, - dap_chain_block_t *a_candidate, size_t a_candidate_size) -{ - - dap_list_t *l_commitsign_list = NULL; - dap_chain_hash_fast_t *l_candidate_hash = NULL; - dap_chain_cs_block_ton_message_item_t *l_message_item=NULL, *l_message_tmp=NULL; - pthread_rwlock_rdlock(&a_session->cur_round.messages_rwlock); - HASH_ITER(hh, a_session->cur_round.messages_items, l_message_item, l_message_tmp) { - uint8_t l_message_type = l_message_item->message->hdr.type; - if ( l_message_type == DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_COMMIT_SIGN ) { - l_candidate_hash = &((dap_chain_cs_block_ton_message_commitsign_t *) - (l_message_item->message->sign_n_message+l_message_item->message->hdr.sign_size))->candidate_hash; - if ( memcmp(l_candidate_hash, a_candidate_hash, sizeof(dap_chain_hash_fast_t)) == 0) { - l_commitsign_list = dap_list_append(l_commitsign_list, (void*)l_message_item->message); - } - } - } - pthread_rwlock_unlock(&a_session->cur_round.messages_rwlock); - if (!l_commitsign_list) { - return; - } - dap_chain_block_t *l_candidate = - (dap_chain_block_t *)DAP_DUP_SIZE(a_candidate, a_candidate_size); - - size_t l_signs_count = 0; - dap_list_t *l_validators_list = dap_list_first(a_session->cur_round.validators_start); - while(l_validators_list) { - dap_chain_node_addr_t *l_validator = (dap_chain_node_addr_t *)l_validators_list->data; - l_validators_list = l_validators_list->next; - dap_list_t *l_submit_temp = dap_list_first(l_commitsign_list); - while(l_submit_temp) { - dap_chain_cs_block_ton_message_t *l_message = (dap_chain_cs_block_ton_message_t *)l_submit_temp->data; - dap_chain_cs_block_ton_message_commitsign_t *l_commitsign = - (dap_chain_cs_block_ton_message_commitsign_t *) - (l_message->sign_n_message+l_message->hdr.sign_size); - if( l_message->hdr.is_verified - && l_message->hdr.sender_node_addr.uint64 == l_validator->uint64) { - dap_sign_t *l_candidate_sign = (dap_sign_t *)l_commitsign->candidate_sign; - size_t l_candidate_sign_size = dap_sign_get_size(l_candidate_sign); - if (!l_candidate_sign_size) { - continue; - } - l_candidate = DAP_REALLOC(l_candidate, a_candidate_size+l_candidate_sign_size); - memcpy(((byte_t *)l_candidate)+a_candidate_size, l_candidate_sign, l_candidate_sign_size); - a_candidate_size += l_candidate_sign_size; - l_signs_count++; - } - l_submit_temp = l_submit_temp->next; - } - } - - if (l_signs_count * 3 >= a_session->cur_round.validators_count * 2) { - dap_chain_atom_verify_res_t l_res = a_session->chain->callback_atom_add(a_session->chain, l_candidate, a_candidate_size); - char *l_candidate_hash_str = dap_chain_hash_fast_to_str_new(a_candidate_hash); - switch (l_res) { - case ATOM_ACCEPT: { - // block save to chain - if (dap_chain_atom_save(a_session->chain, (uint8_t *)l_candidate, a_candidate_size, a_session->chain->cells->id) < 0) { - log_it(L_ERROR, "TON: Can't save atom %s to the file", l_candidate_hash_str); - } - else { - log_it(L_INFO, "TON: atom %s added in chain successfully", l_candidate_hash_str); - dap_chain_hash_fast_t l_block_hash; - dap_hash_fast(l_candidate, a_candidate_size, &l_block_hash); - char *l_block_hash_str = dap_chain_hash_fast_to_str_new(&l_block_hash); - log_it(L_INFO, "TON: block %s added in chain successfully", l_block_hash_str); - DAP_DELETE(l_block_hash_str); - } - } break; - case ATOM_MOVE_TO_THRESHOLD: { - log_it(L_INFO, "TON: Thresholded atom with hash %s", l_candidate_hash_str); - } break; - case ATOM_PASS: { - log_it(L_WARNING, "TON: Atom with hash %s not accepted (code ATOM_PASS, already present)", l_candidate_hash_str); - DAP_DELETE(l_candidate); - } break; - case ATOM_REJECT: { - log_it(L_WARNING,"TON: Atom with hash %s rejected", l_candidate_hash_str); - DAP_DELETE(l_candidate); - } break; - default: - log_it(L_CRITICAL, "TON: Wtf is this ret code ? Atom hash %s code %d", l_candidate_hash_str, l_res); - DAP_DELETE(l_candidate); - } - DAP_DELETE(l_candidate_hash_str); - dap_chain_hash_fast_t l_my_candidate_hash; - dap_hash_fast(a_session->my_candidate, a_session->my_candidate_size, &l_my_candidate_hash); - if (dap_hash_fast_compare(&l_my_candidate_hash, a_candidate_hash)) - s_session_my_candidate_delete(a_session); - } -} - -static void s_session_candidate_submit(dap_chain_cs_block_ton_session_t *a_session) -{ - dap_chain_t *l_chain = a_session->chain; - s_session_my_candidate_delete(a_session); - dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(l_chain); - a_session->my_candidate = l_blocks->callback_new_block_move(l_blocks, &a_session->my_candidate_size); - size_t l_submit_size = a_session->my_candidate ? - sizeof(dap_chain_cs_block_ton_message_submit_t)+a_session->my_candidate_size - : sizeof(dap_chain_cs_block_ton_message_submit_t); - dap_chain_cs_block_ton_message_submit_t *l_submit = - DAP_NEW_SIZE(dap_chain_cs_block_ton_message_submit_t, l_submit_size); - l_submit->round_id.uint64 = a_session->cur_round.id.uint64; - l_submit->candidate_size = a_session->my_candidate_size; - - if ( a_session->my_candidate ) { - dap_chain_hash_fast_t l_candidate_hash; - dap_hash_fast(a_session->my_candidate, a_session->my_candidate_size, &l_candidate_hash); - a_session->cur_round.my_candidate_hash = l_submit->candidate_hash = l_candidate_hash; - memcpy(l_submit->candidate, a_session->my_candidate, a_session->my_candidate_size); - if (PVT(a_session->ton)->debug) { - char *l_hash_str = dap_chain_hash_fast_to_str_new(&l_candidate_hash); - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U" Submit my candidate:%s", - a_session->chain->net_name, a_session->chain->name, - a_session->cur_round.id.uint64, l_hash_str); - DAP_DELETE(l_hash_str); - } - a_session->my_candidate_attempts_count++; - } else { // no my candidate, send null hash - a_session->cur_round.my_candidate_hash = l_submit->candidate_hash = (dap_chain_hash_fast_t){}; - if (PVT(a_session->ton)->debug) - log_it(L_MSG, "TON: 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.uint64, a_session->attempt_current_number); - } - s_message_send(a_session, DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_SUBMIT, - (uint8_t*)l_submit, l_submit_size, a_session->cur_round.validators_start); - DAP_DELETE(l_submit); -} - -static int s_session_atom_validation(dap_chain_cs_blocks_t *a_blocks, dap_chain_block_t *a_block, size_t a_block_size){ - dap_chain_cs_block_ton_t *l_ton = DAP_CHAIN_CS_BLOCK_TON(a_blocks); - dap_chain_atom_verify_res_t l_res = ATOM_ACCEPT; - PVT(l_ton)->flag_sign_verify = false; - l_res = a_blocks->chain->callback_atom_verify(a_blocks->chain, a_block, a_block_size); - PVT(l_ton)->flag_sign_verify = true; - if(l_res == ATOM_ACCEPT){ - return 0; - } - return -1; -} - -static void s_session_my_candidate_delete(dap_chain_cs_block_ton_session_t *a_session) { - if (a_session->my_candidate){ - if (PVT(a_session->ton)->debug) { - dap_chain_hash_fast_t l_candidate_hash; - dap_hash_fast(a_session->my_candidate, a_session->my_candidate_size, &l_candidate_hash); - char *l_hash_str = dap_chain_hash_fast_to_str_new(&l_candidate_hash); - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Delete my candidate %s", - a_session->chain->net_name, a_session->chain->name, a_session->cur_round.id.uint64, - a_session->attempt_current_number, l_hash_str ); - DAP_DELETE(l_hash_str); - } - DAP_DEL_Z(a_session->my_candidate); - } - a_session->my_candidate_size = 0; - a_session->my_candidate_attempts_count = 0; -} - -static void s_session_round_clear(dap_chain_cs_block_ton_session_t *a_session) -{ - a_session->state = DAP_STREAM_CH_CHAIN_SESSION_STATE_IDLE; - a_session->ts_round_finish = dap_time_now(); - // Truncate this group - dap_global_db_del(a_session->gdb_group_store, NULL, NULL, NULL); - dap_chain_cs_block_ton_message_item_t *l_message_item=NULL, *l_message_tmp=NULL; - pthread_rwlock_wrlock(&a_session->cur_round.messages_rwlock); - HASH_ITER(hh, a_session->cur_round.messages_items, l_message_item, l_message_tmp) { - HASH_DEL(a_session->cur_round.messages_items, l_message_item); - DAP_DELETE(l_message_item->message); - DAP_DELETE(l_message_item); - } - pthread_rwlock_unlock(&a_session->cur_round.messages_rwlock); - pthread_rwlock_destroy(&a_session->cur_round.messages_rwlock); - - if (a_session->cur_round.validators_start) - // delete only links - dap_list_free(a_session->cur_round.validators_start); - if (a_session->cur_round.validators_list) - // delete validators - dap_list_free_full(a_session->cur_round.validators_list, NULL); - - dap_chain_cs_block_ton_round_id_t l_round_id = a_session->cur_round.id; - a_session->cur_round = (dap_chain_cs_block_ton_round_t){.id = l_round_id}; - pthread_rwlock_init(&a_session->cur_round.messages_rwlock, NULL); - log_it(L_MSG, "All data for round %"DAP_UINT64_FORMAT_U" cleared", l_round_id.uint64); -} - -/** - * @brief s_session_round_finish_callback_load_store - * @param a_global_db_context - * @param a_rc - * @param a_group - * @param a_key - * @param a_values_total - * @param a_values_shift - * @param a_values_count - * @param a_values - * @param a_arg - */ -static void s_session_round_finish_callback_load_store(dap_global_db_context_t *a_global_db_context, - int a_rc, const char *a_group, - const size_t a_values_total, const size_t a_values_count, - dap_global_db_obj_t *a_values, void *a_arg) - -{ - dap_chain_cs_block_ton_session_t *l_session = (dap_chain_cs_block_ton_session_t *)a_arg; - - pthread_rwlock_wrlock(&l_session->rwlock); // lock for writting - - l_session->state = DAP_STREAM_CH_CHAIN_SESSION_STATE_IDLE; - l_session->ts_round_finish = dap_time_now(); - - for (size_t i = 0; i < a_values_count; i++) { - if (!a_values[i].value_len) - continue; - dap_chain_cs_block_ton_store_t *l_store = (dap_chain_cs_block_ton_store_t*)a_values[i].value; - if (l_store->hdr.round_id.uint64 != l_session->cur_round.id.uint64) - continue; - if (l_store->hdr.sign_collected) - s_session_candidate_to_chain(l_session, &l_store->hdr.candidate_hash, - (dap_chain_block_t*)l_store->candidate_n_signs, - l_store->hdr.candidate_size); - else if (dap_hash_fast_compare(&l_store->hdr.candidate_hash, &l_session->cur_round.my_candidate_hash)) { - if (PVT(l_session->ton)->debug) { - char *l_hash_str = dap_chain_hash_fast_to_str_new(&l_store->hdr.candidate_hash); - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu My candidate:%s %s. Delete block_new.", - l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, - l_session->attempt_current_number, l_hash_str, - (l_store->hdr.approve_collected ? "approved with consensus" : "didn't collect 2/3 approve.")); - DAP_DELETE(l_hash_str); - } - s_session_my_candidate_delete(l_session); - memset(&l_session->cur_round.my_candidate_hash, 0, sizeof(l_session->cur_round.my_candidate_hash)); - - } - } - s_session_round_clear(l_session); - pthread_rwlock_unlock(&l_session->rwlock); // then unlock anyway -} -/** - * @brief Finish TON round (asyncroniusly) - * @param a_session - * @param a_is_time_proc_lock - * @return - */ -static void s_session_round_finish(dap_chain_cs_block_ton_session_t *a_session, bool a_failed) -{ - if (a_failed) { - s_session_round_clear(a_session); - return; - } - if (dap_global_db_get_all(a_session->gdb_group_store,0,s_session_round_finish_callback_load_store, a_session) != 0) - log_it(L_ERROR,"Can't process get_all request for group \"%s\"", a_session->gdb_group_store); -} - -// this is planned for get validator addr if validator addr list to be changed to stakes, -// but currently it using for check validator addr exists -static dap_chain_node_addr_t *s_session_get_validator(dap_chain_cs_block_ton_session_t *a_session, - dap_chain_node_addr_t *a_addr, - dap_list_t *a_validators) -{ - - // dap_chain_cs_block_ton_round_t *l_round = a_round_name == DAP_TON$ROUND_CUR ? // 'c' or 'o' - // &a_session->cur_round : &a_session->old_round; - dap_list_t* l_list_validator = dap_list_first(a_validators); - while(l_list_validator) { - dap_list_t *l_list_validator_next = l_list_validator->next; - if ( ((dap_chain_node_addr_t *)l_list_validator->data)->uint64 == a_addr->uint64 ) - return l_list_validator->data; - l_list_validator = l_list_validator_next; - } - return NULL; -} - -static uint16_t s_session_message_count(dap_chain_cs_block_ton_session_t *a_session, uint8_t a_type, - dap_chain_hash_fast_t *a_candidate_hash, uint16_t *a_attempt_number) -{ - dap_chain_cs_block_ton_message_item_t *l_messages_items = NULL; - l_messages_items = a_session->cur_round.messages_items; - uint16_t l_message_count = 0; - dap_chain_cs_block_ton_message_item_t *l_chain_message=NULL, *l_chain_message_tmp=NULL; - HASH_ITER(hh, l_messages_items, l_chain_message, l_chain_message_tmp) { - dap_chain_cs_block_ton_message_getinfo_t *l_getinfo = (dap_chain_cs_block_ton_message_getinfo_t *) - (l_chain_message->message->sign_n_message+l_chain_message->message->hdr.sign_size); - if (l_chain_message->message->hdr.type == a_type && - (!a_candidate_hash || memcmp(&l_getinfo->candidate_hash, a_candidate_hash, - sizeof(dap_chain_hash_fast_t)) == 0)) { - switch(a_type) { - // case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_PRE_COMMIT: - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE_FOR: - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE: { - if ( a_attempt_number && *a_attempt_number == l_getinfo->attempt_number) { - l_message_count++; - } - } break; - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_APPROVE: - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_COMMIT_SIGN: { - if (l_chain_message->message->hdr.is_verified){ - l_message_count++; - } - } break; - default: - l_message_count++; - break; - } - } - } - return l_message_count; -} - -struct vote_for_load_store_args -{ - dap_chain_cs_block_ton_session_t *session; - dap_chain_hash_fast_t candidate_hash; -}; - -/** - * @brief s_session_packet_in_callback_vote_for_load_store - * @param a_global_db_context - * @param a_rc - * @param a_group - * @param a_key - * @param a_values_total - * @param a_values_shift - * @param a_values_count - * @param a_values - * @param a_arg - */ -static void s_session_packet_in_callback_vote_for_load_store(dap_global_db_context_t *a_global_db_context, - int a_rc, const char *a_group, - const size_t a_values_total, const size_t a_values_count, - dap_global_db_obj_t *a_values, void *a_arg) -{ - dap_chain_cs_block_ton_session_t * l_session = ((struct vote_for_load_store_args *) a_arg)->session; - dap_chain_hash_fast_t * l_candidate_hash = &((struct vote_for_load_store_args *) a_arg)->candidate_hash; - - dap_chain_cs_block_ton_store_t *l_found_best = NULL; - dap_chain_cs_block_ton_store_t *l_found_vote = NULL; - dap_chain_cs_block_ton_store_t *l_found_approve_vf = NULL; - // dap_chain_cs_block_ton_store_t *l_found_approve = NULL; - pthread_rwlock_rdlock(&l_session->rwlock); - if (a_values_count) { - for (size_t i = 0; i < a_values_count; i++) { - if (!a_values[i].value_len) - continue; - dap_chain_cs_block_ton_store_t *l_store = - (dap_chain_cs_block_ton_store_t *)a_values[i].value; - if ( l_store->hdr.round_id.uint64 != l_session->cur_round.id.uint64 ) - continue; - if (l_store->hdr.vote_collected) { - // best choice :-) 2/3 vote (i.e. PreCommit) and VoteFor candidate - if (memcmp(l_candidate_hash, &l_store->hdr.candidate_hash, sizeof(dap_chain_hash_fast_t)) == 0) { - l_found_best = (dap_chain_cs_block_ton_store_t *)a_values[i].value; - break; - } - - // other PreCommit candidate (ignore VoteFor) - if ( !l_found_vote - || l_found_vote->hdr.ts_candidate_submit<l_store->hdr.ts_candidate_submit ) { - l_found_vote = (dap_chain_cs_block_ton_store_t *)a_values[i].value; - } - } - if ( l_store->hdr.approve_collected ) { - // 2/3 Approve & VoteFor - if (memcmp(l_candidate_hash, &l_store->hdr.candidate_hash, sizeof(dap_chain_hash_fast_t)) == 0) { - l_found_approve_vf = (dap_chain_cs_block_ton_store_t *)a_values[i].value; - break; - } - // 2/3 Approve (ignore VoteFor) - // if ( !l_found_approve - // || l_found_approve->hdr.ts_candidate_submit<l_store->hdr.ts_candidate_submit ) { - // l_found_approve = (dap_chain_cs_block_ton_store_t *)l_objs[i].value; - // } - } - } - - dap_chain_cs_block_ton_store_t *l_found_candidate = NULL; - if (l_found_best) { - l_found_candidate = l_found_best; - } - else if (l_found_vote) { - l_found_candidate = l_found_vote; - } - else if (l_found_approve_vf) { - l_found_candidate = l_found_approve_vf; - } - // else if (l_found_approve) { - // l_found_candidate = l_found_approve; - // } - - if (l_found_candidate) { - // candidate found, gen event Vote - dap_chain_cs_block_ton_message_vote_t *l_vote = - DAP_NEW_Z(dap_chain_cs_block_ton_message_vote_t); - l_vote->candidate_hash = l_found_candidate->hdr.candidate_hash; - l_vote->round_id.uint64 = l_session->cur_round.id.uint64; - l_vote->attempt_number = l_session->attempt_current_number; - - s_message_send(l_session, DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE, (uint8_t*)l_vote, - sizeof(dap_chain_cs_block_ton_message_vote_t), l_session->cur_round.validators_start); - if (PVT(l_session->ton)->debug) { - char *l_hash_str = dap_chain_hash_fast_to_str_new(&l_vote->candidate_hash); - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Sent VOTE for candidate:%s", - l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, - l_session->attempt_current_number, l_hash_str); - DAP_DELETE(l_hash_str); - } - DAP_DELETE(l_vote); - } - } - pthread_rwlock_unlock(&l_session->rwlock); - DAP_DELETE(a_arg); -} - -/** - * @brief The proc_msg_type_commit_sign struct - */ -struct proc_msg_type_commit_sign{ - dap_chain_cs_block_ton_session_t *session; - dap_chain_hash_fast_t candidate_hash; - dap_sign_t *candidate_sign; - char * candidate_hash_str; - - dap_chain_cs_block_ton_round_t * round; - dap_chain_cs_block_ton_round_id_t round_id; - - dap_chain_cs_block_ton_message_t * message; - size_t message_size; - dap_chain_node_addr_t sender_node_addr; -}; - -/** - * @brief s_callback_get_candidate_block_and_commit_sign - * @param a_global_db_context - * @param a_rc - * @param a_group - * @param a_key - * @param a_value - * @param a_value_size - * @param a_value_ts - * @param a_is_pinned - * @param a_arg - */ -static void s_callback_get_candidate_block_and_commit_sign(dap_global_db_context_t * a_global_db_context,int a_rc, const char * a_group, const char * a_key, const void * a_value, const size_t a_value_size, dap_nanotime_t a_value_ts, bool a_is_pinned, void * a_arg) -{ - struct proc_msg_type_commit_sign * l_args = (struct proc_msg_type_commit_sign *) a_arg; - dap_chain_cs_block_ton_session_t *l_session = l_args->session; - dap_chain_hash_fast_t l_candidate_hash = l_args->candidate_hash; - dap_sign_t *l_candidate_sign = l_args->candidate_sign; - char * l_candidate_hash_str = l_args->candidate_hash_str; - dap_chain_cs_block_ton_message_t * l_message = l_args->message; - size_t l_message_size = l_args->message_size; - dap_chain_node_addr_t l_sender_node_addr = l_args->sender_node_addr; - dap_chain_cs_block_ton_round_t * l_round = l_args->round; // Part of session, rwlock need to be locked properly with it - dap_chain_cs_block_ton_round_id_t l_round_id = l_args->round_id; - - DAP_DELETE(l_args); - - size_t l_store_size = a_value_size; - dap_chain_cs_block_ton_store_t *l_store = (dap_chain_cs_block_ton_store_t *) a_value; - - pthread_rwlock_wrlock(&l_session->rwlock); - - if (l_store) { - size_t l_candidate_size = l_store->hdr.candidate_size; - dap_chain_block_t *l_candidate = - (dap_chain_block_t *)DAP_DUP_SIZE(&l_store->candidate_n_signs, l_candidate_size); - size_t l_offset = dap_chain_block_get_sign_offset(l_candidate, l_candidate_size); - - int l_sign_verified=0; - // check candidate hash sign - if ( (l_sign_verified=dap_sign_verify(l_candidate_sign, - l_candidate, l_offset+sizeof(l_candidate->hdr))) == 1 ) { - l_store->hdr.sign_collected = true; - s_message_chain_add(l_session, &l_sender_node_addr, l_message, l_message_size, NULL); - if (dap_global_db_set_unsafe(a_global_db_context, l_session->gdb_group_store, l_candidate_hash_str, l_store, - l_store_size, true) == 0 ) { - uint16_t l_commitsign_count = s_session_message_count( - l_session, DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_COMMIT_SIGN, - &l_candidate_hash, NULL); - if (l_commitsign_count * 3 >= l_round->validators_count * 2) { - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Candidate:%s collected COMMIT_SIGN more than 2/3 of the validators, so finish this round", - l_session->chain->net_name, l_session->chain->name, l_round->id.uint64, - l_session->attempt_current_number, l_candidate_hash_str); - if (l_round_id.uint64 == l_session->cur_round.id.uint64) - s_session_round_finish(l_session, false); - } - } - } else - log_it(L_WARNING, "Candidate:%s sign is incorrect: code %d", l_candidate_hash_str, l_sign_verified); - } - pthread_rwlock_unlock(&l_session->rwlock); - DAP_DELETE(l_message); - DAP_DELETE(l_candidate_hash_str); -} - - -/** - * @brief The proc_msg_type_pre_commit struct - */ -struct proc_msg_type_pre_commit{ - dap_chain_cs_block_ton_session_t *session; - dap_chain_hash_fast_t candidate_hash; - char * candidate_hash_str; -}; - -/** - * @brief s_callback_get_candidate_block_and_pre_commit - * @param a_global_db_context - * @param a_rc - * @param a_group - * @param a_key - * @param a_value - * @param a_value_size - * @param a_value_ts - * @param a_is_pinned - * @param a_arg - */ -static void s_callback_get_candidate_block_and_pre_commit (dap_global_db_context_t * a_global_db_context,int a_rc, const char * a_group, const char * a_key, const void * a_value, const size_t a_value_size, dap_nanotime_t a_value_ts, bool a_is_pinned, void * a_arg) -{ - struct proc_msg_type_pre_commit * l_args = (struct proc_msg_type_pre_commit *) a_arg; - dap_chain_cs_block_ton_session_t *l_session = l_args->session; - dap_chain_hash_fast_t l_candidate_hash = l_args->candidate_hash; - char * l_candidate_hash_str = l_args->candidate_hash_str; - DAP_DELETE(l_args); - - size_t l_store_size = a_value_size; - dap_chain_cs_block_ton_store_t *l_store = (dap_chain_cs_block_ton_store_t *) a_value; - - pthread_rwlock_rdlock(&l_session->rwlock); - - // event CommitSign - if (l_store) { - if (PVT(l_session->ton)->blocks_sign_key) { - l_store->hdr.precommit_collected = true; - - if (dap_global_db_set_unsafe(a_global_db_context, l_session->gdb_group_store,l_candidate_hash_str, l_store, - l_store_size, true ) == 0 ) { - size_t l_candidate_size = l_store->hdr.candidate_size; - dap_chain_block_t *l_candidate = - (dap_chain_block_t *)DAP_DUP_SIZE(&l_store->candidate_n_signs, l_candidate_size); - size_t l_offset = dap_chain_block_get_sign_offset(l_candidate, l_candidate_size); - dap_sign_t *l_candidate_sign = dap_sign_create(PVT(l_session->ton)->blocks_sign_key, - l_candidate, l_offset + sizeof(l_candidate->hdr), 0); - size_t l_candidate_sign_size = dap_sign_get_size(l_candidate_sign); - - size_t l_commitsign_size = sizeof(dap_chain_cs_block_ton_message_commitsign_t)+l_candidate_sign_size; - dap_chain_cs_block_ton_message_commitsign_t *l_commitsign = - DAP_NEW_SIZE(dap_chain_cs_block_ton_message_commitsign_t, l_commitsign_size); - l_commitsign->round_id.uint64 = l_session->cur_round.id.uint64; -// memcpy(&l_commitsign->candidate_hash, &l_candidate_hash, sizeof(dap_chain_hash_fast_t)); - l_commitsign->candidate_hash = l_candidate_hash; - memcpy(l_commitsign->candidate_sign, l_candidate_sign, l_candidate_sign_size); - s_message_send(l_session, DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_COMMIT_SIGN, (uint8_t*)l_commitsign, - l_commitsign_size, l_session->cur_round.validators_start); - DAP_DELETE(l_commitsign); - DAP_DELETE(l_candidate); - DAP_DELETE(l_candidate_sign); - pthread_rwlock_unlock(&l_session->rwlock); - - pthread_rwlock_wrlock(&l_session->rwlock); - l_session->state = DAP_STREAM_CH_CHAIN_SESSION_STATE_WAIT_SIGNS; - l_session->ts_round_state_commit = dap_time_now(); - - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U" attempt:%hu Candidate:%s collected PRE_COMMIT more than 2/3 of the validators, so to sent a COMMIT_SIGN", - l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, - l_session->attempt_current_number, l_candidate_hash_str); - } - } - else { - log_it(L_WARNING, "Can't sign block with blocks-sign-cert in [block-ton] section"); - } - } - pthread_rwlock_unlock(&l_session->rwlock); - - DAP_DELETE(l_candidate_hash_str); - -} - -/** - * @brief The proc_msg_type_vote struct - */ -struct proc_msg_type_vote{ - dap_chain_cs_block_ton_session_t *session; - dap_chain_hash_fast_t candidate_hash; - char * candidate_hash_str; -}; - -/** - * @brief s_callback_get_candidate_block_and_vote - * @param a_global_db_context - * @param a_rc - * @param a_group - * @param a_key - * @param a_value - * @param a_value_size - * @param a_value_ts - * @param a_is_pinned - * @param a_arg - */ -static void s_callback_get_candidate_block_and_vote (dap_global_db_context_t * a_global_db_context,int a_rc, const char * a_group, const char * a_key, const void * a_value, const size_t a_value_size, dap_nanotime_t a_value_ts, bool a_is_pinned, void * a_arg) -{ - struct proc_msg_type_vote * l_args = (struct proc_msg_type_vote *) a_arg; - dap_chain_cs_block_ton_session_t *l_session = l_args->session; - dap_chain_hash_fast_t l_candidate_hash = l_args->candidate_hash; - char * l_candidate_hash_str = l_args->candidate_hash_str; - DAP_DELETE(l_args); - size_t l_store_size = a_value_size; - dap_chain_cs_block_ton_store_t *l_store = (dap_chain_cs_block_ton_store_t *) a_value; - if (l_store) { - l_store->hdr.vote_collected = true; - if (dap_global_db_set_unsafe(a_global_db_context, l_session->gdb_group_store, l_candidate_hash_str, - l_store, l_store_size, true ) == 0 ) { - // Send PreCommit - dap_chain_cs_block_ton_message_precommit_t l_precommit = { - .round_id.uint64 = l_session->cur_round.id.uint64, - .candidate_hash = l_candidate_hash, - .attempt_number = l_session->attempt_current_number - }; - s_message_send(l_session, DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_PRE_COMMIT, (uint8_t*)&l_precommit, - sizeof(dap_chain_cs_block_ton_message_precommit_t), l_session->cur_round.validators_start); - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Candidate:%s collected VOTE more than 2/3 of the validators, so to sent a PRE_COMMIT", - l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, - l_session->attempt_current_number, l_candidate_hash_str); - } - } - DAP_DELETE(l_candidate_hash_str); - -} - - -/** - * @brief The proc_msg_type_approve struct - */ -struct proc_msg_type_approve{ - dap_chain_cs_block_ton_session_t *session; - dap_chain_hash_fast_t candidate_hash; - char * candidate_hash_str; -}; - -/** - * @brief s_callback_get_candidate_block_and_approve - * @param a_global_db_context - * @param a_rc - * @param a_group - * @param a_key - * @param a_value - * @param a_value_size - * @param a_value_ts - * @param a_is_pinned - * @param a_arg - */ -static void s_callback_get_candidate_block_and_approve (dap_global_db_context_t * a_global_db_context,int a_rc, const char * a_group, const char * a_key, const void * a_value, const size_t a_value_size, dap_nanotime_t a_value_ts, bool a_is_pinned, void * a_arg) -{ - struct proc_msg_type_approve * l_args = (struct proc_msg_type_approve *) a_arg; - dap_chain_cs_block_ton_session_t *l_session = l_args->session; - dap_chain_hash_fast_t l_candidate_hash = l_args->candidate_hash; - char * l_candidate_hash_str = l_args->candidate_hash_str; - - DAP_DELETE(l_args); - - dap_chain_cs_block_ton_store_t *l_store = (dap_chain_cs_block_ton_store_t *) a_value; - size_t l_store_size = a_value_size; - - pthread_rwlock_rdlock(&l_session->rwlock); - - if (l_store && !l_store->hdr.approve_collected) { - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: APPROVE: candidate found in store:%s & !approve_collected", l_candidate_hash_str); - l_store->hdr.approve_collected = true; - if (dap_global_db_set_unsafe( a_global_db_context, l_session->gdb_group_store,l_candidate_hash_str, - l_store,l_store_size, true) == 0 ) { - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: APPROVE: candidate update:%s approve_collected=true", l_candidate_hash_str); - } else - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: APPROVE: can`t update candidate:%s", l_candidate_hash_str); - - // event Vote - dap_chain_cs_block_ton_message_vote_t l_vote = {}; - l_vote.round_id.uint64 = l_session->cur_round.id.uint64; -// memcpy(&l_vote->candidate_hash, &l_candidate_hash, sizeof(dap_chain_hash_fast_t)); - l_vote.candidate_hash = l_candidate_hash; - l_vote.attempt_number = l_session->attempt_current_number; - s_message_send(l_session, DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE, (uint8_t *)&l_vote, - sizeof(dap_chain_cs_block_ton_message_vote_t), l_session->cur_round.validators_start); - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu This is first attempt, so to sent a VOTE for candidate:%s", - l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, - l_session->attempt_current_number, l_candidate_hash_str); - } - pthread_rwlock_unlock(&l_session->rwlock); - DAP_DELETE(l_candidate_hash_str); -} - -/** - * @brief The proc_msg_type_submit struct - */ -struct proc_msg_type_submit{ - dap_chain_cs_block_ton_session_t *session; - dap_chain_hash_fast_t candidate_hash; - char * candidate_hash_str; - dap_chain_block_t * candidate; - size_t candidate_size; - dap_nanotime_t time; -}; - -/** - * @brief s_check_block_exist_in_store - * @param a_global_db_context - * @param a_rc - * @param a_group - * @param a_key - * @param a_value - * @param a_value_size - * @param a_value_ts - * @param a_is_pinned - * @param a_arg - */ -static void s_callback_check_and_save_candidate_block (dap_global_db_context_t * a_global_db_context,int a_rc, const char * a_group, const char * a_key, const void * a_value, const size_t a_value_size, dap_nanotime_t a_value_ts, bool a_is_pinned, void * a_arg) -{ - struct proc_msg_type_submit * l_args = (struct proc_msg_type_submit *) a_arg; - assert(l_args); - dap_chain_cs_block_ton_session_t *l_session = l_args->session; - char *l_candidate_hash_str = l_args->candidate_hash_str; - dap_chain_block_t * l_candidate = l_args->candidate; - size_t l_candidate_size = l_args->candidate_size; - dap_nanotime_t l_time = l_args->time; - dap_chain_hash_fast_t l_candidate_hash = l_args->candidate_hash; - DAP_DELETE(l_args); - - dap_chain_cs_block_ton_store_t *l_store_temp = (dap_chain_cs_block_ton_store_t *) a_value; - if (l_store_temp) { - log_it(L_WARNING, "TON: Duplicate candidate:%s", l_candidate_hash_str); - DAP_DELETE(l_candidate_hash_str); - DAP_DELETE(l_candidate); - return; - } - // store for new candidate - size_t l_store_size = sizeof(dap_chain_cs_block_ton_store_hdr_t) + l_candidate_size; - dap_chain_cs_block_ton_store_t *l_store = DAP_NEW_Z_SIZE(dap_chain_cs_block_ton_store_t, l_store_size); - - l_store->hdr.candidate_size = l_candidate_size; - l_store->hdr.ts_candidate_submit = l_time; - l_store->hdr.round_id.uint64 = l_session->cur_round.id.uint64; - l_store->hdr.candidate_hash = l_candidate_hash; - memcpy(&l_store->candidate_n_signs, l_candidate, l_candidate_size); - - pthread_rwlock_wrlock(&l_session->rwlock); - // save new block candidate - if (dap_global_db_set_unsafe(a_global_db_context, l_session->gdb_group_store, l_candidate_hash_str, l_store, - l_store_size, true) == 0) { - l_session->cur_round.candidates_count++; - dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(l_session->chain); - if ( !s_session_atom_validation(l_blocks, l_candidate, l_candidate_size) ) { - // validation - OK, gen event Approve - if (PVT(l_session->ton)->blocks_sign_key) { - // size_t l_candidate_size = l_store->hdr.candidate_size; - dap_sign_t *l_hash_sign = dap_sign_create(PVT(l_session->ton)->blocks_sign_key, - &l_candidate_hash, sizeof(dap_chain_hash_fast_t), 0); - - size_t l_hash_sign_size = dap_sign_get_size(l_hash_sign); - size_t l_approve_size = sizeof(dap_chain_cs_block_ton_message_approve_t)+l_hash_sign_size; - - dap_chain_cs_block_ton_message_approve_t *l_approve = - DAP_NEW_SIZE(dap_chain_cs_block_ton_message_approve_t, l_approve_size); - l_approve->round_id.uint64 = l_session->cur_round.id.uint64; - l_approve->candidate_hash = l_candidate_hash; - memcpy(l_approve->candidate_hash_sign, l_hash_sign, l_hash_sign_size); - - s_message_send(l_session, DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_APPROVE, - (uint8_t*)l_approve, l_approve_size, l_session->cur_round.validators_start); - DAP_DELETE(l_approve); - - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Sent APPROVE candidate:%s", - l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, - l_session->attempt_current_number, l_candidate_hash_str); - } - else - log_it(L_WARNING, "Can't sign block with blocks-sign-cert in [block-ton] section"); - } - else { - // validation - fail, gen event Reject - dap_chain_cs_block_ton_message_reject_t *l_reject = - DAP_NEW_Z(dap_chain_cs_block_ton_message_reject_t); - l_reject->round_id.uint64 = l_session->cur_round.id.uint64; - l_reject->candidate_hash = l_candidate_hash; - s_message_send(l_session, DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_REJECT, (uint8_t*)l_reject, - sizeof(dap_chain_cs_block_ton_message_reject_t), l_session->cur_round.validators_start); - DAP_DELETE(l_reject); - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Sent REJECT candidate:%s", - l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, - l_session->attempt_current_number, l_candidate_hash_str); - } - } - pthread_rwlock_unlock(&l_session->rwlock); - - DAP_DELETE(l_store); - DAP_DELETE(l_candidate_hash_str); - DAP_DELETE(l_candidate); -} - -/** - * @brief s_session_packet_in - * @param a_arg - * @param a_sender_node_addr - * @param a_data_hash - * @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, - dap_chain_hash_fast_t *a_data_hash, uint8_t *a_data, size_t a_data_size) -{ - dap_chain_cs_block_ton_session_t *l_session = a_arg; - dap_chain_cs_block_ton_message_t *l_message = (dap_chain_cs_block_ton_message_t *)a_data; - - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: 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.uint64, - l_session->attempt_current_number, l_message->hdr.type, - NODE_ADDR_FP_ARGS(a_sender_node_addr), NODE_ADDR_FP_ARGS(l_session->my_addr)); - - if( sizeof(*l_message)+l_message->hdr.sign_size > a_data_size){ - log_it(L_WARNING, "TON: incorrect message size in header is %zu when data size is only %zu and header size is %zu", - l_message->hdr.sign_size, a_data_size, sizeof(*l_message)); - return; - } - size_t l_message_data_size = a_data_size - sizeof(*l_message) - l_message->hdr.sign_size ; - byte_t * l_message_data = l_message->sign_n_message + l_message->hdr.sign_size; - - if ( !PVT(l_session->ton)->validators_list_by_stake ) { - size_t l_data_size = 0; - dap_sign_t *l_sign = (dap_sign_t*)l_message->sign_n_message; - uint8_t *l_data = s_message_data_sign(l_session, l_message, &l_data_size); - bool l_verify_passed = false; - for (uint16_t j = 0; j < PVT(l_session->ton)->auth_certs_count; j++) { - if ( dap_cert_compare_with_sign(PVT(l_session->ton)->auth_certs[j], l_sign) == 0 - && dap_sign_verify(l_sign, l_data, l_data_size) == 1 ) { - l_verify_passed = true; - break; - } - } - DAP_DELETE(l_data); - if (!l_verify_passed) { - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: 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.uint64, - l_session->attempt_current_number, NODE_ADDR_FP_ARGS(a_sender_node_addr)); - return; - } - } - - if (l_message->hdr.chain_id.uint64 != l_session->chain->id.uint64 ) - return; - - dap_time_t l_time = dap_time_now(); - - dap_chain_hash_fast_t l_data_hash = {}; - dap_hash_fast(a_data, a_data_size, &l_data_hash); - if (!dap_hash_fast_compare(a_data_hash, &l_data_hash)) { - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: 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.uint64, l_session->attempt_current_number); - return; - } - - // consensus round start sync - if ( l_message->hdr.type == DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_START_SYNC ) { - // check time offset - dap_chain_cs_block_ton_message_startsync_t *l_startsync = - (dap_chain_cs_block_ton_message_startsync_t *) - (l_message->sign_n_message+l_message->hdr.sign_size); - - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Receive START_SYNC: from addr:"NODE_ADDR_FP_STR"", - l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, - l_session->attempt_current_number, NODE_ADDR_FP_ARGS(a_sender_node_addr)); - - dap_chain_node_addr_t *l_validator = - s_session_get_validator(l_session, a_sender_node_addr, l_session->cur_round.validators_list); - - if (!l_validator) { - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Message rejected: validator addr:"NODE_ADDR_FP_STR" not in the list.", - l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, - l_session->attempt_current_number, NODE_ADDR_FP_ARGS(a_sender_node_addr)); - return; - } - - if ( - (l_time>l_startsync->ts && (l_time-l_startsync->ts) > PVT(l_session->ton)->allowed_clock_offset ) - || (l_time<l_startsync->ts && (l_startsync->ts-l_time) > PVT(l_session->ton)->allowed_clock_offset ) - ) { - // offset is more than allowed_clock_offset - // skip this validator - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Message rejected: too much time difference: my time:%"DAP_UINT64_FORMAT_U" sender time:%"DAP_UINT64_FORMAT_U"", - l_session->chain->net_name, l_session->chain->name, - l_session->cur_round.id.uint64, l_session->attempt_current_number, l_time, l_startsync->ts); - return; - } - - // add check&save sender addr - dap_list_t *l_list_temp = dap_list_first(l_session->cur_round.validators_start); - while(l_list_temp) { - dap_list_t *l_list_next = l_list_temp->next; - if (((dap_chain_node_addr_t *)l_list_temp->data)->uint64 == l_validator->uint64) { - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Message rejected: repeated sync message from addr:"NODE_ADDR_FP_STR"", - l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, - l_session->attempt_current_number, NODE_ADDR_FP_ARGS(a_sender_node_addr)); - return; - } - l_list_temp = l_list_next; - } - - //sync round_id - if ( l_session->cur_round.id.uint64 < l_startsync->round_id.uint64 ) { - l_session->cur_round.id.uint64 = l_startsync->round_id.uint64; - } - - l_session->cur_round.validators_start = dap_list_append(l_session->cur_round.validators_start, l_validator); - l_session->cur_round.validators_start_count = dap_list_length(l_session->cur_round.validators_start); - s_session_send_startsync(l_session); - return; - } - - // validator check - uint64_t l_round_id = - ((dap_chain_cs_block_ton_message_getinfo_t *) - (l_message->sign_n_message+l_message->hdr.sign_size))->round_id.uint64; - dap_chain_node_addr_t *l_validator = NULL; - if (l_round_id == l_session->cur_round.id.uint64) - l_validator = s_session_get_validator(l_session, a_sender_node_addr, l_session->cur_round.validators_start); - if (!l_validator) { - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Message rejected: validator addr:"NODE_ADDR_FP_STR" not in the list.", - l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, - l_session->attempt_current_number, NODE_ADDR_FP_ARGS(a_sender_node_addr)); - return; - } - - // round check - if ( l_message->hdr.type != DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_COMMIT_SIGN ) { - if ( l_session->state != DAP_STREAM_CH_CHAIN_SESSION_STATE_CS_PROC - && l_session->state != DAP_STREAM_CH_CHAIN_SESSION_STATE_WAIT_SIGNS ) { - return; - } - if ( l_round_id != l_session->cur_round.id.uint64) { - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Message rejected: round in message does not match to current round", - l_session->chain->net_name, l_session->chain->name, - l_session->cur_round.id.uint64, l_session->attempt_current_number); - return; - } - } else { - if (l_round_id != l_session->cur_round.id.uint64) { - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Message rejected: round in message does not match to current round", - l_session->chain->net_name, l_session->chain->name, - l_session->cur_round.id.uint64, l_session->attempt_current_number); - return; - } - } - - if ( l_session->attempt_current_number != 1 ) { - switch (l_message->hdr.type) { // this types allow only in first attempt - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_SUBMIT: - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_APPROVE: - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_REJECT: { - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Message rejected: message type:%x allowed only in first attempt", - l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, - l_session->attempt_current_number, l_message->hdr.type); - return; - } - } - } - - dap_chain_cs_block_ton_round_t *l_round = &l_session->cur_round; - - // check hash message dup - dap_chain_cs_block_ton_message_item_t *l_message_item_temp = NULL; - pthread_rwlock_rdlock(&l_round->messages_rwlock); - HASH_FIND(hh, l_round->messages_items, a_data_hash, sizeof(dap_chain_hash_fast_t), l_message_item_temp); - pthread_rwlock_unlock(&l_round->messages_rwlock); - if (l_message_item_temp) { - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: 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.uint64, l_session->attempt_current_number); - return; - } - - // check validator index in queue for event Submit - if ( l_message->hdr.type == DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_SUBMIT ) { - dap_list_t *l_validators_list = dap_list_first(l_session->cur_round.validators_start); - int l_validator_number = 0; - int i = 0; - while(l_validators_list) { - if( ((dap_chain_node_addr_t *)l_validators_list->data)->uint64 == a_sender_node_addr->uint64) { - l_validator_number = i; - break; - } - i++; - l_validators_list = l_validators_list->next; - } - if ( l_validator_number ) { // pass if I first validator - int l_submit_count = 0; - dap_chain_cs_block_ton_message_item_t *l_chain_message=NULL, *l_chain_message_tmp=NULL; - pthread_rwlock_rdlock(&l_round->messages_rwlock); - HASH_ITER(hh, l_round->messages_items, l_chain_message, l_chain_message_tmp) { - if ( l_chain_message->message->hdr.type == DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_SUBMIT ) { - l_submit_count++; - } - } - pthread_rwlock_unlock(&l_round->messages_rwlock); - if ( l_validator_number < l_submit_count ) { - // Skip this SUBMIT. Validator must wait its queue. - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Message rejected: Validator must wait its queue for sent SUBMIT", - l_session->chain->net_name, l_session->chain->name, - l_session->cur_round.id.uint64, l_session->attempt_current_number); - return; - } - } - } - - uint32_t /* l_approve_count = 0, */ l_vote_count = 0, l_precommit_count = 0; - // check messages chain - dap_chain_cs_block_ton_message_item_t *l_chain_message=NULL, *l_chain_message_tmp=NULL; - pthread_rwlock_rdlock(&l_round->messages_rwlock); - HASH_ITER(hh, l_round->messages_items, l_chain_message, l_chain_message_tmp) { - if (l_chain_message->message->hdr.sender_node_addr.uint64 == a_sender_node_addr->uint64) { - dap_chain_hash_fast_t *l_candidate_hash_cur = - &((dap_chain_cs_block_ton_message_getinfo_t *) - (l_message->sign_n_message+l_message->hdr.sign_size))->candidate_hash; - - dap_chain_hash_fast_t *l_candidate_hash = - &((dap_chain_cs_block_ton_message_getinfo_t *) - (l_chain_message->message->sign_n_message+l_chain_message->message->hdr.sign_size))->candidate_hash; - - bool l_candidate_hash_match = (memcmp(l_candidate_hash_cur, l_candidate_hash, - sizeof(dap_chain_hash_fast_t)) == 0); - - uint8_t l_chain_msg_type = l_chain_message->message->hdr.type; - - // search & check messages from this validator - switch (l_chain_msg_type) { - // check dup messages APPROVE, REJECT for one candidate - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_APPROVE: - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_REJECT: { - switch (l_message->hdr.type) { - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_APPROVE: - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_REJECT: - if (l_candidate_hash_match) { - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Message rejected: duplicate messages APPROVE or REJECT for one candidate", - l_session->chain->net_name, l_session->chain->name, - l_session->cur_round.id.uint64, l_session->attempt_current_number); - return; - } - } - } break; - //check dup messages VOTE for one candidate in this attempt - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE: { - dap_chain_cs_block_ton_message_vote_t *l_vote = - (dap_chain_cs_block_ton_message_vote_t *) - (l_message->sign_n_message+l_message->hdr.sign_size); - dap_chain_cs_block_ton_message_vote_t *l_vote_item = - (dap_chain_cs_block_ton_message_vote_t *) - (l_chain_message->message->sign_n_message+l_chain_message->message->hdr.sign_size); - if ( l_chain_msg_type == l_message->hdr.type - && l_vote->attempt_number == l_vote_item->attempt_number ) { - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Message rejected: duplicate messages VOTE for one candidate for one attempt", - l_session->chain->net_name, l_session->chain->name, - l_session->cur_round.id.uint64, l_session->attempt_current_number); - return; - } - } break; - // this messages should only appear once per round //attempt - // case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE: - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_PRE_COMMIT: - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_COMMIT_SIGN: - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_SUBMIT:{ - if ( l_chain_msg_type == l_message->hdr.type ){ - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Message rejected: duplicate messages VOTE or PRE_COMMIT for one candidate for one attempt", - l_session->chain->net_name, l_session->chain->name, - l_session->cur_round.id.uint64, l_session->attempt_current_number); - return; - } - } - } - // count messages in chain for this candidate - if (l_candidate_hash_match) { - switch (l_chain_msg_type) { - // case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_APPROVE: { - // l_approve_count++; - // } break; - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE: { - l_vote_count++; - } break; - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_PRE_COMMIT: { - l_precommit_count++; - } break; - } - } - } - } - pthread_rwlock_unlock(&l_round->messages_rwlock); - - // check message chain is correct - switch (l_message->hdr.type) { - // case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE: { - // if (!l_approve_count) { // if this validator not sent Approve for this candidate - // goto handler_finish; - // } - // } break; - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_PRE_COMMIT: { - if (!l_vote_count) { // if this validator not sent Vote for this candidate - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Message rejected: this validator can't send a PRE_COMMIT because it didn't send a VOTE for this candidate", - l_session->chain->net_name, l_session->chain->name, - l_session->cur_round.id.uint64, l_session->attempt_current_number); - return; - } - } break; - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_COMMIT_SIGN: { - if (!l_precommit_count) { // if this validator not sent PreCommit for this candidate - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Message rejected: this validator can't send a COMMIT_SIGN because it didn't send a PRE_COMMIT for this candidate", - l_session->chain->net_name, l_session->chain->name, - l_session->cur_round.id.uint64, l_session->attempt_current_number); - return; - } - } break; - } - - switch (l_message->hdr.type) { - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_SUBMIT: { - if( sizeof(dap_chain_cs_block_ton_message_submit_t) > l_message_data_size){ - log_it(L_WARNING, "Wrong submit message size,have %zu bytes for data section when only a header requires %zu bytes", - l_message_data_size,sizeof(dap_chain_cs_block_ton_message_submit_t)); - return; - } - dap_chain_cs_block_ton_message_submit_t *l_submit = (dap_chain_cs_block_ton_message_submit_t *)l_message_data; - size_t l_candidate_size = l_submit->candidate_size; - if( l_message_data_size < l_candidate_size + sizeof(*l_submit) ){ - log_it(L_WARNING, "Wrong submit message size %zu when maximum is %zu for received message", l_candidate_size, - l_message_data_size - sizeof(*l_submit)); - return; - } - - dap_chain_hash_fast_t l_candidate_hash; - dap_hash_fast(l_submit->candidate, l_candidate_size, &l_candidate_hash); - - // check candidate hash - if (!dap_hash_fast_compare(&l_submit->candidate_hash, &l_candidate_hash)) - return; - - s_message_chain_add(l_session, a_sender_node_addr, l_message, a_data_size, NULL); - if (!l_candidate_size || dap_hash_fast_is_blank(&l_submit->candidate_hash)) { // null candidate - save chain and exit - - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: 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.uint64, l_session->attempt_current_number); - return; - } - - dap_chain_block_t *l_candidate = (dap_chain_block_t *) DAP_DUP_SIZE(l_submit->candidate, l_candidate_size); - char *l_candidate_hash_str = dap_chain_hash_fast_to_str_new(&l_candidate_hash); - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: 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.uint64, - l_session->attempt_current_number, l_candidate_hash_str, l_candidate_size); - - // check block exist in store - //s_check_block_exist_in_store(,) - struct proc_msg_type_submit * l_args = DAP_NEW_Z(struct proc_msg_type_submit); - l_args->session = l_session; - l_args->candidate_hash_str = l_candidate_hash_str; - l_args->candidate = l_candidate; - l_args->candidate_size = l_candidate_size; - l_args->candidate_hash = l_candidate_hash; - l_args->time = l_time; - if(dap_global_db_get(l_session->gdb_group_store,l_candidate_hash_str,s_callback_check_and_save_candidate_block, l_args) != 0){ - log_it(L_ERROR, "Can't call get request for s_check_block_exist_in_store() callback"); - DAP_DELETE(l_candidate_hash_str); - DAP_DELETE(l_args); - } - } break; - - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_REJECT: { - if ( sizeof(dap_chain_cs_block_ton_message_reject_t) >l_message_data_size ){ - log_it(L_WARNING, "Wrong reject message size,have %zu bytes for data section when requires %zu bytes", - l_message_data_size,sizeof(dap_chain_cs_block_ton_message_reject_t)); - return; - } - dap_chain_cs_block_ton_message_reject_t *l_reject = (dap_chain_cs_block_ton_message_reject_t *) l_message_data; - dap_chain_hash_fast_t *l_candidate_hash = &l_reject->candidate_hash; - - s_message_chain_add(l_session, a_sender_node_addr, l_message, a_data_size, NULL); - - pthread_rwlock_rdlock(&l_session->rwlock); - if (dap_hash_fast_is_blank(l_candidate_hash)) { - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Receive REJECT: NULL", - l_session->chain->net_name, l_session->chain->name, - l_session->cur_round.id.uint64, l_session->attempt_current_number); - pthread_rwlock_unlock(&l_session->rwlock); - return; - } - char *l_candidate_hash_str = dap_chain_hash_fast_to_str_new(l_candidate_hash); - - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: 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.uint64, - l_session->attempt_current_number, l_candidate_hash_str); - pthread_rwlock_unlock(&l_session->rwlock); - - pthread_rwlock_wrlock(&l_session->rwlock); - uint16_t l_reject_count = s_session_message_count(l_session, DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_REJECT, - l_candidate_hash, NULL); - if (l_reject_count * 3 >= l_session->cur_round.validators_count * 2) { - dap_global_db_del_sync(l_session->gdb_group_store, l_candidate_hash_str); - dap_chain_hash_fast_t l_my_candidate_hash; - dap_hash_fast(l_session->my_candidate, l_session->my_candidate_size, &l_my_candidate_hash); - if (dap_hash_fast_compare(&l_my_candidate_hash, l_candidate_hash)) - s_session_my_candidate_delete(l_session); - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Candidate:%s collected rejected more than 2/3 of the validators, so to removed this candidate", - l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, - l_session->attempt_current_number, l_candidate_hash_str); - } - pthread_rwlock_unlock(&l_session->rwlock); - DAP_DELETE(l_candidate_hash_str); - } break; - - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_APPROVE: { - if ( sizeof(dap_chain_cs_block_ton_message_approve_t) >l_message_data_size ){ - log_it(L_WARNING, "Wrong approve message size,have %zu bytes for data section when requires %zu bytes", - l_message_data_size,sizeof(dap_chain_cs_block_ton_message_approve_t)); - return; - } - dap_chain_cs_block_ton_message_approve_t *l_approve = (dap_chain_cs_block_ton_message_approve_t *) l_message_data; - dap_sign_t * l_candidate_sign = (dap_sign_t *) l_approve->candidate_hash_sign; - size_t l_candidate_sign_size = dap_sign_get_size(l_candidate_sign); - size_t l_candidate_hash_sign_size = l_message_data_size - sizeof(dap_chain_cs_block_ton_message_approve_t); - if (l_candidate_sign_size > l_candidate_hash_sign_size) { - log_it(L_WARNING, "Wrong approve message size,have %zu bytes for candidate sign section when requires maximum %zu bytes", - l_candidate_sign_size, l_candidate_hash_sign_size); - return; - } - dap_chain_hash_fast_t *l_candidate_hash = &l_approve->candidate_hash; - if (dap_hash_fast_is_blank(l_candidate_hash)) { - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Receive APPROVE: candidate: NULL", - l_session->chain->net_name, l_session->chain->name, - l_session->cur_round.id.uint64, l_session->attempt_current_number); - return; - } - char *l_candidate_hash_str = dap_chain_hash_fast_to_str_new(l_candidate_hash); - - pthread_rwlock_rdlock(&l_session->rwlock); - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: 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.uint64, - l_session->attempt_current_number, l_candidate_hash_str); - - int l_sign_verified=0; - // check candidate hash sign - if ( (l_sign_verified=dap_sign_verify( (dap_sign_t*)l_approve->candidate_hash_sign, - l_candidate_hash, sizeof(dap_chain_hash_fast_t))) == 1 ) { - - s_message_chain_add(l_session, a_sender_node_addr, l_message, a_data_size, NULL); - - if ( l_session->attempt_current_number == 1 ) { // if this first attempt then send Vote event - uint16_t l_approve_count = s_session_message_count( - l_session, DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_APPROVE, - l_candidate_hash, NULL); - if (l_approve_count * 3 >= l_session->cur_round.validators_count * 2) { - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U" attempt:%hu Candidate:%s collected approve more than 2/3 of the validators", - l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, - l_session->attempt_current_number, l_candidate_hash_str); - - struct proc_msg_type_approve * l_args = DAP_NEW_Z(struct proc_msg_type_approve); - l_args->session = l_session; - l_args->candidate_hash_str = l_candidate_hash_str; - l_args->candidate_hash = *l_candidate_hash; - - if ( dap_global_db_get(l_session->gdb_group_store,l_candidate_hash_str,s_callback_get_candidate_block_and_approve, l_args) != 0 ){ - log_it(L_ERROR, "Can't get candidate block for approvement"); - DAP_DELETE(l_args); - DAP_DELETE(l_candidate_hash_str); - } - }else{ - DAP_DELETE(l_candidate_hash_str); - } - }else{ - DAP_DELETE(l_candidate_hash_str); - } - } else { - log_it(L_WARNING, "Candidate hash sign is incorrect: code %d", l_sign_verified); - DAP_DELETE(l_candidate_hash_str); - } - pthread_rwlock_unlock(&l_session->rwlock); - } break; - - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE_FOR: { - if ( sizeof(dap_chain_cs_block_ton_message_votefor_t) >l_message_data_size ){ - log_it(L_WARNING, "Wrong vote_for message size,have %zu bytes for data section when requires %zu bytes", - l_message_data_size,sizeof(dap_chain_cs_block_ton_message_votefor_t)); - return; - } - - dap_chain_cs_block_ton_message_votefor_t *l_votefor = (dap_chain_cs_block_ton_message_votefor_t *) l_message_data; - dap_chain_hash_fast_t *l_candidate_hash = &l_votefor->candidate_hash; - - pthread_rwlock_rdlock(&l_session->rwlock); - - uint16_t l_attempt_current = l_session->attempt_current_number; - if ( l_votefor->attempt_number != l_attempt_current) { - pthread_rwlock_unlock(&l_session->rwlock); - return; // wrong attempt number in message - } - - if (PVT(l_session->ton)->debug) { - char *l_candidate_hash_str = dap_chain_hash_fast_to_str_new(l_candidate_hash); - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Receive VOTE_FOR: candidate:%s", - l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, - l_session->attempt_current_number, l_candidate_hash_str); - DAP_DELETE(l_candidate_hash_str); - } - - if ( a_sender_node_addr->uint64 != l_session->attempt_coordinator->uint64 ) { - pthread_rwlock_unlock(&l_session->rwlock); - return; // wrong coordinator addr - } - - uint16_t l_votefor_count = s_session_message_count( - l_session, DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE_FOR, - NULL, &l_attempt_current); - if ( l_votefor_count != 0 ) { - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Ignored because it's not the first VOTE_FOR in this attempt", - l_session->chain->net_name, l_session->chain->name, - l_session->cur_round.id.uint64, l_session->attempt_current_number); - pthread_rwlock_unlock(&l_session->rwlock); - return; - } - - s_message_chain_add(l_session, a_sender_node_addr, l_message, a_data_size, NULL); - - struct vote_for_load_store_args * l_args = DAP_NEW_Z(struct vote_for_load_store_args); - l_args->session = l_session; - l_args->candidate_hash = *l_candidate_hash; - // search candidate with 2/3 vote - if(dap_global_db_get_all(l_session->gdb_group_store, 0, - s_session_packet_in_callback_vote_for_load_store, - l_session) != 0 ){ - log_it (L_ERROR, "Can't process get_all request for vote_for_load_store"); - DAP_DELETE(l_args); - } - pthread_rwlock_unlock(&l_session->rwlock); - } return; - - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE: { - if ( sizeof(dap_chain_cs_block_ton_message_vote_t) >l_message_data_size ){ - log_it(L_WARNING, "Wrong vote message size,have %zu bytes for data section when requires %zu bytes", - l_message_data_size,sizeof(dap_chain_cs_block_ton_message_vote_t)); - return; - } - dap_chain_cs_block_ton_message_vote_t *l_vote = (dap_chain_cs_block_ton_message_vote_t *) l_message_data; - dap_chain_hash_fast_t *l_candidate_hash = &l_vote->candidate_hash; - - if ( l_vote->attempt_number != l_session->attempt_current_number) { - return; - } - - if (dap_hash_fast_is_blank(l_candidate_hash)) { - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Receive VOTE: candidate: NULL", - l_session->chain->net_name, l_session->chain->name, - l_session->cur_round.id.uint64, l_session->attempt_current_number); - return; - } - - char *l_candidate_hash_str = dap_chain_hash_fast_to_str_new(l_candidate_hash); - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Receive VOTE: candidate:%s", - l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, - l_session->attempt_current_number, l_candidate_hash_str); - - s_message_chain_add(l_session, a_sender_node_addr, l_message, a_data_size, NULL); - - pthread_rwlock_rdlock(&l_session->rwlock); - uint16_t l_attempt_number = l_session->attempt_current_number; - uint16_t l_vote_count = s_session_message_count( - l_session, DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE, - l_candidate_hash, &l_attempt_number); - - if (l_vote_count * 3 >= l_session->cur_round.validators_count * 2) { - struct proc_msg_type_vote * l_args = DAP_NEW_Z(struct proc_msg_type_vote); - l_args->session = l_session; - l_args->candidate_hash_str = l_candidate_hash_str; - l_args->candidate_hash = *l_candidate_hash; - if (dap_global_db_get(l_session->gdb_group_store,l_candidate_hash_str,s_callback_get_candidate_block_and_vote, l_args ) != 0 ){ - log_it (L_ERROR, "Can't process get request for s_callback_get_candidate_block_and_vote()"); - DAP_DELETE(l_candidate_hash_str); - DAP_DELETE(l_args); - } - } - pthread_rwlock_unlock(&l_session->rwlock); - } return; - - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_PRE_COMMIT: { - if ( sizeof(dap_chain_cs_block_ton_message_precommit_t) >l_message_data_size ){ - log_it(L_WARNING, "Wrong pre_commit message size,have %zu bytes for data section when requires %zu bytes", - l_message_data_size,sizeof(dap_chain_cs_block_ton_message_precommit_t)); - return; - } - - dap_chain_cs_block_ton_message_precommit_t *l_precommit = (dap_chain_cs_block_ton_message_precommit_t *) l_message_data; - dap_chain_hash_fast_t *l_candidate_hash = &l_precommit->candidate_hash; - - pthread_rwlock_wrlock(&l_session->rwlock); - - if ( l_precommit->attempt_number != l_session->attempt_current_number) { - pthread_rwlock_unlock(&l_session->rwlock); - return; - } - if (dap_hash_fast_is_blank(l_candidate_hash)) { - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Receive PRE_COMMIT: candidate: NULL", - l_session->chain->net_name, l_session->chain->name, - l_session->cur_round.id.uint64, l_session->attempt_current_number); - pthread_rwlock_unlock(&l_session->rwlock); - return; - } - - s_message_chain_add(l_session, a_sender_node_addr, l_message, a_data_size, NULL); - - char *l_candidate_hash_str = dap_chain_hash_fast_to_str_new(l_candidate_hash); - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: 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.uint64, - l_session->attempt_current_number, l_candidate_hash_str); - - uint16_t l_attempt_number = l_session->attempt_current_number; - uint16_t l_precommit_count = s_session_message_count(l_session, DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_PRE_COMMIT, - l_candidate_hash, &l_attempt_number); - - if ( 3* l_precommit_count >= 2*l_session->cur_round.validators_count ) { - struct proc_msg_type_pre_commit * l_args = DAP_NEW_Z(struct proc_msg_type_pre_commit); - l_args->session = l_session; - l_args->candidate_hash = *l_candidate_hash; - l_args->candidate_hash_str = l_candidate_hash_str; - if( dap_global_db_get(l_session->gdb_group_store, l_candidate_hash_str,s_callback_get_candidate_block_and_pre_commit, l_args ) != 0 ){ - log_it (L_ERROR, "Can't process get request for s_callback_get_candidate_block_and_pre_commit()"); - DAP_DELETE(l_candidate_hash_str); - DAP_DELETE(l_args); - } - } - pthread_rwlock_unlock(&l_session->rwlock); - } return; - - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_COMMIT_SIGN: { - if ( sizeof(dap_chain_cs_block_ton_message_commitsign_t) >l_message_data_size ){ - log_it(L_WARNING, "Wrong commit_sign message size,have %zu bytes for data section when requires %zu bytes", - l_message_data_size,sizeof(dap_chain_cs_block_ton_message_commitsign_t)); - return; - } - - dap_chain_cs_block_ton_message_commitsign_t *l_commitsign = (dap_chain_cs_block_ton_message_commitsign_t *) l_message_data; - dap_chain_hash_fast_t *l_candidate_hash = &l_commitsign->candidate_hash; - - dap_sign_t * l_candidate_sign = (dap_sign_t *) l_commitsign->candidate_sign; - size_t l_candidate_sign_size = dap_sign_get_size(l_candidate_sign); - size_t l_message_candidate_sign_size_max = l_message_data_size - sizeof(dap_chain_cs_block_ton_message_commitsign_t); - if (l_candidate_sign_size > l_message_candidate_sign_size_max ){ - log_it(L_WARNING, "Wrong commit_sign message size,have %zu bytes for candidate sign section when requires maximum %zu bytes", - l_candidate_sign_size, l_message_candidate_sign_size_max); - return; - } - - pthread_rwlock_rdlock(&l_session->rwlock); - dap_chain_cs_block_ton_round_t *l_round = &l_session->cur_round; - if (dap_hash_fast_is_blank(l_candidate_hash)) { - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Receive COMMIT_SIGN: candidate: NULL", - l_session->chain->net_name, l_session->chain->name, - l_round->id.uint64, l_session->attempt_current_number); - pthread_rwlock_unlock(&l_session->rwlock); - - return; - } - - char *l_candidate_hash_str = dap_chain_hash_fast_to_str_new(l_candidate_hash); - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: 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_round->id.uint64, - l_session->attempt_current_number, l_candidate_hash_str); - - struct proc_msg_type_commit_sign * l_args = DAP_NEW_Z(struct proc_msg_type_commit_sign); - l_args->session = l_session; - l_args->round = l_round; - l_args->round_id = l_commitsign->round_id; - l_args->candidate_hash_str = l_candidate_hash_str; - l_args->candidate_hash = *l_candidate_hash; - l_args->candidate_sign = DAP_DUP_SIZE(l_candidate_sign, l_candidate_sign_size); - l_args->message = DAP_DUP_SIZE(l_message, a_data_size); - l_args->message_size = a_data_size; - l_args->sender_node_addr = *a_sender_node_addr; - - if (dap_global_db_get(l_session->gdb_group_store, l_candidate_hash_str,s_callback_get_candidate_block_and_commit_sign , l_args) != 0 ){ - log_it (L_ERROR, "Can't process get request for s_callback_get_candidate_block_and_commit_sign()"); - DAP_DELETE(l_candidate_hash_str); - DAP_DELETE(l_args); - } // Message we'll proc in callback later - pthread_rwlock_unlock(&l_session->rwlock); - return; - } - default: - break; - } -} - -static uint8_t *s_message_data_sign(dap_chain_cs_block_ton_session_t *a_session, - dap_chain_cs_block_ton_message_t *a_message, size_t *a_sign_size) -{ - struct ton_msg_signing_data { - dap_chain_cs_block_ton_msg_id_t id; - dap_time_t ts_created; - uint8_t type; - dap_chain_id_t chain_id; - dap_chain_node_addr_t sender_node_addr; - } DAP_ALIGN_PACKED; - - struct ton_msg_signing_data *l_data = DAP_NEW(struct ton_msg_signing_data); - l_data->id = a_message->hdr.id; - l_data->ts_created = a_message->hdr.ts_created; - l_data->type = a_message->hdr.type; - l_data->chain_id = a_message->hdr.chain_id; - l_data->sender_node_addr = a_message->hdr.sender_node_addr; - if (a_sign_size) - *a_sign_size = sizeof(l_data); - return (uint8_t *)l_data; -} - - -static void s_message_send(dap_chain_cs_block_ton_session_t *a_session, uint8_t a_message_type, - uint8_t *a_data, size_t a_data_size, dap_list_t *a_validators) -{ - dap_chain_net_t *l_net = dap_chain_net_by_id(a_session->chain->net_id); - size_t l_message_size = sizeof(dap_chain_cs_block_ton_message_hdr_t)+a_data_size; - dap_chain_cs_block_ton_message_t *l_message = - DAP_NEW_SIZE(dap_chain_cs_block_ton_message_t, l_message_size); - l_message->hdr.id.uint64 = (uint64_t)a_session->cur_round.messages_count; - l_message->hdr.chain_id.uint64 = a_session->chain->id.uint64; - l_message->hdr.ts_created = dap_time_now(); - l_message->hdr.type = a_message_type; - l_message->hdr.sender_node_addr = *dap_chain_net_get_cur_addr(l_net); - - size_t l_sign_size = 0; - if ( !PVT(a_session->ton)->validators_list_by_stake ) { - size_t l_data_size = sizeof(l_message->hdr.sender_node_addr); - uint8_t *l_data = s_message_data_sign(a_session, l_message, &l_data_size); - dap_sign_t *l_sign = dap_sign_create(PVT(a_session->ton)->blocks_sign_key, l_data, l_data_size, 0); - l_sign_size = dap_sign_get_size(l_sign); - l_message_size += l_sign_size; - l_message = DAP_REALLOC(l_message, l_message_size); - memcpy(l_message->sign_n_message, l_sign, l_sign_size); - DAP_DELETE(l_sign); - DAP_DELETE(l_data); - } - l_message->hdr.sign_size = l_sign_size; - memcpy(l_message->sign_n_message+l_sign_size, a_data, a_data_size); - l_message->hdr.message_size = a_data_size; - - dap_chain_hash_fast_t l_message_hash; - dap_hash_fast(l_message, l_message_size, &l_message_hash); - - dap_stream_ch_chain_voting_message_write(l_net, a_validators, //a_session->cur_round.validators_start, - &l_message_hash, l_message, l_message_size); - DAP_DELETE(l_message); -} - - -static void s_message_chain_add(dap_chain_cs_block_ton_session_t *a_session, dap_chain_node_addr_t *a_sender_node_addr, - dap_chain_cs_block_ton_message_t *a_message, - size_t a_message_size, dap_chain_hash_fast_t *a_message_hash) -{ - if (a_session->state == DAP_STREAM_CH_CHAIN_SESSION_STATE_IDLE) - return; - dap_chain_cs_block_ton_round_t *l_round = &a_session->cur_round; - a_message->hdr.is_genesis = dap_hash_fast_is_blank(&l_round->last_message_hash); - if (!a_message->hdr.is_genesis) { - a_message->hdr.prev_message_hash = l_round->last_message_hash; - } - - dap_chain_cs_block_ton_message_item_t *l_message_item = DAP_NEW_Z(dap_chain_cs_block_ton_message_item_t); - dap_chain_hash_fast_t l_message_hash; - dap_hash_fast(a_message, a_message_size, &l_message_hash); - l_round->last_message_hash = l_message_item->message_hash = l_message_hash; - l_message_item->message = DAP_DUP_SIZE(a_message, a_message_size); - if (a_message->hdr.type == DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE_FOR || - a_message->hdr.type == DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE) - l_message_item->message->hdr.is_verified = true; - - pthread_rwlock_wrlock(&l_round->messages_rwlock); - HASH_ADD(hh, l_round->messages_items, message_hash, sizeof(l_message_item->message_hash), l_message_item); - pthread_rwlock_unlock(&l_round->messages_rwlock); - - l_round->messages_count++; - if (a_message_hash) - *a_message_hash = l_message_hash; -} - -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) -{ - assert(a_blocks); - dap_chain_cs_block_ton_t *l_ton = DAP_CHAIN_CS_BLOCK_TON(a_blocks); - dap_chain_cs_block_ton_pvt_t *l_ton_pvt = PVT(l_ton); - if (!l_ton_pvt->blocks_sign_key) { - log_it(L_WARNING, "Can't sign block with blocks-sign-cert in [block-ton] section"); - return 0; - } - if (!a_block_ptr || !(*a_block_ptr) || !a_block_size) { - log_it(L_WARNING, "Block size or block pointer is NULL"); - return 0; - } - return dap_chain_block_sign_add(a_block_ptr, a_block_size, l_ton_pvt->blocks_sign_key); -} - -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_chain_cs_block_ton_t *l_ton = DAP_CHAIN_CS_BLOCK_TON(a_blocks); - dap_chain_cs_block_ton_pvt_t *l_ton_pvt = PVT(l_ton); - if (a_blocks->chain->ledger == NULL) { - log_it(L_CRITICAL,"Ledger is NULL can't check TON on this chain %s", a_blocks->chain->name); - 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); - return -7; - } - - if ( l_ton_pvt->flag_sign_verify && !l_ton_pvt->validators_list_by_stake ) { // PoA mode - 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, - a_block_size-sizeof(a_block->hdr)-l_offset, &l_signs_count); - if (!l_signs_count){ - log_it(L_ERROR, "No any signatures at all for block"); - DAP_DELETE(l_signs); - return -2; - } - - if (l_signs_count * 3 < l_ton_pvt->poa_validators_count * 2) { - log_it(L_ERROR, "Corrupted block: not enough signs: %zu of %hu", l_signs_count, l_ton_pvt->poa_validators_count); - DAP_DELETE(l_signs); - return -1; - } - - // 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); - 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))) { - log_it(L_ERROR, "Corrupted block: sign size is bigger than block size"); - l_ret = -3; - break; - } - - // Compare signature with auth_certs - for (uint16_t j = 0; j < l_ton_pvt->auth_certs_count; j++) { - if (dap_cert_compare_with_sign( l_ton_pvt->auth_certs[j], l_sign) == 0 - && dap_sign_verify(l_sign, a_block, l_block_excl_sign_size) == 1 ){ - l_signs_verified_count++; - break; - } - } - } - DAP_DELETE(l_signs); - if ( l_ret != 0 ) { - return l_ret; - } - if (l_signs_verified_count * 3 < l_ton_pvt->poa_validators_count * 2) { - log_it(L_ERROR, "Corrupted block: not enough signs: %u of %u", l_signs_verified_count, l_ton_pvt->poa_validators_count); - return -1; - } - } - return 0; -} - diff --git a/modules/consensus/block-ton/include/dap_chain_cs_block_ton.h b/modules/consensus/block-ton/include/dap_chain_cs_block_ton.h deleted file mode 100644 index 562b4f662d34eb56b65cab0a0815819da8ff82ca..0000000000000000000000000000000000000000 --- a/modules/consensus/block-ton/include/dap_chain_cs_block_ton.h +++ /dev/null @@ -1,204 +0,0 @@ - -#include "dap_chain.h" -#include "dap_chain_block.h" -#include "dap_chain_cs_blocks.h" -#include "dap_cert.h" - -#define DAP_STREAM_CH_CHAIN_SESSION_STATE_IDLE 0x04 -#define DAP_STREAM_CH_CHAIN_SESSION_STATE_WAIT_START 0x08 -#define DAP_STREAM_CH_CHAIN_SESSION_STATE_CS_PROC 0x12 -#define DAP_STREAM_CH_CHAIN_SESSION_STATE_WAIT_SIGNS 0x16 - -#define DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_START_SYNC 0x32 - -#define DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_SUBMIT 0x04 -#define DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_APPROVE 0x08 -#define DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_REJECT 0x12 -#define DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_COMMIT_SIGN 0x16 -#define DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE 0x20 -#define DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE_FOR 0x24 -#define DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_PRE_COMMIT 0x28 - -#define DAP_CHAIN_BLOCKS_SESSION_ROUND_ID_SIZE 8 -#define DAP_CHAIN_BLOCKS_SESSION_MESSAGE_ID_SIZE 8 - -typedef struct dap_chain_cs_block_ton_message dap_chain_cs_block_ton_message_t; -typedef struct dap_chain_cs_block_ton_message_item dap_chain_cs_block_ton_message_item_t; - -typedef struct dap_chain_cs_block_ton -{ - dap_chain_t *chain; - dap_chain_cs_blocks_t *blocks; - void *_pvt; -} dap_chain_cs_block_ton_t; - -typedef union dap_chain_cs_block_ton_round_id { - uint8_t raw[DAP_CHAIN_BLOCKS_SESSION_ROUND_ID_SIZE]; - uint64_t uint64; -} DAP_ALIGN_PACKED dap_chain_cs_block_ton_round_id_t; - -typedef union dap_chain_cs_block_ton_msg_id { - uint8_t raw[DAP_CHAIN_BLOCKS_SESSION_MESSAGE_ID_SIZE]; - uint64_t uint64; -} DAP_ALIGN_PACKED dap_chain_cs_block_ton_msg_id_t; - -typedef struct dap_chain_cs_block_ton_round { - dap_chain_cs_block_ton_round_id_t id; - dap_list_t *validators_start; // dap_chain_node_addr_t - uint16_t validators_start_count; - dap_chain_hash_fast_t last_message_hash; - dap_chain_cs_block_ton_message_item_t *messages_items; - pthread_rwlock_t messages_rwlock; - bool submit; - uint16_t messages_count; - dap_chain_hash_fast_t my_candidate_hash; - dap_list_t *validators_list; // dap_chain_node_addr_t - uint16_t validators_count; - uint16_t candidates_count; -} dap_chain_cs_block_ton_round_t; - -typedef struct dap_chain_cs_block_ton_session { - dap_chain_t *chain; - dap_chain_cs_block_ton_t *ton; - - dap_chain_node_addr_t *my_addr; - - dap_chain_block_t *my_candidate; - size_t my_candidate_size; - uint16_t my_candidate_attempts_count; - - uint8_t state; // session state - dap_chain_cs_block_ton_round_t cur_round; - - dap_chain_node_addr_t *attempt_coordinator; // validator-coordinator in current attempt - uint16_t attempt_current_number; - - dap_time_t ts_round_sync_start; // time start sync - dap_time_t ts_round_start; // time round-start - dap_time_t ts_round_state_commit; - dap_time_t ts_round_finish; - - char * gdb_group_setup; - char * gdb_group_store; - char * gdb_group_message; - - dap_enc_key_t *blocks_sign_key; - - struct dap_chain_cs_block_ton_session *next; - struct dap_chain_cs_block_ton_session *prev; - - dap_worker_t * worker; // Worker where it was processed last time - pthread_rwlock_t rwlock; -} dap_chain_cs_block_ton_session_t; - -typedef struct dap_chain_cs_block_ton_message_hdr { - uint8_t type; - dap_chain_cs_block_ton_msg_id_t id; - uint64_t sign_size; - uint64_t message_size; - dap_time_t ts_created; - dap_chain_node_addr_t sender_node_addr; - uint16_t is_genesis; - uint16_t is_verified; - dap_chain_hash_fast_t prev_message_hash; - dap_chain_id_t chain_id; -} DAP_ALIGN_PACKED dap_chain_cs_block_ton_message_hdr_t; - -typedef struct dap_chain_cs_block_ton_message { - dap_chain_cs_block_ton_message_hdr_t hdr; - uint8_t sign_n_message[]; -} DAP_ALIGN_PACKED dap_chain_cs_block_ton_message_t; - -typedef struct dap_chain_cs_block_ton_message_item { - dap_chain_cs_block_ton_message_t *message; - dap_chain_hash_fast_t message_hash; - UT_hash_handle hh; -} dap_chain_cs_block_ton_message_item_t; - -// struct for get info from any messages -typedef struct dap_chain_cs_block_ton_message_getinfo { - dap_chain_hash_fast_t candidate_hash; - dap_chain_cs_block_ton_round_id_t round_id; - uint16_t attempt_number; -} DAP_ALIGN_PACKED dap_chain_cs_block_ton_message_getinfo_t; - -// technical messages -typedef struct dap_chain_cs_block_ton_message_startsync { - dap_time_t ts; - dap_chain_cs_block_ton_round_id_t round_id; -} DAP_ALIGN_PACKED dap_chain_cs_block_ton_message_startsync_t; - -/* -consensus messages -• Submit(round, candidate) — suggest a new block candidate -• Approve(round, candidate, signature) — a block candidate has passed local validation -• Reject(round, candidate) — a block candidate has failed local valida- tion -• CommitSign(round,candidate,signature) — a block candidate has been accepted and signed -• Vote(round, candidate) — a vote for a block candidate -• VoteFor(round, candidate) — this block candidate must be voted for -in this round (even if the current process has another opinion) -• PreCommit(round,candidate) — a preliminary commitment to a block candidate (used in three-phase commit scheme) -*/ - -typedef struct dap_chain_cs_block_ton_message_submit { - dap_chain_hash_fast_t candidate_hash; - dap_chain_cs_block_ton_round_id_t round_id; - size_t candidate_size; - uint8_t candidate[]; -} DAP_ALIGN_PACKED dap_chain_cs_block_ton_message_submit_t; - -typedef struct dap_chain_cs_block_ton_message_approve { - dap_chain_hash_fast_t candidate_hash; - dap_chain_cs_block_ton_round_id_t round_id; - uint8_t candidate_hash_sign[]; -} DAP_ALIGN_PACKED dap_chain_cs_block_ton_message_approve_t; - -typedef struct dap_chain_cs_block_ton_message_reject { - dap_chain_hash_fast_t candidate_hash; - dap_chain_cs_block_ton_round_id_t round_id; -} DAP_ALIGN_PACKED dap_chain_cs_block_ton_message_reject_t; - -typedef struct dap_chain_cs_block_ton_message_votefor { - dap_chain_hash_fast_t candidate_hash; - dap_chain_cs_block_ton_round_id_t round_id; - uint16_t attempt_number; -} DAP_ALIGN_PACKED dap_chain_cs_block_ton_message_votefor_t; - -typedef struct dap_chain_cs_block_ton_message_vote { - dap_chain_hash_fast_t candidate_hash; - dap_chain_cs_block_ton_round_id_t round_id; - uint16_t attempt_number; -} DAP_ALIGN_PACKED dap_chain_cs_block_ton_message_vote_t; - -typedef struct dap_chain_cs_block_ton_message_precommit { - dap_chain_hash_fast_t candidate_hash; - dap_chain_cs_block_ton_round_id_t round_id; - uint16_t attempt_number; -} DAP_ALIGN_PACKED dap_chain_cs_block_ton_message_precommit_t; - -typedef struct dap_chain_cs_block_ton_message_commitsign { - dap_chain_hash_fast_t candidate_hash; - dap_chain_cs_block_ton_round_id_t round_id; - uint8_t candidate_sign[]; -} DAP_ALIGN_PACKED dap_chain_cs_block_ton_message_commitsign_t; - -typedef struct dap_chain_cs_block_ton_store_hdr { - bool sign_collected; // collect 2/3 min - bool approve_collected; - // bool reject_done; - bool vote_collected; - bool precommit_collected; - size_t candidate_size; - dap_chain_cs_block_ton_round_id_t round_id; - dap_chain_hash_fast_t candidate_hash; - dap_time_t ts_candidate_submit; -} DAP_ALIGN_PACKED dap_chain_cs_block_ton_store_hdr_t; - -typedef struct dap_chain_cs_block_ton_store { - dap_chain_cs_block_ton_store_hdr_t hdr; - uint8_t candidate_n_signs[]; -} DAP_ALIGN_PACKED dap_chain_cs_block_ton_store_t; - -#define DAP_CHAIN_CS_BLOCK_TON(a) ((dap_chain_cs_block_ton_t *)(a)->_inheritor) -int dap_chain_cs_block_ton_init(); -void dap_chain_cs_block_ton_deinit(void); diff --git a/modules/consensus/block-ton/CMakeLists.txt b/modules/consensus/esbocs/CMakeLists.txt similarity index 57% rename from modules/consensus/block-ton/CMakeLists.txt rename to modules/consensus/esbocs/CMakeLists.txt index 0f5cf209e1c22c0a365281bbf63e48eb700e0eb4..beada9e5a9f93e97c545212b9a73c83bfd95d610 100644 --- a/modules/consensus/block-ton/CMakeLists.txt +++ b/modules/consensus/esbocs/CMakeLists.txt @@ -1,10 +1,10 @@ cmake_minimum_required(VERSION 3.10) -project (dap_chain_cs_block_ton) +project (dap_chain_cs_esbocs) -file(GLOB DAP_CHAIN_CS_BLOCK_TON_SRCS *.c) -file(GLOB DAP_CHAIN_CS_BLOCK_TON_HEADERS include/*.h) +file(GLOB DAP_CHAIN_ESBOCS_SRCS *.c) +file(GLOB DAP_CHAIN_CS_ESBOCS_HEADERS include/*.h) -add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_CS_BLOCK_TON_SRCS} ${DAP_CHAIN_CS_BLOCK_TON_HEADERS}) +add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_ESBOCS_SRCS} ${DAP_CHAIN_CS_ESBOCS_HEADERS}) target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_chain dap_chain_cs_blocks dap_chain_net_srv_stake_pos_delegate dap_stream_ch_chain_voting) target_include_directories(${PROJECT_NAME} INTERFACE .) diff --git a/modules/consensus/esbocs/dap_chain_cs_esbocs.c b/modules/consensus/esbocs/dap_chain_cs_esbocs.c new file mode 100644 index 0000000000000000000000000000000000000000..9616097550628889d9ccae6096505c7b4854e464 --- /dev/null +++ b/modules/consensus/esbocs/dap_chain_cs_esbocs.c @@ -0,0 +1,1377 @@ +#include "utlist.h" +#include "dap_timerfd.h" +#include "rand/dap_rand.h" +#include "dap_chain_net.h" +#include "dap_chain_common.h" +#include "dap_chain_cell.h" +#include "dap_chain_cs.h" +#include "dap_chain_cs_blocks.h" +#include "dap_chain_cs_esbocs.h" +#include "dap_stream_ch_chain_voting.h" +#include "dap_chain_net_srv_stake_pos_delegate.h" +#include "dap_chain_ledger.h" + +#define LOG_TAG "dap_chain_cs_esbocs" + +enum s_esbocs_session_state { + DAP_CHAIN_ESBOCS_SESSION_STATE_WAIT_START, + DAP_CHAIN_ESBOCS_SESSION_STATE_WAIT_PROC, + DAP_CHAIN_ESBOCS_SESSION_STATE_WAIT_SIGNS, + DAP_CHAIN_ESBOCS_SESSION_STATE_WAIT_FINISH +}; + +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, + 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); +static void s_session_candidate_to_chain( + dap_chain_esbocs_session_t *a_session, dap_chain_hash_fast_t *a_candidate_hash, + dap_chain_block_t *a_candidate, size_t a_candidate_size); +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); +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); + +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); +static int s_callback_created(dap_chain_t *a_chain, dap_config_t *a_chain_net_cfg); +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) +{ + switch (a_type) { + case DAP_STREAM_CH_VOTING_MSG_TYPE_START_SYNC: return "START_SYNC"; + case DAP_STREAM_CH_VOTING_MSG_TYPE_SUBMIT: return "SUBMIT"; + case DAP_STREAM_CH_VOTING_MSG_TYPE_APPROVE: return "APPROVE"; + case DAP_STREAM_CH_VOTING_MSG_TYPE_REJECT: return "REJECT"; + case DAP_STREAM_CH_VOTING_MSG_TYPE_COMMIT_SIGN: return "COMMIT_SIGN"; + //case DAP_STREAM_CH_VOTING_MSG_TYPE_VOTE: return "VOTE"; + //case DAP_STREAM_CH_VOTING_MSG_TYPE_VOTE_FOR: return "VOTE_FOR" + case DAP_STREAM_CH_VOTING_MSG_TYPE_PRE_COMMIT: return "PRE_COMMIT"; + default: return "UNKNOWN"; + } +} + +static dap_chain_esbocs_session_t * s_session_items; +static dap_timerfd_t *s_session_cs_timer = NULL; + +typedef struct dap_chain_esbocs_pvt { + // Base params + dap_enc_key_t *blocks_sign_key; + // Validators section + bool poa_mode; + uint16_t min_validators_count; + // Debug flag + bool debug; + // Round params + uint16_t new_round_delay; + uint16_t round_start_sync_timeout; + uint16_t round_attempts_max; + uint16_t round_attempt_timeout; + // PoA section + dap_list_t *poa_validators; +} dap_chain_esbocs_pvt_t; + +#define PVT(a) ((dap_chain_esbocs_pvt_t *)a->_pvt) + +int dap_chain_cs_esbocs_init() +{ + dap_stream_ch_chain_voting_init(); + dap_chain_cs_add("esbocs", s_callback_new); + return 0; +} + +void dap_chain_cs_esbocs_deinit(void) +{ +} + +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_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->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); + + int l_ret = 0; + l_esbocs_pvt->min_validators_count = dap_config_get_item_uint16(a_chain_cfg, "esbocs", "min_validators_count"); + if (!l_esbocs_pvt->min_validators_count) { + l_ret = -1; + goto lb_err; + } + if (l_esbocs_pvt->poa_mode) { // auth by certs in PoA mode + const char *l_auth_certs_prefix = dap_config_get_item_str(a_chain_cfg, "esbocs", "auth_certs_prefix"); + uint16_t l_node_addrs_count; + char **l_addrs = dap_config_get_array_str(a_chain_cfg, "esbocs", "validators_addrs", &l_node_addrs_count); + uint16_t l_auth_certs_count = l_node_addrs_count; + if (l_auth_certs_count < l_esbocs_pvt->min_validators_count) { + l_ret = -2; + goto lb_err; + } + char l_cert_name[512]; + dap_cert_t *l_cert_cur; + for (size_t i = 0; i < l_auth_certs_count; i++) { + dap_chain_esbocs_validator_t *l_validator = DAP_NEW(dap_chain_esbocs_validator_t); + + dap_snprintf(l_cert_name, sizeof(l_cert_name), "%s.%zu", l_auth_certs_prefix, i); + if ((l_cert_cur = dap_cert_find_by_name(l_cert_name)) == NULL) { + dap_snprintf(l_cert_name, sizeof(l_cert_name), "%s.%zu.pub", l_auth_certs_prefix, i); + if ((l_cert_cur = dap_cert_find_by_name(l_cert_name)) == NULL) { + log_it(L_ERROR, "ESBOCS: Can't find cert \"%s\"", l_cert_name); + DAP_DELETE(l_validator); + l_ret = -3; + goto lb_err; + } + } + log_it(L_NOTICE, "ESBOCS: Initialized auth cert \"%s\"", l_cert_name); + dap_chain_addr_fill_from_key(&l_validator->signing_addr, l_cert_cur->enc_key, a_chain->net_id); + + if (dap_sscanf(l_addrs[i], NODE_ADDR_FP_STR, NODE_ADDR_FPS_ARGS_S(l_validator->node_addr) ) != 4) { + log_it(L_ERROR,"ESBOCS: Wrong address format, should be like 0123::4567::89AB::CDEF"); + DAP_DELETE(l_validator); + l_ret = -4; + goto lb_err; + } + log_it(L_MSG, "ESBOCS: add validator addr:"NODE_ADDR_FP_STR"", NODE_ADDR_FP_ARGS_S(l_validator->node_addr)); + + l_validator->weight = uint256_1; + l_esbocs_pvt->poa_validators = dap_list_append(l_esbocs_pvt->poa_validators, l_validator); + } + } + l_blocks->chain->callback_created = s_callback_created; + return 0; + +lb_err: + dap_list_free_full(l_esbocs_pvt->poa_validators, NULL); + DAP_DELETE(l_esbocs_pvt); + DAP_DELETE(l_esbocs); + l_blocks->_inheritor = NULL; + l_blocks->callback_delete = NULL; + l_blocks->callback_block_verify = NULL; + 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, + 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); + 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); +} + +static int s_callback_created(dap_chain_t *a_chain, dap_config_t *a_chain_net_cfg) { + + dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(a_chain); + dap_chain_esbocs_t *l_esbocs = DAP_CHAIN_ESBOCS(l_blocks); + dap_chain_esbocs_pvt_t *l_esbocs_pvt = PVT(l_esbocs); + + const char *l_sign_cert_str = NULL; + if ((l_sign_cert_str = dap_config_get_item_str(a_chain_net_cfg, "esbocs", "blocks-sign-cert")) != NULL) { + dap_cert_t *l_sign_cert = dap_cert_find_by_name(l_sign_cert_str); + if (l_sign_cert == NULL) { + log_it(L_ERROR, "Can't load sign certificate, name \"%s\" is wrong", l_sign_cert_str); + return 0; + } else if (l_sign_cert->enc_key->priv_key_data) { + l_esbocs_pvt->blocks_sign_key = l_sign_cert->enc_key; + log_it(L_INFO, "Loaded \"%s\" certificate to sign TON blocks", l_sign_cert_str); + } else { + log_it(L_ERROR, "Certificate \"%s\" has no private key", l_sign_cert_str); + return 0; + } + } else { + log_it(L_NOTICE, "No sign certificate provided, can't sign any blocks. This node can't be a consensus validator"); + return 0; + } + + dap_chain_net_t *l_net = dap_chain_net_by_id(a_chain->net_id); + dap_chain_node_role_t l_role = dap_chain_net_get_role(l_net); + if (l_role.enums > NODE_ROLE_MASTER) { + log_it(L_NOTICE, "Node role is lower than master role, so this node can't be a consensus validator"); + return 0; + } + + dap_chain_addr_t l_my_signing_addr; + dap_chain_addr_fill_from_key(&l_my_signing_addr, l_esbocs_pvt->blocks_sign_key, a_chain->net_id); + if (!l_esbocs_pvt->poa_mode) { + if (!dap_chain_net_srv_stake_key_delegated(&l_my_signing_addr)) { + log_it(L_WARNING, "Signing key is not delegated by stake service. Switch off validator mode"); + return 0; + } + } else { + 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; + l_session->my_addr.uint64 = dap_chain_net_get_cur_addr_int(l_net); + pthread_rwlock_init(&l_session->rwlock, NULL); + 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); + 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); + DL_APPEND(s_session_items, l_session); + if (!s_session_cs_timer) { + s_session_cs_timer = dap_timerfd_start(1000, s_session_timer, NULL); + debug_if(l_esbocs_pvt->debug, L_MSG, "ESBOCS: Consensus main timer is started"); + } + return 0; +} + +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); + DL_DELETE(s_session_items, l_session); + if (!s_session_items) + dap_timerfd_delete(s_session_cs_timer); + s_session_round_clear(l_session); + dap_chain_esbocs_sync_item_t *l_item, *l_tmp; + HASH_ITER(hh, l_session->sync_items, l_item, l_tmp) { + HASH_DEL(l_session->sync_items, l_item); + dap_list_free_full(l_item->messages, NULL); + DAP_DELETE(l_item); + } + pthread_rwlock_unlock(&l_session->rwlock); + DAP_DELETE(l_session); + if (l_esbocs->_pvt) + DAP_DELETE(l_esbocs->_pvt); + DAP_DEL_Z(a_blocks->_inheritor); +} + +static void *s_callback_list_copy(const void *a_validator, UNUSED_ARG void *a_data) +{ + return DAP_DUP((dap_chain_esbocs_validator_t *)a_validator); +} + +static void *s_callback_list_form(const void *a_srv_validator, UNUSED_ARG void *a_data) +{ + dap_chain_esbocs_validator_t *l_validator = DAP_NEW(dap_chain_esbocs_validator_t); + l_validator->node_addr = ((dap_chain_net_srv_stake_item_t *)a_srv_validator)->node_addr; + l_validator->signing_addr = ((dap_chain_net_srv_stake_item_t *)a_srv_validator)->signing_addr; + l_validator->weight = ((dap_chain_net_srv_stake_item_t *)a_srv_validator)->value; + l_validator->is_synced = false; + return l_validator; +} + +static dap_list_t *s_get_validators_list(dap_chain_esbocs_session_t *a_session, dap_chain_hash_fast_t *a_seed_hash) +{ + dap_chain_esbocs_pvt_t *l_esbocs_pvt = PVT(a_session->esbocs); + dap_list_t *l_ret = NULL; + + if (!l_esbocs_pvt->poa_mode) { + dap_list_t *l_validators = dap_chain_net_srv_stake_get_validators(); + size_t l_validators_count = dap_list_length(l_validators); + if (l_validators_count < l_esbocs_pvt->min_validators_count) { + dap_list_free_full(l_validators, NULL); + return NULL; + } + size_t n = (size_t)l_esbocs_pvt->min_validators_count * 3; + size_t l_consensus_optimum = (n / 2) + (n % 2); + size_t l_need_vld_cnt = MIN(l_validators_count, l_consensus_optimum); + if (l_validators_count == l_need_vld_cnt) { + l_ret = dap_list_copy_deep(l_validators, s_callback_list_form, NULL); + dap_list_free_full(l_validators, NULL); + return l_ret; + } + + // TODO: make dap_chain_net_srv_stake_get_total_weight() call + uint256_t l_total_weight = uint256_0; + for (dap_list_t *it = l_validators; it; it = it->next) { + if (SUM_256_256(l_total_weight, + ((dap_chain_net_srv_stake_item_t *)it->data)->value, + &l_total_weight)) { + log_it(L_CRITICAL, "Total stake locked value overflow"); // Is it possible? + dap_list_free_full(l_validators, NULL); + return NULL; + } + } + if (a_seed_hash) + dap_pseudo_random_seed(*(uint256_t *)a_seed_hash); + for (size_t l_current_vld_cnt = 0; l_current_vld_cnt < l_need_vld_cnt; l_current_vld_cnt++) { + uint256_t l_chosen_weight = dap_pseudo_random_get(l_total_weight); + dap_list_t *l_chosen = NULL; + uint256_t l_cur_weight = uint256_0; + for (dap_list_t *it = l_validators; it; it = it->next) { + SUM_256_256(l_cur_weight, + ((dap_chain_net_srv_stake_item_t *)it->data)->value, + &l_cur_weight); + if (compare256(l_chosen_weight, l_cur_weight) == -1) { + l_chosen = it; + break; + } + } + l_ret = dap_list_append(l_ret, s_callback_list_form(l_chosen->data, NULL)); + + SUBTRACT_256_256(l_total_weight, + ((dap_chain_net_srv_stake_item_t *)l_chosen->data)->value, + &l_total_weight); + l_validators = dap_list_remove_link(l_validators, l_chosen); + DAP_DELETE(l_chosen->data); + DAP_DELETE(l_chosen); + } + dap_list_free_full(l_validators, NULL); + } else + l_ret = dap_list_copy_deep(l_esbocs_pvt->poa_validators, s_callback_list_copy, NULL); + + return l_ret; +} + +static void s_get_last_block_hash(dap_chain_t *a_chain, dap_chain_hash_fast_t *a_last_hash_ptr) +{ + 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_chain->callback_atom_iter_delete(l_iter); +} + +static int s_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); +} + +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); +} + +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(); + 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 + 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); +} + +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); + s_session_send_startsync(l_session); + pthread_rwlock_unlock(&l_session->rwlock); + return false; +} + +static void s_session_round_clear(dap_chain_esbocs_session_t *a_session) +{ + dap_chain_esbocs_message_item_t *l_message_item, *l_message_tmp; + HASH_ITER(hh, a_session->cur_round.message_items, l_message_item, l_message_tmp) { + HASH_DEL(a_session->cur_round.message_items, l_message_item); + DAP_DELETE(l_message_item->message); + DAP_DELETE(l_message_item); + } + dap_chain_esbocs_store_t *l_store_item, *l_store_tmp; + HASH_ITER(hh, a_session->cur_round.store_items, l_store_item, l_store_tmp) { + HASH_DEL(a_session->cur_round.store_items, l_store_item); + dap_list_free_full(l_store_item->candidate_signs, NULL); + DAP_DELETE(l_store_item); + } + dap_list_free_full(a_session->cur_round.validators_list, NULL); + + 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 + }; + 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->state = DAP_CHAIN_ESBOCS_SESSION_STATE_WAIT_START; + 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); + if (dap_hash_fast_is_blank(&a_session->cur_round.last_block_hash) || + !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.validators_list = s_get_validators_list(a_session, l_seed_hash); + + 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); + 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); + } + } + HASH_ITER(hh, a_session->sync_items, l_item, l_tmp) { + HASH_DEL(a_session->sync_items, l_item); + 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); + } + 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); + else + s_session_send_startsync(a_session); +} + +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 ) { + 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", + a_session->chain->net_name, a_session->chain->name, + a_session->cur_round.id); + s_session_round_new(a_session); + return; + } + for (dap_list_t *it = a_session->cur_round.validators_list; it; it = it->next) { + 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", + 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()); + } + } + 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", + a_session->chain->net_name, a_session->chain->name, + a_session->cur_round.id); + s_session_round_new(a_session); +} + +static uint64_t s_session_calc_current_round_id(dap_chain_esbocs_session_t *a_session) +{ + struct { + uint64_t id; + uint16_t counter; + } l_id_candidates[a_session->cur_round.validators_synced_count]; + uint16_t l_fill_idx = 0; + dap_chain_esbocs_message_item_t *l_item, *l_tmp; + HASH_ITER(hh, a_session->cur_round.message_items, l_item, l_tmp) { + if (l_item->message->hdr.type == DAP_STREAM_CH_VOTING_MSG_TYPE_START_SYNC) { + uint64_t l_id_candidate = l_item->message->hdr.round_id; + bool l_candidate_found = false; + for (uint16_t i = 0; i < l_fill_idx; i++) + if (l_id_candidates[i].id == l_id_candidate) { + l_id_candidates[i].counter++; + l_candidate_found = true; + break; + } + if (!l_candidate_found) { + l_id_candidates[l_fill_idx].id = l_id_candidate; + l_id_candidates[l_fill_idx].counter = 1; + l_fill_idx++; + } + } + } + uint64_t l_ret = 0; + uint16_t l_counter_max = 0; + for (uint16_t i = 0; i < l_fill_idx; i++) { + if (l_id_candidates[i].counter > l_counter_max) { // Choose maximum counter + l_counter_max = l_id_candidates[i].counter; + l_ret = l_id_candidates[i].id; + } else if (l_id_candidates[i].counter == l_counter_max) // Choose maximum round ID + l_ret = MAX(l_ret, l_id_candidates[i].id); + } + return l_ret; +} + +static int s_signs_sort_callback(const void *a_sign1, const void *a_sign2, UNUSED_ARG void *a_user_data) +{ + size_t l_size1 = dap_sign_get_size((dap_sign_t *)a_sign1); + size_t l_size2 = dap_sign_get_size((dap_sign_t *)a_sign2); + size_t l_size_min = MIN(l_size1, l_size2); + int l_ret = memcmp(a_sign1, a_sign2, l_size_min); + if (!l_ret) { + if (l_size1 < l_size2) + l_ret = -1; + else if (l_size1 > l_size2) + l_ret = 1; + } + return l_ret; +} + +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) +{ + a_session->state = a_new_state; + a_session->ts_attempt_start = a_time; + switch (a_session->state) { + case DAP_CHAIN_ESBOCS_SESSION_STATE_WAIT_PROC: { + uint256_t l_total_weight = uint256_0; + dap_chain_esbocs_validator_t *l_validator; + for (dap_list_t *it = a_session->cur_round.validators_list; it; it = it->next) { + l_validator = it->data; + if (l_validator->is_synced && !l_validator->is_chosen) + SUM_256_256(l_total_weight, l_validator->weight, &l_total_weight); + } + uint256_t l_chosen_weight = dap_pseudo_random_get(l_total_weight); + uint256_t l_cur_weight = uint256_0; + for (dap_list_t *it = a_session->cur_round.validators_list; it; it = it->next) { + l_validator = it->data; + if (l_validator->is_synced && !l_validator->is_chosen) { + SUM_256_256(l_total_weight, l_validator->weight, &l_cur_weight); + if (compare256(l_chosen_weight, l_cur_weight) == -1) { + l_validator->is_chosen = true; + break; + } + } + } + a_session->cur_round.attempt_submit_validator = l_validator->signing_addr; + if (dap_chain_addr_compare(&a_session->cur_round.attempt_submit_validator, &a_session->my_signing_addr)) + s_session_candidate_submit(a_session); + else { + dap_chain_esbocs_message_item_t *l_item, *l_tmp; + HASH_ITER(hh, a_session->cur_round.message_items, l_item, l_tmp) { + if (l_item->message->hdr.type == DAP_STREAM_CH_VOTING_MSG_TYPE_SUBMIT && + dap_chain_addr_compare(&l_item->signing_addr, &a_session->cur_round.attempt_submit_validator)) { + // Verify and vote already submitted candidate + s_session_candidate_verify(a_session, (dap_chain_block_t *)l_item->message->msg_n_sign, + l_item->message->hdr.message_size, &l_item->message->hdr.candidate_hash); + } + } + } + } break; + case DAP_CHAIN_ESBOCS_SESSION_STATE_WAIT_FINISH: { + dap_chain_esbocs_store_t *l_store; + HASH_FIND(hh, a_session->cur_round.store_items, &a_session->cur_round.attempt_candidate_hash, sizeof(dap_hash_fast_t), l_store); + if (!l_store) { + log_it(L_ERROR, "ESBOCS: No finish candidate found!"); + break; + } + dap_list_sort(l_store->candidate_signs, s_signs_sort_callback); + size_t l_candidate_size_exclude_signs = l_store->candidate_size; + for (dap_list_t *it = l_store->candidate_signs; it; it = it->next) { + dap_sign_t *l_candidate_sign = (dap_sign_t *)it->data; + size_t l_candidate_sign_size = dap_sign_get_size(l_candidate_sign); + dap_chain_addr_t l_signing_addr_cur; + dap_chain_addr_fill_from_sign(&l_signing_addr_cur, l_candidate_sign, a_session->chain->net_id); + l_store->candidate = DAP_REALLOC(l_store->candidate, l_store->candidate_size + l_candidate_sign_size); + if (dap_chain_addr_compare(&l_signing_addr_cur, &a_session->cur_round.attempt_submit_validator)) { + // If it's the primary attempt validator sign, place it in the beginnig + if (l_store->candidate_size > l_candidate_size_exclude_signs) + memmove((byte_t *)l_store->candidate + l_candidate_size_exclude_signs + l_candidate_sign_size, + (byte_t *)l_store->candidate + l_candidate_size_exclude_signs, + l_candidate_sign_size); + memcpy((byte_t *)l_store->candidate + l_candidate_size_exclude_signs, l_candidate_sign, l_candidate_sign_size); + } else + memcpy(((byte_t *)l_store->candidate) + l_store->candidate_size, l_candidate_sign, l_candidate_sign_size); + l_store->candidate_size += l_candidate_sign_size; + } + l_store->candidate->hdr.meta_n_datum_n_signs_size = l_store->candidate_size - sizeof(l_store->candidate->hdr); + dap_hash_fast(l_store->candidate, l_store->candidate_size, &l_store->precommit_candidate_hash); + // Send PreCommit + s_message_send(a_session, DAP_STREAM_CH_VOTING_MSG_TYPE_PRE_COMMIT, &l_store->candidate_hash, + &l_store->precommit_candidate_hash, sizeof(dap_chain_hash_fast_t), + a_session->cur_round.validators_list); + } break; + default: + break; + } +} + +static void s_session_proc_state(dap_chain_esbocs_session_t *a_session) +{ + if (pthread_rwlock_trywrlock(&a_session->rwlock) != 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) { + 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", + 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", + a_session->chain->net_name, a_session->chain->name, + a_session->cur_round.id, a_session->cur_round.attempt_num); + s_session_round_new(a_session); + } + } + 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", + 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); + } + break; + case DAP_CHAIN_ESBOCS_SESSION_STATE_WAIT_SIGNS: + if (l_time - a_session->ts_attempt_start >= PVT(a_session->esbocs)->round_attempt_timeout) { + dap_chain_esbocs_store_t *l_store; + HASH_FIND(hh, a_session->cur_round.store_items, &a_session->cur_round.attempt_candidate_hash, sizeof(dap_hash_fast_t), l_store); + if (!l_store) { + log_it(L_ERROR, "ESBOCS: No round candidate found!"); + s_session_attempt_new(a_session); + break; + } + if (dap_list_length(l_store->candidate_signs) >= PVT(a_session->esbocs)->min_validators_count) { + 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", + 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); + } + s_session_state_change(a_session, DAP_CHAIN_ESBOCS_SESSION_STATE_WAIT_FINISH, l_time); + 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", + 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); + } + break; + 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", + 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); + } + break; + default: + break; + } + + pthread_rwlock_unlock(&a_session->rwlock); +} + +static bool s_session_timer(void *a_arg) +{ + UNUSED(a_arg); + dap_chain_esbocs_session_t *l_session = NULL; + DL_FOREACH(s_session_items, l_session) { + s_session_proc_state(l_session); + } + return true; +} + +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_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); + if (!a_message_hash) { + dap_chain_hash_fast_t l_message_hash; + dap_hash_fast(a_message, a_message_size, &l_message_hash); + l_message_item->message_hash = l_message_hash; + } else + l_message_item->message_hash = *a_message_hash; + 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); +} + +static void s_session_candidate_submit(dap_chain_esbocs_session_t *a_session) +{ + dap_chain_t *l_chain = a_session->chain; + dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(l_chain); + dap_chain_block_t *l_candidate; + size_t l_candidate_size = 0; + dap_hash_fast_t l_candidate_hash = {0}; + dap_chain_node_mempool_process_all(a_session->chain); + l_candidate = l_blocks->callback_new_block_move(l_blocks, &l_candidate_size); + if (l_candidate_size) { + 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", + a_session->chain->net_name, a_session->chain->name, + a_session->cur_round.id, 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); + } + 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); +} + +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) +{ + 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 + s_message_send(a_session, DAP_STREAM_CH_VOTING_MSG_TYPE_APPROVE, a_candidate_hash, + NULL, 0, a_session->cur_round.validators_list); + if (PVT(a_session->esbocs)->debug) { + char *l_candidate_hash_str = dap_chain_hash_fast_to_str_new(a_candidate_hash); + log_it(L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Sent APPROVE candidate:%s", + 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); + } + } else { + // validation - fail, gen event Reject + s_message_send(a_session, DAP_STREAM_CH_VOTING_MSG_TYPE_REJECT, a_candidate_hash, + NULL, 0, a_session->cur_round.validators_list); + if (PVT(a_session->esbocs)->debug) { + char *l_candidate_hash_str = dap_chain_hash_fast_to_str_new(a_candidate_hash); + log_it(L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Sent REJECT candidate:%s", + 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); + } + } +} + +static void s_session_candidate_to_chain(dap_chain_esbocs_session_t *a_session, dap_chain_hash_fast_t *a_candidate_hash, + dap_chain_block_t *a_candidate, size_t a_candidate_size) +{ + dap_chain_block_t *l_candidate = DAP_DUP_SIZE(a_candidate, a_candidate_size); + dap_chain_atom_verify_res_t l_res = a_session->chain->callback_atom_add(a_session->chain, l_candidate, a_candidate_size); + char *l_candidate_hash_str = dap_chain_hash_fast_to_str_new(a_candidate_hash); + switch (l_res) { + case ATOM_ACCEPT: + // block save to chain + if (dap_chain_atom_save(a_session->chain, (uint8_t *)l_candidate, a_candidate_size, a_session->chain->cells->id) < 0) + log_it(L_ERROR, "ESBOCS: Can't save atom %s to the file", l_candidate_hash_str); + else + log_it(L_INFO, "ESBOCS: block %s added in chain successfully", l_candidate_hash_str); + break; + case ATOM_MOVE_TO_THRESHOLD: + log_it(L_INFO, "ESBOCS: Thresholded atom with hash %s", l_candidate_hash_str); + break; + case ATOM_PASS: + log_it(L_WARNING, "ESBOCS: Atom with hash %s not accepted (code ATOM_PASS, already present)", l_candidate_hash_str); + DAP_DELETE(l_candidate); + break; + case ATOM_REJECT: + log_it(L_WARNING,"ESBOCS: Atom with hash %s rejected", l_candidate_hash_str); + DAP_DELETE(l_candidate); + break; + default: + log_it(L_CRITICAL, "ESBOCS: Wtf is this ret code ? Atom hash %s code %d", l_candidate_hash_str, l_res); + DAP_DELETE(l_candidate); + } + DAP_DELETE(l_candidate_hash_str); +} + +static void s_session_round_finish(dap_chain_esbocs_session_t *a_session, dap_chain_esbocs_store_t *l_store) +{ + bool l_cs_debug = PVT(a_session->esbocs)->debug; + uint16_t l_cs_level = PVT(a_session->esbocs)->min_validators_count; + + if (!dap_hash_fast_compare(&a_session->cur_round.attempt_candidate_hash, &l_store->candidate_hash)) { + char *l_current_candidate_hash_str = dap_chain_hash_fast_to_str_new(&a_session->cur_round.attempt_candidate_hash); + char *l_finish_candidate_hash_str = dap_chain_hash_fast_to_str_new(&l_store->candidate_hash); + debug_if(l_cs_debug, L_WARNING, "ESBOCS: Trying to finish candidate of not the current attempt (%s but not %s)", + l_current_candidate_hash_str, l_finish_candidate_hash_str); + DAP_DELETE(l_current_candidate_hash_str); + DAP_DELETE(l_finish_candidate_hash_str); + return; + } + + if (l_store->reject_count >= l_cs_level) { + char *l_finish_candidate_hash_str = dap_chain_hash_fast_to_str_new(&l_store->candidate_hash); + debug_if(l_cs_debug, L_WARNING, "ESBOCS: Trying to finish rejected candidate %s", l_finish_candidate_hash_str); + DAP_DELETE(l_finish_candidate_hash_str); + return; + } + + if (l_store->approve_count < l_cs_level) { + char *l_finish_candidate_hash_str = dap_chain_hash_fast_to_str_new(&l_store->candidate_hash); + debug_if(l_cs_debug, L_WARNING, "ESBOCS: Trying to finish not properly approved candidate %s", l_finish_candidate_hash_str); + DAP_DELETE(l_finish_candidate_hash_str); + return; + } + + if (dap_list_length(l_store->candidate_signs) < l_cs_level) { + char *l_finish_candidate_hash_str = dap_chain_hash_fast_to_str_new(&l_store->candidate_hash); + debug_if(l_cs_debug, L_WARNING, "ESBOCS: Trying to finish not properly signed candidate %s", l_finish_candidate_hash_str); + DAP_DELETE(l_finish_candidate_hash_str); + return; + } + + if (l_store->precommit_count < l_cs_level) { + char *l_finish_candidate_hash_str = dap_chain_hash_fast_to_str_new(&l_store->candidate_hash); + debug_if(l_cs_debug, L_WARNING, "ESBOCS: Trying to finish not properly precommited candidate %s", l_finish_candidate_hash_str); + DAP_DELETE(l_finish_candidate_hash_str); + return; + } + + 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" + "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); + DAP_DELETE(l_finish_candidate_hash_str); + DAP_DELETE(l_finish_block_hash_str); + } + s_session_candidate_to_chain(a_session, &l_store->precommit_candidate_hash, l_store->candidate, l_store->candidate_size); +} + +/** + * @brief s_session_packet_in + * @param a_arg + * @param a_sender_node_addr + * @param a_data_hash + * @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, + 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; + dap_chain_esbocs_message_t *l_message = (dap_chain_esbocs_message_t *)a_data; + bool l_cs_debug = PVT(l_session->esbocs)->debug; + uint16_t l_cs_level = PVT(l_session->esbocs)->min_validators_count; + size_t l_message_data_size = l_message->hdr.message_size; + byte_t *l_message_data = l_message->msg_n_sign; + 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)); + + 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", + l_message->hdr.sign_size, a_data_size, sizeof(*l_message)); + goto session_unlock; + } + + if (l_message->hdr.chain_id.uint64 != l_session->chain->id.uint64) { + debug_if(l_cs_debug, L_MSG, "ESBOCS: Invalid chain ID %"DAP_UINT64_FORMAT_U, l_message->hdr.chain_id.uint64); + goto session_unlock; + } + + 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); + 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)); + goto session_unlock; + } + l_message->hdr.sign_size = l_sign_size; // restore original header + + // 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)); + 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); + goto session_unlock; + } + } + // Process local & network messages + dap_chain_addr_t l_signing_addr; + char *l_validator_addr_str = NULL; + dap_chain_addr_fill_from_sign(&l_signing_addr, l_sign, l_session->chain->net_id); + 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); + goto session_unlock; + } + + dap_chain_esbocs_round_t *l_round = &l_session->cur_round; + + // check hash message dup + 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); + goto session_unlock; + } + + // check messages chain + dap_chain_esbocs_message_item_t *l_chain_message, *l_chain_message_tmp; + HASH_ITER(hh, l_round->message_items, l_chain_message, l_chain_message_tmp) { + bool l_same_type = l_chain_message->message->hdr.type == l_message->hdr.type || + (l_chain_message->message->hdr.type == DAP_STREAM_CH_VOTING_MSG_TYPE_APPROVE && + l_message->hdr.type == DAP_STREAM_CH_VOTING_MSG_TYPE_REJECT) || + (l_chain_message->message->hdr.type == DAP_STREAM_CH_VOTING_MSG_TYPE_REJECT && + 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", + 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)); + 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); + 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)) + l_validator->is_synced = true; + } + if (++l_session->cur_round.validators_synced_count == dap_list_length(l_session->cur_round.validators_list)) { + l_session->cur_round.id = s_session_calc_current_round_id(l_session); + debug_if(l_cs_debug, L_MSG, "ESBOCS: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu." + " All validators are synchronized, wait to submit candidate", + l_session->chain->net_name, l_session->chain->name, + 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; + 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", + 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)) + s_session_attempt_new(l_session); + break; + } + // check candidate hash + 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", + 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); + + 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); + DAP_DELETE(l_candidate_hash_str); + } + + dap_chain_esbocs_store_t *l_store; + HASH_FIND(hh, l_session->cur_round.store_items, l_candidate_hash, sizeof(dap_chain_hash_fast_t), l_store); + if (l_store) { + char *l_candidate_hash_str = dap_chain_hash_fast_to_str_new(l_candidate_hash); + log_it(L_WARNING, "ESBOCS: Duplicate candidate:%s", l_candidate_hash_str); + DAP_DELETE(l_candidate_hash_str); + break; + } + + // store for new candidate + l_store = DAP_NEW_Z(dap_chain_esbocs_store_t); + l_store->candidate_size = l_candidate_size; + l_store->candidate_hash = *l_candidate_hash; + l_store->candidate = DAP_DUP_SIZE(l_candidate, l_candidate_size); + + // save new block candidate + HASH_ADD(hh, l_session->cur_round.store_items, candidate_hash, sizeof(dap_hash_fast_t), l_store); + // check it and send APPROVE/REJECT + if (dap_chain_addr_compare(&l_session->cur_round.attempt_submit_validator, &l_signing_addr)) { + l_session->cur_round.attempt_candidate_hash = *l_candidate_hash; + s_session_state_change(l_session, DAP_CHAIN_ESBOCS_SESSION_STATE_WAIT_SIGNS, dap_time_now()); + s_session_candidate_verify(l_session, l_store->candidate, l_store->candidate_size, &l_store->candidate_hash); + } + } break; + + case DAP_STREAM_CH_VOTING_MSG_TYPE_REJECT: { + dap_chain_esbocs_store_t *l_store; + char *l_candidate_hash_str = NULL; + 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); + DAP_DELETE(l_candidate_hash_str); + break; + } + + s_message_chain_add(l_session, l_message, a_data_size, a_data_hash); + + 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); + } + 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", + 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); + } + DAP_DEL_Z(l_candidate_hash_str); + } break; + + case DAP_STREAM_CH_VOTING_MSG_TYPE_APPROVE: { + dap_chain_esbocs_store_t *l_store; + char *l_candidate_hash_str = NULL; + 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); + DAP_DELETE(l_candidate_hash_str); + break; + } + + s_message_chain_add(l_session, l_message, a_data_size, a_data_hash); + + 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); + } + 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", + 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); + dap_sign_t *l_candidate_sign = dap_sign_create(PVT(l_session->esbocs)->blocks_sign_key, + l_store->candidate, l_offset + sizeof(l_store->candidate->hdr), 0); + size_t l_candidate_sign_size = dap_sign_get_size(l_candidate_sign); + s_message_send(l_session, DAP_STREAM_CH_VOTING_MSG_TYPE_COMMIT_SIGN, l_candidate_hash, + l_candidate_sign, l_candidate_sign_size, l_session->cur_round.validators_list); + DAP_DELETE(l_candidate_sign); + } + DAP_DEL_Z(l_candidate_hash_str); + } break; + + case DAP_STREAM_CH_VOTING_MSG_TYPE_COMMIT_SIGN: { + 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); + break; + } + + dap_chain_esbocs_store_t *l_store; + char *l_candidate_hash_str = NULL; + 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); + 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); + } + + size_t l_offset = dap_chain_block_get_sign_offset(l_store->candidate, l_store->candidate_size); + bool l_sign_verified = dap_sign_verify(l_candidate_sign, l_store->candidate, + 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); + 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); + s_session_state_change(l_session, DAP_CHAIN_ESBOCS_SESSION_STATE_WAIT_FINISH, dap_time_now()); + } + } else { + if (!l_candidate_hash_str) + l_candidate_hash_str = dap_chain_hash_fast_to_str_new(l_candidate_hash); + log_it(L_WARNING, "Candidate:%s sign is incorrect: code %d", l_candidate_hash_str, l_sign_verified); + } + DAP_DEL_Z(l_candidate_hash_str); + } break; + + case DAP_STREAM_CH_VOTING_MSG_TYPE_PRE_COMMIT: { + dap_chain_esbocs_store_t *l_store; + char *l_candidate_hash_str = NULL; + 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); + DAP_DELETE(l_candidate_hash_str); + break; + } + + dap_hash_fast_t *l_precommit_hash = (dap_hash_fast_t *)l_message_data; + if (!dap_hash_fast_compare(l_precommit_hash, &l_store->precommit_candidate_hash)) { + if (l_cs_debug) { + 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); + DAP_DELETE(l_candidate_hash_str); + DAP_DELETE(l_my_precommit_hash_str); + DAP_DELETE(l_remote_precommit_hash_str); + } + break; + } + + s_message_chain_add(l_session, l_message, a_data_size, a_data_hash); + + 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); + } + 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); + s_session_round_finish(l_session, l_store); + s_session_round_new(l_session); + } + DAP_DEL_Z(l_candidate_hash_str); + } break; + default: + break; + } +session_unlock: + pthread_rwlock_unlock(&l_session->rwlock); +} + +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) +{ + dap_chain_net_t *l_net = dap_chain_net_by_id(a_session->chain->net_id); + size_t l_message_size = sizeof(dap_chain_esbocs_message_hdr_t) + a_data_size; + dap_chain_esbocs_message_t *l_message = + DAP_NEW_Z_SIZE(dap_chain_esbocs_message_t, l_message_size); + l_message->hdr.round_id = a_session->cur_round.id; + l_message->hdr.attempt_num = a_session->cur_round.attempt_num; + l_message->hdr.chain_id = a_session->chain->id; + l_message->hdr.ts_created = dap_time_now(); + l_message->hdr.type = a_message_type; + l_message->hdr.message_size = a_data_size; + l_message->hdr.candidate_hash = *a_block_hash; + if (a_data && a_data_size) + memcpy(l_message->msg_n_sign, a_data, a_data_size); + + dap_sign_t *l_sign = dap_sign_create(PVT(a_session->esbocs)->blocks_sign_key, l_message, + sizeof(l_message->hdr) + a_data_size, 0); + size_t l_sign_size = dap_sign_get_size(l_sign); + l_message_size += l_sign_size; + l_message = DAP_REALLOC(l_message, l_message_size); + memcpy(l_message->msg_n_sign + a_data_size, l_sign, l_sign_size); + 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_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) + dap_stream_ch_chain_voting_message_write(l_net, &l_validator->node_addr, l_voting_pkt); + } + DAP_DELETE(l_voting_pkt); +} + + +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) +{ + assert(a_blocks); + dap_chain_esbocs_t *l_esbocs = DAP_CHAIN_ESBOCS(a_blocks); + dap_chain_esbocs_pvt_t *l_esbocs_pvt = PVT(l_esbocs); + if (!l_esbocs_pvt->blocks_sign_key) { + log_it(L_WARNING, "Can't sign block with blocks-sign-cert in [esbocs] section"); + return 0; + } + if (!a_block_ptr || !(*a_block_ptr) || !a_block_size) { + log_it(L_WARNING, "Block size or block pointer is NULL"); + return 0; + } + return dap_chain_block_sign_add(a_block_ptr, a_block_size, l_esbocs_pvt->blocks_sign_key); +} + +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_chain_esbocs_t *l_esbocs = DAP_CHAIN_ESBOCS(a_blocks); + dap_chain_esbocs_pvt_t *l_esbocs_pvt = PVT(l_esbocs); + if (a_blocks->chain->ledger == NULL) { + log_it(L_CRITICAL,"Ledger is NULL can't check consensus conditions on this chain %s", a_blocks->chain->name); + 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); + return -7; + } + + 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, + a_block_size-sizeof(a_block->hdr)-l_offset, &l_signs_count); + if (!l_signs_count){ + log_it(L_ERROR, "No any signatures at all for block"); + DAP_DELETE(l_signs); + return -2; + } + + if (l_signs_count < l_esbocs_pvt->min_validators_count) { + log_it(L_ERROR, "Corrupted block: not enough signs: %zu of %hu", l_signs_count, l_esbocs_pvt->min_validators_count); + DAP_DELETE(l_signs); + return -1; + } + + // 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); + 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))) { + log_it(L_ERROR, "Corrupted block: sign size is bigger than block size"); + l_ret = -3; + break; + } + + dap_chain_addr_t l_signing_addr; + dap_chain_addr_fill_from_sign(&l_signing_addr, l_sign, a_blocks->chain->net_id); + if (!l_esbocs_pvt->poa_mode) { + // Compare signature with delegated keys + if (!dap_chain_net_srv_stake_key_delegated(&l_signing_addr)) + continue; + } else { + // Compare signature with auth_certs + if (!s_validator_check(&l_signing_addr, l_esbocs_pvt->poa_validators)) + continue; + } + if (dap_sign_verify(l_sign, a_block, l_block_excl_sign_size) == 1) + l_signs_verified_count++; + } + DAP_DELETE(l_signs); + if ( l_ret != 0 ) { + return l_ret; + } + if (l_signs_verified_count < l_esbocs_pvt->min_validators_count) { + log_it(L_ERROR, "Corrupted block: not enough signs: %u of %u", l_signs_verified_count, l_esbocs_pvt->min_validators_count); + return -1; + } + return 0; +} diff --git a/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h b/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h new file mode 100644 index 0000000000000000000000000000000000000000..b0828c54b0b77691898c4ffd0c93ef2bd377a393 --- /dev/null +++ b/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h @@ -0,0 +1,133 @@ +#include "dap_timerfd.h" +#include "dap_chain.h" +#include "dap_chain_block.h" +#include "dap_chain_cs_blocks.h" +#include "dap_cert.h" + +#define DAP_STREAM_CH_VOTING_MSG_TYPE_SUBMIT 0x04 +#define DAP_STREAM_CH_VOTING_MSG_TYPE_APPROVE 0x08 +#define DAP_STREAM_CH_VOTING_MSG_TYPE_REJECT 0x12 +#define DAP_STREAM_CH_VOTING_MSG_TYPE_COMMIT_SIGN 0x16 +//#define DAP_STREAM_CH_VOTING_MSG_TYPE_VOTE 0x20 +//#define DAP_STREAM_CH_VOTING_MSG_TYPE_VOTE_FOR 0x24 +#define DAP_STREAM_CH_VOTING_MSG_TYPE_PRE_COMMIT 0x28 +#define DAP_STREAM_CH_VOTING_MSG_TYPE_START_SYNC 0x32 + +#define DAP_CHAIN_BLOCKS_SESSION_ROUND_ID_SIZE 8 +#define DAP_CHAIN_BLOCKS_SESSION_MESSAGE_ID_SIZE 8 + +typedef struct dap_chain_esbocs_session dap_chain_esbocs_session_t; + +/* consensus messages +• 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 +• CommitSign(round, candidate, signature) — a block candidate has been accepted and signed *** sign in data section +• Vote(round, candidate) — a vote for a block candidate in this round (even if the current process has another opinion) +• PreCommit(round, candidate, final_hash) — a preliminary commitment to a block candidate *** candidate with signs hash in data section +*/ +typedef struct dap_chain_esbocs_message_hdr { + uint8_t version; + uint8_t padding; + uint8_t type; + uint8_t attempt_num; + uint64_t round_id; + uint64_t sign_size; + uint64_t message_size; + dap_time_t ts_created; + dap_chain_net_id_t net_it; + dap_chain_id_t chain_id; + dap_chain_cell_id_t cell_id; + dap_hash_fast_t candidate_hash; +} DAP_ALIGN_PACKED dap_chain_esbocs_message_hdr_t; + +typedef struct dap_chain_esbocs_message { + dap_chain_esbocs_message_hdr_t hdr; + uint8_t msg_n_sign[]; +} DAP_ALIGN_PACKED dap_chain_esbocs_message_t; + +typedef struct dap_chain_esbocs_message_item { + dap_hash_fast_t message_hash; + dap_chain_esbocs_message_t *message; + dap_chain_addr_t signing_addr; + UT_hash_handle hh; +} dap_chain_esbocs_message_item_t; + +typedef struct dap_chain_esbocs_sync_item { + dap_hash_fast_t last_block_hash; + dap_list_t *messages; + UT_hash_handle hh; +} dap_chain_esbocs_sync_item_t; + +typedef struct dap_chain_esbocs_store { + dap_hash_fast_t candidate_hash; + dap_hash_fast_t precommit_candidate_hash; + dap_chain_block_t *candidate; + size_t candidate_size; + dap_list_t *candidate_signs; + uint16_t approve_count; + uint16_t reject_count; + uint16_t precommit_count; + bool decide_reject; + bool decide_approve; + bool decide_commit; + UT_hash_handle hh; +} dap_chain_esbocs_store_t; + +typedef struct dap_chain_esbocs { + dap_chain_t *chain; + dap_chain_cs_blocks_t *blocks; + dap_chain_esbocs_session_t *session; + void *_pvt; +} dap_chain_esbocs_t; + +typedef struct dap_chain_esbocs_round { + // Base fields + uint64_t id; + uint8_t attempt_num; + dap_hash_fast_t last_block_hash; + // Round ancillary + dap_chain_esbocs_store_t *store_items; + dap_chain_esbocs_message_item_t *message_items; + // Attempt dependent fields + dap_chain_addr_t attempt_submit_validator; + dap_hash_fast_t attempt_candidate_hash; + // Validators section + uint16_t validators_synced_count; + dap_list_t *validators_list; +} dap_chain_esbocs_round_t; + +typedef struct dap_chain_esbocs_validator { + dap_chain_node_addr_t node_addr; + dap_chain_addr_t signing_addr; + uint256_t weight; + bool is_synced; + bool is_chosen; +} dap_chain_esbocs_validator_t; + +typedef struct dap_chain_esbocs_session { + pthread_rwlock_t rwlock; + + dap_chain_t *chain; + dap_chain_esbocs_t *esbocs; + + dap_chain_node_addr_t my_addr; + uint8_t state; // session state + dap_chain_esbocs_round_t cur_round; + + dap_time_t ts_round_sync_start; // time of start sync + dap_time_t ts_attempt_start; // time of current attempt start + + dap_chain_esbocs_sync_item_t *sync_items; + dap_timerfd_t *sync_timer; + + dap_enc_key_t *blocks_sign_key; + dap_chain_addr_t my_signing_addr; + + struct dap_chain_esbocs_session *next; + struct dap_chain_esbocs_session *prev; +} dap_chain_esbocs_session_t; + +#define DAP_CHAIN_ESBOCS(a) ((dap_chain_esbocs_t *)(a)->_inheritor) +int dap_chain_cs_esbocs_init(); +void dap_chain_cs_esbocs_deinit(void); diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c index 3eb1fdde3c3bdf13c30b07024330ef5c0378c30b..8fe82b923809a865b070c52b119e11c363a244e6 100644 --- a/modules/net/dap_chain_node_cli_cmd.c +++ b/modules/net/dap_chain_node_cli_cmd.c @@ -5849,6 +5849,71 @@ end: return 0; } +static char **s_parse_items(const char *a_str, char a_delimiter, int *a_count, const int a_only_digit) +{ + int l_count_temp = *a_count = 0; + int l_len_str = strlen(a_str); + if (l_len_str == 0) return NULL; + char *s, *l_temp_str; + s = l_temp_str = dap_strdup(a_str); + + int l_buf = 0; + for (int i = 0; i < l_len_str; i++) { + if (s[i] == a_delimiter && !l_buf) { + s[i] = 0; + continue; + } + if (s[i] == a_delimiter && l_buf) { + s[i] = 0; + l_buf = 0; + continue; + } + if (!dap_is_alpha(s[i]) && l_buf) { + s[i] = 0; + l_buf = 0; + continue; + } + if (!dap_is_alpha(s[i]) && !l_buf) { + s[i] = 0; + continue; + } + if (a_only_digit) { + if (dap_is_digit(s[i])) { + l_buf++; + if (l_buf == 1) l_count_temp++; + continue; + } + } else if (dap_is_alpha(s[i])) { + l_buf++; + if (l_buf == 1) l_count_temp++; + continue; + } + if (!dap_is_alpha(s[i])) { + l_buf = 0; + s[i] = 0; + continue; + } + } + + s = l_temp_str; + if (l_count_temp == 0) { + DAP_FREE(l_temp_str); + return NULL; + } + + char **lines = DAP_CALLOC(l_count_temp, sizeof (void *)); + for (int i = 0; i < l_count_temp; i++) { + while (*s == 0) s++; + lines[i] = strdup(s); + s = strchr(s, '\0'); + s++; + } + + DAP_FREE(l_temp_str); + *a_count = l_count_temp; + return lines; +} + static int s_get_key_from_file(const char *a_file, const char *a_mime, const char *a_cert_name, dap_sign_t **a_sign) { char **l_items_mime = NULL; @@ -5858,7 +5923,7 @@ static int s_get_key_from_file(const char *a_file, const char *a_mime, const cha if (a_mime) { - l_items_mime = dap_parse_items(a_mime, ',', &l_items_mime_count, 0); + l_items_mime = s_parse_items(a_mime, ',', &l_items_mime_count, 0); } if (l_items_mime && l_items_mime_count > 0) { diff --git a/modules/net/dap_chain_node_client.c b/modules/net/dap_chain_node_client.c index e8c4e591510e73b3aae5d8a31eaf5b9c15f6de9e..9259bdc35b3ec799232f7110be07084b58c3a32d 100644 --- a/modules/net/dap_chain_node_client.c +++ b/modules/net/dap_chain_node_client.c @@ -622,7 +622,7 @@ static void s_ch_chain_callback_notify_packet_R(dap_stream_ch_chain_net_srv_t* a case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_CHECK_RESPONSE: { dap_stream_ch_chain_net_srv_pkt_test_t *l_request = (dap_stream_ch_chain_net_srv_pkt_test_t *) a_pkt->data; size_t l_request_size = l_request->data_size + sizeof(dap_stream_ch_chain_net_srv_pkt_test_t); - if(a_pkt->hdr.size != l_request_size) { + if(a_pkt->hdr.data_size != l_request_size) { log_it(L_WARNING, "Wrong request size, less or more than required"); break; } @@ -697,7 +697,7 @@ dap_chain_node_client_t *dap_chain_node_client_create(dap_chain_net_t *a_net, } - void s_client_delete_callback(UNUSED_ATTR dap_client_t *a_client, void *a_arg) + void s_client_delete_callback(UNUSED_ARG dap_client_t *a_client, void *a_arg) { assert(a_arg); dap_chain_node_client_close_unsafe(a_arg); @@ -797,7 +797,7 @@ void dap_chain_node_client_close_unsafe(dap_chain_node_client_t *a_node_client) DAP_DELETE(a_node_client); } -void s_close_on_worker_callback(UNUSED_ATTR dap_worker_t *a_worker, void *a_arg) +void s_close_on_worker_callback(UNUSED_ARG dap_worker_t *a_worker, void *a_arg) { assert(a_arg); dap_chain_node_client_close_unsafe(a_arg); diff --git a/modules/net/include/dap_chain_node.h b/modules/net/include/dap_chain_node.h index aa9f8f90688a0ea23ae148bc70760efd76eb1beb..a545a6d2f3530a5666ed5c94b3559cf8f45d71e1 100644 --- a/modules/net/include/dap_chain_node.h +++ b/modules/net/include/dap_chain_node.h @@ -82,8 +82,7 @@ typedef struct dap_chain_node_decl{ } accept_info; } DAP_ALIGN_PACKED dap_chain_node_decl_t; -typedef struct dap_chain_node_info -{ +typedef struct dap_chain_node_info { struct { dap_chain_node_addr_t address; dap_chain_cell_id_t cell_id; diff --git a/modules/net/srv/dap_chain_net_srv_client.c b/modules/net/srv/dap_chain_net_srv_client.c index 6f0cb58542fb9b6b9304a426eb8c297b01d4b36d..90259de8c283a9acb95c40e29b25ef05e653c6ad 100644 --- a/modules/net/srv/dap_chain_net_srv_client.c +++ b/modules/net/srv/dap_chain_net_srv_client.c @@ -112,8 +112,8 @@ static void s_srv_client_pkt_in(dap_stream_ch_chain_net_srv_t *a_ch_chain, uint8 case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_CHECK_RESPONSE: { dap_stream_ch_chain_net_srv_pkt_test_t *l_response = (dap_stream_ch_chain_net_srv_pkt_test_t *)a_pkt->data; size_t l_response_size = l_response->data_size + sizeof(dap_stream_ch_chain_net_srv_pkt_test_t); - if (a_pkt->hdr.size != l_response_size) { - log_it(L_WARNING, "Wrong response size %u, required %zu", a_pkt->hdr.size, l_response_size); + if (a_pkt->hdr.data_size != l_response_size) { + log_it(L_WARNING, "Wrong response size %u, required %zu", a_pkt->hdr.data_size, l_response_size); if (l_srv_client->callbacks.error) l_srv_client->callbacks.error(l_srv_client, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_WRONG_SIZE, @@ -136,8 +136,8 @@ static void s_srv_client_pkt_in(dap_stream_ch_chain_net_srv_t *a_ch_chain, uint8 case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_SIGN_REQUEST: { log_it(L_NOTICE, "Requested receipt to sign"); dap_chain_datum_tx_receipt_t *l_receipt = (dap_chain_datum_tx_receipt_t *)a_pkt->data; - if (a_pkt->hdr.size != l_receipt->size) { - log_it(L_WARNING, "Wrong response size %u, required %"DAP_UINT64_FORMAT_U, a_pkt->hdr.size, l_receipt->size); + if (a_pkt->hdr.data_size != l_receipt->size) { + log_it(L_WARNING, "Wrong response size %u, required %"DAP_UINT64_FORMAT_U, a_pkt->hdr.data_size, l_receipt->size); if (l_srv_client->callbacks.error) l_srv_client->callbacks.error(l_srv_client, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_WRONG_SIZE, @@ -161,19 +161,19 @@ static void s_srv_client_pkt_in(dap_stream_ch_chain_net_srv_t *a_ch_chain, uint8 case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_SUCCESS: { log_it( L_NOTICE, "Responsed with success"); dap_stream_ch_chain_net_srv_pkt_success_t *l_success = (dap_stream_ch_chain_net_srv_pkt_success_t *)a_pkt->data; - size_t l_success_size = a_pkt->hdr.size; + size_t l_success_size = a_pkt->hdr.data_size; if (l_srv_client->callbacks.success) { l_srv_client->callbacks.success(l_srv_client, l_success, l_success_size, l_srv_client->callbacks_arg); } } break; case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR: { - if (a_pkt->hdr.size == sizeof (dap_stream_ch_chain_net_srv_pkt_error_t)) { + if (a_pkt->hdr.data_size == sizeof (dap_stream_ch_chain_net_srv_pkt_error_t)) { dap_stream_ch_chain_net_srv_pkt_error_t *l_err = (dap_stream_ch_chain_net_srv_pkt_error_t *)a_pkt->data; log_it(L_WARNING, "Remote responsed with error code 0x%08X", l_err->code); if (l_srv_client->callbacks.error) l_srv_client->callbacks.error(l_srv_client, l_err->code, l_srv_client->callbacks_arg); } else { - log_it(L_ERROR, "Wrong error response size, %u when expected %zu", a_pkt->hdr.size, + log_it(L_ERROR, "Wrong error response size, %u when expected %zu", a_pkt->hdr.data_size, sizeof ( dap_stream_ch_chain_net_srv_pkt_error_t) ); } } break; diff --git a/modules/service/stake_pos_delegate/CMakeLists.txt b/modules/service/stake_pos_delegate/CMakeLists.txt index 6cf03e2d8c7c83848a7d2a248738fcf222d5ceb2..958cc783e4de4029bb603949a7e0357647f00cef 100644 --- a/modules/service/stake_pos_delegate/CMakeLists.txt +++ b/modules/service/stake_pos_delegate/CMakeLists.txt @@ -9,4 +9,4 @@ add_library(${PROJECT_NAME} STATIC ${DAP_SRV_STAKE_POS_DELEGATE_SRCS} ${DAP_SRV_ target_include_directories(${PROJECT_NAME} INTERFACE .) target_include_directories(${PROJECT_NAME} PUBLIC include) -target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_chain dap_chain_net dap_chain_net_srv dap_chain_cs_dag_poa dap_chain_cs_block_ton dap_chain_cs_block_poa) +target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_chain dap_chain_net dap_chain_net_srv dap_chain_cs_dag_poa dap_chain_cs_block_poa) diff --git a/modules/service/stake_pos_delegate/dap_chain_net_srv_stake_pos_delegate.c b/modules/service/stake_pos_delegate/dap_chain_net_srv_stake_pos_delegate.c index d6d3315ea14d5fac8d2eec04a47d2fe2433ea342..aa5c65b8a2c06711c7be65d03c4c0c5bdb729a4b 100644 --- a/modules/service/stake_pos_delegate/dap_chain_net_srv_stake_pos_delegate.c +++ b/modules/service/stake_pos_delegate/dap_chain_net_srv_stake_pos_delegate.c @@ -292,6 +292,7 @@ dap_list_t *dap_chain_net_srv_stake_get_validators() return l_ret; } + bool dap_chain_net_srv_stake_validator(dap_chain_addr_t *a_addr, dap_chain_datum_t *a_datum) { if (!s_srv_stake) { // Drop all atoms if stake service inactivated @@ -615,11 +616,6 @@ dap_chain_net_srv_stake_item_t *s_stake_item_from_order(dap_chain_net_t *a_net, static bool s_stake_block_commit(dap_chain_net_t *a_net, dap_list_t *a_tx_hash_list) { size_t l_all_tx = 0, l_process_tx = 0; - // find all stake - dap_list_t *l_staker_list0 = dap_chain_net_srv_stake_get_validators(); - if(!l_staker_list0){ - return false; - } // find all certs size_t l_auth_certs_count = 0; dap_cert_t **l_auth_certs = NULL; @@ -709,7 +705,7 @@ static bool s_stake_block_commit(dap_chain_net_t *a_net, dap_list_t *a_tx_hash_l l_process_tx++; a_tx_hash_list = dap_list_next(a_tx_hash_list); } - dap_list_free_full(l_staker_list0, free); + log_it(L_INFO, "Processed %ld tx from %ld", l_process_tx, l_all_tx); if(!IS_ZERO_256(l_fee_sum_total)) { diff --git a/modules/service/vpn/dap_chain_net_srv_vpn.c b/modules/service/vpn/dap_chain_net_srv_vpn.c index 1c27d9d61c7a5a38a1010ed62fb83c24c421e449..174e3cfa29ba9aac2763089ff85455e278a7690a 100644 --- a/modules/service/vpn/dap_chain_net_srv_vpn.c +++ b/modules/service/vpn/dap_chain_net_srv_vpn.c @@ -1452,7 +1452,7 @@ void s_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) //dap_chain_net_srv_vpn_t * l_srv_vpn =(dap_chain_net_srv_vpn_t *) l_usage->service->_internal; ch_vpn_pkt_t * l_vpn_pkt = (ch_vpn_pkt_t *) l_pkt->data; - size_t l_vpn_pkt_size = l_pkt->hdr.size - sizeof (l_vpn_pkt->header); + size_t l_vpn_pkt_size = l_pkt->hdr.data_size - sizeof (l_vpn_pkt->header); debug_if(s_debug_more, L_INFO, "Got srv_vpn packet with op_code=0x%02x", l_vpn_pkt->header.op_code); diff --git a/modules/service/vpn/dap_chain_net_vpn_client.c b/modules/service/vpn/dap_chain_net_vpn_client.c index 79388b31622ecb97db2af1edd7f3989a2d1e2580..2481518673392dbc182c73e57728c19b941b54fb 100644 --- a/modules/service/vpn/dap_chain_net_vpn_client.c +++ b/modules/service/vpn/dap_chain_net_vpn_client.c @@ -694,9 +694,9 @@ dap_chain_net_vpn_client_status_t dap_chain_net_vpn_client_status(void) void dap_chain_net_vpn_client_pkt_in(dap_stream_ch_t* a_ch, dap_stream_ch_pkt_t* a_pkt) { ch_vpn_pkt_t * l_sf_pkt = (ch_vpn_pkt_t *) a_pkt->data; - size_t l_sf_pkt_data_size = a_pkt->hdr.size - sizeof(l_sf_pkt->header); + size_t l_sf_pkt_data_size = a_pkt->hdr.data_size - sizeof(l_sf_pkt->header); - if(!a_pkt->hdr.size) { + if(!a_pkt->hdr.data_size) { log_it(L_WARNING, "Bad input packet"); return; } diff --git a/modules/type/blocks/dap_chain_cs_blocks.c b/modules/type/blocks/dap_chain_cs_blocks.c index e8d19aefd4d6345628429c3ec4171678ba07ee7c..6e2dca0267a7d759a67753f2108f54d2347c3b0b 100644 --- a/modules/type/blocks/dap_chain_cs_blocks.c +++ b/modules/type/blocks/dap_chain_cs_blocks.c @@ -78,16 +78,8 @@ typedef struct dap_chain_cs_blocks_pvt } dap_chain_cs_blocks_pvt_t; -typedef struct dap_chain_cs_blocks_iter -{ - dap_chain_cs_blocks_t * blocks; - dap_chain_block_cache_t * cache; -} dap_chain_cs_blocks_iter_t; - #define PVT(a) ((dap_chain_cs_blocks_pvt_t *)(a)->_pvt ) -#define ITER_PVT(a) ((dap_chain_cs_blocks_iter_t *) a->_inheritor ) - static int s_cli_parse_cmd_hash(char ** a_argv, int a_arg_index, int a_argc, char **a_str_reply,const char * a_param, dap_chain_hash_fast_t * a_datum_hash); static void s_cli_meta_hash_print( dap_string_t * a_str_tmp, const char * a_meta_title, dap_chain_block_meta_t * a_meta); static int s_cli_blocks(int a_argc, char ** a_argv, char **a_str_reply); @@ -937,9 +929,6 @@ static dap_chain_atom_iter_t *s_callback_atom_iter_create(dap_chain_t *a_chain, l_atom_iter->chain = a_chain; l_atom_iter->cell_id = a_cell_id; l_atom_iter->with_treshold = a_with_treshold; - l_atom_iter->_inheritor = DAP_NEW_Z(dap_chain_cs_blocks_iter_t); - ITER_PVT(l_atom_iter)->blocks = DAP_CHAIN_CS_BLOCKS(a_chain); - return l_atom_iter; } @@ -958,7 +947,7 @@ static dap_chain_atom_iter_t* s_callback_atom_iter_create_from(dap_chain_t * a_c dap_chain_atom_iter_t * l_atom_iter = s_callback_atom_iter_create(a_chain, a_chain->cells->id, 0); if (l_atom_iter){ dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(a_chain); - l_atom_iter->cur_item = ITER_PVT(l_atom_iter)->cache = dap_chain_block_cs_cache_get_by_hash(l_blocks, &l_atom_hash); + l_atom_iter->cur_item = dap_chain_block_cs_cache_get_by_hash(l_blocks, &l_atom_hash); l_atom_iter->cur = a_atom; l_atom_iter->cur_size = a_atom_size; return l_atom_iter; @@ -979,17 +968,22 @@ static dap_chain_atom_ptr_t s_callback_atom_iter_find_by_hash(dap_chain_atom_ite size_t * a_atom_size) { assert(a_atom_iter); - dap_chain_atom_ptr_t l_ret = NULL; - pthread_rwlock_rdlock(& PVT(ITER_PVT(a_atom_iter)->blocks)->rwlock ); + dap_chain_cs_blocks_pvt_t *l_blocks_pvt = PVT(DAP_CHAIN_CS_BLOCKS(a_atom_iter->chain)); + pthread_rwlock_rdlock(&l_blocks_pvt->rwlock); dap_chain_block_cache_t * l_block_cache = NULL; - HASH_FIND(hh, PVT(ITER_PVT(a_atom_iter)->blocks)->blocks, a_atom_hash,sizeof (*a_atom_hash), l_block_cache); + HASH_FIND(hh, l_blocks_pvt->blocks, a_atom_hash, sizeof(*a_atom_hash), l_block_cache); + pthread_rwlock_unlock(&l_blocks_pvt->rwlock); a_atom_iter->cur_item = l_block_cache; - if (l_block_cache){ - l_ret = a_atom_iter->cur = l_block_cache->block; - *a_atom_size = a_atom_iter->cur_size = l_block_cache->block_size; + if (l_block_cache) { + a_atom_iter->cur = l_block_cache->block; + a_atom_iter->cur_size = l_block_cache->block_size; + } else { + a_atom_iter->cur = NULL; + a_atom_iter->cur_size = 0; } - pthread_rwlock_unlock(& PVT(ITER_PVT(a_atom_iter)->blocks)->rwlock ); - return l_ret; + if (a_atom_size) + *a_atom_size = a_atom_iter->cur_size; + return a_atom_iter->cur; } /** @@ -1041,19 +1035,11 @@ static dap_chain_atom_ptr_t s_callback_atom_iter_get_first( dap_chain_atom_iter_ dap_chain_cs_blocks_t * l_blocks = DAP_CHAIN_CS_BLOCKS(a_atom_iter->chain); dap_chain_cs_blocks_pvt_t *l_blocks_pvt = l_blocks ? PVT(l_blocks) : NULL; assert(l_blocks_pvt); - // a_atom_iter->cur_item = l_blocks_pvt->block_cache_last ; - // a_atom_iter->cur = l_blocks_pvt->block_cache_last ? l_blocks_pvt->block_cache_last->block : NULL ; - // a_atom_iter->cur_size = l_blocks_pvt->block_cache_last ? l_blocks_pvt->block_cache_last->block_size : 0; - // a_atom_iter->cur_hash = l_blocks_pvt->block_cache_last ? &l_blocks_pvt->block_cache_last->block_hash : NULL; - a_atom_iter->cur_item = l_blocks_pvt->block_cache_first; a_atom_iter->cur = l_blocks_pvt->block_cache_first ? l_blocks_pvt->block_cache_first->block : NULL; a_atom_iter->cur_size = l_blocks_pvt->block_cache_first ? l_blocks_pvt->block_cache_first->block_size : 0; a_atom_iter->cur_hash = l_blocks_pvt->block_cache_first ? &l_blocks_pvt->block_cache_first->block_hash : NULL; -// a_atom_iter->cur = a_atom_iter->cur ? -// (dap_chain_cs_dag_event_t*) PVT (DAP_CHAIN_CS_DAG( a_atom_iter->chain) )->events->event : NULL; -// a_atom_iter->cur_item = PVT (DAP_CHAIN_CS_DAG( a_atom_iter->chain) )->events; if (a_atom_size) *a_atom_size = a_atom_iter->cur_size; return a_atom_iter->cur; @@ -1068,8 +1054,8 @@ static dap_chain_atom_ptr_t s_callback_atom_iter_get_first( dap_chain_atom_iter_ static dap_chain_atom_ptr_t s_callback_atom_iter_get_next( dap_chain_atom_iter_t * a_atom_iter,size_t *a_atom_size ) { assert(a_atom_iter); - // assert(a_atom_size); assert(a_atom_iter->cur_item); + dap_chain_block_cache_t * l_cur_cache =(dap_chain_block_cache_t *) a_atom_iter->cur_item; a_atom_iter->cur_item = l_cur_cache = l_cur_cache->next; if (l_cur_cache){ @@ -1127,23 +1113,33 @@ static dap_chain_atom_ptr_t *s_callback_atom_iter_get_links( dap_chain_atom_iter * @param a_lasts_size_ptr * @return */ -static dap_chain_atom_ptr_t *s_callback_atom_iter_get_lasts( dap_chain_atom_iter_t * a_atom_iter ,size_t *a_links_size, size_t ** a_lasts_size_ptr ) +static dap_chain_atom_ptr_t *s_callback_atom_iter_get_lasts( dap_chain_atom_iter_t *a_atom_iter, size_t *a_links_size, size_t **a_lasts_size_ptr) { assert(a_atom_iter); - assert(a_links_size); - assert(a_links_size); - dap_chain_block_cache_t * l_block_cache_last = PVT(ITER_PVT(a_atom_iter)->blocks)->block_cache_last; - if ( l_block_cache_last ){ - *a_links_size = 1; - *a_lasts_size_ptr = DAP_NEW_Z_SIZE(size_t,sizeof (size_t)*1 ); - dap_chain_atom_ptr_t * l_ret = DAP_NEW_Z_SIZE(dap_chain_atom_ptr_t, sizeof (dap_chain_atom_ptr_t)*1); - (*a_lasts_size_ptr)[0] = l_block_cache_last->block_size; + dap_chain_block_cache_t *l_block_cache_last = PVT(DAP_CHAIN_CS_BLOCKS(a_atom_iter->chain))->block_cache_last; + if (l_block_cache_last) { + a_atom_iter->cur = l_block_cache_last->block; + a_atom_iter->cur_size = l_block_cache_last->block_size; + a_atom_iter->cur_hash = &l_block_cache_last->block_hash; + if (a_links_size) + *a_links_size = 1; + if (a_lasts_size_ptr) { + *a_lasts_size_ptr = DAP_NEW_Z(size_t); + (*a_lasts_size_ptr)[0] = l_block_cache_last->block_size; + } + dap_chain_atom_ptr_t *l_ret = DAP_NEW_Z(dap_chain_atom_ptr_t); l_ret[0] = l_block_cache_last->block; return l_ret; - }else{ - return NULL; } + a_atom_iter->cur = NULL; + a_atom_iter->cur_size = 0; + a_atom_iter->cur_hash = NULL; + if (a_links_size) + *a_links_size = 0; + if (a_lasts_size_ptr) + *a_lasts_size_ptr = NULL; + return NULL; } /** @@ -1152,7 +1148,6 @@ static dap_chain_atom_ptr_t *s_callback_atom_iter_get_lasts( dap_chain_atom_iter */ static void s_callback_atom_iter_delete(dap_chain_atom_iter_t * a_atom_iter ) { - DAP_DELETE( ITER_PVT(a_atom_iter)); DAP_DELETE(a_atom_iter); } diff --git a/modules/type/blocks/include/dap_chain_cs_blocks.h b/modules/type/blocks/include/dap_chain_cs_blocks.h index fa654cce8118eee0157ee63ab79a4667b97276fe..e244a7925ec63eacd75b283cc12277c9af2de546 100644 --- a/modules/type/blocks/include/dap_chain_cs_blocks.h +++ b/modules/type/blocks/include/dap_chain_cs_blocks.h @@ -56,7 +56,7 @@ typedef struct dap_chain_cs_blocks void * _inheritor; } dap_chain_cs_blocks_t; -#define DAP_CHAIN_CS_BLOCKS(a) ((dap_chain_cs_blocks_t*) a->_inheritor) +#define DAP_CHAIN_CS_BLOCKS(a) ((dap_chain_cs_blocks_t *)(a)->_inheritor) typedef int (*dap_chain_blocks_block_callback_ptr_t)(dap_chain_cs_blocks_t *, dap_chain_block_t *); int dap_chain_cs_blocks_init();