diff --git a/CMakeLists.txt b/CMakeLists.txt index a60dbe9ae4cf8d5883f933416bb394007726fe5f..5f096702e1a90c309aeba0b5f7e6a00fd316c4e5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,15 +11,15 @@ set(BUILD_CRYPTO_TESTS ON) if(NOT DEFINED ${CELLFRAME_MODULES}) include (cmake/OS_Detection.cmake) if (WIN32) - set(CELLFRAME_MODULES "core chains mining network srv cs-dag-poa cs-block-poa cs-dag-pos cs-block-pos cs-none srv-app srv-app-db srv-datum srv-stake srv-xchange") + 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 srv-xchange") elseif(BSD) - set(CELLFRAME_MODULES "core chains mining network srv cs-dag-poa cs-block-poa cs-dag-pos cs-block-pos cs-none srv-app srv-app-db srv-datum srv-stake srv-xchange") + 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 srv-xchange") elseif(DARWIN) - set(CELLFRAME_MODULES "core chains mining network srv cs-dag-poa cs-block-poa cs-dag-pos cs-block-pos cs-none srv-app srv-app-db srv-datum srv-stake srv-xchange") + 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 srv-xchange") elseif(ANDROID) - set(CELLFRAME_MODULES "core chains mining network srv cs-dag-poa cs-block-poa cs-dag-pos cs-block-pos cs-none srv-app srv-app-db srv-datum srv-stake srv-xchange") + 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 srv-xchange") elseif(LINUX) - set(CELLFRAME_MODULES "core chains mining network srv cs-dag-poa cs-block-poa cs-dag-pos cs-block-pos cs-none srv-app srv-app-db srv-datum srv-stake srv-xchange modules-dynamic srv-vpn") + 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 srv-xchange modules-dynamic srv-vpn") endif() endif() @@ -28,15 +28,15 @@ set(DAPSDK_MODULES "") if(NOT DEFINED ${CELLFRAME_MODULES}) include (cmake/OS_Detection.cmake) if (WIN32) - set(CELLFRAME_MODULES "core chains mining network srv cs-dag-poa cs-block-poa cs-dag-pos cs-block-pos cs-none srv-app srv-app-db srv-datum srv-stake srv-xchange") + 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 srv-xchange") elseif(BSD) - set(CELLFRAME_MODULES "core chains mining network srv cs-dag-poa cs-block-poa cs-dag-pos cs-block-pos cs-none srv-app srv-app-db srv-datum srv-stake srv-xchange") + 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 srv-xchange") elseif(DARWIN) - set(CELLFRAME_MODULES "core chains mining network srv cs-dag-poa cs-block-poa cs-dag-pos cs-block-pos cs-none srv-app srv-app-db srv-datum srv-stake srv-xchange") + 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 srv-xchange") elseif(ANDROID) - set(CELLFRAME_MODULES "core chains mining network srv cs-dag-poa cs-block-poa cs-dag-pos cs-block-pos cs-none srv-app srv-app-db srv-datum srv-stake srv-xchange") + 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 srv-xchange") elseif(LINUX) - set(CELLFRAME_MODULES "core chains mining network srv cs-dag-poa cs-block-poa cs-dag-pos cs-block-pos cs-none srv-app srv-app-db srv-datum srv-stake srv-xchange modules-dynamic srv-vpn") + 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 srv-xchange modules-dynamic srv-vpn") endif() endif() @@ -165,10 +165,16 @@ if (CELLFRAME_MODULES MATCHES "cs-block-pos") set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_chain_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) +endif() + # PoW consensus for blocks if (CELLFRAME_MODULES MATCHES "cs-block-pow") message("[+] Module 'cs-block-pow'") - set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_chain_cs_block_pos) + set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_chain_cs_block_pow) endif() diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt index 7554b3e25b719e7be01547e4afc4e245549af3bf..ef1bd8dca8d8b76f7ecd38bc864cdaa498884161 100644 --- a/modules/CMakeLists.txt +++ b/modules/CMakeLists.txt @@ -68,6 +68,11 @@ if (CELLFRAME_MODULES MATCHES "cs-block-pos") add_subdirectory(consensus/block-pos) endif() +# Block TON +if (CELLFRAME_MODULES MATCHES "cs-block-ton") + add_subdirectory(consensus/block-ton) +endif() + # Block PoW if (CELLFRAME_MODULES MATCHES "cs-block-pow") add_subdirectory(consensus/block-pow) 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 46c2fa71d5957f37732974d73df4614d3ce7fa54..92be6c67b29c2b3a793f47a5ff62b0572b3121e3 100644 --- a/modules/channel/chain-voting/dap_stream_ch_chain_voting.c +++ b/modules/channel/chain-voting/dap_stream_ch_chain_voting.c @@ -20,7 +20,6 @@ typedef struct voting_pkt_in_callback{ voting_ch_callback_t packet_in_callback; } voting_pkt_in_callback_t; -// буфер раÑÑылки по клиентам typedef struct voting_pkt_addr { //dap_client_t *client; @@ -29,7 +28,6 @@ typedef struct voting_pkt_addr dap_stream_ch_chain_voting_pkt_t *voting_pkt; } voting_pkt_addr_t; -// буфер раÑÑылки typedef struct voting_pkt_items { //size_t count; @@ -41,9 +39,17 @@ typedef struct voting_pkt_items // dap_timerfd_t * timer_in; } voting_pkt_items_t; +typedef struct voting_node_client_list { + 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; +} DAP_ALIGN_PACKED 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(dap_chain_node_addr_t *a_remote_node_addr); static void s_callback_send_all_unsafe(dap_client_t *a_client, void *a_arg); @@ -53,10 +59,12 @@ static void s_callback_channel_pkt_free_unsafe(uint64_t node_addr_uint64); 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 bool s_packet_in_callback_handler(); +static bool s_packet_in_callback_handler(void); 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 dap_timerfd_t * s_packet_in_callback_timer = NULL; + //static int s_cli_voting(int argc, char ** argv, char **a_str_reply); int dap_stream_ch_chain_voting_init() { @@ -75,9 +83,14 @@ int dap_stream_ch_chain_voting_init() { s_stream_ch_delete, s_stream_ch_packet_in, s_stream_ch_packet_out); -//dap_chain_node_cli_cmd_item_create("voting", s_cli_voting, "Voting commands", "send"); - s_packet_in_callback_handler(); + if (!s_packet_in_callback_timer) { + s_packet_in_callback_timer = dap_timerfd_start(1*1000, + (dap_timerfd_callback_t)s_packet_in_callback_handler, + NULL); + } + + // s_packet_in_callback_handler(); return 0; } @@ -88,40 +101,24 @@ void dap_stream_ch_chain_voting_in_callback_add(void* a_arg, voting_ch_callback_ s_pkt_in_callback_count++; } -// static int s_cli_voting(int argc, char ** argv, char **a_str_reply) { -// int arg_index = 1; -// const char * l_net_name = NULL; -// dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-net", &l_net_name); -// if ( l_net_name == NULL){ -// dap_chain_node_cli_set_reply_text(a_str_reply, "Need -net <net name> param!"); -// return -1; -// } -// dap_chain_net_t * l_net = dap_chain_net_by_name( l_net_name ); - -// char *l_pkg = "test_V_REQ"; -// dap_stream_ch_chain_voting_message_write(l_net, l_pkg, 10); -// } - 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){ pthread_rwlock_rdlock(&s_pkt_items->rwlock_out); 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_Z_SIZE(dap_stream_ch_chain_voting_pkt_t, l_voting_pkt_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; - //dap_hash_fast(a_data, a_data_size, &l_voting_pkt->hdr.data_hash); 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) + if (a_data_size && a_data) { memcpy( l_voting_pkt->data, a_data, a_data_size); + } voting_pkt_addr_t * l_pkt_addr = DAP_NEW_Z(voting_pkt_addr_t); - // l_pkt_addr->client = NULL; l_pkt_addr->node_addr.uint64 = 0; l_pkt_addr->voting_pkt = l_voting_pkt; - //s_pkt_items->count++; s_pkt_items->pkts_out = dap_list_append(s_pkt_items->pkts_out, l_pkt_addr); pthread_rwlock_unlock(&s_pkt_items->rwlock_out); @@ -134,17 +131,14 @@ static void s_callback_channel_pkt_free_unsafe(uint64_t node_addr_uint64) { return; dap_list_t* l_first_list = dap_list_first(s_pkt_items->pkts_out); - dap_list_t* l_next_list; - while( true ) { - l_next_list=dap_list_next(l_first_list); + + while( l_first_list ) { + dap_list_t *l_next_list = l_first_list->next; voting_pkt_addr_t * l_pkt_addr = l_first_list->data; if ( l_pkt_addr->node_addr.uint64 == node_addr_uint64) { DAP_DELETE(l_pkt_addr->voting_pkt); DAP_DELETE(l_pkt_addr); - s_pkt_items->pkts_out = l_first_list = dap_list_remove_link(s_pkt_items->pkts_out, l_first_list); - } - if( !l_next_list ) { - break; + s_pkt_items->pkts_out = dap_list_remove_link(s_pkt_items->pkts_out, l_first_list); } l_first_list = l_next_list; } @@ -155,51 +149,65 @@ void dap_stream_ch_chain_voting_pkt_broadcast(dap_chain_net_t * a_net, dap_list_ //if (dap_chain_net_get_state(a_net) == NET_STATE_ONLINE) { pthread_rwlock_rdlock(&s_pkt_items->rwlock_out); - // dap_list_t *l_node_list = dap_chain_net_get_node_list(a_net); - //size_t l_nodes_count = dap_list_length(a_sendto_nodes); - - //size_t l_pkts_count = dap_list_length(s_pkt_items->pkts_out); - - dap_list_t* l_nodes_list = dap_list_first(a_sendto_nodes); - while(l_nodes_list) { - dap_list_t *l_nodes_list_next = l_nodes_list->next; + 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; - //for (int i=0; i<l_nodes_count; i++) { - //dap_list_t *l_tmp_list = dap_list_nth(a_sendto_nodes, i); - dap_chain_node_client_t *l_node_client; + + voting_node_client_list_t *l_node_item = NULL; if ( l_remote_node_addr->uint64 != dap_chain_net_get_cur_addr_int(a_net) ) { - char *l_key = dap_chain_node_addr_to_hash_str(l_remote_node_addr); - size_t node_info_size = 0; - dap_chain_node_info_t *l_node_info = + HASH_FIND(hh, s_node_client_list, l_remote_node_addr, sizeof(dap_chain_node_addr_t), l_node_item); + if ( l_node_item + && l_node_item->node_client + && !dap_client_get_stream(l_node_item->node_client->client) ) { + dap_chain_node_client_close(l_node_item->node_client); + // DAP_DELETE(l_node_item->node_client); + char l_channels[] = {dap_stream_ch_chain_voting_get_id(),0}; + l_node_item->node_client = dap_chain_node_client_connect_channels(a_net, l_node_item->node_info, l_channels); + } + + if (!l_node_item) { + 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_chain_global_db_gr_get(l_key, &node_info_size, a_net->pub.gdb_nodes); - //dap_chain_node_client_t *l_node_client = dap_chain_node_client_connect(a_net, l_node_info); - char l_channels[] = {dap_stream_ch_chain_voting_get_id(),0}; - l_node_client = dap_chain_node_client_connect_channels(a_net, l_node_info, l_channels); - // if ( l_node_client->remote_node_addr.uint64 == dap_chain_net_get_cur_addr_int(a_net) ) - // continue; - - if (!l_node_client) - continue; - - dap_client_pvt_t * l_client_pvt = dap_client_pvt_find(l_node_client->client->pvt_uuid); + DAP_DELETE(l_key); + if (!l_node_info) { + continue; + } + voting_node_client_list_t *l_node_client_item = DAP_NEW_Z(voting_node_client_list_t); + l_node_client_item->node_info = NULL; + l_node_client_item->node_client = NULL; + memcpy(&l_node_client_item->node_addr, l_remote_node_addr, sizeof(dap_chain_node_addr_t)); + + 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); + // DAP_DELETE(l_node_info); + if (!l_node_client) { + continue; + } + 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; + } + dap_client_pvt_t * l_client_pvt = dap_client_pvt_find(l_node_item->node_client->client->pvt_uuid); if (NULL == l_client_pvt) { continue; } } - //for (int i=0; i<l_pkts_count; i++) { - // voting_pkt_addr_t * l_pkt_addr = ((dap_list_t *)dap_list_nth(s_pkt_items->pkts_out, i))->data; - dap_list_t* l_pkts_list = dap_list_first(s_pkt_items->pkts_out); - while(l_pkts_list) { - dap_list_t *l_pkts_list_next = l_pkts_list->next; + dap_list_t* l_pkts_list_temp = dap_list_first(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->client) { if (!l_pkt_addr->node_addr.uint64) { voting_pkt_addr_t * l_pkt_addr_new = DAP_NEW_Z(voting_pkt_addr_t); l_pkt_addr_new->node_addr.uint64 = l_remote_node_addr->uint64; - //l_pkt_addr_new->client = l_node_client->client; - //l_pkt_addr_new->voting_pkt = l_pkt_addr->voting_pkt; 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)); memcpy(&l_pkt_addr_new->voting_pkt->hdr.sender_node_addr, @@ -208,16 +216,13 @@ void dap_stream_ch_chain_voting_pkt_broadcast(dap_chain_net_t * a_net, dap_list_ l_remote_node_addr, sizeof(dap_chain_node_addr_t)); s_pkt_items->pkts_out = dap_list_append(s_pkt_items->pkts_out, l_pkt_addr_new); } - l_pkts_list = l_pkts_list_next; } if ( l_remote_node_addr->uint64 != dap_chain_net_get_cur_addr_int(a_net) ) { - // dap_worker_exec_callback_on(l_client_pvt->worker, s_callback_channel_go_stage, l_client_pvt); - dap_client_go_stage(l_node_client->client, STAGE_STREAM_STREAMING, s_callback_send_all_unsafe); + dap_client_go_stage(l_node_item->node_client->client, STAGE_STREAM_STREAMING, s_callback_send_all_unsafe); } else { s_callback_send_all_loopback(l_remote_node_addr); } - l_nodes_list = l_nodes_list_next; } s_callback_channel_pkt_free_unsafe(0); @@ -250,12 +255,9 @@ static void s_callback_send_all_unsafe(dap_client_t *a_client, void *a_arg){ dap_chain_node_client_t *l_node_client = DAP_CHAIN_NODE_CLIENT(a_client); if (l_node_client) { dap_stream_ch_t * l_ch_chain = dap_client_get_stream_ch_unsafe(a_client, dap_stream_ch_chain_voting_get_id() ); - // size_t l_pkts_count = dap_list_length(s_pkt_items->pkts_out); - // for (int i=0; i<l_pkts_count; i++) { dap_list_t* l_pkts_list = dap_list_first(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 *)dap_list_nth(s_pkt_items->pkts_out, i)->data); 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; @@ -277,7 +279,12 @@ static void s_callback_send_all_unsafe(dap_client_t *a_client, void *a_arg){ void dap_stream_ch_chain_voting_deinit() { - + voting_node_client_list_t *l_node_info_item=NULL, *l_node_info_tmp=NULL; + HASH_ITER(hh, s_node_client_list, l_node_info_item, l_node_info_tmp) { + HASH_DEL(s_node_client_list, l_node_info_item); + DAP_DELETE(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) { @@ -288,14 +295,11 @@ 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) { - //dap_proc_queue_add_callback_inter(a_ch->stream_worker->worker->proc_queue_input,s_stream_ch_delete_in_proc,a_ch->internal ); a_ch->internal = NULL; // To prevent its cleaning in worker } -static bool s_packet_in_callback_handler() { - +static bool s_packet_in_callback_handler(void) { if (dap_list_length(s_pkt_items->pkts_in)) { - pthread_rwlock_rdlock(&s_pkt_items->rwlock_in); dap_list_t* l_list_pkts = dap_list_copy(s_pkt_items->pkts_in); dap_list_free(s_pkt_items->pkts_in); @@ -304,14 +308,11 @@ static bool s_packet_in_callback_handler() { dap_list_t* l_list_temp = dap_list_first(l_list_pkts); while(l_list_temp) { - //for (int i=0; i<l_pkts_count; i++) { - //dap_list_t *l_tmp = dap_list_nth(l_list_pkts, i); dap_list_t *l_list_next = l_list_temp->next; dap_stream_ch_chain_voting_pkt_t * l_voting_pkt = (dap_stream_ch_chain_voting_pkt_t *)l_list_temp->data; for (int 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) { - // void*,dap_chain_node_addr_t*,dap_chain_hash_fast_t*,void*,size_t dap_chain_node_addr_t *l_sender_node_addr = DAP_NEW(dap_chain_node_addr_t); memcpy(l_sender_node_addr, &l_voting_pkt->hdr.sender_node_addr, sizeof(dap_chain_node_addr_t)); @@ -322,6 +323,9 @@ static bool s_packet_in_callback_handler() { memcpy(l_data, &l_voting_pkt->data, l_voting_pkt->hdr.data_size); l_callback->packet_in_callback(l_callback->arg, l_sender_node_addr, l_data_hash, l_data, l_voting_pkt->hdr.data_size); + DAP_DELETE(l_sender_node_addr); + DAP_DELETE(l_data_hash); + DAP_DELETE(l_data); } } l_list_temp = l_list_next; @@ -329,10 +333,7 @@ static bool s_packet_in_callback_handler() { } dap_list_free(l_list_pkts); } - dap_timerfd_start(1000, - (dap_timerfd_callback_t)s_packet_in_callback_handler, - NULL); - return false; + return true; } @@ -340,7 +341,6 @@ 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; pthread_rwlock_rdlock(&s_pkt_items->rwlock_in); uint32_t l_voting_pkt_size = l_ch_pkt->hdr.size; - // dap_stream_ch_chain_voting_pkt_t * l_voting_pkt = (dap_stream_ch_chain_voting_pkt_t *)&l_ch_pkt->data; dap_stream_ch_chain_voting_pkt_t * l_voting_pkt = DAP_NEW_SIZE(dap_stream_ch_chain_voting_pkt_t, l_voting_pkt_size); memcpy(l_voting_pkt, &l_ch_pkt->data, l_voting_pkt_size); s_pkt_items->pkts_in = dap_list_append(s_pkt_items->pkts_in, l_voting_pkt); @@ -349,31 +349,9 @@ 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) { UNUSED(a_arg); - // test_send((void *)a_ch); - //char *l_pkg = "test_VS"; - //size_t l_ret = dap_stream_ch_pkt_write_unsafe(a_ch, 0x11 , l_pkg, 7); } -// 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 * 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.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_mt(a_worker, a_ch_uuid, a_type , l_chain_pkt, l_chain_pkt_size); -// DAP_DELETE(l_chain_pkt); -// return l_ret; -// } - - 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/consensus/block-pos/dap_chain_cs_block_pos.c b/modules/consensus/block-pos/dap_chain_cs_block_pos.c index d110de4c1d92ada770a75a5dba34752fb6a38f29..2d25331b5acfeb651077af67145fec394a3d41fb 100644 --- a/modules/consensus/block-pos/dap_chain_cs_block_pos.c +++ b/modules/consensus/block-pos/dap_chain_cs_block_pos.c @@ -29,7 +29,7 @@ #include "dap_strfuncs.h" #include "dap_chain_cs.h" #include "dap_chain_cs_blocks.h" -#include "dap_chain_cs_blocks_session.h" +// #include "dap_chain_cs_blocks_session.h" #include "dap_chain_cs_block_pos.h" #include "dap_chain_net_srv_stake.h" #include "dap_chain_ledger.h" @@ -160,7 +160,7 @@ static int s_callback_created(dap_chain_t *a_chain, dap_config_t *a_chain_net_cf } else { log_it(L_ERROR, "No sign certificate provided, can't sign any blocks"); } - dap_chain_cs_blocks_session_init(a_chain, PVT(l_pos)->blocks_sign_key ); + //dap_chain_cs_blocks_session_init(a_chain, PVT(l_pos)->blocks_sign_key ); return 0; } diff --git a/modules/consensus/block-ton/CMakeLists.txt b/modules/consensus/block-ton/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..5f76c80777aa8a81b1eec4e7f9bb2863306a832e --- /dev/null +++ b/modules/consensus/block-ton/CMakeLists.txt @@ -0,0 +1,11 @@ +cmake_minimum_required(VERSION 3.10) +project (dap_chain_cs_block_ton) + +file(GLOB DAP_CHAIN_CS_BLOCK_TON_SRCS *.c) +file(GLOB DAP_CHAIN_CS_BLOCK_TON_HEADERS include/*.h) + +add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_CS_BLOCK_TON_SRCS} ${DAP_CHAIN_CS_BLOCK_TON_HEADERS}) + +target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_chain dap_chain_cs_blocks dap_chain_net_srv_stake dap_stream_ch_chain_voting) +target_include_directories(${PROJECT_NAME} INTERFACE .) +target_include_directories(${PROJECT_NAME} PUBLIC include) diff --git a/modules/consensus/block-ton/dap_chain_cs_block_ton.c b/modules/consensus/block-ton/dap_chain_cs_block_ton.c new file mode 100644 index 0000000000000000000000000000000000000000..127bb8c16b91940e6adc143e11d401072a094713 --- /dev/null +++ b/modules/consensus/block-ton/dap_chain_cs_block_ton.c @@ -0,0 +1,1827 @@ + +#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.h" +#include "dap_chain_ledger.h" + +#define LOG_TAG "dap_chain_cs_blocks_ton" + +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_items_t *a_session, dap_chain_hash_fast_t *a_candidate_hash, + dap_chain_block_t *a_candidate, size_t a_candidate_size); +static bool s_session_candidate_submit(dap_chain_cs_block_ton_items_t *a_session); +static bool s_session_timer(); +static int s_session_datums_validation(dap_chain_cs_blocks_t *a_blocks, dap_chain_block_t *a_block, size_t a_block_size); + +static void s_message_send(dap_chain_cs_block_ton_items_t * a_session, + uint8_t a_message_type, uint8_t *a_data, size_t a_data_size); +static void s_message_chain_add(dap_chain_cs_block_ton_items_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_start(dap_chain_cs_block_ton_items_t *a_session); +static void s_session_block_new_delete(dap_chain_cs_block_ton_items_t *a_sessio); +static bool s_session_round_finish(dap_chain_cs_block_ton_items_t *a_session); + +static dap_chain_node_addr_t * s_session_get_validator_by_addr( + dap_chain_cs_block_ton_items_t * a_session, dap_chain_node_addr_t * a_addr); +static int s_callback_new(dap_chain_t *a_chain, dap_config_t *a_chain_cfg); +static void s_callback_delete(dap_chain_cs_blocks_t *a_blocks); +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_t *a_chain); + +static bool s_hash_is_null(dap_chain_hash_fast_t *a_hash); + +static dap_chain_cs_block_ton_items_t * s_session_items; +static dap_timerfd_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; + + bool debug; + bool validators_list_by_stake; + uint16_t round_start_sync_timeout; + 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; +} 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_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->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->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", 10); + l_ton_pvt->first_message_delay = dap_config_get_item_uint16_default(a_chain_cfg,"block-ton", "first_message_delay", 3); + + 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_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_t *a_chain) { + + 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); + 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_chain->net_id); + l_ret = dap_chain_net_get_node_list(l_net); + 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_NOTICE, "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_cs_block_ton_items_t *l_session = DAP_NEW_Z(dap_chain_cs_block_ton_items_t); + + dap_chain_net_t *l_net = dap_chain_net_by_id(a_chain->net_id); + + l_session->debug = l_ton_pvt->debug; + l_session->round_start_sync_timeout = l_ton_pvt->round_start_sync_timeout; + l_session->consensus_start_period = 20; // hint: if((time()/10) % consensus_start)==0 + l_session->allowed_clock_offset = l_ton_pvt->allowed_clock_offset; + l_session->session_idle_min = l_ton_pvt->session_idle_min; + l_session->round_candidates_max = l_ton_pvt->round_candidates_max; + l_session->next_candidate_delay = l_ton_pvt->next_candidate_delay; + l_session->round_attempts_max = l_ton_pvt->round_attempts_max; + l_session->round_attempt_duration = l_ton_pvt->round_attempt_duration; + l_session->first_message_delay = l_ton_pvt->first_message_delay; + + l_session->cur_round.validators_list = s_get_validators_addr_list(a_chain); + 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 = 0; + l_session->old_round.id.uint64 = 0; + 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->chain = a_chain; + l_session->state = DAP_STREAM_CH_CHAIN_SESSION_STATE_IDLE; + l_session->blocks_sign_key = PVT(l_ton)->blocks_sign_key; + l_session->time_proc_lock = false; + + dap_chain_time_t l_time = (dap_chain_time_t)time(NULL); + while (true) { + l_time++; + if ( (l_time % l_session->consensus_start_period) == 0) { + l_session->ts_round_sync_start = l_time; + break; + } + } + pthread_rwlock_init(&l_session->rwlock, NULL); + + log_it(L_NOTICE, "TON: init session for net:%s, chain:%s", a_chain->net_name, a_chain->name); + DL_APPEND(s_session_items, l_session); + if ( s_session_get_validator_by_addr(l_session, l_session->my_addr) ) { + if (!s_session_cs_timer) { + s_session_cs_timer = dap_timerfd_start(1*1000, + (dap_timerfd_callback_t)s_session_timer, + NULL); + if (l_session->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; +} + +static void s_session_round_start(dap_chain_cs_block_ton_items_t *a_session) { + + a_session->cur_round.validators_start = NULL; + a_session->cur_round.validators_start_count = 0; + + a_session->cur_round.validators_list = NULL; + a_session->cur_round.validators_count = 0; + + a_session->ts_round_start = 0; + a_session->ts_round_state_commit = 0; + a_session->attempt_current_number = 1; + + a_session->cur_round.my_candidate_hash = NULL; + a_session->cur_round.last_message_hash = NULL; + a_session->cur_round.messages_count = 0; + a_session->cur_round.submit = false; + + a_session->ts_round_sync_start = (dap_chain_time_t)time(NULL); + a_session->cur_round.id.uint64++; +} + +static bool s_session_send_startsync(dap_chain_cs_block_ton_items_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)); + if (a_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu 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_items_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_items_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)); + DAP_DELETE(l_votefor); + DAP_DELETE(a_data); + return false; +} + +static bool s_session_timer() { + dap_chain_time_t l_time = (dap_chain_time_t)time(NULL); + dap_chain_cs_block_ton_items_t *l_session = NULL; + DL_FOREACH(s_session_items, l_session) { + if ( l_session->time_proc_lock ) { + continue; + } + pthread_rwlock_rdlock(&l_session->rwlock); + l_session->time_proc_lock = true; // lock - skip check by reasons: prev check is not finish + switch (l_session->state) { + case DAP_STREAM_CH_CHAIN_SESSION_STATE_IDLE: { + if ( (((l_time/10)*10) % l_session->consensus_start_period) == 0 + && (l_time - ((l_time/10)*10)) <= 3 + && l_time > l_session->ts_round_finish + && (l_time-l_session->ts_round_finish) >= l_session->session_idle_min) { + + // round start + l_session->state = DAP_STREAM_CH_CHAIN_SESSION_STATE_WAIT_START; + s_session_round_start(l_session); + + l_session->cur_round.validators_list = s_get_validators_addr_list(l_session->chain); + l_session->cur_round.validators_count = dap_list_length(l_session->cur_round.validators_list); + + dap_timerfd_start(l_session->first_message_delay*1000, + (dap_timerfd_callback_t)s_session_send_startsync, + l_session); + + if (l_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu, attempt:%hu Start syncing validators ", + l_session->chain->net_name, l_session->chain->name, + l_session->cur_round.id.uint64, l_session->attempt_current_number); + } + goto session_unlock; + } //break; + case DAP_STREAM_CH_CHAIN_SESSION_STATE_WAIT_START: { + if ( (l_time-l_session->ts_round_sync_start) >= l_session->round_start_sync_timeout ) { // timeout start sync + uint16_t l_startsync_count = l_session->cur_round.validators_start_count; + if ( ((float)l_startsync_count/l_session->cur_round.validators_count) >= ((float)2/3) ) { + // if sync more 2/3 validators then start round and submit candidate + if (l_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu, attempt:%hu More than 2/3 of the validators are synchronized, so starting the round and send the candidate", + l_session->chain->net_name, l_session->chain->name, + l_session->cur_round.id.uint64, l_session->attempt_current_number); + + l_session->ts_round_start = l_time; + l_session->state = DAP_STREAM_CH_CHAIN_SESSION_STATE_CS_PROC; + + // sort validators list + dap_list_t *l_validators_start = l_session->cur_round.validators_start; + l_session->cur_round.validators_start = NULL; + dap_list_t *l_validators_list_temp = dap_list_first(l_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 ) { + l_session->cur_round.validators_start = + dap_list_append(l_session->cur_round.validators_start, l_validator_1); + } + } + } + + // first coordinator + l_session->attempt_coordinator = + (dap_chain_node_addr_t *)(dap_list_first(l_session->cur_round.validators_start)->data); + } else { + s_session_round_finish(l_session); + if (l_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu, attempt:%hu Round finish by reason: can't synchronized 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); + } + } + goto session_unlock; + } //break; + case DAP_STREAM_CH_CHAIN_SESSION_STATE_WAIT_SIGNS: + case DAP_STREAM_CH_CHAIN_SESSION_STATE_CS_PROC: { + if ( !l_session->cur_round.submit && l_session->attempt_current_number == 1 ) { + dap_list_t *l_validators_list = dap_list_first(l_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 == l_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-l_session->ts_round_start) + >= ((l_session->next_candidate_delay*l_my_number)+l_session->first_message_delay) ) { + l_session->cur_round.submit = true; + s_session_candidate_submit(l_session); + } + } + } + + if ( (l_time-l_session->ts_round_start) + >= (l_session->round_attempt_duration*l_session->attempt_current_number) ) { + l_session->attempt_current_number++; + if ( l_session->attempt_current_number > l_session->round_attempts_max ) { + s_session_round_finish(l_session); // attempts is out + if (l_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu, attempt:%hu Round finish by reason: attempts is out", + l_session->chain->net_name, l_session->chain->name, + l_session->cur_round.id.uint64, l_session->attempt_current_number); + goto session_unlock; + } + if ( l_session->state == DAP_STREAM_CH_CHAIN_SESSION_STATE_WAIT_SIGNS ) { + goto session_unlock; + } + + uint16_t l_validators_count = l_session->cur_round.validators_start_count; + uint16_t l_validators_index = + ( (l_session->attempt_current_number-2) + - (l_validators_count + *((l_session->attempt_current_number-2)/l_validators_count))); + + l_session->attempt_coordinator = (dap_chain_node_addr_t *) + (dap_list_nth(l_session->cur_round.validators_start, + l_validators_index)->data); + if (l_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu, attempt:%hu Start attempt: selected coordinator "NODE_ADDR_FP_STR"(index:%u)", + l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, + l_session->attempt_current_number, NODE_ADDR_FP_ARGS(l_session->attempt_coordinator), + l_validators_index); + + if ( l_session->my_addr->uint64 == l_session->attempt_coordinator->uint64 ) { + // I coordinator :-) select candidate + dap_list_t *l_list_candidate = NULL; + size_t l_objs_size = 0; + dap_global_db_obj_t *l_objs = dap_chain_global_db_gr_load(l_session->gdb_group_store, &l_objs_size); + if (l_objs_size) { + for (size_t i = 0; i < l_objs_size; i++) { + if (!l_objs[i].value_len) + continue; + + dap_chain_cs_block_ton_store_t *l_store = + (dap_chain_cs_block_ton_store_t *)l_objs[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(l_objs[i].key, l_hash); + l_list_candidate = dap_list_append(l_list_candidate, l_hash); + } + } + dap_chain_global_db_objs_delete(l_objs, l_objs_size); + } + 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)); + memcpy(&l_votefor->candidate_hash, l_candidate_hash, sizeof(dap_chain_hash_fast_t)); + dap_list_free_full(l_list_candidate, free); + } + else { + dap_chain_hash_fast_t l_candidate_hash_null={0}; + memcpy(&l_votefor->candidate_hash, &l_candidate_hash_null, sizeof(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(l_session->first_message_delay*1000, // pause before send votefor + (dap_timerfd_callback_t)s_session_send_votefor, + l_data); + if (l_session->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:%llu, 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); + } + } + } + goto session_unlock; + } + } +session_unlock: + l_session->time_proc_lock = false; // unlock + pthread_rwlock_unlock(&l_session->rwlock); + } + return true; +} + +static void s_session_candidate_to_chain( + dap_chain_cs_block_ton_items_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_cs_block_ton_message_item_t *l_message_item=NULL, *l_message_tmp=NULL; + HASH_ITER(hh, a_session->old_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 ) { + dap_chain_hash_fast_t *l_candidate_hash = + &((dap_chain_cs_block_ton_message_commitsign_t *)l_message_item->message->message)->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); + } + } + } + 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->old_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->message; + 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 ( ((float)l_signs_count/a_session->old_round.validators_count) >= ((float)2/3) ) { + // delete my new block if it passed consensus + char *l_candidate_hash_str = dap_chain_hash_fast_to_str_new(a_candidate_hash); + // 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 add block %s to the file", l_candidate_hash_str); + } + else { + log_it(L_NOTICE, "TON: Block %s added in chain successfully", l_candidate_hash_str); + } + DAP_DELETE(l_candidate_hash_str); + } + DAP_DELETE(l_candidate); +} + +static bool s_session_candidate_submit(dap_chain_cs_block_ton_items_t *a_session){ + dap_chain_t *l_chain = a_session->chain; + dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(l_chain); + + size_t l_submit_size = l_blocks->block_new ? + sizeof(dap_chain_cs_block_ton_message_submit_t)+l_blocks->block_new_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 = l_blocks->block_new_size; + + if (l_blocks->block_new) { // exists my candidate + dap_chain_hash_fast_t l_candidate_hash; + dap_hash_fast(l_blocks->block_new, l_blocks->block_new_size, &l_candidate_hash); + memcpy(&l_submit->candidate_hash, &l_candidate_hash, sizeof(dap_chain_hash_fast_t)); + a_session->cur_round.my_candidate_hash = + (dap_chain_hash_fast_t*)DAP_DUP_SIZE(&l_candidate_hash, sizeof(dap_chain_hash_fast_t)); + memcpy(l_submit->candidate, l_blocks->block_new, l_blocks->block_new_size); + if (a_session->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:%llu 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); + } + } + else { // no my candidate, send null hash + dap_chain_hash_fast_t l_candidate_hash_null={0}; + a_session->cur_round.my_candidate_hash = NULL; + memcpy(&l_submit->candidate_hash, &l_candidate_hash_null, sizeof(dap_chain_hash_fast_t)); + if (a_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu, 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); + DAP_DELETE(l_submit); + + // DAP_DELETE(l_blocks->block_new); + // l_blocks->block_new = NULL; + // l_blocks->block_new_size = 0; + return false; // for timer +} + + +static int s_session_datums_validation(dap_chain_cs_blocks_t *a_blocks, dap_chain_block_t *a_block, size_t a_block_size){ + size_t l_datums_count = 0; + dap_chain_datum_t **l_datums = dap_chain_block_get_datums(a_block, a_block_size, &l_datums_count); + + if (!l_datums || !l_datums_count) { + return -2; + } + + for(size_t i=0; i<l_datums_count; i++){ + dap_chain_datum_t *l_datum = l_datums[i]; + switch (l_datum->header.type_id) { + case DAP_CHAIN_DATUM_TX: { + dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t*) l_datum->data; + int ret = dap_chain_ledger_tx_add_check(a_blocks->chain->ledger, l_tx); + if (ret != 0) { + return -1; + } + } + } + } + return 0; +} + +static void s_session_block_new_delete(dap_chain_cs_block_ton_items_t *a_session) { + dap_chain_t *l_chain = a_session->chain; + dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(l_chain); + if ( l_blocks->block_new ) { + DAP_DEL_Z(l_blocks->block_new); + l_blocks->block_new_size = 0; + } +} + +static bool s_hash_is_null(dap_chain_hash_fast_t *a_hash){ + if (!a_hash) + return true; + dap_chain_hash_fast_t l_candidate_hash_null={0}; + return (memcmp(&l_candidate_hash_null, a_hash, + sizeof(dap_chain_hash_fast_t)) == 0) + ? true : false; +} + +static bool s_session_round_finish(dap_chain_cs_block_ton_items_t *a_session) { + + a_session->state = DAP_STREAM_CH_CHAIN_SESSION_STATE_IDLE; + a_session->ts_round_finish = (dap_chain_time_t)time(NULL); + + size_t l_objs_size = 0; + dap_global_db_obj_t *l_objs = dap_chain_global_db_gr_load(a_session->gdb_group_store, &l_objs_size); + if (l_objs_size) { + dap_chain_cs_block_ton_store_t *l_store_candidate_ready = NULL; + size_t l_candidate_ready_size = 0; + for (size_t i = 0; i < l_objs_size; i++) { + if (!l_objs[i].value_len) + continue; + dap_chain_cs_block_ton_store_t *l_store = + (dap_chain_cs_block_ton_store_t *)l_objs[i].value; + if ( l_store->hdr.round_id.uint64 != a_session->cur_round.id.uint64 + || (l_store->hdr.round_id.uint64 == a_session->cur_round.id.uint64 + && !l_store->hdr.sign_collected) ) { + dap_chain_global_db_gr_del(dap_strdup(l_objs[i].key), a_session->gdb_group_store); + if ( l_store->hdr.sign_collected ) { + l_store_candidate_ready = l_store; + } + } + + if ( l_store->hdr.round_id.uint64 == a_session->cur_round.id.uint64 ) { + if ( a_session->cur_round.my_candidate_hash + //&& !l_store->hdr.approve_collected + && memcmp(&l_store->hdr.candidate_hash, + a_session->cur_round.my_candidate_hash, sizeof(dap_chain_hash_fast_t)) == 0) { + + // delete my candidate if it passed consensus or not collected 2/3 approve + if ( !l_store->hdr.approve_collected || l_store->hdr.sign_collected ) { + s_session_block_new_delete(a_session); + DAP_DELETE(a_session->cur_round.my_candidate_hash); + a_session->cur_round.my_candidate_hash=NULL; + if (a_session->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:%llu, attempt:%hu My candidate:%s %s Delete block_new.", + a_session->chain->net_name, a_session->chain->name, a_session->cur_round.id.uint64, + a_session->attempt_current_number, l_hash_str, + (l_store->hdr.sign_collected ? "passed consensus!" : "didn't collected 2/3 approve.") ); + DAP_DELETE(l_hash_str); + } + } + } + } + } + if (l_store_candidate_ready) { + s_session_candidate_to_chain(a_session, &l_store_candidate_ready->hdr.candidate_hash, + (dap_chain_block_t*)l_store_candidate_ready->candidate_n_signs, l_store_candidate_ready->hdr.candidate_size); + } + dap_chain_global_db_objs_delete(l_objs, l_objs_size); + } + + dap_chain_cs_block_ton_message_item_t *l_message_item=NULL, *l_message_tmp=NULL; + HASH_ITER(hh, a_session->old_round.messages_items, l_message_item, l_message_tmp) { + HASH_DEL(a_session->old_round.messages_items, l_message_item); + DAP_DELETE(l_message_item->message); + DAP_DELETE(l_message_item); + } + + if ( a_session->old_round.validators_start ) { + // delete only links + dap_list_free(a_session->old_round.validators_start); + } + a_session->old_round.validators_start = NULL; + + if ( a_session->old_round.validators_list ) { + // delete validators + dap_list_free_full(a_session->old_round.validators_list, free); + } + a_session->old_round.validators_list = NULL; + + if ( a_session->old_round.last_message_hash ) { + DAP_DELETE(a_session->old_round.last_message_hash); + a_session->old_round.last_message_hash = NULL; + } + + if ( a_session->old_round.my_candidate_hash ) { + DAP_DELETE(a_session->old_round.my_candidate_hash); + a_session->old_round.my_candidate_hash = NULL; + } + + // move cur round to old + a_session->old_round.id.uint64 = a_session->cur_round.id.uint64; + + a_session->old_round.messages_items = a_session->cur_round.messages_items; + a_session->cur_round.messages_items = NULL; + + a_session->old_round.validators_start_count = a_session->cur_round.validators_start_count; + a_session->old_round.validators_start = a_session->cur_round.validators_start; + a_session->cur_round.validators_start = NULL; + + a_session->old_round.validators_count = a_session->cur_round.validators_count; + a_session->old_round.validators_list = a_session->cur_round.validators_list; + a_session->cur_round.validators_list = NULL; + + a_session->old_round.last_message_hash = a_session->cur_round.last_message_hash; + a_session->cur_round.last_message_hash = NULL; + a_session->old_round.messages_count = a_session->cur_round.messages_count; + + a_session->old_round.my_candidate_hash = a_session->cur_round.my_candidate_hash; + a_session->cur_round.my_candidate_hash = NULL; + + return false; +} + +// 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_by_addr( + dap_chain_cs_block_ton_items_t * a_session, dap_chain_node_addr_t * a_addr) { + dap_list_t* l_list_validator = dap_list_first(a_session->cur_round.validators_list); + 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_items_t *a_session, uint8_t a_round, 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_round == 'c' ? // 'c' or 'o' + a_session->cur_round.messages_items + : a_session->old_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->message; + 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; +} + + +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_items_t *l_session = (dap_chain_cs_block_ton_items_t *)a_arg; + dap_chain_cs_block_ton_message_t *l_message = + (dap_chain_cs_block_ton_message_t *)DAP_DUP_SIZE(a_data, a_data_size); + + if (l_message->hdr.chain_id.uint64 != l_session->chain->id.uint64 ) { + goto handler_finish; + } + + if (l_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu, 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)); + + dap_chain_time_t l_time = (dap_chain_time_t)time(NULL); + l_message->hdr.is_verified=false; + + dap_chain_node_addr_t *l_validator = s_session_get_validator_by_addr(l_session, a_sender_node_addr); + if (!l_validator) { + if (l_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu, attempt:%hu Message rejected: validator addr:"NODE_ADDR_FP_STR" not on 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)); + goto handler_finish; + } + + 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 (l_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu, 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); + goto handler_finish; + } + } + } + + dap_chain_hash_fast_t l_data_hash; + dap_hash_fast(a_data, a_data_size, &l_data_hash); + if (memcmp(a_data_hash, &l_data_hash, sizeof(dap_chain_hash_fast_t)) != 0) { + if (l_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu, 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); + goto handler_finish; + } + + // 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->message; + + if (l_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu, 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)); + + if ( + (l_time>l_startsync->ts && (l_time-l_startsync->ts) > l_session->allowed_clock_offset ) + || (l_time<l_startsync->ts && (l_startsync->ts-l_time) > l_session->allowed_clock_offset ) + ) { + // offset is more than allowed_clock_offset + // skip this validator + if (l_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu, attempt:%hu Message rejected: too much time difference", + l_session->chain->net_name, l_session->chain->name, + l_session->cur_round.id.uint64, l_session->attempt_current_number); + goto handler_finish; + } + + // 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 (l_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu, 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)); + goto handler_finish; + } + 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); + // if ( l_session->ts_round_start_pub < l_startsync->ts ) + // l_session->ts_round_start_pub = l_startsync->ts; + // l_session->ts_round_start = (dap_chain_time_t)time(NULL); // l_startsync->ts; // set max time of start consensus + goto handler_finish; + } + + if ( l_session->state != DAP_STREAM_CH_CHAIN_SESSION_STATE_CS_PROC + && l_session->state != DAP_STREAM_CH_CHAIN_SESSION_STATE_WAIT_SIGNS ) { + goto handler_finish; + } + + // round check + uint64_t l_round_id = + ((dap_chain_cs_block_ton_message_getinfo_t *)l_message->message)->round_id.uint64; + if ( l_message->hdr.type != DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_COMMIT_SIGN ) { + if ( l_round_id != l_session->cur_round.id.uint64) { + if (l_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu, 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); + goto handler_finish; + } + } else { + if ( l_round_id != l_session->cur_round.id.uint64 + && l_round_id != l_session->old_round.id.uint64 ) { + if (l_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu, 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); + goto handler_finish; + } + } + + dap_chain_cs_block_ton_message_item_t *l_messages_items = NULL; + l_messages_items = l_round_id == l_session->cur_round.id.uint64 ? + l_session->cur_round.messages_items : l_session->old_round.messages_items; + + // check hash message dup + dap_chain_cs_block_ton_message_item_t *l_message_item_temp = NULL; + HASH_FIND(hh, l_messages_items, a_data_hash, sizeof(dap_chain_hash_fast_t), l_message_item_temp); + if (l_message_item_temp) { + if (l_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu, 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); + goto handler_finish; + } + + // 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; + HASH_ITER(hh, l_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++; + } + } + if ( l_validator_number < l_submit_count ) { + // Skip this SUBMIT. Validator must wait its queue. + if (l_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu, 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); + goto handler_finish; + } + } + } + + 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; + HASH_ITER(hh, l_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->message)->candidate_hash; + + dap_chain_hash_fast_t *l_candidate_hash = + &((dap_chain_cs_block_ton_message_getinfo_t *)l_chain_message->message->message)->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 (l_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu, 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); + goto handler_finish; + } + } + } 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->message; + dap_chain_cs_block_ton_message_vote_t *l_vote_item = + (dap_chain_cs_block_ton_message_vote_t *)&l_chain_message->message->message; + if ( l_chain_msg_type == l_message->hdr.type + && l_vote->attempt_number == l_vote_item->attempt_number ) { + if (l_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu, 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); + goto handler_finish; + } + } 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 (l_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu, 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); + goto handler_finish; + } + } + } + // 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; + } + } + } + } + + // 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 (l_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu, 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); + goto handler_finish; + } + } break; + case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_COMMIT_SIGN: { + if (!l_precommit_count) { // if this validator not sent PreCommit for this candidate + if (l_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu, 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); + goto handler_finish; + } + } break; + } + + bool l_finalize_consensus = false; + switch (l_message->hdr.type) { + case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_SUBMIT: { + dap_chain_cs_block_ton_message_submit_t *l_submit = + (dap_chain_cs_block_ton_message_submit_t *)&l_message->message; + + size_t l_candidate_size = l_submit->candidate_size; + if (!l_candidate_size || s_hash_is_null(&l_submit->candidate_hash)) { // null candidate - save chain and exit + if (l_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu, 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); + goto handler_finish_save; + } + + dap_chain_block_t *l_candidate = (dap_chain_block_t *)l_submit->candidate; + dap_chain_hash_fast_t l_candidate_hash; + dap_hash_fast(l_candidate, l_candidate_size, &l_candidate_hash); + + // check candidate hash + if (memcmp(&l_submit->candidate_hash, &l_candidate_hash, + sizeof(dap_chain_hash_fast_t)) != 0) { + goto handler_finish; + } + + char *l_candidate_hash_str = dap_chain_hash_fast_to_str_new(&l_candidate_hash); + if (l_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu, 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 + size_t l_store_temp_size = 0; + dap_chain_cs_block_ton_store_t *l_store_temp = + (dap_chain_cs_block_ton_store_t *)dap_chain_global_db_gr_get( + l_candidate_hash_str, &l_store_temp_size, l_session->gdb_group_store); + if (l_store_temp) { + log_it(L_WARNING, "TON: Duplicate candidate:%s", l_candidate_hash_str); + DAP_DELETE(l_store_temp); + DAP_DELETE(l_candidate_hash_str); + goto handler_finish; + } + + pthread_rwlock_rdlock(&l_session->rwlock); + // stor for new candidate + size_t l_store_size = sizeof(dap_chain_cs_block_ton_store_hdr_t)+a_data_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.sign_collected = false; + l_store->hdr.approve_collected = false; + l_store->hdr.vote_collected = false; + l_store->hdr.precommit_collected = false; + 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; + memcpy( &l_store->hdr.candidate_hash, &l_candidate_hash, sizeof(dap_chain_hash_fast_t)); + memcpy( &l_store->candidate_n_signs, l_candidate, l_candidate_size); + + // save new block candidate + if (dap_chain_global_db_gr_set(dap_strdup(l_candidate_hash_str), l_store, + l_store_size, l_session->gdb_group_store) ) { + dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(l_session->chain); + if ( !s_session_datums_validation(l_blocks, l_candidate, l_candidate_size) ) { + // validation - OK, gen event Approve + if (l_session->blocks_sign_key) { + // size_t l_candidate_size = l_store->hdr.candidate_size; + dap_sign_t *l_hash_sign = dap_sign_create(l_session->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; + memcpy(&l_approve->candidate_hash, &l_candidate_hash, sizeof(dap_chain_hash_fast_t)); + 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); + DAP_DELETE(l_approve); + + if (l_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu, 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; + memcpy(&l_reject->candidate_hash, &l_candidate_hash, sizeof(dap_chain_hash_fast_t)); + 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)); + DAP_DELETE(l_reject); + if (l_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu, 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_store_temp); + DAP_DELETE(l_candidate_hash_str); + } break; + case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_REJECT: { + dap_chain_cs_block_ton_message_reject_t *l_reject = + (dap_chain_cs_block_ton_message_reject_t *)&l_message->message; + dap_chain_hash_fast_t *l_candidate_hash = &l_reject->candidate_hash; + + if ( s_hash_is_null(l_candidate_hash) ) { + if (l_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu, 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); + goto handler_finish_save; + } + char *l_candidate_hash_str = dap_chain_hash_fast_to_str_new(l_candidate_hash); + + if (l_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu, 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_rdlock(&l_session->rwlock); + + uint16_t l_reject_count = s_session_message_count( + l_session, 'c', DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_REJECT, + l_candidate_hash, NULL); + l_reject_count++; + if ( ((float)l_reject_count/l_session->cur_round.validators_count) >= ((float)2/3) ) { + dap_chain_global_db_gr_del(dap_strdup(l_candidate_hash_str), l_session->gdb_group_store); + if (l_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu, 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: { + dap_chain_cs_block_ton_message_approve_t *l_approve = + (dap_chain_cs_block_ton_message_approve_t *)&l_message->message; + dap_chain_hash_fast_t *l_candidate_hash = &l_approve->candidate_hash; + + if ( s_hash_is_null(l_candidate_hash) ) { + if (l_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu, 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); + goto handler_finish_save; + } + char *l_candidate_hash_str = dap_chain_hash_fast_to_str_new(l_candidate_hash); + + if (l_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu, 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 ) { + l_message->hdr.is_verified=true; + pthread_rwlock_rdlock(&l_session->rwlock); + + 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, 'c', DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_APPROVE, + l_candidate_hash, NULL); + l_approve_count++; + if ( ((float)l_approve_count/l_session->cur_round.validators_count) >= ((float)2/3) ) { + if (l_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu 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); + + size_t l_store_size = 0; + dap_chain_cs_block_ton_store_t *l_store = + (dap_chain_cs_block_ton_store_t *)dap_chain_global_db_gr_get( + l_candidate_hash_str, &l_store_size, l_session->gdb_group_store); + if (l_store) { + l_store->hdr.approve_collected = true; + if (dap_chain_global_db_gr_set(dap_strdup(l_candidate_hash_str), l_store, + l_store_size, l_session->gdb_group_store) ) { + // 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->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->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)); + DAP_DELETE(l_vote); + if (l_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu, 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 ); + } + DAP_DELETE(l_store); + } + } + } + pthread_rwlock_unlock(&l_session->rwlock); + } else { + log_it(L_WARNING, "Candidate hash sign is incorrect: code %d", l_sign_verified); + } + DAP_DELETE(l_candidate_hash_str); + } break; + case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE_FOR: { + dap_chain_cs_block_ton_message_votefor_t *l_votefor = + (dap_chain_cs_block_ton_message_votefor_t *)&l_message->message; + dap_chain_hash_fast_t *l_candidate_hash = &l_votefor->candidate_hash; + + uint16_t l_attempt_current = l_session->attempt_current_number; + if ( l_votefor->attempt_number != l_attempt_current) { + goto handler_finish; // wrong attempt number in message + } + + if (l_session->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:%llu, 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 ) { + goto handler_finish; // wrong coordinator addr + } + + uint16_t l_votefor_count = s_session_message_count( + l_session, 'c', DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE_FOR, + NULL, &l_attempt_current); + if ( l_votefor_count != 0 ) { + if (l_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu, 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); + goto handler_finish; + } + + // search candidate with 2/3 vote + pthread_rwlock_rdlock(&l_session->rwlock); + + size_t l_objs_size = 0; + 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; + dap_global_db_obj_t *l_objs = dap_chain_global_db_gr_load(l_session->gdb_group_store, &l_objs_size); + if (l_objs_size) { + for (size_t i = 0; i < l_objs_size; i++) { + if (!l_objs[i].value_len) + continue; + dap_chain_cs_block_ton_store_t *l_store = + (dap_chain_cs_block_ton_store_t *)l_objs[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 *)l_objs[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 *)l_objs[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 *)l_objs[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); + memcpy(&l_vote->candidate_hash, &l_found_candidate->hdr.candidate_hash, sizeof(dap_chain_hash_fast_t)); + 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)); + if (l_session->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:%llu, 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); + } + dap_chain_global_db_objs_delete(l_objs, l_objs_size); + } + pthread_rwlock_unlock(&l_session->rwlock); + } break; + 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->message; + dap_chain_hash_fast_t *l_candidate_hash = &l_vote->candidate_hash; + + if ( l_vote->attempt_number != l_session->attempt_current_number) { + goto handler_finish; + } + + if ( s_hash_is_null(l_candidate_hash) ) { + if (l_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu, 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); + goto handler_finish_save; + } + + char *l_candidate_hash_str = dap_chain_hash_fast_to_str_new(l_candidate_hash); + if (l_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu, 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); + + 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, 'c', DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE, + l_candidate_hash, &l_attempt_number); + l_vote_count++; + if ( ((float)l_vote_count/l_session->cur_round.validators_count) >= ((float)2/3) ) { + size_t l_store_size = 0; + dap_chain_cs_block_ton_store_t *l_store = + (dap_chain_cs_block_ton_store_t *)dap_chain_global_db_gr_get( + l_candidate_hash_str, &l_store_size, l_session->gdb_group_store); + if (l_store) { + l_store->hdr.vote_collected = true; + if (dap_chain_global_db_gr_set(dap_strdup(l_candidate_hash_str), l_store, + l_store_size, l_session->gdb_group_store) ) { + // Send PreCommit + dap_chain_cs_block_ton_message_precommit_t *l_precommit = + DAP_NEW_Z(dap_chain_cs_block_ton_message_precommit_t); + l_precommit->round_id.uint64 = l_session->cur_round.id.uint64; + memcpy(&l_precommit->candidate_hash, l_candidate_hash, sizeof(dap_chain_hash_fast_t)); + l_precommit->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)); + DAP_DELETE(l_precommit); + if (l_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu, 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_store); + } + } + DAP_DELETE(l_candidate_hash_str); + pthread_rwlock_unlock(&l_session->rwlock); + } break; + case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_PRE_COMMIT: { + dap_chain_cs_block_ton_message_precommit_t *l_precommit = + (dap_chain_cs_block_ton_message_precommit_t *)&l_message->message; + dap_chain_hash_fast_t *l_candidate_hash = &l_precommit->candidate_hash; + + if ( l_precommit->attempt_number != l_session->attempt_current_number) { + goto handler_finish; + } + if ( s_hash_is_null(l_candidate_hash) ) { + if (l_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu, 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); + goto handler_finish_save; + } + + char *l_candidate_hash_str = dap_chain_hash_fast_to_str_new(l_candidate_hash); + if (l_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu, 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); + + pthread_rwlock_rdlock(&l_session->rwlock); + uint16_t l_attempt_number = l_session->attempt_current_number; + uint16_t l_precommit_count = s_session_message_count( + l_session, 'c', DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_PRE_COMMIT, + l_candidate_hash, &l_attempt_number); + l_precommit_count++; + if ( ((float)l_precommit_count/l_session->cur_round.validators_count) >= ((float)2/3) ) { + size_t l_store_size = 0; + dap_chain_cs_block_ton_store_t *l_store = + (dap_chain_cs_block_ton_store_t *)dap_chain_global_db_gr_get( + l_candidate_hash_str, &l_store_size, l_session->gdb_group_store); + // event CommitSign + if (l_store) { + if (l_session->blocks_sign_key) { + l_store->hdr.precommit_collected = true; + + if (dap_chain_global_db_gr_set(dap_strdup(l_candidate_hash_str), l_store, + l_store_size, l_session->gdb_group_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); + dap_sign_t *l_candidate_sign = dap_sign_create(l_session->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)); + 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); + DAP_DELETE(l_commitsign); + DAP_DELETE(l_candidate); + DAP_DELETE(l_candidate_sign); + + l_session->state = DAP_STREAM_CH_CHAIN_SESSION_STATE_WAIT_SIGNS; + l_session->ts_round_state_commit = (dap_chain_time_t)time(NULL); + + if (l_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu 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"); + } + DAP_DELETE(l_store); + } + } + DAP_DELETE(l_candidate_hash_str); + } break; + case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_COMMIT_SIGN: { + dap_chain_cs_block_ton_message_commitsign_t *l_commitsign = + (dap_chain_cs_block_ton_message_commitsign_t *)&l_message->message; + dap_chain_hash_fast_t *l_candidate_hash = &l_commitsign->candidate_hash; + + if ( s_hash_is_null(l_candidate_hash) ) { + if (l_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu, attempt:%hu Receive COMMIT_SIGN: candidate: NULL", + l_session->chain->net_name, l_session->chain->name, + l_session->cur_round.id.uint64, l_session->attempt_current_number); + goto handler_finish_save; + } + + char *l_candidate_hash_str = dap_chain_hash_fast_to_str_new(l_candidate_hash); + if (l_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu, attempt:%hu Receive COMMIT_SIGN: 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); + + size_t l_store_size = 0; + dap_chain_cs_block_ton_store_t *l_store = + (dap_chain_cs_block_ton_store_t *)dap_chain_global_db_gr_get( + l_candidate_hash_str, &l_store_size, l_session->gdb_group_store); + 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((dap_sign_t*)l_commitsign->candidate_sign, + l_candidate, l_offset+sizeof(l_candidate->hdr))) == 1 ) { + l_message->hdr.is_verified = true; + l_store->hdr.sign_collected = true; + if (dap_chain_global_db_gr_set(dap_strdup(l_candidate_hash_str), l_store, + l_store_size, l_session->gdb_group_store) ) { + uint16_t l_commitsign_count = s_session_message_count( + l_session, 'c', DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_COMMIT_SIGN, + l_candidate_hash, NULL); + l_commitsign_count++; + if ( ((float)l_commitsign_count/l_session->cur_round.validators_count) >= ((float)2/3) ) { + // s_session_round_finish(l_session); + l_finalize_consensus = true; + if (l_session->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%llu, attempt:%hu Candidate:%s collected COMMIT_SIGN more than 2/3 of the validators, so to finished this round", + 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, "Candidate:%s sign is incorrect: code %d", l_candidate_hash_str, l_sign_verified); + } + } + pthread_rwlock_unlock(&l_session->rwlock); + DAP_DELETE(l_store); + DAP_DELETE(l_candidate_hash_str); + + } break; + default: + break; + } + +handler_finish_save: +{ + // save to messages chain + dap_chain_hash_fast_t l_message_hash; + s_message_chain_add(l_session, a_sender_node_addr, l_message, a_data_size, &l_message_hash); + if (l_finalize_consensus) { + s_session_round_finish(l_session); + } +} +handler_finish: + // DAP_DELETE(l_message); //no leak + return; +} + + +static void s_message_send(dap_chain_cs_block_ton_items_t *a_session, + uint8_t a_message_type, uint8_t *a_data, size_t a_data_size) { + + 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_Z_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_chain_time_t)time(NULL); + l_message->hdr.type = a_message_type; + memcpy(&l_message->message, a_data, a_data_size); + l_message->hdr.message_size = a_data_size; + dap_chain_net_t *l_net = dap_chain_net_by_id(a_session->chain->net_id); + + memcpy(&l_message->hdr.sender_node_addr, + dap_chain_net_get_cur_addr(l_net), sizeof(dap_chain_node_addr_t)); + + 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_session->cur_round.validators_list, + &l_message_hash, l_message, l_message_size); + DAP_DELETE(l_message); +} + + +static void s_message_chain_add(dap_chain_cs_block_ton_items_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) { + + pthread_rwlock_rdlock(&a_session->rwlock); + dap_chain_cs_block_ton_message_t *l_message = a_message; + + l_message->hdr.is_genesis = !a_session->cur_round.last_message_hash ? true : false; + if (!l_message->hdr.is_genesis) { + memcpy(&l_message->hdr.prev_message_hash, a_session->cur_round.last_message_hash, sizeof(dap_hash_fast_t)); + } + + dap_chain_hash_fast_t l_message_hash; + dap_hash_fast(a_message, a_message_size, &l_message_hash); + + dap_chain_cs_block_ton_message_item_t *l_message_items = DAP_NEW_Z(dap_chain_cs_block_ton_message_item_t); + l_message_items->message = l_message; + + memcpy( &l_message_items->message_hash, &l_message_hash, sizeof(dap_chain_hash_fast_t)); + a_session->cur_round.last_message_hash = + (dap_chain_hash_fast_t*)DAP_DUP_SIZE(&l_message_hash, sizeof(dap_chain_hash_fast_t)); + HASH_ADD(hh, a_session->cur_round.messages_items, message_hash, sizeof(l_message_items->message_hash), l_message_items); + + a_session->cur_round.messages_count++; + memcpy( a_message_hash, &l_message_hash, sizeof(dap_chain_hash_fast_t)); + + pthread_rwlock_unlock(&a_session->rwlock); +} + +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 PoS 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_signs_count = dap_chain_block_get_signs_count(a_block, a_block_size); + if (l_signs_count < l_ton_pvt->confirmations_minimum) { + log_it(L_WARNING,"Wrong signature number with block %p on chain %s", a_block, a_blocks->chain->name); + return -2; // Wrong signatures number + } + + uint16_t l_verified_num = 0; + for (size_t l_sig_ton = 0; l_sig_ton < l_signs_count; l_sig_ton++) { + dap_sign_t *l_sign = dap_chain_block_sign_get(a_block, a_block_size, l_sig_ton); + if (l_sign == NULL) { + log_it(L_WARNING, "Block isn't signed with anything: sig ton %zu, event size %zu", l_sig_ton, a_block_size); + return -4; + } + + bool l_sign_size_correct = dap_sign_verify_size(l_sign, a_block_size); + if (!l_sign_size_correct) { + log_it(L_WARNING, "Block's sign #%zu size is incorrect", l_sig_ton); + return -44; + } + size_t l_block_data_size = dap_chain_block_get_sign_offset(a_block, a_block_size)+sizeof(a_block->hdr); + if (l_block_data_size == a_block_size) { + log_it(L_WARNING,"Block has nothing except sign, nothing to verify so I pass it (who knows why we have it?)"); + return 0; + } + + int l_sign_verified = dap_sign_verify(l_sign, a_block, l_block_data_size); + if (l_sign_verified != 1) { + log_it(L_WARNING, "Block's sign is incorrect: code %d", l_sign_verified); + return -41; + } + + if (l_sig_ton == 0) { + dap_chain_addr_t l_addr = {}; + dap_chain_hash_fast_t l_pkey_hash; + dap_sign_get_pkey_hash(l_sign, &l_pkey_hash); + dap_chain_addr_fill(&l_addr, l_sign->header.type, &l_pkey_hash, a_blocks->chain->net_id); + size_t l_datums_count = 0; + dap_chain_datum_t **l_datums = dap_chain_block_get_datums(a_block, a_block_size, &l_datums_count); + if (!l_datums || !l_datums_count) { + log_it(L_WARNING, "No datums in block %p on chain %s", a_block, a_blocks->chain->name); + return -7; + } + for (size_t i = 0; i < l_datums_count; i++) { + if (!dap_chain_net_srv_stake_validator(&l_addr, l_datums[i])) { + log_it(L_WARNING, "Not passed stake validator datum %zu with block %p on chain %s", i, a_block, a_blocks->chain->name); + DAP_DELETE(l_datums); + return -6; + } + } + DAP_DELETE(l_datums); + } + } + + // Check number + if (l_verified_num >= l_ton_pvt->confirmations_minimum) { + // Passed all checks + return 0; + } else { + log_it(L_WARNING, "Wrong block: only %hu/%hu signs are valid", l_verified_num, l_ton_pvt->confirmations_minimum); + return -2; + } +} + + + + 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 new file mode 100644 index 0000000000000000000000000000000000000000..b5b762e0280309050cfdc0351b5f70271635ce04 --- /dev/null +++ b/modules/consensus/block-ton/include/dap_chain_cs_block_ton.h @@ -0,0 +1,217 @@ + +#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 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 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; + 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; +} dap_chain_cs_block_ton_round_t; + +typedef struct dap_chain_cs_block_ton_items { + dap_chain_t *chain; + + dap_chain_node_addr_t *my_addr; + + uint8_t state; // session state + dap_chain_cs_block_ton_round_t cur_round; + dap_chain_cs_block_ton_round_t old_round; + + dap_chain_node_addr_t *attempt_coordinator; // validator-coordinator in current attempt + uint16_t attempt_current_number; + + dap_chain_time_t ts_round_sync_start; // time start sync + dap_chain_time_t ts_round_start; // time round-start + dap_chain_time_t ts_round_state_commit; + dap_chain_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_items *next; + struct dap_chain_cs_block_ton_items *prev; + + bool debug; + + uint16_t round_start_sync_timeout; + uint16_t consensus_start_period; + 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; + + bool time_proc_lock; // flag - skip check if prev check is not finish + + pthread_rwlock_t rwlock; + +} dap_chain_cs_block_ton_items_t; + +typedef struct dap_chain_cs_block_ton_message_hdr { + uint8_t type; + + union { + uint8_t raw[DAP_CHAIN_BLOCKS_SESSION_MESSAGE_ID_SIZE]; + uint64_t uint64; + } DAP_ALIGN_PACKED id; + + size_t message_size; + + dap_chain_time_t ts_created; + dap_chain_cs_block_ton_round_id_t round_id; + + dap_chain_node_addr_t sender_node_addr; + + bool is_genesis; + bool 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; + // UT_hash_handle hh; + uint8_t 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_ALIGN_PACKED 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_chain_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; // cellect 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_chain_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; + +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; + +#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/type/blocks/CMakeLists.txt b/modules/type/blocks/CMakeLists.txt index 0bd58e05cb19c5aa187618fd4824ee55e5008ce1..9922441f1c42c683485d21b56b4e993888e28249 100644 --- a/modules/type/blocks/CMakeLists.txt +++ b/modules/type/blocks/CMakeLists.txt @@ -7,6 +7,6 @@ file(GLOB DAP_CHAIN_BLOCK_HEADERS include/*.h) add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_BLOCK_SRCS} ${DAP_CHAIN_BLOCK_HEADERS}) -target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_chain dap_stream_ch_chain_voting) +target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_chain) target_include_directories(${PROJECT_NAME} INTERFACE .) target_include_directories(${PROJECT_NAME} PUBLIC include) diff --git a/modules/type/blocks/dap_chain_block.c b/modules/type/blocks/dap_chain_block.c index 0001945c7ffd7dafabcc2a6896540902f70a4a4f..6b40b5ac4d2ebee2bd5faf5609397baf6c68aac8 100644 --- a/modules/type/blocks/dap_chain_block.c +++ b/modules/type/blocks/dap_chain_block.c @@ -360,7 +360,7 @@ dap_sign_t *dap_chain_block_sign_get ( dap_chain_block_t * a_block, size_t a_blo } l_offset += l_sign_size; l_sign_cur++; - l_sign = (dap_sign_t*) a_block->meta_n_datum_n_sign+l_offset; + l_sign = (dap_sign_t*)(a_block->meta_n_datum_n_sign+l_offset); } return l_sign_cur == a_sign_num ? l_sign : NULL; } diff --git a/modules/type/blocks/dap_chain_cs_blocks_session.c b/modules/type/blocks/dap_chain_cs_blocks_session.c deleted file mode 100644 index 67284346abd04f3f98599a1a5d75875b732c1c09..0000000000000000000000000000000000000000 --- a/modules/type/blocks/dap_chain_cs_blocks_session.c +++ /dev/null @@ -1,880 +0,0 @@ - -#include "dap_timerfd.h" -#include "utlist.h" -#include "dap_chain_net.h" -#include "dap_chain_cell.h" -#include "dap_chain_cs_blocks.h" -#include "dap_chain_cs_blocks_session.h" -#include "dap_stream_ch_chain_voting.h" - -#define LOG_TAG "dap_chain_cs_blocks_session" - -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 bool s_session_block_submit(dap_chain_cs_blocks_session_items_t *a_session); -static bool s_session_timer(); -static int s_session_datums_validation(dap_chain_cs_blocks_t *a_blocks, dap_chain_block_t *a_block, size_t a_block_size); - -static void s_message_send(dap_chain_cs_blocks_session_items_t * a_session, - uint8_t a_message_type, uint8_t *a_data, size_t a_data_size); -static void s_message_chain_add(dap_chain_cs_blocks_session_items_t * a_session, dap_chain_node_addr_t * a_sender_node_addr, - dap_chain_cs_blocks_session_message_t * a_message, - size_t a_message_size, dap_chain_hash_fast_t *a_message_hash); -static bool s_session_finish(dap_chain_cs_blocks_session_items_t *a_session); -static bool s_session_finish_notstart(dap_chain_cs_blocks_session_items_t *a_session); -// static int s_message_block_sign_add(dap_chain_cs_blocks_session_items_t * a_session, -// dap_chain_hash_fast_t *a_block_hash, dap_sign_t *a_sign); -static dap_chain_node_addr_t * s_session_get_validator_by_addr( - dap_chain_cs_blocks_session_items_t * a_session, dap_chain_node_addr_t * a_addr); - -// static char * s_gdb_group_session_store; -// dap_chain_hash_fast_t * s_prev_message_hash = NULL; -static dap_chain_cs_blocks_session_items_t * s_session_items; // double-linked list of chains -static dap_timerfd_t * s_session_cs_timer = NULL; - -int dap_chain_cs_blocks_session_init(dap_chain_t *a_chain, dap_enc_key_t *a_blocks_sign_key) -{ - - //dap_chain_net_t * l_net = dap_chain_net_by_id(a_chain->net_id); - dap_chain_cs_blocks_session_items_t * l_session = DAP_NEW_Z(dap_chain_cs_blocks_session_items_t); - - // l_session->validators_list = dap_chain_net_get_node_list(l_net); - // l_session->validators_count = dap_list_length(l_session->validators_list); - -// l_session->gdb_group_store = dap_strdup_printf("local.ton.setup"); - -// time session -// attempts in round -// attempt time -// rounds count -> max round -> change validator - l_session->round_id.uint64 = 1; - l_session->gdb_group_store = dap_strdup_printf("local.ton.%s.%s.round.%llu.store", - a_chain->net_name, a_chain->name, l_session->round_id.uint64); - l_session->gdb_group_message = dap_strdup_printf("local.ton.%s.%s.round.%llu.message", - a_chain->net_name, a_chain->name, l_session->round_id.uint64); - l_session->chain = a_chain; - l_session->last_message_hash = NULL; - l_session->messages_count = 0; - - l_session->consensus_start_period = 20; // hint: if((time()/10) % consensus_start)==0 - l_session->validators_start = NULL; - l_session->state = DAP_STREAM_CH_CHAIN_SESSION_STATE_IDLE; - - l_session->blocks_sign_key = a_blocks_sign_key; - - // l_session->timer_consensus_finish = NULL; - // l_session->timer_consensus_cancel = NULL; - l_session->ts_consensus_start = 0; - l_session->ts_consensus_state_commit = 0; - - dap_chain_time_t l_time = (dap_chain_time_t)time(NULL); - //l_session->ts_consensus_finish = ((l_time/10)*10) + l_session->consensus_start_period; - while (true) { - l_time++; - if ( (l_time % l_session->consensus_start_period) == 0) { - l_session->ts_consensus_finish = l_time+l_session->consensus_start_period; - break; - } - } - - // l_session->cs_timer = dap_timerfd_start(60*1000, - // (dap_timerfd_callback_t)s_session_check, - // l_session); - - pthread_rwlock_init(&l_session->rwlock, NULL); - - DL_APPEND(s_session_items, l_session); - if (!s_session_cs_timer) { - s_session_cs_timer = dap_timerfd_start(1*1000, - (dap_timerfd_callback_t)s_session_timer, - NULL); - } - - dap_stream_ch_chain_voting_in_callback_add(l_session, s_session_packet_in); - return 0; -} - -static bool s_session_send_startsync(dap_chain_cs_blocks_session_items_t *a_session){ - dap_chain_cs_blocks_session_message_startsync_t * l_startsync = - DAP_NEW_Z(dap_chain_cs_blocks_session_message_startsync_t); - l_startsync->ts = a_session->ts_consensus_start; - s_message_send(a_session, DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_START_SYNC, - (uint8_t*)l_startsync, sizeof(dap_chain_cs_blocks_session_message_startsync_t)); - return false; -} - -static bool s_session_timer() { - dap_chain_time_t l_time = (dap_chain_time_t)time(NULL); - dap_chain_cs_blocks_session_items_t * l_session = NULL; - DL_FOREACH(s_session_items, l_session) { - - switch (l_session->state) { - case DAP_STREAM_CH_CHAIN_SESSION_STATE_IDLE: { - if ( (((l_time/10)*10) % l_session->consensus_start_period) == 0 - && l_time > l_session->ts_consensus_finish - && (l_time-l_session->ts_consensus_finish) >= l_session->consensus_start_period ) { - l_session->state = DAP_STREAM_CH_CHAIN_SESSION_STATE_WAIT_START; - l_session->ts_consensus_start = (dap_chain_time_t)time(NULL); - - dap_chain_net_t * l_net = dap_chain_net_by_id(l_session->chain->net_id); - l_session->validators_list = dap_chain_net_get_node_list(l_net); - l_session->validators_count = dap_list_length(l_session->validators_list); - - dap_timerfd_start(3*1000, - (dap_timerfd_callback_t)s_session_send_startsync, - l_session); - } - } break; - case DAP_STREAM_CH_CHAIN_SESSION_STATE_WAIT_START: { - if ( (l_time-l_session->ts_consensus_start) >= 10 ) - s_session_finish(l_session); - } break; - case DAP_STREAM_CH_CHAIN_SESSION_STATE_CS_PROC: { - if ( (l_time-l_session->ts_consensus_start) >= 30 ) - s_session_finish(l_session); - } break; - case DAP_STREAM_CH_CHAIN_SESSION_STATE_WAIT_SIGNS: { - if ( (l_time-l_session->ts_consensus_state_commit) >= 10 ) - s_session_finish(l_session); - } break; - } - } - - return true; -} - -// static void s_session_start (dap_chain_cs_blocks_session_items_t * a_session) { -// dap_chain_time_t l_time = (dap_chain_time_t)time(NULL); -// } - -static bool s_session_block_submit(dap_chain_cs_blocks_session_items_t *a_session){ - -// uint16_t l_net_list_size = 0; -// dap_chain_net_t **l_net_list = dap_chain_net_list(&l_net_list_size); -// for (int i=0; i<l_net_list_size; i++) { -// dap_chain_t *l_chain; -// DL_FOREACH(l_net_list[i]->pub.chains, l_chain) { -// if (!l_chain) { -// continue; -// } -// } -// } - - dap_chain_t * l_chain = a_session->chain; - // dap_chain_net_t * l_net = dap_chain_net_by_id(l_chain->net_id); - dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(l_chain); - - if (!l_blocks->block_new) { - return false; // for timer - } - size_t l_submit_size = sizeof(dap_chain_cs_blocks_session_message_submit_t)+l_blocks->block_new_size; - dap_chain_cs_blocks_session_message_submit_t * l_submit = - DAP_NEW_SIZE(dap_chain_cs_blocks_session_message_submit_t, l_submit_size); - - dap_chain_hash_fast_t l_candidate_hash; - dap_hash_fast(l_blocks->block_new, l_blocks->block_new_size, &l_candidate_hash); - - l_submit->candidate_size = l_blocks->block_new_size; - memcpy(&l_submit->candidate_hash, &l_candidate_hash, sizeof(dap_chain_hash_fast_t)); - memcpy(l_submit->candidate, l_blocks->block_new, l_blocks->block_new_size); - - s_message_send(a_session, DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_SUBMIT, (uint8_t*)l_submit, l_submit_size); - - DAP_DELETE(l_blocks->block_new); - l_blocks->block_new = NULL; - l_blocks->block_new_size = 0; - - //return true; - return false; // for timer -} - - -static int s_session_datums_validation(dap_chain_cs_blocks_t *a_blocks, dap_chain_block_t *a_block, size_t a_block_size){ - // a_blocks->chain->ledger - // dap_chain_ledger_tx_add_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx); - - return 0; - - size_t l_datums_count = 0; - dap_chain_datum_t **l_datums = dap_chain_block_get_datums(a_block, a_block_size, &l_datums_count); - - if (!l_datums || !l_datums_count) { - //log_it(L_WARNING, "No datums in block %p on chain %s", a_block, a_blocks->chain->name); - return -2; - } - - for(size_t i=0; i<l_datums_count; i++){ - dap_chain_datum_t *l_datum = l_datums[i]; - switch (l_datum->header.type_id) { - case DAP_CHAIN_DATUM_TX: { - dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t*) l_datum->data; - int ret = dap_chain_ledger_tx_add_check(a_blocks->chain->ledger, l_tx); - if (ret != 0) { - return -1; - } - } - } - } - - return 0; -} - -// static bool s_session_finish_notstart(dap_chain_cs_blocks_session_items_t *a_session) { -// if ( a_session->state == DAP_STREAM_CH_CHAIN_SESSION_STATE_WAIT_START ) { -// s_session_finish(a_session); -// } -// return false; -// } - -static bool s_session_finish(dap_chain_cs_blocks_session_items_t *a_session) { - - if ( a_session->state == DAP_STREAM_CH_CHAIN_SESSION_STATE_CS_PROC ){ - // {...} if exists candidate check sign and save to chain - } - - a_session->state = DAP_STREAM_CH_CHAIN_SESSION_STATE_IDLE; - a_session->last_message_hash = NULL; - a_session->messages_count = 0; - - dap_list_free(a_session->validators_start); - a_session->validators_start = NULL; - - a_session->ts_consensus_finish = (dap_chain_time_t)time(NULL); - a_session->ts_consensus_start = 0; - a_session->ts_consensus_state_commit = 0; - - // if (a_session->timer_consensus_cancel) - // dap_timerfd_delete(a_session->timer_consensus_cancel); - // a_session->timer_consensus_cancel = NULL; - - // if (a_session->timer_consensus_finish) - // dap_timerfd_delete(a_session->timer_consensus_finish); - // a_session->timer_consensus_finish = NULL; - - size_t l_objs_size = 0; - dap_global_db_obj_t *l_objs; - // delete all candidate - l_objs = dap_chain_global_db_gr_load(a_session->gdb_group_store, &l_objs_size); - if (l_objs_size) { - for (size_t i = 0; i < l_objs_size; i++) { - if (!l_objs[i].value_len) - continue; - } - dap_chain_global_db_objs_delete(l_objs, l_objs_size); - } - - // delete messages chain - l_objs = dap_chain_global_db_gr_load(a_session->gdb_group_message, &l_objs_size); - if (l_objs_size) { - for (size_t i = 0; i < l_objs_size; i++) { - if (!l_objs[i].value_len) - continue; - } - dap_chain_global_db_objs_delete(l_objs, l_objs_size); - } - - dap_chain_cs_blocks_session_message_item_t *l_message_item=NULL, *l_message_tmp=NULL; - HASH_ITER(hh, a_session->messages_items, l_message_item, l_message_tmp) { - HASH_DEL(a_session->messages_items, l_message_item); - DAP_DELETE(l_message_item->message); - DAP_DELETE(l_message_item); - } - return false; -} - -// must change to validator list -static dap_chain_node_addr_t * s_session_get_validator_by_addr( - dap_chain_cs_blocks_session_items_t * a_session, dap_chain_node_addr_t * a_addr) { - dap_list_t* l_list_validator = dap_list_first(a_session->validators_list); - 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 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_blocks_session_items_t * l_session = (dap_chain_cs_blocks_session_items_t *)a_arg; - - dap_chain_node_addr_t * l_validator = s_session_get_validator_by_addr(l_session, a_sender_node_addr); - if (!l_validator) { - goto handler_finish; - } - - dap_chain_cs_blocks_session_message_t * l_message = (dap_chain_cs_blocks_session_message_t *)a_data; - //char * l_message_hash_hex_str = dap_chain_hash_fast_to_str_new(&l_message->hdr.message_hash); - - dap_chain_hash_fast_t l_data_hash; - dap_hash_fast(a_data, a_data_size, &l_data_hash); - - if (l_message->hdr.chain_id.uint64 != l_session->chain->id.uint64 ) { - goto handler_finish; - } - - if (memcmp(a_data_hash, &l_data_hash, sizeof(dap_chain_hash_fast_t)) != 0) - goto handler_finish; - - if ( l_message->hdr.type == DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_START_SYNC ) { - // add check&save sender addr - dap_list_t* l_list_temp = dap_list_first(l_session->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) - goto handler_finish; - l_list_temp = l_list_next; - } - l_session->validators_start = dap_list_append(l_session->validators_start, l_validator); - size_t startsync_count = dap_list_length(l_session->validators_start); - if ( ((float)startsync_count/l_session->validators_count) >= ((float)2/3) ) { - l_session->state = DAP_STREAM_CH_CHAIN_SESSION_STATE_CS_PROC; - dap_timerfd_start(3*1000, // pause before candidate submit - (dap_timerfd_callback_t)s_session_block_submit, - l_session); - // l_session->timer_consensus_finish = dap_timerfd_start((3+30)*1000, // consensus timeout - // (dap_timerfd_callback_t)s_session_finish, - // l_session); - } - goto handler_finish; - } - - if ( l_session->state != DAP_STREAM_CH_CHAIN_SESSION_STATE_CS_PROC - && l_session->state != DAP_STREAM_CH_CHAIN_SESSION_STATE_WAIT_SIGNS ) - goto handler_finish; - - // check hash message dup - dap_chain_cs_blocks_session_message_item_t * l_message_item_temp = NULL; - HASH_FIND(hh, l_session->messages_items, a_data_hash, sizeof(dap_chain_hash_fast_t), l_message_item_temp); - if (l_message_item_temp) - goto handler_finish; - - uint32_t l_approve_count = 0, l_vote_count = 0, l_precommit_count = 0; - // check messages chain - dap_chain_cs_blocks_session_message_item_t *l_message_item=NULL, *l_message_tmp=NULL; - HASH_ITER(hh, l_session->messages_items, l_message_item, l_message_tmp) { - if (l_message_item->message->hdr.sender_node_addr.uint64 == a_sender_node_addr->uint64) { - dap_chain_hash_fast_t * l_candidate_hash_cur = - &((dap_chain_cs_blocks_session_message_gethash_t *)l_message->message)->candidate_hash; - - dap_chain_hash_fast_t * l_candidate_hash = - &((dap_chain_cs_blocks_session_message_gethash_t *)l_message_item->message->message)->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_msg_type = l_message_item->message->hdr.type; - - // search & check messages from this validator - switch (l_msg_type) { - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_APPROVE: - // if (l_candidate_hash_match) - // l_approve_count++; - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_REJECT: { - if ( l_message->hdr.type == DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_APPROVE || - l_message->hdr.type == DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_REJECT ) { - // check dup message APPROVE or REJECT for one candidate - if (l_candidate_hash_match) { - goto handler_finish; - } - } - } break; - // this messages should only appear once per 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_msg_type == l_message->hdr.type ){ - goto handler_finish; - } - } - } - - // count messages in chain for this candidate - if (l_candidate_hash_match) - switch (l_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; - } - } - } - - // 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 - goto handler_finish; - } break; - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_COMMIT_SIGN: { - if (!l_precommit_count) // if this validator not sent PreCommit for this candidate - goto handler_finish; - } break; - } - - // save to messages chain - dap_chain_hash_fast_t l_message_hash; - s_message_chain_add(l_session, a_sender_node_addr, l_message, a_data_size, &l_message_hash); - - dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(l_session->chain); - - // uint8_t* l_message_data = (uint8_t*)&l_message->message; - // size_t l_message_data_size = l_message->hdr.message_size; - // dap_chain_hash_fast_t l_message_data_hash; - // dap_hash_fast(l_message_data, l_message_data_size, &l_message_data_hash); - // char * l_message_data_hash_str = dap_chain_hash_fast_to_str_new(&l_message_data_hash); - - switch (l_message->hdr.type) { - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_SUBMIT: { - int ret = 0; - dap_chain_cs_blocks_session_message_submit_t * l_submit = - (dap_chain_cs_blocks_session_message_submit_t *)&l_message->message; - - size_t l_candidate_size = l_submit->candidate_size; - dap_chain_block_t * l_candidate = (dap_chain_block_t *)l_submit->candidate; - - dap_chain_hash_fast_t l_candidate_hash; - dap_hash_fast(l_candidate, l_candidate_size, &l_candidate_hash); - - // check candidate hash - if (memcmp(&l_submit->candidate_hash, &l_candidate_hash, - sizeof(dap_chain_hash_fast_t)) != 0) { - goto handler_finish; - } - - char * l_candidate_hash_str = dap_chain_hash_fast_to_str_new(&l_candidate_hash); - - // check block exist in store - size_t l_store_temp_size = 0; - dap_chain_cs_blocks_session_store_t * l_store_temp = - (dap_chain_cs_blocks_session_store_t *)dap_chain_global_db_gr_get( - l_candidate_hash_str, &l_store_temp_size, l_session->gdb_group_store); - if (l_store_temp) { - DAP_DELETE(l_store_temp); - DAP_DELETE(l_candidate_hash_str); - goto handler_finish; - } - - pthread_rwlock_rdlock(&l_session->rwlock); - - // save to messages chain - // dap_chain_hash_fast_t l_message_hash; - // s_message_chain_add(l_session, a_sender_node_addr, l_message, a_data_size, &l_message_hash); - - dap_chain_net_t * l_net = dap_chain_net_by_id( l_session->chain->net_id); - - // dap_chain_block_t * l_candidate = (dap_chain_block_t *)l_message_data; - - if ( !(ret = s_session_datums_validation(l_blocks, l_candidate, l_candidate_size)) ) { - size_t l_store_size = sizeof(dap_chain_cs_blocks_session_store_hdr_t)+a_data_size; - dap_chain_cs_blocks_session_store_t * l_store = - DAP_NEW_Z_SIZE(dap_chain_cs_blocks_session_store_t, l_store_size); - l_store->hdr.sign_count = 0; - l_store->hdr.approve_count = 0; - l_store->hdr.reject_count = 0; - l_store->hdr.vote_count = 0; - l_store->hdr.candidate_size = l_candidate_size; - // l_store->hdr.approve_count = 1; - - memcpy( &l_store->candidate_n_signs, l_candidate, l_candidate_size); - if (dap_chain_global_db_gr_set(dap_strdup(l_candidate_hash_str), l_store, - l_store_size, l_session->gdb_group_store) ) { - // event Approve - if (l_session->blocks_sign_key) { - size_t l_candidate_size = l_store->hdr.candidate_size; - dap_sign_t *l_hash_sign = dap_sign_create(l_session->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_blocks_session_message_approve_t)+l_hash_sign_size; - - dap_chain_cs_blocks_session_message_approve_t * l_approve = - DAP_NEW_SIZE(dap_chain_cs_blocks_session_message_approve_t, l_approve_size); - - memcpy(&l_approve->candidate_hash, &l_candidate_hash, sizeof(dap_chain_hash_fast_t)); - 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); - } - else - log_it(L_WARNING, "Can't sign block with blocks-sign-cert in [block-pos] section"); - } - } - else { - // event Reject - dap_chain_cs_blocks_session_message_reject_t * l_reject = - DAP_NEW_Z(dap_chain_cs_blocks_session_message_reject_t); - memcpy(&l_reject->candidate_hash, &l_candidate_hash, sizeof(dap_chain_hash_fast_t)); - s_message_send(l_session, DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_REJECT, - (uint8_t*)l_reject, sizeof(dap_chain_cs_blocks_session_message_reject_t)); - } - pthread_rwlock_unlock(&l_session->rwlock); - DAP_DELETE(l_store_temp); - DAP_DELETE(l_candidate_hash_str); - } break; - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_REJECT: { - - dap_chain_cs_blocks_session_message_reject_t * l_reject = - (dap_chain_cs_blocks_session_message_reject_t *)&l_message->message; - dap_chain_hash_fast_t * l_candidate_hash = &l_reject->candidate_hash; - char * l_candidate_hash_str = dap_chain_hash_fast_to_str_new(l_candidate_hash); - - pthread_rwlock_rdlock(&l_session->rwlock); - size_t l_store_size = 0; - dap_chain_cs_blocks_session_store_t * l_store = - (dap_chain_cs_blocks_session_store_t *)dap_chain_global_db_gr_get( - l_candidate_hash_str, &l_store_size, l_session->gdb_group_store); - if (l_store) { - dap_chain_global_db_gr_del(dap_strdup(l_candidate_hash_str), l_session->gdb_group_store); - l_store->hdr.reject_count++; - if ( ((float)l_store->hdr.reject_count/l_session->validators_count) < ((float)2/3) ) { - dap_chain_global_db_gr_set(dap_strdup(l_candidate_hash_str), l_store, - l_store_size, l_session->gdb_group_store); - } - } - pthread_rwlock_unlock(&l_session->rwlock); - DAP_DELETE(l_candidate_hash_str); - } break; - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_APPROVE: { - dap_chain_cs_blocks_session_message_approve_t * l_approve = - (dap_chain_cs_blocks_session_message_approve_t *)&l_message->message; - dap_chain_hash_fast_t * l_candidate_hash = &l_approve->candidate_hash; - - // size_t l_sign_size = dap_sign_get_size(l_approve->candidate_hash_sign); - // dap_sign_t *l_hash_sign = DAP_NEW_SIZE(dap_sign_t, l_sign_size); - // memcpy(l_hash_sign, l_approve->candidate_hash_sign, l_sign_size); - - 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 ) { - pthread_rwlock_rdlock(&l_session->rwlock); - char * l_candidate_hash_str = dap_chain_hash_fast_to_str_new(l_candidate_hash); - size_t l_store_size = 0; - dap_chain_cs_blocks_session_store_t * l_store = - (dap_chain_cs_blocks_session_store_t *)dap_chain_global_db_gr_get( - l_candidate_hash_str, &l_store_size, l_session->gdb_group_store); - if (l_store) { - dap_chain_global_db_gr_del(dap_strdup(l_candidate_hash_str), l_session->gdb_group_store); - l_store->hdr.approve_count++; - - dap_chain_cs_blocks_session_store_t * l_store_gdb = - (dap_chain_cs_blocks_session_store_t *)DAP_DUP_SIZE(l_store, l_store_size); - if (dap_chain_global_db_gr_set(dap_strdup(l_candidate_hash_str), l_store_gdb, - l_store_size, l_session->gdb_group_store) ) - if ( ((float)l_store->hdr.approve_count/l_session->validators_count) >= ((float)2/3) ) { - // event Vote - dap_chain_cs_blocks_session_message_vote_t * l_vote = - DAP_NEW_Z(dap_chain_cs_blocks_session_message_vote_t); - memcpy(&l_vote->candidate_hash, l_candidate_hash, sizeof(dap_chain_hash_fast_t)); - s_message_send(l_session, DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE, - (uint8_t*)l_vote, sizeof(dap_chain_cs_blocks_session_message_vote_t)); - } - } - pthread_rwlock_unlock(&l_session->rwlock); - DAP_DELETE(l_store); - DAP_DELETE(l_candidate_hash_str); - } else { - log_it(L_WARNING, "Candidate hash sign is incorrect: code %d", l_sign_verified); - } - } break; - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE: { - dap_chain_cs_blocks_session_message_vote_t * l_vote = - (dap_chain_cs_blocks_session_message_vote_t *)&l_message->message; - dap_chain_hash_fast_t * l_candidate_hash = &l_vote->candidate_hash; - char * l_candidate_hash_str = dap_chain_hash_fast_to_str_new(l_candidate_hash); - - pthread_rwlock_rdlock(&l_session->rwlock); - size_t l_store_size = 0; - dap_chain_cs_blocks_session_store_t * l_store = - (dap_chain_cs_blocks_session_store_t *)dap_chain_global_db_gr_get( - l_candidate_hash_str, &l_store_size, l_session->gdb_group_store); - - size_t l_obj_size = 0; - dap_global_db_obj_t* l_obj = dap_chain_global_db_gr_load(l_session->gdb_group_store, &l_obj_size); - - if (l_store) { - dap_chain_global_db_gr_del(dap_strdup(l_candidate_hash_str), l_session->gdb_group_store); - l_store->hdr.vote_count++; - dap_chain_cs_blocks_session_store_t * l_store_gdb = - (dap_chain_cs_blocks_session_store_t *)DAP_DUP_SIZE(l_store, l_store_size); - dap_chain_global_db_gr_set(dap_strdup(l_candidate_hash_str), l_store_gdb, - l_store_size, l_session->gdb_group_store); - - if ( ((float)l_store->hdr.vote_count/l_session->validators_count) >= ((float)2/3) ) { - // Delete other candidates - ? dont delete if multi-rounds - size_t l_objs_size = 0; - dap_global_db_obj_t *l_objs = dap_chain_global_db_gr_load(l_session->gdb_group_store, &l_objs_size); - if (l_objs_size) { - for (size_t i = 0; i < l_objs_size; i++) { - if (!l_objs[i].value_len) - continue; - if ( strcmp(l_candidate_hash_str, l_objs[i].key) != 0 ) { - dap_chain_global_db_gr_del(dap_strdup(l_objs[i].key), l_session->gdb_group_store); - } - } - dap_chain_global_db_objs_delete(l_objs, l_objs_size); - } - // Send PreCommit - dap_chain_cs_blocks_session_message_precommit_t * l_precommit = - DAP_NEW_Z(dap_chain_cs_blocks_session_message_precommit_t); - memcpy(&l_precommit->candidate_hash, l_candidate_hash, sizeof(dap_chain_hash_fast_t)); - s_message_send(l_session, DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_PRE_COMMIT, - (uint8_t*)l_precommit, sizeof(dap_chain_cs_blocks_session_message_precommit_t)); - } - } - pthread_rwlock_unlock(&l_session->rwlock); - DAP_DELETE(l_store); - DAP_DELETE(l_candidate_hash_str); - } break; - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_PRE_COMMIT: { - dap_chain_cs_blocks_session_message_precommit_t * l_precommit = - (dap_chain_cs_blocks_session_message_precommit_t *)&l_message->message; - dap_chain_hash_fast_t * l_candidate_hash = &l_precommit->candidate_hash; - char * l_candidate_hash_str = dap_chain_hash_fast_to_str_new(l_candidate_hash); - - pthread_rwlock_rdlock(&l_session->rwlock); - size_t l_store_size = 0; - dap_chain_cs_blocks_session_store_t * l_store = - (dap_chain_cs_blocks_session_store_t *)dap_chain_global_db_gr_get( - l_candidate_hash_str, &l_store_size, l_session->gdb_group_store); - if (l_store) { - dap_chain_global_db_gr_del(dap_strdup(l_candidate_hash_str), l_session->gdb_group_store); - l_store->hdr.precommit_count++; - - dap_chain_cs_blocks_session_store_t * l_store_gdb = - (dap_chain_cs_blocks_session_store_t *)DAP_DUP_SIZE(l_store, l_store_size); - if (dap_chain_global_db_gr_set(dap_strdup(l_candidate_hash_str), l_store_gdb, - l_store_size, l_session->gdb_group_store) ) { - if ( ((float)l_store->hdr.precommit_count/l_session->validators_count) >= ((float)2/3) ) { - // event CommitSign - if (l_session->blocks_sign_key) { - 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(l_session->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_blocks_session_message_commitsign_t)+l_candidate_sign_size; - dap_chain_cs_blocks_session_message_commitsign_t * l_commitsign = - DAP_NEW_SIZE(dap_chain_cs_blocks_session_message_commitsign_t, l_commitsign_size); - - memcpy(&l_commitsign->candidate_hash, l_candidate_hash, sizeof(dap_chain_hash_fast_t)); - 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); - DAP_DELETE(l_candidate); - DAP_DELETE(l_candidate_sign); - - l_session->state = DAP_STREAM_CH_CHAIN_SESSION_STATE_WAIT_SIGNS; - l_session->ts_consensus_state_commit = (dap_chain_time_t)time(NULL); - } - else - log_it(L_WARNING, "Can't sign block with blocks-sign-cert in [block-pos] section"); - } - } - } - pthread_rwlock_unlock(&l_session->rwlock); - DAP_DELETE(l_store); - DAP_DELETE(l_candidate_hash_str); - - } break; - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_COMMIT_SIGN: { - dap_chain_cs_blocks_session_message_commitsign_t * l_commitsign = - (dap_chain_cs_blocks_session_message_commitsign_t *)&l_message->message; - dap_chain_hash_fast_t * l_candidate_hash = &l_commitsign->candidate_hash; - - pthread_rwlock_unlock(&l_session->rwlock); - char * l_candidate_hash_str = dap_chain_hash_fast_to_str_new(l_candidate_hash); - size_t l_store_size = 0; - dap_chain_cs_blocks_session_store_t * l_store = - (dap_chain_cs_blocks_session_store_t *)dap_chain_global_db_gr_get( - l_candidate_hash_str, &l_store_size, l_session->gdb_group_store); - if (l_store) { - dap_chain_global_db_gr_del(dap_strdup(l_candidate_hash_str), l_session->gdb_group_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((dap_sign_t*)l_commitsign->candidate_sign, - l_candidate, l_offset+sizeof(l_candidate->hdr))) == 1 ) { - - size_t l_candidate_sign_size = dap_sign_get_size((dap_sign_t*)l_commitsign->candidate_sign); - size_t l_store_size_new = l_store_size+l_candidate_sign_size; - l_store = DAP_REALLOC(l_store, l_store_size_new); - memcpy(((byte_t *)l_store)+l_store_size, l_commitsign->candidate_sign, l_candidate_sign_size); - l_store->hdr.sign_count++; - - dap_chain_cs_blocks_session_store_t * l_store_gdb = - (dap_chain_cs_blocks_session_store_t *)DAP_DUP_SIZE(l_store, l_store_size_new); - - if (dap_chain_global_db_gr_set(dap_strdup(l_candidate_hash_str), l_store_gdb, - l_store_size_new, l_session->gdb_group_store)){ - // if ( ((float)l_store->hdr.sign_count/l_session->validators_count) >= ((float)2/3) ) { - // l_session->state = DAP_STREAM_CH_CHAIN_SESSION_STATE_WAIT_SIGNS; - // } - } - - } else { - log_it(L_WARNING, "Candidate hash sign is incorrect: code %d", l_sign_verified); - } - } - pthread_rwlock_unlock(&l_session->rwlock); - DAP_DELETE(l_store); - DAP_DELETE(l_candidate_hash_str); - - } break; - // case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE_FOR: { - // } break; - default: - break; - } - -handler_finish: - DAP_DELETE(a_sender_node_addr); - DAP_DELETE(a_data_hash); - DAP_DELETE(a_data); -} - - -static void s_message_send(dap_chain_cs_blocks_session_items_t * a_session, - uint8_t a_message_type, uint8_t *a_data, size_t a_data_size) { - - size_t l_message_size = sizeof(dap_chain_cs_blocks_session_message_hdr_t)+a_data_size; - - dap_chain_cs_blocks_session_message_t * l_message = - DAP_NEW_Z_SIZE(dap_chain_cs_blocks_session_message_t, l_message_size); - - l_message->hdr.id.uint64 = (uint64_t)a_session->messages_count; - l_message->hdr.chain_id.uint64 = a_session->chain->id.uint64; - l_message->hdr.ts_created = (dap_chain_time_t)time(NULL); - l_message->hdr.type = a_message_type; - memcpy(&l_message->message, a_data, a_data_size); - l_message->hdr.message_size = a_data_size; - //a_session->messages_count++; - - //dap_chain_cs_blocks_session_message_item_t * l_message_items = DAP_NEW_Z(dap_chain_cs_blocks_session_message_item_t); - //l_message_items->message = l_message; - - // save to messages chain - // dap_chain_hash_fast_t l_message_hash; - // s_message_chain_add(a_session, NULL, l_message, l_message_size, &l_message_hash); - - //dap_hash_fast(l_message, l_message_size, l_message_hash); - // dap_hash_fast(l_message, l_message_size, &l_message_items->message_hash); - // a_session->last_message_hash = &l_message_items->message_hash; - - //HASH_ADD(hh, a_session->messages_items, message_hash, sizeof(l_message_items->message_hash), l_message_items); - - dap_chain_net_t * l_net = dap_chain_net_by_id(a_session->chain->net_id); - - memcpy(&l_message->hdr.sender_node_addr, - dap_chain_net_get_cur_addr(l_net), sizeof(dap_chain_node_addr_t)); - - 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_session->validators_list, &l_message_hash, l_message, l_message_size); - - DAP_DELETE(a_data); -} - - -static void s_message_chain_add(dap_chain_cs_blocks_session_items_t * a_session, dap_chain_node_addr_t * a_sender_node_addr, - dap_chain_cs_blocks_session_message_t * a_message, - size_t a_message_size, dap_chain_hash_fast_t *a_message_hash) { - - pthread_rwlock_rdlock(&a_session->rwlock); - - dap_chain_cs_blocks_session_message_t * l_message = - (dap_chain_cs_blocks_session_message_t *)DAP_DUP_SIZE(a_message, a_message_size); - - l_message->hdr.is_genesis = !a_session->last_message_hash ? true : false; - if (!l_message->hdr.is_genesis) { - memcpy(&l_message->hdr.prev_message_hash, a_session->last_message_hash, sizeof(dap_hash_fast_t)); - //DAP_DELETE(a_session->last_message_hash); - } - // if (a_link_hash) { - // memcpy( &l_message->hdr.link_message_hash, a_link_hash, sizeof(dap_chain_hash_fast_t)); - // } - - // if (a_sender_node_addr) { - // // memcpy( &l_message->hdr.sender_node_addr, a_sender_node_addr, sizeof(dap_chain_node_addr_t)); - // l_message->hdr.sender_node_addr.uint64 = a_sender_node_addr->uint64; - // } - - dap_chain_hash_fast_t l_message_hash; - dap_hash_fast(a_message, a_message_size, &l_message_hash); - - dap_chain_cs_blocks_session_message_item_t * l_message_items = DAP_NEW_Z(dap_chain_cs_blocks_session_message_item_t); - l_message_items->message = l_message; - - memcpy( &l_message_items->message_hash, &l_message_hash, sizeof(dap_chain_hash_fast_t)); - a_session->last_message_hash = &l_message_hash; - HASH_ADD(hh, a_session->messages_items, message_hash, sizeof(l_message_items->message_hash), l_message_items); - - char * l_hash_str = dap_chain_hash_fast_to_str_new(&l_message_hash); - // dap_chain_global_db_gr_set(dap_strdup(l_hash_str), (uint8_t *)a_message, a_message_size, a_session->gdb_group_message); - - a_session->messages_count++; - memcpy( a_message_hash, &l_message_hash, sizeof(dap_chain_hash_fast_t)); - - pthread_rwlock_unlock(&a_session->rwlock); -} - - -// static int s_message_block_sign_add(dap_chain_cs_blocks_session_items_t * a_session, -// dap_chain_hash_fast_t *a_block_hash, dap_sign_t *a_sign){ - -// int ret = -1; -// size_t l_session_store_size = 0; -// char * l_block_hash_str = dap_chain_hash_fast_to_str_new(a_block_hash); -// dap_chain_cs_blocks_session_store_t *l_store = -// (dap_chain_cs_blocks_session_store_t *)dap_chain_global_db_gr_get(l_block_hash_str, -// &l_session_store_size, a_session->gdb_group_store ); -// if (l_store) { -// dap_chain_global_db_gr_del(dap_strdup(l_block_hash_str), a_session->gdb_group_store); -// } - -// // size_t l_sign_offset = l_session_store->hdr.candidate_size; -// size_t l_sign_size = dap_sign_get_size(a_sign); -// // dap_chain_hash_fast_t l_pkey_hash = {}; -// // dap_sign_get_pkey_hash(a_sign, &l_pkey_hash); -// // dap_chain_addr_t l_addr = {}; -// // dap_chain_addr_fill(&l_addr, a_sign->header.type, &l_pkey_hash, l_session->chain->net_id); - -// l_store = DAP_REALLOC(l_store, l_session_store_size+l_sign_size); -// memcpy(((byte_t *)l_store)+l_session_store_size, a_sign, l_sign_size); -// l_store->hdr.sign_count = 0; - -// if (dap_chain_global_db_gr_set(dap_strdup(l_block_hash_str), l_store, -// l_session_store_size+l_sign_size, a_session->gdb_group_store) ) { -// ret = 0; -// } - -// return ret; -// } - - - - - - diff --git a/modules/type/blocks/include/dap_chain_cs_blocks_session.h b/modules/type/blocks/include/dap_chain_cs_blocks_session.h deleted file mode 100644 index de9080339869c4d12e46b223065add45be25251b..0000000000000000000000000000000000000000 --- a/modules/type/blocks/include/dap_chain_cs_blocks_session.h +++ /dev/null @@ -1,184 +0,0 @@ - -#include "dap_chain.h" -#include "dap_chain_block.h" - - -// • 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)—ablockcandidatehasbeen 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) - -#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_blocks_session_message dap_chain_cs_blocks_session_message_t; -typedef struct dap_chain_cs_blocks_session_message_item dap_chain_cs_blocks_session_message_item_t; - -typedef union dap_chain_blocks_session_round_id { - uint8_t raw[DAP_CHAIN_BLOCKS_SESSION_ROUND_ID_SIZE]; - uint64_t uint64; -} DAP_ALIGN_PACKED dap_chain_blocks_session_round_id_t; - -typedef struct dap_chain_cs_blocks_session_items { - dap_chain_t *chain; - dap_chain_hash_fast_t * last_message_hash; - //dap_chain_cs_blocks_session_message_t * messages; - dap_chain_cs_blocks_session_message_item_t * messages_items; - uint16_t messages_count; - - dap_list_t *validators_list; // dap_chain_node_addr_t - uint16_t validators_count; - - //uint16_t startsync_count; - dap_list_t *validators_start; // dap_chain_node_addr_t - uint16_t consensus_start_period; - - // dap_timerfd_t* timer_consensus_finish; - // dap_timerfd_t* timer_consensus_cancel; - dap_chain_time_t ts_consensus_start; - dap_chain_time_t ts_consensus_state_commit; - dap_chain_time_t ts_consensus_finish; - - dap_chain_blocks_session_round_id_t round_id; - uint8_t state; - - char * gdb_group_setup; - char * gdb_group_store; - char * gdb_group_message; - - dap_enc_key_t *blocks_sign_key; - // dap_timerfd_t *cs_timer; - - struct dap_chain_cs_blocks_session_items * next; - struct dap_chain_cs_blocks_session_items * prev; - - pthread_rwlock_t rwlock; - -} DAP_ALIGN_PACKED dap_chain_cs_blocks_session_items_t; - -typedef struct dap_chain_cs_blocks_session_message_hdr { - uint8_t type; - - union { - uint8_t raw[DAP_CHAIN_BLOCKS_SESSION_MESSAGE_ID_SIZE]; - uint64_t uint64; - } DAP_ALIGN_PACKED id; - - size_t message_size; - - dap_chain_time_t ts_created; - dap_chain_blocks_session_round_id_t round_id; - - dap_chain_node_addr_t sender_node_addr; - - // dap_chain_hash_fast_t block_candidate_hash; - // char* block_candidate_hash_str; - // size_t block_candidate_size; - - bool is_genesis; - - //dap_chain_hash_fast_t genesis_message_hash; - //dap_chain_hash_fast_t message_hash; - dap_chain_hash_fast_t prev_message_hash; - //dap_chain_hash_fast_t link_message_hash; - - dap_chain_id_t chain_id; - //dap_chain_cell_id_t cell_id; - -} DAP_ALIGN_PACKED dap_chain_cs_blocks_session_message_hdr_t; - - -typedef struct dap_chain_cs_blocks_session_message { - dap_chain_cs_blocks_session_message_hdr_t hdr; - // UT_hash_handle hh; - uint8_t message[]; -} DAP_ALIGN_PACKED dap_chain_cs_blocks_session_message_t; - - -typedef struct dap_chain_cs_blocks_session_message_item { - dap_chain_cs_blocks_session_message_t * message; - dap_chain_hash_fast_t message_hash; - UT_hash_handle hh; -} DAP_ALIGN_PACKED dap_chain_cs_blocks_session_message_item_t; - - -// struct for get hash from any messages -typedef struct dap_chain_cs_blocks_session_message_gethash { - dap_chain_hash_fast_t candidate_hash; -} DAP_ALIGN_PACKED dap_chain_cs_blocks_session_message_gethash_t; - -// technical messages -typedef struct dap_chain_cs_blocks_session_message_startsync { - dap_chain_time_t ts; -} DAP_ALIGN_PACKED dap_chain_cs_blocks_session_message_startsync_t; - -// consensus messages -typedef struct dap_chain_cs_blocks_session_message_submit { - dap_chain_hash_fast_t candidate_hash; - size_t candidate_size; - uint8_t candidate[]; -} DAP_ALIGN_PACKED dap_chain_cs_blocks_session_message_submit_t; - -typedef struct dap_chain_cs_blocks_session_message_approve { - dap_chain_hash_fast_t candidate_hash; - uint8_t candidate_hash_sign[]; -} DAP_ALIGN_PACKED dap_chain_cs_blocks_session_message_approve_t; - -typedef struct dap_chain_cs_blocks_session_message_reject { - dap_chain_hash_fast_t candidate_hash; -} DAP_ALIGN_PACKED dap_chain_cs_blocks_session_message_reject_t; - -typedef struct dap_chain_cs_blocks_session_message_votefor { - dap_chain_hash_fast_t candidate_hash; -} DAP_ALIGN_PACKED dap_chain_cs_blocks_session_message_votefor_t; - -typedef struct dap_chain_cs_blocks_session_message_vote { - dap_chain_hash_fast_t candidate_hash; -} DAP_ALIGN_PACKED dap_chain_cs_blocks_session_message_vote_t; - -typedef struct dap_chain_cs_blocks_session_message_precommit { - dap_chain_hash_fast_t candidate_hash; -} DAP_ALIGN_PACKED dap_chain_cs_blocks_session_message_precommit_t; - -typedef struct dap_chain_cs_blocks_session_message_commitsign { - dap_chain_hash_fast_t candidate_hash; - uint8_t candidate_sign[]; -} DAP_ALIGN_PACKED dap_chain_cs_blocks_session_message_commitsign_t; - - -typedef struct dap_chain_cs_blocks_session_store_hdr { - uint16_t sign_count; - uint16_t approve_count; - uint16_t reject_count; - uint16_t vote_count; - uint16_t precommit_count; - size_t candidate_size; -} DAP_ALIGN_PACKED dap_chain_cs_blocks_session_store_hdr_t; - -typedef struct dap_chain_cs_blocks_session_store { - dap_chain_cs_blocks_session_store_hdr_t hdr; - uint8_t candidate_n_signs[]; -} DAP_ALIGN_PACKED dap_chain_cs_blocks_session_store_t; - - - -int dap_chain_cs_blocks_session_init(dap_chain_t *a_chain, dap_enc_key_t *a_blocks_sign_key);