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);