diff --git a/cmake/OS_Detection.cmake b/cmake/OS_Detection.cmake
index 29ba720c909c61c35b2c365caf475ce52cca3db1..ce71fbfdf36b4c18c95ad4ac43091a87779da1fe 100644
--- a/cmake/OS_Detection.cmake
+++ b/cmake/OS_Detection.cmake
@@ -120,12 +120,37 @@ if(UNIX)
                 set(_LOPT "${_LOPT} -fsanitize=thread")
             elseif(DEFINED ENV{DAP_UBSAN})
                 message("[!] Undefined behaviour Sanitizer enabled")
+                set(_CCOPT "${_CCOPT} -fsanitize=undefined -fsanitize=bounds -fno-omit-frame-pointer")
+                set(_LOPT "${_LOPT} -fsanitize=undefined")
             endif()
             SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -pg")
         else()
-            set(_CCOPT "${CFLAGS_WARNINGS} -O3 -fPIC -fno-strict-aliasing -fno-ident -ffast-math -ftree-vectorize -fno-asynchronous-unwind-tables -ffunction-sections -Wl,--gc-sections -std=gnu11")
-            if(NOT DAP_DBG_INFO)
-                set(_CCOPT "${_CCOPT} -Wl,--strip-all")
+            set(_CCOPT "${CFLAGS_WARNINGS} -fPIC -fno-ident -ffast-math -ftree-vectorize -fno-asynchronous-unwind-tables -ffunction-sections -Wl,--gc-sections -std=gnu11")
+            if (DEFINED ENV{DAP_ASAN})
+                message("[!] Address Sanitizer enabled")
+                set(_CCOPT "${_CCOPT} -fsanitize=address -fsanitize-address-use-after-scope -fno-omit-frame-pointer -fno-common -O2")
+                set(_LOPT "${_LOPT} -fsanitize=address")
+            elseif(DEFINED ENV{DAP_MSAN})
+                if (CMAKE_C_COMPILER_ID MATCHES ".*[Cc][Ll][Aa][Nn][Gg].*")
+                    message("[!] Memory Sanitizer enabled")
+                    set(_CCOPT "${_CCOPT} -fsanitize=memory -fPIE -pie -fno-omit-frame-pointer -O2")
+                    set(_LOPT "${_LOPT} -fsanitize=memory -fPIE -pie")
+                else()
+                    message("[!] Memory Sanitizer is not available on this compiler")
+                endif()
+            elseif(DEFINED ENV{DAP_TSAN})
+                message("[!] Thread Sanitizer enabled")
+                set(_CCOPT "${_CCOPT} -fsanitize=thread")
+                set(_LOPT "${_LOPT} -fsanitize=thread")
+            elseif(DEFINED ENV{DAP_UBSAN})
+                message("[!] Undefined behaviour Sanitizer enabled")
+                set(_CCOPT "${_CCOPT} -fsanitize=undefined -fsanitize=bounds -fno-omit-frame-pointer")
+                set(_LOPT "${_LOPT} -fsanitize=undefined")
+            else()
+                set(_CCOPT "${_CCOPT} -O3")
+                if(NOT DAP_DBG_INFO)
+                    set(_CCOPT "${_CCOPT} -Wl,--strip-all")
+                endif()
             endif()
         endif()
     elseif (DARWIN)
diff --git a/dap-sdk b/dap-sdk
index 3ef80ce7eefc7777c7fbb94101419318e7c59fce..c2bc19eb99aefc325077e6da5cff34c50b5a2d34 160000
--- a/dap-sdk
+++ b/dap-sdk
@@ -1 +1 @@
-Subproject commit 3ef80ce7eefc7777c7fbb94101419318e7c59fce
+Subproject commit c2bc19eb99aefc325077e6da5cff34c50b5a2d34
diff --git a/modules/chain/dap_chain.c b/modules/chain/dap_chain.c
index 4119cdd53186a06eede64983bf0a8eb0a5fdf513..f13ddb8e6c12647deaa3c04aa59e48b54220cfe4 100644
--- a/modules/chain/dap_chain.c
+++ b/modules/chain/dap_chain.c
@@ -174,7 +174,6 @@ void dap_chain_delete(dap_chain_t * a_chain)
     DAP_DEL_Z(a_chain->_inheritor);
     pthread_rwlock_destroy(&a_chain->rwlock);
     pthread_rwlock_destroy(&a_chain->cell_rwlock);
-    pthread_rwlock_destroy(&a_chain->rwlock);
 }
 
 /**
diff --git a/modules/chain/dap_chain_ledger.c b/modules/chain/dap_chain_ledger.c
index a5ac3b20fe8a44818fd8744a4ab4e6e98d2988ba..e2999fbe5e201d1ef06de58cf287cd8997d71194 100644
--- a/modules/chain/dap_chain_ledger.c
+++ b/modules/chain/dap_chain_ledger.c
@@ -619,8 +619,9 @@ static bool s_ledger_token_update_check(dap_chain_ledger_token_item_t *a_cur_tok
     //Check new count signs
     size_t l_new_signs_total = auth_signs_total + l_quantity_tsd_add_pkeys - l_quantity_tsd_remote_pkeys;
     if (l_tsd_signs_valid) {
-        size_t l_signs_valid_from_tsd = (size_t)(dap_tsd_get_scalar(l_tsd_signs_valid,uint16_t));
-        if (l_new_signs_total < l_signs_valid_from_tsd || l_signs_valid_from_tsd < 1) {
+        uint16_t l_signs_valid_from_tsd = 0;
+        _dap_tsd_get_scalar(l_tsd_signs_valid, &l_signs_valid_from_tsd);
+        if (l_new_signs_total < (size_t)l_signs_valid_from_tsd || l_signs_valid_from_tsd < 1) {
             dap_list_free(l_tsd_list_added_pkeys);
             dap_list_free(l_tsd_list_remote_pkeys);
             return false;
@@ -639,7 +640,8 @@ static bool s_ledger_token_update_check(dap_chain_ledger_token_item_t *a_cur_tok
     else {
         for (dap_list_t *l_ptr = l_tsd_list_remote_pkeys; l_ptr; l_ptr = dap_list_next(l_ptr)) {
             dap_tsd_t *l_tsd = (dap_tsd_t *) l_ptr->data;
-            dap_hash_fast_t l_hash = dap_tsd_get_scalar(l_tsd, dap_hash_fast_t);
+            dap_hash_fast_t l_hash = { };
+            _dap_tsd_get_scalar(l_tsd, &l_hash);
             bool accepted = false;
             for (size_t i = 0; i < auth_signs_total; i++) {
                 if (dap_hash_fast_compare(&a_cur_token_item->auth_pkeys_hash[i], &l_hash)) {
@@ -1342,36 +1344,39 @@ static int s_token_tsd_parse(dap_ledger_t * a_ledger, dap_chain_ledger_token_ite
         switch (l_tsd->type) {
            // set flags
             case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_SET_FLAGS:{
-                a_token_item->flags |= dap_tsd_get_scalar(l_tsd,uint16_t);
+                uint16_t l_flags = 0;
+                a_token_item->flags |= _dap_tsd_get_scalar(l_tsd, &l_flags);
             }break;
 
            // unset flags
             case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_UNSET_FLAGS:{
-                a_token_item->flags &= ~dap_tsd_get_scalar(l_tsd,uint16_t);
+                uint16_t l_flags = 0;
+                a_token_item->flags &= ~_dap_tsd_get_scalar(l_tsd, &l_flags);
             }break;
 
             // set total supply
             case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SUPPLY:{ // 256
-                a_token_item->total_supply = dap_tsd_get_scalar(l_tsd,uint256_t);
+                a_token_item->total_supply = uint256_0;
+                _dap_tsd_get_scalar(l_tsd, &a_token_item->total_supply);
             }break;
 
             case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SUPPLY_OLD:{ // 128
-                a_token_item->total_supply = GET_256_FROM_128(dap_tsd_get_scalar(l_tsd,uint128_t));
+                uint128_t l_total_supply128 = uint128_0;
+                a_token_item->total_supply = GET_256_FROM_128(_dap_tsd_get_scalar(l_tsd,&l_total_supply128));
             }break;
 
             // Set total signs count value to set to be valid
             case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_VALID:{
-                a_token_item->auth_signs_valid = dap_tsd_get_scalar(l_tsd,uint16_t);
+                uint16_t l_signs_valid = 0;
+                a_token_item->auth_signs_valid = _dap_tsd_get_scalar(l_tsd, &l_signs_valid);
             }break;
 
             //Allowed tx receiver addres list add, remove or clear
             case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_ADD:{
                 if( l_tsd->size == sizeof (dap_chain_addr_t) ){
-
-                    if (a_token_item->tx_recv_allow)
-                        a_token_item->tx_recv_allow = DAP_REALLOC(a_token_item->tx_recv_allow,(a_token_item->tx_recv_allow_size+1)*sizeof (*a_token_item->tx_recv_allow));
-                    else
-                        a_token_item->tx_recv_allow = DAP_NEW_Z_SIZE( dap_chain_addr_t,sizeof(*a_token_item->tx_recv_allow));
+                    a_token_item->tx_recv_allow = a_token_item->tx_recv_allow
+                            ? DAP_REALLOC(a_token_item->tx_recv_allow, (a_token_item->tx_recv_allow_size + 1) * sizeof(*a_token_item->tx_recv_allow))
+                            : DAP_NEW_Z_SIZE(dap_chain_addr_t,sizeof(*a_token_item->tx_recv_allow));
 
                     // Check if its correct
                     dap_chain_addr_t * l_add_addr = (dap_chain_addr_t *) l_tsd->data;
@@ -1770,7 +1775,8 @@ static int s_tsd_sign_apply(dap_ledger_t *a_ledger, dap_chain_ledger_token_item_
     }
     for (dap_list_t *l_ptr = l_remove_pkeys; l_ptr; l_ptr = dap_list_next(l_ptr)) {
         dap_tsd_t *l_tsd = l_ptr->data;
-        dap_hash_fast_t l_hash = dap_tsd_get_scalar(l_tsd, dap_chain_hash_fast_t);
+        dap_hash_fast_t l_hash = { };
+        _dap_tsd_get_scalar(l_tsd, &l_hash);
         for( size_t i=0; i<a_token_item->auth_signs_total; i++){
             if (dap_hash_fast_compare(&l_hash, &a_token_item->auth_pkeys_hash[i] )){
                 if (i+1 != a_token_item->auth_signs_total){
@@ -1803,7 +1809,8 @@ static int s_tsd_sign_apply(dap_ledger_t *a_ledger, dap_chain_ledger_token_item_
         dap_pkey_get_hash(l_pkey, &a_token_item->auth_pkeys_hash[a_token_item->auth_signs_total-1]);
     }
     if (l_new_signs_valid) {
-        a_token_item->auth_signs_valid = dap_tsd_get_scalar(l_new_signs_valid,uint16_t);
+        uint16_t l_tmp = 0;
+        a_token_item->auth_signs_valid = _dap_tsd_get_scalar(l_new_signs_valid, &l_tmp);
     }
     return 0;
 }
@@ -3706,8 +3713,8 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
                     l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_STAKE_LOCK_INVALID_TOKEN;
                     break;
                 }
-                dap_chain_datum_token_tsd_delegate_from_stake_lock_t *l_tsd_section = dap_tsd_get_object(l_tsd, dap_chain_datum_token_tsd_delegate_from_stake_lock_t);
-                if (!dap_chain_ledger_token_ticker_check(a_ledger, (char *)l_tsd_section->ticker_token_from)) {
+                dap_chain_datum_token_tsd_delegate_from_stake_lock_t *l_tsd_section = _dap_tsd_get_object(l_tsd, dap_chain_datum_token_tsd_delegate_from_stake_lock_t);
+                if (!dap_chain_ledger_token_ticker_check(a_ledger, (char*)l_tsd_section->ticker_token_from)) {
                     debug_if(s_debug_more, L_WARNING, "Token [%s] not found", l_tsd_section->ticker_token_from);
                     l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_CHECK_TICKER_NOT_FOUND;
                     break;
diff --git a/modules/channel/chain-net/dap_stream_ch_chain_net.c b/modules/channel/chain-net/dap_stream_ch_chain_net.c
index 2f0a0f63b66aa441daa04f133bc978623f6557ec..4c48527ab98af6f590b5077c0c9adbabae5052ea 100644
--- a/modules/channel/chain-net/dap_stream_ch_chain_net.c
+++ b/modules/channel/chain-net/dap_stream_ch_chain_net.c
@@ -64,10 +64,8 @@ static void s_stream_ch_packet_in(dap_stream_ch_t* ch, void* arg);
 static void s_stream_ch_packet_out(dap_stream_ch_t* ch, void* arg);
 
 typedef struct dap_chain_net_session_data {
-    unsigned int session_id;
-
+    uint32_t session_id;
     dap_chain_node_addr_t addr_remote;
-
     UT_hash_handle hh;
 } dap_chain_net_session_data_t;
 
@@ -77,20 +75,20 @@ static dap_chain_net_session_data_t *s_chain_net_data = NULL;
 static pthread_mutex_t s_hash_mutex = PTHREAD_MUTEX_INITIALIZER;
 
 
-static dap_chain_net_session_data_t* session_data_find(unsigned int a_id)
+static dap_chain_net_session_data_t* session_data_find(uint32_t a_id)
 {
     dap_chain_net_session_data_t *l_sdata;
     pthread_mutex_lock(&s_hash_mutex);
-    HASH_FIND_INT(s_chain_net_data, &a_id, l_sdata);
+    HASH_FIND(hh, s_chain_net_data, &a_id, sizeof(uint32_t), l_sdata);
     pthread_mutex_unlock(&s_hash_mutex);
     return l_sdata;
 }
 
-static void session_data_del(unsigned int a_id)
+static void session_data_del(uint32_t a_id)
 {
     dap_chain_net_session_data_t *l_sdata;
     pthread_mutex_lock(&s_hash_mutex);
-    HASH_FIND_INT(s_chain_net_data, &a_id, l_sdata);
+    HASH_FIND(hh, s_chain_net_data, &a_id, sizeof(uint32_t), l_sdata);
     if(l_sdata) {
         // Clang bug at this, l_sdata should change at every loop cycle
         HASH_DEL(s_chain_net_data, l_sdata);
@@ -114,7 +112,7 @@ static void session_data_del_all()
 
 
 
-dap_chain_node_addr_t dap_stream_ch_chain_net_from_session_data_extract_node_addr(unsigned int a_session_id) {
+dap_chain_node_addr_t dap_stream_ch_chain_net_from_session_data_extract_node_addr(uint32_t a_session_id) {
     dap_chain_node_addr_t l_addr= {0};
     dap_chain_net_session_data_t *l_sdata, *l_sdata_tmp;
     pthread_mutex_lock(&s_hash_mutex);
@@ -165,7 +163,7 @@ void s_stream_ch_new(dap_stream_ch_t* a_ch, void* a_arg)
     // Create chain net session ever it created
     dap_chain_net_session_data_t *l_sdata;
     pthread_mutex_lock(&s_hash_mutex);
-    HASH_FIND_INT(s_chain_net_data, &a_ch->stream->session->id, l_sdata);
+    HASH_FIND(hh, s_chain_net_data, &a_ch->stream->session->id, sizeof(uint32_t), l_sdata);
     if(l_sdata == NULL) {
         l_sdata = DAP_NEW_Z(dap_chain_net_session_data_t);
         if (!l_sdata) {
@@ -174,7 +172,7 @@ void s_stream_ch_new(dap_stream_ch_t* a_ch, void* a_arg)
             return;
         }
         l_sdata->session_id = a_ch->stream->session->id;
-        HASH_ADD_INT(s_chain_net_data, session_id, l_sdata);
+        HASH_ADD(hh, s_chain_net_data, session_id, sizeof(uint32_t), l_sdata);
     }
     pthread_mutex_unlock(&s_hash_mutex);
 }
@@ -388,7 +386,7 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg)
                         flags = l_orders_num ? flags | F_ORDR : flags & ~F_ORDR;
                         bool auto_online = dap_config_get_item_bool_default( g_config, "general", "auto_online", false );
                         bool auto_update = false;
-                        if(system("systemctl status cellframe-updater.service") == 0)
+                        if((system("systemctl status cellframe-updater.service") == 768) && (system("systemctl status cellframe-updater.timer") == 0))
                             auto_update = true;
                         else
                             auto_update = false;
diff --git a/modules/channel/chain-net/include/dap_stream_ch_chain_net.h b/modules/channel/chain-net/include/dap_stream_ch_chain_net.h
index 78dc6d609a869a9c46e501bb073448113469baf6..9b53d5c21ae7fc739b9a463480ca7d167f3b9c95 100644
--- a/modules/channel/chain-net/include/dap_stream_ch_chain_net.h
+++ b/modules/channel/chain-net/include/dap_stream_ch_chain_net.h
@@ -65,7 +65,7 @@ typedef struct dap_stream_ch_chain_validator_test{
 #define DAP_STREAM_CH_ID_NET 'N'
 #define DAP_STREAM_CH_CHAIN_NET(a) ((dap_stream_ch_chain_net_t *) ((a)->internal) )
 
-dap_chain_node_addr_t dap_stream_ch_chain_net_from_session_data_extract_node_addr(unsigned int a_session_id);
+dap_chain_node_addr_t dap_stream_ch_chain_net_from_session_data_extract_node_addr(uint32_t a_session_id);
 
 int dap_stream_ch_chain_net_init();
 void dap_stream_ch_chain_net_deinit();
diff --git a/modules/channel/chain/dap_stream_ch_chain.c b/modules/channel/chain/dap_stream_ch_chain.c
index 27efe47aeed63aa9a2d4a10999a1de10a8caf52e..09b6481acde2df21c3538b6a177012b80b8f1652 100644
--- a/modules/channel/chain/dap_stream_ch_chain.c
+++ b/modules/channel/chain/dap_stream_ch_chain.c
@@ -83,6 +83,7 @@ struct sync_request
     dap_stream_ch_chain_hash_item_t *remote_gdbs; // Remote gdbs
 
     uint64_t stats_request_elemets_processed;
+    int last_err;
     union{
         struct{
             dap_db_log_list_t *db_log; //  db log
@@ -493,8 +494,12 @@ static bool s_sync_update_gdb_proc_callback(dap_proc_thread_t *a_thread, void *a
         return true;
     }
     dap_chain_net_add_downlink(l_net, l_ch->stream_worker, l_ch->uuid, l_ch->stream->esocket_uuid,
-                               /*l_ch->stream->esocket->remote_addr_str*/ l_ch->stream->esocket->hostaddr,
-                               dap_config_get_item_int32(g_config, "server", "listen_port_tcp"));
+                               l_ch->stream->esocket->hostaddr[0]
+            ? l_ch->stream->esocket->hostaddr : l_ch->stream->esocket->remote_addr_str,
+            l_ch->stream->esocket->service[0]
+            ? strtoll(l_ch->stream->esocket->service, NULL, 10)
+            : l_ch->stream->esocket->remote_addr.sin_port);
+
     dap_stream_ch_chain_t *l_ch_chain = DAP_STREAM_CH_CHAIN(l_ch);
     int l_flags = 0;
     if (dap_chain_net_get_extra_gdb_group(l_net, l_sync_request->request.node_addr))
@@ -606,7 +611,7 @@ static void s_gdb_in_pkt_error_worker_callback(dap_worker_t *a_worker, void *a_a
         dap_stream_ch_chain_pkt_write_error_unsafe(l_ch, l_sync_request->request_hdr.net_id.uint64,
                                                    l_sync_request->request_hdr.chain_id.uint64,
                                                    l_sync_request->request_hdr.cell_id.uint64,
-                                                   "ERROR_GLOBAL_DB_INTERNAL_NOT_SAVED");
+                                                   "%s : err %d", "ERROR_GLOBAL_DB_INTERNAL_NOT_SAVED", l_sync_request->last_err);
     }
     DAP_DELETE(l_sync_request);
 }
@@ -784,6 +789,7 @@ static void s_gdb_in_pkt_proc_set_raw_callback(dap_global_db_context_t *a_global
     struct sync_request *l_sync_req = (struct sync_request*) a_arg;
     if( a_rc != 0){
         debug_if(s_debug_more, L_ERROR, "Can't save GlobalDB request, code %d", a_rc);
+        l_sync_req->last_err = a_rc;
         dap_worker_exec_callback_inter(a_global_db_context->queue_worker_callback_input[l_sync_req->worker->id],
                                     s_gdb_in_pkt_error_worker_callback, l_sync_req);
     }else{
@@ -826,8 +832,9 @@ static void s_stream_ch_write_error_unsafe(dap_stream_ch_t *a_ch, uint64_t a_net
 static bool s_chain_timer_callback(void *a_arg)
 {
     dap_worker_t *l_worker = dap_worker_get_current();
-    dap_stream_ch_t *l_ch = dap_stream_ch_find_by_uuid_unsafe(DAP_STREAM_WORKER(l_worker), *(dap_stream_ch_uuid_t *)a_arg);
+    dap_stream_ch_t *l_ch = dap_stream_ch_find_by_uuid_unsafe(DAP_STREAM_WORKER(l_worker), *(dap_stream_ch_uuid_t*)a_arg);
     if (!l_ch) {
+        //dap_chain_net_del_downlink((dap_stream_ch_uuid_t*)a_arg);
         DAP_DELETE(a_arg);
         return false;
     }
@@ -925,7 +932,7 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg)
         } else {
             log_it(L_ERROR, "Invalid request from %s with ext_id %016"DAP_UINT64_FORMAT_x" net id 0x%016"DAP_UINT64_FORMAT_x
                             " chain id 0x%016"DAP_UINT64_FORMAT_x" cell_id 0x%016"DAP_UINT64_FORMAT_x" in packet",
-                            a_ch->stream->esocket->remote_addr_str, l_chain_pkt->hdr.ext_id,
+                            a_ch->stream->esocket->hostaddr, l_chain_pkt->hdr.ext_id,
                             l_chain_pkt->hdr.net_id.uint64, l_chain_pkt->hdr.chain_id.uint64,
                             l_chain_pkt->hdr.cell_id.uint64);
             s_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id.uint64,
@@ -946,7 +953,8 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg)
     uint16_t l_acl_idx = dap_chain_net_get_acl_idx(l_net);
     uint8_t l_acl = a_ch->stream->session->acl ? a_ch->stream->session->acl[l_acl_idx] : 1;
     if (!l_acl) {
-        log_it(L_WARNING, "Unauthorized request attempt from %s to network %s", a_ch->stream->esocket->remote_addr_str,
+        log_it(L_WARNING, "Unauthorized request attempt from %s to network %s",
+               a_ch->stream->esocket->hostaddr,
                dap_chain_net_by_id(l_chain_pkt->hdr.net_id)->pub.name);
         s_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id.uint64,
                                             l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64,
@@ -1212,7 +1220,7 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg)
             if (!l_chain) {
                 log_it(L_ERROR, "Invalid UPDATE_CHAINS_START request from %s with ext_id %016"DAP_UINT64_FORMAT_x" net id 0x%016"DAP_UINT64_FORMAT_x
                                 " chain id 0x%016"DAP_UINT64_FORMAT_x" cell_id 0x%016"DAP_UINT64_FORMAT_x" in packet",
-                                a_ch->stream->esocket->remote_addr_str, l_chain_pkt->hdr.ext_id,
+                                a_ch->stream->esocket->hostaddr, l_chain_pkt->hdr.ext_id,
                                 l_chain_pkt->hdr.net_id.uint64, l_chain_pkt->hdr.chain_id.uint64,
                                 l_chain_pkt->hdr.cell_id.uint64);
                 s_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id.uint64,
@@ -1461,8 +1469,8 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg)
                 l_error_str[l_chain_pkt_data_size-1]='\0'; // To be sure that nobody sends us garbage
                                                            // without trailing zero
             log_it(L_WARNING,"In from remote addr %s chain id 0x%016"DAP_UINT64_FORMAT_x" got error on his side: '%s'",
-                                DAP_STREAM_CH(l_ch_chain)->stream->esocket->remote_addr_str,
-                                l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt_data_size ? l_error_str : "<empty>");
+                   DAP_STREAM_CH(l_ch_chain)->stream->esocket->hostaddr,
+                   l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt_data_size ? l_error_str : "<empty>");
         } break;
 
         case DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_ALL: {
diff --git a/modules/common/dap_chain_datum.c b/modules/common/dap_chain_datum.c
index d893124eb3cd5e02f094001da2608217511ec8ef..48fa8d157b1dba9488a596a50fce44f6f541fa50 100644
--- a/modules/common/dap_chain_datum.c
+++ b/modules/common/dap_chain_datum.c
@@ -97,64 +97,70 @@ void s_datum_token_dump_tsd(dap_string_t *a_str_out, dap_chain_datum_token_t *a_
                    l_tsd->size, l_tsd_total_size - l_offset);
             return;
         }
-        switch( l_tsd->type){
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_SET_FLAGS:
-                dap_string_append_printf(a_str_out,"flags_set: ");
-                dap_chain_datum_token_flags_dump(a_str_out,
-                                                 dap_tsd_get_scalar(l_tsd, uint16_t));
-                continue;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_UNSET_FLAGS:
-                dap_string_append_printf(a_str_out,"flags_unset: ");
-                dap_chain_datum_token_flags_dump(a_str_out,
-                                                 dap_tsd_get_scalar(l_tsd, uint16_t));
+        switch(l_tsd->type) {
+        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_SET_FLAGS: {
+            dap_string_append_printf(a_str_out,"flags_set: ");
+            uint16_t l_t = 0;
+            dap_chain_datum_token_flags_dump(a_str_out, _dap_tsd_get_scalar(l_tsd, &l_t));
             continue;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SUPPLY: { // 256
-                char *l_balance = dap_chain_balance_print(dap_tsd_get_scalar(l_tsd, uint256_t));
-                dap_string_append_printf(a_str_out, "total_supply: %s\n", l_balance);
-                DAP_DELETE(l_balance);
-            }
+        }
+        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_UNSET_FLAGS: {
+            dap_string_append_printf(a_str_out,"flags_unset: ");
+            uint16_t l_t = 0;
+            dap_chain_datum_token_flags_dump(a_str_out, _dap_tsd_get_scalar(l_tsd, &l_t));
             continue;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SUPPLY_OLD: {// 128
-                char *l_balance = dap_chain_balance_print(GET_256_FROM_128(dap_tsd_get_scalar(l_tsd, uint128_t)));
-                dap_string_append_printf(a_str_out, "total_supply: %s\n", l_balance);
-                DAP_DELETE(l_balance);
-            }
+        }
+        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SUPPLY: {     // 256
+            uint256_t l_t = uint256_0;
+            char *l_balance = dap_chain_balance_print(_dap_tsd_get_scalar(l_tsd, &l_t));
+            dap_string_append_printf(a_str_out, "total_supply: %s\n", l_balance);
+            DAP_DELETE(l_balance);
             continue;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_VALID :
-                dap_string_append_printf(a_str_out,"total_signs_valid: %u\n",
-                                         dap_tsd_get_scalar(l_tsd, uint16_t) );
+        }
+        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SUPPLY_OLD: { // 128
+            uint128_t l_t = uint128_0;
+            char *l_balance = dap_chain_balance_print(GET_256_FROM_128(_dap_tsd_get_scalar(l_tsd, &l_t)));
+            dap_string_append_printf(a_str_out, "total_supply: %s\n", l_balance);
+            DAP_DELETE(l_balance);
             continue;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_PKEYS_ADD:
-                if(l_tsd->size >= sizeof(dap_pkey_t)){
-                    char *l_hash_str;
-                    dap_pkey_t *l_pkey = (dap_pkey_t*)l_tsd->data;
-                    dap_hash_fast_t l_hf = {0};
-                    if (!dap_pkey_get_hash(l_pkey, &l_hf)) {
-                        dap_string_append_printf(a_str_out,"total_pkeys_add: <WRONG CALCULATION FINGERPRINT>\n");
-                    } else {
-                        if (!dap_strcmp(a_hash_out_type, "hex") || !dap_strcmp(a_hash_out_type, "content_hash"))
-                            l_hash_str = dap_chain_hash_fast_to_str_new(&l_hf);
-                        else
-                            l_hash_str = dap_enc_base58_encode_hash_to_str(&l_hf);
-                        dap_string_append_printf(a_str_out, "total_pkeys_add: %s\n", l_hash_str);
-                        DAP_DELETE(l_hash_str);
-                    }
-                } else
+        }
+        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_VALID: {
+            uint16_t l_t = 0;
+            dap_string_append_printf(a_str_out,"total_signs_valid: %u\n", _dap_tsd_get_scalar(l_tsd, &l_t));
+            continue;
+        }
+        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_PKEYS_ADD:
+            if(l_tsd->size >= sizeof(dap_pkey_t)) {
+                char *l_hash_str;
+                dap_pkey_t *l_pkey = (dap_pkey_t*)l_tsd->data;
+                dap_hash_fast_t l_hf = { };
+                if (!dap_pkey_get_hash(l_pkey, &l_hf)) {
+                    dap_string_append_printf(a_str_out,"total_pkeys_add: <WRONG CALCULATION FINGERPRINT>\n");
+                } else {
+                    if (!dap_strcmp(a_hash_out_type, "hex") || !dap_strcmp(a_hash_out_type, "content_hash"))
+                        l_hash_str = dap_chain_hash_fast_to_str_new(&l_hf);
+                    else
+                        l_hash_str = dap_enc_base58_encode_hash_to_str(&l_hf);
+                    dap_string_append_printf(a_str_out, "total_pkeys_add: %s\n", l_hash_str);
+                    DAP_DELETE(l_hash_str);
+                }
+            } else
                     dap_string_append_printf(a_str_out,"total_pkeys_add: <WRONG SIZE %u>\n", l_tsd->size);
             continue;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_PKEYS_REMOVE:
+
+        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_PKEYS_REMOVE:
                 if(l_tsd->size == sizeof(dap_chain_hash_fast_t) ){
                     char *l_hash_str = (!dap_strcmp(a_hash_out_type,"hex")|| !dap_strcmp(a_hash_out_type, "content_hash"))
                             ? dap_chain_hash_fast_to_str_new((dap_chain_hash_fast_t*) l_tsd->data)
                             : dap_enc_base58_encode_hash_to_str((dap_chain_hash_fast_t*) l_tsd->data);
                     dap_string_append_printf(a_str_out,"total_pkeys_remove: %s\n", l_hash_str);
                     DAP_DELETE( l_hash_str );
-                }else
+                } else
                     dap_string_append_printf(a_str_out,"total_pkeys_remove: <WRONG SIZE %u>\n", l_tsd->size);
             continue;
             case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DELEGATE_EMISSION_FROM_STAKE_LOCK: {
                 char *balance = NULL;
-                dap_chain_datum_token_tsd_delegate_from_stake_lock_t *l_tsd_section = dap_tsd_get_object(l_tsd, dap_chain_datum_token_tsd_delegate_from_stake_lock_t);
+                dap_chain_datum_token_tsd_delegate_from_stake_lock_t *l_tsd_section = _dap_tsd_get_object(l_tsd, dap_chain_datum_token_tsd_delegate_from_stake_lock_t);
                 dap_string_append_printf(a_str_out, "ticker_token_from: %s\nemission_rate: %s\n",
                                          l_tsd_section->ticker_token_from, (balance = dap_chain_balance_to_coins(l_tsd_section->emission_rate)));
                 DAP_DEL_Z(balance);
diff --git a/modules/common/dap_chain_datum_anchor.c b/modules/common/dap_chain_datum_anchor.c
index 736781fc7d6a822c135e557fd6cc542dcd76dc8e..76fa90c0af98aef46e2a93753c0cf82dce58aa36 100644
--- a/modules/common/dap_chain_datum_anchor.c
+++ b/modules/common/dap_chain_datum_anchor.c
@@ -51,7 +51,7 @@ int dap_chain_datum_anchor_get_hash_from_data(dap_chain_datum_anchor_t* a_anchor
                 log_it(L_WARNING,"Wrong fee tsd data size.");
                 return -1;
             }
-            *l_out_hash = dap_tsd_get_scalar(l_tsd, dap_hash_fast_t);
+            _dap_tsd_get_scalar(l_tsd, l_out_hash);
             return 0;
         }
         l_tsd_offset += l_tsd_size;
diff --git a/modules/common/dap_chain_datum_decree.c b/modules/common/dap_chain_datum_decree.c
index 69941575b310fda910657a4ed0ccd38bd4d9f94b..52853e994297a7387da524bc6782d62fa55f003e 100644
--- a/modules/common/dap_chain_datum_decree.c
+++ b/modules/common/dap_chain_datum_decree.c
@@ -35,319 +35,121 @@
 
 dap_sign_t *dap_chain_datum_decree_get_signs(dap_chain_datum_decree_t *a_decree, size_t* a_signs_size)
 {
-    if (!a_decree)
+    if (!a_decree || !a_signs_size) {
+        log_it(L_CRITICAL, "Invalid arguments");
         return NULL;
+    }
 
-    dap_sign_t *l_signs_section = (dap_sign_t *)(a_decree->data_n_signs + a_decree->header.data_size);
-
+    dap_sign_t *l_signs_section = (dap_sign_t*)(a_decree->data_n_signs + a_decree->header.data_size);
     *a_signs_size = a_decree->header.signs_size;
-
     return l_signs_section;
 }
 
 int dap_chain_datum_decree_get_fee(dap_chain_datum_decree_t *a_decree, uint256_t *a_fee_value)
 {
-    if(!a_decree || !a_fee_value){
-        log_it(L_WARNING,"Wrong arguments");
+    if(!a_decree || !a_fee_value) {
+        log_it(L_CRITICAL, "Invalid arguments");
         return -1;
     }
-
-    size_t l_tsd_offset = 0, tsd_data_size = a_decree->header.data_size;
-
-    while(l_tsd_offset < tsd_data_size){
-        dap_tsd_t *l_tsd = (dap_tsd_t *)(a_decree->data_n_signs + l_tsd_offset);
-        size_t l_tsd_size = l_tsd->size + sizeof(dap_tsd_t);
-        if(l_tsd_size > tsd_data_size){
-            log_it(L_WARNING,"TSD size is greater than all data size. It's possible corrupt data.");
-            return -1;
-        }
-        if (l_tsd->type == DAP_CHAIN_DATUM_DECREE_TSD_TYPE_FEE){
-            if(l_tsd->size > sizeof(uint256_t)){
-                log_it(L_WARNING,"Wrong fee tsd data size.");
-                return -1;
-            }
-            *a_fee_value = dap_tsd_get_scalar(l_tsd, uint256_t);
-            return 0;
-        }
-        l_tsd_offset += l_tsd_size;
-    }
-    return 1;
+    dap_tsd_t* l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_FEE);
+    return l_tsd ? ({ _dap_tsd_get_scalar(l_tsd, a_fee_value); 0; }) : 1;
 }
 
 int dap_chain_datum_decree_get_fee_addr(dap_chain_datum_decree_t *a_decree, dap_chain_addr_t *a_fee_wallet)
 {
-    if(!a_decree || !a_fee_wallet){
-        log_it(L_WARNING,"Wrong arguments");
+    if(!a_decree || !a_fee_wallet) {
+        log_it(L_CRITICAL, "Invalid arguments");
         return -1;
     }
+    dap_tsd_t* l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_FEE_WALLET);
+    return l_tsd ? ({ _dap_tsd_get_scalar(l_tsd, a_fee_wallet); 0; }) : 1;
+}
 
-    size_t l_tsd_offset = 0, tsd_data_size = a_decree->header.data_size;
-
-    while(l_tsd_offset < tsd_data_size){
-        dap_tsd_t *l_tsd = (dap_tsd_t *)(a_decree->data_n_signs + l_tsd_offset);
-        size_t l_tsd_size = l_tsd->size + sizeof(dap_tsd_t);
-        if(l_tsd_size > tsd_data_size){
-            log_it(L_WARNING,"TSD size is greater than all data size. It's possible corrupt data.");
-            return -1;
-        }
-        if (l_tsd->type == DAP_CHAIN_DATUM_DECREE_TSD_TYPE_FEE_WALLET){
-            if(l_tsd->size > sizeof(dap_chain_addr_t)){
-                log_it(L_WARNING,"Wrong fee tsd data size.");
-                return -1;
-            }
-            dap_chain_addr_t l_addr = {0};
-            l_addr = dap_tsd_get_scalar(l_tsd, dap_chain_addr_t);
-            *a_fee_wallet = l_addr;
-            return 0;
-        }
-        l_tsd_offset += l_tsd_size;
-    }
-    return 1;
+static void *s_cb_copy_pkeys(const void *a_pkey, UNUSED_ARG void *a_data) {
+    return DAP_DUP((dap_pkey_t*)a_pkey);
 }
 
 dap_list_t *dap_chain_datum_decree_get_owners(dap_chain_datum_decree_t *a_decree, uint16_t *a_owners_num)
 {
     if(!a_decree || !a_owners_num){
-        log_it(L_WARNING,"Wrong arguments");
+        log_it(L_CRITICAL, "Invalid arguments");
         return NULL;
     }
-
-    size_t l_tsd_offset = 0, tsd_data_size = a_decree->header.data_size;
-    uint64_t l_owners_num = 0;
-    dap_list_t *l_key_list = NULL;
-
-
-    while(l_tsd_offset < tsd_data_size){
-        dap_tsd_t *l_tsd = (dap_tsd_t *)(a_decree->data_n_signs + l_tsd_offset);
-        size_t l_tsd_size = dap_tsd_size(l_tsd);
-        if(l_tsd_size > tsd_data_size){
-            log_it(L_WARNING,"TSD size is greater than all data size. It's possible corrupt data.");
-            if (l_key_list)
-                dap_list_free_full(l_key_list, NULL);
-            return NULL;
-        }
-        if (l_tsd->type == DAP_CHAIN_DATUM_DECREE_TSD_TYPE_OWNER){
-            dap_pkey_t *l_owner_pkey = DAP_NEW_Z_SIZE(dap_pkey_t, l_tsd->size);
-            if (!l_owner_pkey){
-                log_it(L_WARNING,"Memory allocate failed.");
-                dap_list_free_full(l_key_list, NULL);
-                return NULL;
-            }
-
-            memcpy(l_owner_pkey, l_tsd->data, l_tsd->size);
-            l_key_list = dap_list_append(l_key_list, l_owner_pkey);
-            l_owners_num++;
-        }
-        l_tsd_offset += l_tsd_size;
-    }
-    if (a_owners_num)
-        *a_owners_num = l_owners_num;
-    return l_key_list;
+    dap_list_t *l_tsd_list = dap_tsd_find_all(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_OWNER);
+    *a_owners_num = (uint16_t)dap_list_length(l_tsd_list);
+    dap_list_t *l_ret = dap_list_copy_deep(l_tsd_list, s_cb_copy_pkeys, NULL);
+    dap_list_free(l_tsd_list);
+    return l_ret;
 }
 
 int dap_chain_datum_decree_get_min_owners(dap_chain_datum_decree_t *a_decree, uint16_t *a_min_owners_num)
 {
     if(!a_decree || !a_min_owners_num){
-        log_it(L_WARNING,"Wrong arguments");
+        log_it(L_CRITICAL, "Invalid arguments");
         return -1;
     }
-
-    size_t l_tsd_offset = 0, tsd_data_size = a_decree->header.data_size;
-
-    while(l_tsd_offset < tsd_data_size){
-        dap_tsd_t *l_tsd = (dap_tsd_t *)(a_decree->data_n_signs + l_tsd_offset);
-        size_t l_tsd_size = dap_tsd_size(l_tsd);
-        if(l_tsd_size > tsd_data_size){
-            log_it(L_WARNING,"TSD size is greater than all data size. It's possible corrupt data.");
-            return -1;
-        }
-        if (l_tsd->type == DAP_CHAIN_DATUM_DECREE_TSD_TYPE_MIN_OWNER){
-            if(l_tsd->size > sizeof(uint256_t)){
-                log_it(L_WARNING,"Wrong fee tsd data size.");
-                return -1;
-            }
-            uint256_t l_min_owners_num = dap_tsd_get_scalar(l_tsd, uint256_t);
-            if (a_min_owners_num)
-                *a_min_owners_num = dap_chain_uint256_to(l_min_owners_num);
-            return 0;
-        }
-        l_tsd_offset += l_tsd_size;
-    }
-    return 1;
+    dap_tsd_t* l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_MIN_OWNER);
+    return l_tsd ? ({ _dap_tsd_get_scalar(l_tsd, a_min_owners_num); 0; }) : 1;
 }
 
 int dap_chain_datum_decree_get_stake_tx_hash(dap_chain_datum_decree_t *a_decree, dap_hash_fast_t *a_tx_hash)
 {
     if(!a_decree || !a_tx_hash){
-        log_it(L_WARNING,"Wrong arguments");
+        log_it(L_CRITICAL, "Invalid arguments");
         return -1;
     }
-
-    size_t l_tsd_offset = 0, tsd_data_size = a_decree->header.data_size;
-
-    while(l_tsd_offset < tsd_data_size){
-        dap_tsd_t *l_tsd = (dap_tsd_t *)(a_decree->data_n_signs + l_tsd_offset);
-        size_t l_tsd_size = dap_tsd_size(l_tsd);
-        if(l_tsd_size > tsd_data_size){
-            log_it(L_WARNING,"TSD size is greater than all data size. It's possible corrupt data.");
-            return -1;
-        }
-        if (l_tsd->type == DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_TX_HASH){
-            if(l_tsd->size > sizeof(dap_hash_fast_t)){
-                log_it(L_WARNING,"Wrong fee tsd data size.");
-                return -1;
-            }
-            *a_tx_hash = dap_tsd_get_scalar(l_tsd, dap_hash_fast_t);
-            return 0;
-        }
-        l_tsd_offset += l_tsd_size;
-    }
-    return 1;
+    dap_tsd_t* l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_TX_HASH);
+    return l_tsd ? ({ _dap_tsd_get_scalar(l_tsd, a_tx_hash); 0; }) : 1;
 }
 
 int dap_chain_datum_decree_get_stake_value(dap_chain_datum_decree_t *a_decree, uint256_t *a_stake_value)
 {
     if(!a_decree || !a_stake_value){
-        log_it(L_WARNING,"Wrong arguments");
+        log_it(L_CRITICAL, "Invalid arguments");
         return -1;
     }
-
-    size_t l_tsd_offset = 0, tsd_data_size = a_decree->header.data_size;
-
-    while(l_tsd_offset < tsd_data_size){
-        dap_tsd_t *l_tsd = (dap_tsd_t *)(a_decree->data_n_signs + l_tsd_offset);
-        size_t l_tsd_size = dap_tsd_size(l_tsd);
-        if(l_tsd_size > tsd_data_size){
-            log_it(L_WARNING,"TSD size is greater than all data size. It's possible corrupt data.");
-            return -1;
-        }
-        if (l_tsd->type == DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_VALUE){
-            if(l_tsd->size > sizeof(uint256_t)){
-                log_it(L_WARNING,"Wrong fee tsd data size.");
-                return -1;
-            }
-            *a_stake_value = dap_tsd_get_scalar(l_tsd, uint256_t);
-            return 0;
-        }
-        l_tsd_offset += l_tsd_size;
-    }
-    return 1;
+    dap_tsd_t* l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_VALUE);
+    return l_tsd ? ({ _dap_tsd_get_scalar(l_tsd, a_stake_value); 0; }) : 1;
 }
 
 int dap_chain_datum_decree_get_stake_signing_addr(dap_chain_datum_decree_t *a_decree, dap_chain_addr_t *a_signing_addr)
 {
     if(!a_decree || !a_signing_addr){
-        log_it(L_WARNING,"Wrong arguments");
+        log_it(L_CRITICAL, "Invalid arguments");
         return -1;
     }
-
-    size_t l_tsd_offset = 0, tsd_data_size = a_decree->header.data_size;
-
-    while(l_tsd_offset < tsd_data_size){
-        dap_tsd_t *l_tsd = (dap_tsd_t *)(a_decree->data_n_signs + l_tsd_offset);
-        size_t l_tsd_size = dap_tsd_size(l_tsd);
-        if(l_tsd_size > tsd_data_size){
-            log_it(L_WARNING,"TSD size is greater than all data size. It's possible corrupt data.");
-            return -1;
-        }
-        if (l_tsd->type == DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_SIGNING_ADDR){
-            if(l_tsd->size > sizeof(dap_chain_addr_t)){
-                log_it(L_WARNING,"Wrong fee tsd data size.");
-                return -1;
-            }
-            *a_signing_addr = dap_tsd_get_scalar(l_tsd, dap_chain_addr_t);
-            return 0;
-        }
-        l_tsd_offset += l_tsd_size;
-    }
-    return 1;
+    dap_tsd_t* l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_SIGNING_ADDR);
+    return l_tsd ? ({ _dap_tsd_get_scalar(l_tsd, a_signing_addr); 0; }) : 1;
 }
 
 int dap_chain_datum_decree_get_stake_signer_node_addr(dap_chain_datum_decree_t *a_decree, dap_chain_node_addr_t *a_node_addr)
 {
     if(!a_decree || !a_node_addr){
-        log_it(L_WARNING,"Wrong arguments");
+        log_it(L_CRITICAL, "Invalid arguments");
         return -1;
     }
-
-    size_t l_tsd_offset = 0, tsd_data_size = a_decree->header.data_size;
-
-    while(l_tsd_offset < tsd_data_size){
-        dap_tsd_t *l_tsd = (dap_tsd_t *)(a_decree->data_n_signs + l_tsd_offset);
-        size_t l_tsd_size = dap_tsd_size(l_tsd);
-        if(l_tsd_size > tsd_data_size){
-            log_it(L_WARNING,"TSD size is greater than all data size. It's possible corrupt data.");
-            return -1;
-        }
-        if (l_tsd->type == DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_SIGNER_NODE_ADDR){
-            if(l_tsd->size > sizeof(dap_chain_node_addr_t)){
-                log_it(L_WARNING,"Wrong fee tsd data size.");
-                return -1;
-            }
-            *a_node_addr = dap_tsd_get_scalar(l_tsd, dap_chain_node_addr_t);
-            return 0;
-        }
-        l_tsd_offset += l_tsd_size;
-    }
-    return 1;
+    dap_tsd_t* l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_SIGNER_NODE_ADDR);
+    return l_tsd ? ({ _dap_tsd_get_scalar(l_tsd, a_node_addr); 0; }) : 1;
 }
 
 int dap_chain_datum_decree_get_stake_min_value(dap_chain_datum_decree_t *a_decree, uint256_t *a_min_value)
 {
     if(!a_decree || !a_min_value){
-        log_it(L_WARNING,"Wrong arguments");
+        log_it(L_CRITICAL, "Invalid arguments");
         return -1;
     }
-
-    size_t l_tsd_offset = 0, tsd_data_size = a_decree->header.data_size;
-
-    while(l_tsd_offset < tsd_data_size){
-        dap_tsd_t *l_tsd = (dap_tsd_t *)(a_decree->data_n_signs + l_tsd_offset);
-        size_t l_tsd_size = dap_tsd_size(l_tsd);
-        if(l_tsd_size > tsd_data_size){
-            log_it(L_WARNING,"TSD size is greater than all data size. It's possible corrupt data.");
-            return -1;
-        }
-        if (l_tsd->type == DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_MIN_VALUE){
-            if(l_tsd->size > sizeof(uint256_t)){
-                log_it(L_WARNING,"Wrong fee tsd data size.");
-                return -1;
-            }
-            *a_min_value = dap_tsd_get_scalar(l_tsd, uint256_t);
-            return 0;
-        }
-        l_tsd_offset += l_tsd_size;
-    }
-    return 1;
+    dap_tsd_t* l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_MIN_VALUE);
+    return l_tsd ? ({ _dap_tsd_get_scalar(l_tsd, a_min_value); 0; }) : 1;
 }
 
 int dap_chain_datum_decree_get_stake_min_signers_count(dap_chain_datum_decree_t *a_decree, uint256_t *a_min_signers_count)
 {
     if(!a_decree || !a_min_signers_count){
-        log_it(L_WARNING,"Wrong arguments");
+        log_it(L_CRITICAL, "Invalid arguments");
         return -1;
     }
-
-    size_t l_tsd_offset = 0, tsd_data_size = a_decree->header.data_size;
-
-    while(l_tsd_offset < tsd_data_size){
-        dap_tsd_t *l_tsd = (dap_tsd_t *)(a_decree->data_n_signs + l_tsd_offset);
-        size_t l_tsd_size = dap_tsd_size(l_tsd);
-        if(l_tsd_size > tsd_data_size){
-            log_it(L_WARNING,"TSD size is greater than all data size. It's possible corrupt data.");
-            return -1;
-        }
-        if (l_tsd->type == DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_MIN_SIGNERS_COUNT){
-            if(l_tsd->size > sizeof(uint256_t)){
-                log_it(L_WARNING,"Wrong fee tsd data size.");
-                return -1;
-            }
-            *a_min_signers_count = dap_tsd_get_scalar(l_tsd, uint256_t);
-            return 0;
-        }
-        l_tsd_offset += l_tsd_size;
-    }
-    return 1;
+    dap_tsd_t* l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_MIN_SIGNERS_COUNT);
+    return l_tsd ? ({ _dap_tsd_get_scalar(l_tsd, a_min_signers_count); 0; }) : 1;
 }
 
 void dap_chain_datum_decree_dump(dap_string_t *a_str_out, dap_chain_datum_decree_t *a_decree, size_t a_decree_size, const char *a_hash_out_type) {
@@ -372,13 +174,15 @@ void dap_chain_datum_decree_dump(dap_string_t *a_str_out, dap_chain_datum_decree
         l_offset += dap_tsd_size(l_tsd);
         switch(l_tsd->type) {
             case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_SIGN:
+            break;
 //                return "DAP_CHAIN_DATUM_DECREE_TSD_TYPE_SIGN";
             case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_FEE:
                 if (l_tsd->size > sizeof(uint256_t)){
                     dap_string_append_printf(a_str_out, "\tFee: <WRONG SIZE>\n");
                     break;
                 }
-                uint256_t l_fee_value = dap_tsd_get_scalar(l_tsd, uint256_t);
+                uint256_t l_fee_value = uint256_0;
+                _dap_tsd_get_scalar(l_tsd, &l_fee_value);
                 char *l_fee_value_str = dap_chain_balance_print(l_fee_value);
                 dap_string_append_printf(a_str_out, "\tFee: %s\n", l_fee_value_str);
                 DAP_DELETE(l_fee_value_str);
@@ -388,12 +192,10 @@ void dap_chain_datum_decree_dump(dap_string_t *a_str_out, dap_chain_datum_decree
                     dap_string_append_printf(a_str_out, "\tOwner fingerprint: <WRONG SIZE>\n");
                     break;
                 }
-                dap_pkey_t *l_owner_pkey = DAP_NEW_Z_SIZE(dap_pkey_t, l_tsd->size);
-                memcpy(l_owner_pkey, l_tsd->data, l_tsd->size);
-                dap_hash_fast_t l_owner_pkey_hash = {0};
-                dap_hash_fast(l_owner_pkey->pkey, l_owner_pkey->header.size, &l_owner_pkey_hash);
-                char l_owner_pkey_str[DAP_CHAIN_HASH_FAST_STR_SIZE];
-                dap_chain_hash_fast_to_str(&l_owner_pkey_hash, l_owner_pkey_str, sizeof(l_owner_pkey_str));
+                dap_pkey_t *l_owner_pkey = /*DAP_NEW_STACK_SIZE(dap_pkey_t, l_tsd->size);
+                memcpy(l_owner_pkey, l_tsd->data, l_tsd->size);*/ _dap_tsd_get_object(l_tsd, dap_pkey_t);
+                char *l_owner_pkey_str;
+                dap_get_data_hash_str_static(l_owner_pkey->pkey, l_owner_pkey->header.size, l_owner_pkey_str);
                 dap_string_append_printf(a_str_out, "\tOwner fingerprint: %s\n", l_owner_pkey_str);
                 break;
             case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_MIN_OWNER:
@@ -401,7 +203,8 @@ void dap_chain_datum_decree_dump(dap_string_t *a_str_out, dap_chain_datum_decree
                     dap_string_append_printf(a_str_out, "\tOwner min: <WRONG SIZE>\n");
                     break;
                 }
-                uint256_t l_owner_min = dap_tsd_get_scalar(l_tsd, uint256_t);
+                uint256_t l_owner_min = uint256_0;
+                _dap_tsd_get_scalar(l_tsd, &l_owner_min);
                 char *l_owner_min_str = dap_chain_balance_print(l_owner_min);
                 dap_string_append_printf(a_str_out, "\tOwner min: %s\n", l_owner_min_str);
                 DAP_DELETE(l_owner_min_str);
@@ -411,9 +214,9 @@ void dap_chain_datum_decree_dump(dap_string_t *a_str_out, dap_chain_datum_decree
                     dap_string_append_printf(a_str_out, "\tWallet for fee: <WRONG SIZE>\n");
                     break;
                 }
-                dap_chain_addr_t l_addr_fee_wallet = {0};
-                l_addr_fee_wallet = dap_tsd_get_scalar(l_tsd, dap_chain_addr_t);
-                char *l_addr_fee_wallet_str = dap_chain_addr_to_str(&l_addr_fee_wallet);
+                dap_chain_addr_t *l_addr_fee_wallet = /*{ };
+                _dap_tsd_get_scalar(l_tsd, &l_addr_fee_wallet);*/ _dap_tsd_get_object(l_tsd, dap_chain_addr_t);
+                char *l_addr_fee_wallet_str = dap_chain_addr_to_str(l_addr_fee_wallet);
                 dap_string_append_printf(a_str_out, "\tWallet for fee: %s\n", l_addr_fee_wallet_str);
                 DAP_DELETE(l_addr_fee_wallet_str);
                 break;
@@ -422,11 +225,11 @@ void dap_chain_datum_decree_dump(dap_string_t *a_str_out, dap_chain_datum_decree
                     dap_string_append_printf(a_str_out, "\tStake tx: <WRONG SIZE>\n");
                     break;
                 }
-                dap_hash_fast_t l_stake_tx = {0};
-                l_stake_tx = dap_tsd_get_scalar(l_tsd, dap_hash_fast_t);
+                dap_hash_fast_t *l_stake_tx = /*{ };
+                _dap_tsd_get_scalar(l_tsd, &l_stake_tx);*/ _dap_tsd_get_object(l_tsd, dap_hash_fast_t);
                 char *l_stake_tx_hash = dap_strcmp(a_hash_out_type, "hex")
-                        ? dap_enc_base58_encode_hash_to_str(&l_stake_tx)
-                        : dap_chain_hash_fast_to_str_new(&l_stake_tx);
+                        ? dap_enc_base58_encode_hash_to_str(l_stake_tx)
+                        : dap_chain_hash_fast_to_str_new(l_stake_tx);
                 dap_string_append_printf(a_str_out, "\tStake tx: %s\n", l_stake_tx_hash);
                 DAP_DELETE(l_stake_tx_hash);
                 break;
@@ -435,7 +238,8 @@ void dap_chain_datum_decree_dump(dap_string_t *a_str_out, dap_chain_datum_decree
                     dap_string_append_printf(a_str_out, "\tStake value: <WRONG SIZE>\n");
                     break;
                 }
-                uint256_t l_stake_value = dap_tsd_get_scalar(l_tsd, uint256_t);
+                uint256_t l_stake_value = uint256_0;
+                _dap_tsd_get_scalar(l_tsd, &l_stake_value);
                 char *l_stake_value_str = dap_chain_balance_print(l_stake_value);
                 dap_string_append_printf(a_str_out, "\tStake value: %s\n", l_stake_value_str);
                 DAP_DELETE(l_stake_value_str);
@@ -445,40 +249,34 @@ void dap_chain_datum_decree_dump(dap_string_t *a_str_out, dap_chain_datum_decree
                     dap_string_append_printf(a_str_out, "\tSigning addr: <WRONG SIZE>\n");
                     break;
                 }
-                dap_chain_addr_t l_stake_addr_signing = {0};
-                l_stake_addr_signing = dap_tsd_get_scalar(l_tsd, dap_chain_addr_t);
-                char *l_stake_addr_signing_str = dap_chain_addr_to_str(&l_stake_addr_signing);
+                dap_chain_addr_t *l_stake_addr_signing = /*{ };
+                _dap_tsd_get_scalar(l_tsd, &l_stake_addr_signing);*/ _dap_tsd_get_object(l_tsd, dap_chain_addr_t);
+                char *l_stake_addr_signing_str = dap_chain_addr_to_str(l_stake_addr_signing);
                 dap_string_append_printf(a_str_out, "\tSigning addr: %s\n", l_stake_addr_signing_str);
-                dap_chain_hash_fast_t *l_pkey_signing = DAP_NEW(dap_chain_hash_fast_t);
-                if (!l_pkey_signing) {
-                    log_it(L_CRITICAL, "Memory allocation error");
-                    DAP_DELETE(l_stake_addr_signing_str);
-                    return;
-                }
-                memcpy(l_pkey_signing, l_stake_addr_signing.data.key, sizeof(dap_chain_hash_fast_t));
+                dap_chain_hash_fast_t l_pkey_signing = l_stake_addr_signing->data.hash_fast;
                 char *l_pkey_signing_str = dap_strcmp(a_hash_out_type, "hex")
-                        ? dap_enc_base58_encode_hash_to_str(l_pkey_signing)
-                        : dap_chain_hash_fast_to_str_new(l_pkey_signing);
+                        ? dap_enc_base58_encode_hash_to_str(&l_pkey_signing)
+                        : dap_chain_hash_fast_to_str_new(&l_pkey_signing);
                 dap_string_append_printf(a_str_out, "\tSigning pkey fingerprint: %s\n", l_pkey_signing_str);
                 DAP_DELETE(l_stake_addr_signing_str);
                 DAP_DELETE(l_pkey_signing_str);
-                DAP_DELETE(l_pkey_signing);
                 break;
             case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_SIGNER_NODE_ADDR:
                 if(l_tsd->size > sizeof(dap_chain_node_addr_t)){
                     dap_string_append_printf(a_str_out, "\tNode addr: <WRONG SIZE>\n");
                     break;
                 }
-                dap_chain_node_addr_t l_node_addr = dap_tsd_get_scalar(l_tsd, dap_chain_node_addr_t);
+                dap_chain_node_addr_t *l_node_addr = _dap_tsd_get_object(l_tsd, dap_chain_node_addr_t);
                 dap_string_append_printf(a_str_out, "\tNode addr: "NODE_ADDR_FP_STR"\n",
-                                         NODE_ADDR_FP_ARGS_S(l_node_addr));
+                                         NODE_ADDR_FP_ARGS(l_node_addr));
                 break;
             case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_MIN_VALUE:
                 if (l_tsd->size > sizeof(uint256_t)) {
                     dap_string_append_printf(a_str_out, "\tMin value: <WRONG SIZE>\n");
                     break;
                 }
-                uint256_t l_min_value = dap_tsd_get_scalar(l_tsd, uint256_t);
+                uint256_t l_min_value = uint256_0;
+                _dap_tsd_get_scalar(l_tsd, &l_min_value);
                 char *l_min_value_str = dap_chain_balance_print(l_min_value);
                 dap_string_append_printf(a_str_out, "\tMin value: %s\n", l_min_value_str);
                 DAP_DELETE(l_min_value_str);
@@ -488,7 +286,8 @@ void dap_chain_datum_decree_dump(dap_string_t *a_str_out, dap_chain_datum_decree
                     dap_string_append_printf(a_str_out, "\tMin signers count: <WRONG SIZE>\n");
                     break;
                 }
-                uint256_t l_min_signers_count = dap_tsd_get_scalar(l_tsd, uint256_t);
+                uint256_t l_min_signers_count = uint256_0;
+                _dap_tsd_get_scalar(l_tsd, &l_min_signers_count);
                 char *l_min_signers_count_str = dap_chain_balance_print(l_min_signers_count);
                 dap_string_append_printf(a_str_out, "\tMin signers count: %s\n", l_min_signers_count_str);
                 DAP_DELETE(l_min_signers_count_str);
diff --git a/modules/consensus/esbocs/dap_chain_cs_esbocs.c b/modules/consensus/esbocs/dap_chain_cs_esbocs.c
index a574c1cb7100be815d7fad8c32782843828660b8..fe516a0684f9e7a8a0bdec1fab18c55cc05b9fdf 100644
--- a/modules/consensus/esbocs/dap_chain_cs_esbocs.c
+++ b/modules/consensus/esbocs/dap_chain_cs_esbocs.c
@@ -516,8 +516,15 @@ static dap_enc_key_t *s_callback_get_sign_key(dap_chain_t *a_chain)
 
 static void s_callback_delete(dap_chain_cs_blocks_t *a_blocks)
 {
+
     dap_chain_esbocs_t *l_esbocs = DAP_CHAIN_ESBOCS(a_blocks);
+    DAP_DEL_Z(l_esbocs->_pvt);
+    DAP_DEL_Z(a_blocks->_inheritor);
     dap_chain_esbocs_session_t *l_session = l_esbocs->session;
+    if (!l_session) {
+        log_it(L_INFO, "No session found");
+        return;
+    }
     pthread_mutex_lock(&l_session->mutex);
     DL_DELETE(s_session_items, l_session);
     dap_timerfd_delete_mt(l_session->cs_timer->worker, l_session->cs_timer->esocket_uuid);
@@ -535,9 +542,6 @@ static void s_callback_delete(dap_chain_cs_blocks_t *a_blocks)
     }
     pthread_mutex_unlock(&l_session->mutex);
     DAP_DELETE(l_session);
-    if (l_esbocs->_pvt)
-        DAP_DELETE(l_esbocs->_pvt);
-    DAP_DEL_Z(a_blocks->_inheritor);
 }
 
 static void *s_callback_list_copy(const void *a_validator, UNUSED_ARG void *a_data)
diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c
index 2b40a6d9118168c2ca27837128141b87fbe796da..43375d798cc96c76ac84a80752804408ecee5819 100644
--- a/modules/net/dap_chain_net.c
+++ b/modules/net/dap_chain_net.c
@@ -89,6 +89,7 @@
 #include "dap_chain_datum_anchor.h"
 #include "dap_chain_tx.h"
 #include "dap_chain_net.h"
+#include "dap_chain_net_node_list.h"
 #include "dap_chain_net_tx.h"
 #include "dap_chain_net_anchor.h"
 #include "dap_chain_net_decree.h"
@@ -114,7 +115,7 @@
 #include "dap_stream_ch_pkt.h"
 #include "dap_chain_node_dns_client.h"
 #include "dap_module.h"
-
+#include "rand/dap_rand.h"
 #include "json.h"
 #include "json_object.h"
 #include "dap_chain_net_srv_stake_pos_delegate.h"
@@ -150,7 +151,7 @@ struct downlink {
     dap_stream_worker_t *worker;
     dap_stream_ch_uuid_t ch_uuid;
     dap_events_socket_uuid_t esocket_uuid;
-    char *addr;
+    char addr[INET_ADDRSTRLEN];
     int port;
     UT_hash_handle hh;
 };
@@ -199,6 +200,8 @@ typedef struct dap_chain_net_pvt{
 
     uint16_t seed_aliases_count;
     struct in_addr *seed_nodes_addrs_v4;
+    uint16_t *seed_nodes_ports;
+    uint64_t *seed_nodes_addrs;
 
     dap_chain_net_state_t state;
     dap_chain_net_state_t state_target;
@@ -295,7 +298,7 @@ static void s_update_links_timer_callback(void *a_arg){
     }
     l_node_info->hdr.blocks_events = l_blocks_events;
     char *l_key = dap_chain_node_addr_to_hash_str(l_current_addr);
-    dap_global_db_set_sync(l_net->pub.gdb_nodes, l_key, l_node_info, dap_chain_node_info_get_size(l_node_info), false);
+    //dap_global_db_set_sync(l_net->pub.gdb_nodes, l_key, l_node_info, dap_chain_node_info_get_size(l_node_info), false);
     DAP_DELETE(l_node_info);
 }
 
@@ -482,13 +485,33 @@ int dap_chain_net_add_downlink(dap_chain_net_t *a_net, dap_stream_worker_t *a_wo
             .worker     = a_worker,
             .ch_uuid    = a_ch_uuid,
             .esocket_uuid = a_esocket_uuid,
-            .addr       = a_addr,
             .port       = a_port
     };
+    strncpy(l_downlink->addr, a_addr, INET_ADDRSTRLEN - 1);
     HASH_ADD_BYHASHVALUE(hh, l_net_pvt->downlinks, ch_uuid, sizeof(a_ch_uuid), a_hash_value, l_downlink);
     pthread_rwlock_unlock(&l_net_pvt->downlinks_lock);
     return 0;
 }
+
+void dap_chain_net_del_downlink(dap_stream_ch_uuid_t *a_ch_uuid) {
+    unsigned l_hash_value;
+    HASH_VALUE(*a_ch_uuid, sizeof(*a_ch_uuid), l_hash_value);
+    pthread_rwlock_rdlock(&s_net_items_rwlock);
+    struct downlink *l_downlink = NULL;
+    for (dap_chain_net_item_t *l_net_item = s_net_items; l_net_item && !l_downlink; l_net_item = l_net_item->hh.next) {
+        dap_chain_net_pvt_t *l_net_pvt = PVT(l_net_item->chain_net);
+        pthread_rwlock_wrlock(&l_net_pvt->downlinks_lock);
+        HASH_FIND_BYHASHVALUE(hh, l_net_pvt->downlinks, a_ch_uuid, sizeof(*a_ch_uuid), l_hash_value, l_downlink);
+        if (l_downlink) {
+            HASH_DEL(l_net_pvt->downlinks, l_downlink);
+            log_it(L_MSG, "Remove downlink %s : %d from net ht", l_downlink->addr, l_downlink->port);
+            DAP_DELETE(l_downlink);
+        }
+        pthread_rwlock_unlock(&l_net_pvt->downlinks_lock);
+    }
+    pthread_rwlock_unlock(&s_net_items_rwlock);
+}
+
 /**
  * @brief executes, when you add data to gdb and sends it to current network connected nodes
  * @param a_arg arguments. Can be network object (dap_chain_net_t)
@@ -575,7 +598,11 @@ static void s_chain_callback_notify(void *a_arg, dap_chain_t *a_chain, dap_chain
         return;
     }
     dap_chain_net_t *l_net = (dap_chain_net_t *)a_arg;
-    if (!HASH_COUNT(PVT(l_net)->downlinks))
+    int l_downcount = 0;
+    pthread_rwlock_rdlock(&PVT(l_net)->downlinks_lock);
+    l_downcount = HASH_COUNT(PVT(l_net)->downlinks);
+    pthread_rwlock_unlock(&PVT(l_net)->downlinks_lock);
+    if (!l_downcount)
         return;
     // Check object lifetime for broadcasting decision
     dap_time_t l_time_diff = dap_time_now() - a_chain->callback_atom_get_timestamp(a_atom);
@@ -644,26 +671,30 @@ dap_chain_node_info_t *dap_get_balancer_link_from_cfg(dap_chain_net_t *a_net)
     uint16_t i, l_port = 0;
     uint64_t l_node_adrr = 0;
     if (l_net_pvt->seed_aliases_count) {
-        i = rand() % l_net_pvt->seed_aliases_count;
-        dap_chain_node_addr_t *l_remote_addr = dap_chain_node_alias_find(a_net, l_net_pvt->seed_aliases[i]);
+        do {
+            i = dap_random_uint16() % l_net_pvt->seed_aliases_count;
+        } while (l_net_pvt->seed_nodes_addrs[i] == l_net_pvt->node_addr->uint64);
+
+        /*dap_chain_node_addr_t *l_remote_addr = dap_chain_node_alias_find(a_net, l_net_pvt->seed_aliases[i]);
         if (l_remote_addr){
-            dap_chain_node_info_t *l_remote_node_info = dap_chain_node_info_read(a_net, l_remote_addr);
-            if (l_remote_node_info) {
-                dap_chain_node_info_t *l_ret = l_remote_node_info->hdr.ext_addr_v4.s_addr ? l_remote_node_info : NULL;
-                if (!l_ret)
-                    DAP_DELETE(l_remote_node_info);
-                return l_ret;
-            } else{
-                log_it(L_WARNING,"Can't find node info for node addr "NODE_ADDR_FP_STR,
-                       NODE_ADDR_FP_ARGS(l_remote_addr));
+            */
+            dap_chain_node_info_t *l_link_node_info = DAP_NEW_Z(dap_chain_node_info_t);
+            if(l_link_node_info){
+                l_link_node_info->hdr.address.uint64 = l_net_pvt->seed_nodes_addrs[i];
+                l_link_node_info->hdr.ext_addr_v4.s_addr = l_net_pvt->seed_nodes_addrs_v4[i].s_addr;
+                l_link_node_info->hdr.ext_port = l_net_pvt->seed_nodes_ports[i];
+                return l_link_node_info;
+            }else{
+                log_it(L_WARNING,"Can't allocate memory");
                 return NULL;
             }
-        }else{
+        /*}
+        else{
             log_it(L_WARNING,"Can't find alias info for seed alias %s",l_net_pvt->seed_aliases[i]);
             return NULL;
-        }
+        }*/
     } else if (l_net_pvt->bootstrap_nodes_count) {
-        i = rand() % l_net_pvt->bootstrap_nodes_count;
+        i = dap_random_uint16() % l_net_pvt->bootstrap_nodes_count;
         l_node_adrr = 0;
         l_addr = l_net_pvt->bootstrap_nodes_addrs[i];
         l_port = l_net_pvt->bootstrap_nodes_ports[i];
@@ -814,18 +845,19 @@ static void s_fill_links_from_root_aliases(dap_chain_net_t * a_net)
     int ret = 0;
     dap_chain_net_pvt_t *l_pvt_net = PVT(a_net);
     for (size_t i = 0; i < l_pvt_net->seed_aliases_count; i++) {
+        /*
         dap_chain_node_addr_t *l_link_addr = dap_chain_node_alias_find(a_net, l_pvt_net->seed_aliases[i]);
         if (!l_link_addr)
             continue;
         dap_chain_node_info_t *l_link_node_info = dap_chain_node_info_read(a_net, l_link_addr);
+        */
+        dap_chain_node_info_t *l_link_node_info = dap_get_balancer_link_from_cfg(a_net);
         if (!l_link_node_info)
-            log_it(L_WARNING, "Not found link %s."NODE_ADDR_FP_STR" in the node list",
-                                              a_net->pub.name, NODE_ADDR_FP_ARGS(l_link_addr));
+            log_it(L_WARNING, "Not found any root nodes");
         else {
             ret = s_net_link_add(a_net, l_link_node_info);
             DAP_DELETE(l_link_node_info);
         }
-        DAP_DELETE(l_link_addr);
         if (ret > 0)    // Maximum links count reached
             break;
     }
@@ -904,7 +936,7 @@ static void s_node_link_callback_disconnected(dap_chain_node_client_t *a_node_cl
         }
         if (!l_net_pvt->only_static_links) {
             size_t l_current_links_prepared = HASH_COUNT(l_net_pvt->net_links);
-            for (size_t i = l_current_links_prepared; i < l_net_pvt->max_links_count ; i++) {                
+            for (size_t i = l_current_links_prepared; i < l_net_pvt->max_links_count ; i++) {
                 s_new_balancer_link_request(l_net, 0);
             }
         }
@@ -1172,14 +1204,14 @@ static bool s_new_balancer_link_request(dap_chain_net_t *a_net, int a_link_repla
     }
     if(!a_link_replace_tries){
 
-        dap_chain_net_node_balancer_t *l_link_full_node_list = dap_chain_net_balancer_get_node(a_net->pub.name,l_net_pvt->max_links_count*2);        
+        dap_chain_net_node_balancer_t *l_link_full_node_list = dap_chain_net_balancer_get_node(a_net->pub.name,l_net_pvt->max_links_count*2);
         size_t node_cnt = 0,i = 0;
         if(l_link_full_node_list)
         {
             dap_chain_node_info_t * l_node_info = (dap_chain_node_info_t *)l_link_full_node_list->nodes_info;
             node_cnt = l_link_full_node_list->count_node;
             int l_net_link_add = 0;
-            size_t l_links_count = 0;            
+            size_t l_links_count = 0;
             while(!l_net_link_add){
                 if(i >= node_cnt)
                     break;
@@ -1193,7 +1225,7 @@ static bool s_new_balancer_link_request(dap_chain_net_t *a_net, int a_link_repla
                     break;
                 case 1:
                     log_it(L_MSG, "Network links table is full");
-                    break;                
+                    break;
                 default:
                     break;
                 }
@@ -1253,6 +1285,7 @@ static bool s_new_balancer_link_request(dap_chain_net_t *a_net, int a_link_repla
                                                 s_net_http_link_prepare_error,
                                                 l_balancer_request,
                                                 NULL) == NULL;
+        DAP_DELETE(l_request);
     } else {
         l_link_node_info->hdr.ext_port = DNS_LISTEN_PORT;
         ret = dap_chain_node_info_dns_request(l_balancer_request->worker,
@@ -1347,12 +1380,6 @@ static bool s_net_states_proc(dap_proc_thread_t *a_thread, void *a_arg)
                     dap_timerfd_delete_mt(l_link->delay_timer->worker, l_link->delay_timer->esocket_uuid);
                 if (l_link->link) {
                     dap_chain_node_client_t *l_client = l_link->link;
-                    HASH_FIND(hh, l_net_pvt->downlinks, &l_client->ch_chain_uuid,
-                              sizeof(dap_stream_ch_uuid_t), l_downlink);
-                    if (l_downlink) {
-                        HASH_DEL(l_net_pvt->downlinks, l_downlink);
-                        DAP_DELETE(l_downlink);
-                    }
                     l_client->callbacks.delete = NULL;
                     dap_chain_node_client_close_mt(l_client);
                 }
@@ -1360,11 +1387,13 @@ static bool s_net_states_proc(dap_proc_thread_t *a_thread, void *a_arg)
                 DAP_DEL_Z(l_link->link_info);
                 DAP_DELETE(l_link);
             }
+            pthread_rwlock_wrlock(&PVT(l_net)->downlinks_lock);
             HASH_ITER(hh, l_net_pvt->downlinks, l_downlink, l_dltmp) {
                 HASH_DEL(l_net_pvt->downlinks, l_downlink);
                 dap_events_socket_delete_mt(l_downlink->worker->worker, l_downlink->esocket_uuid);
                 DAP_DELETE(l_downlink);
             }
+            pthread_rwlock_unlock(&PVT(l_net)->downlinks_lock);
             l_net_pvt->balancer_link_requests = 0;
             l_net_pvt->active_link = NULL;
             dap_list_free(l_net_pvt->links_queue);
@@ -1490,8 +1519,8 @@ bool dap_chain_net_sync_trylock(dap_chain_net_t *a_net, dap_chain_node_client_t
     }
     if (l_found && !dap_list_find(l_net_pvt->links_queue, a_client, NULL))
         l_net_pvt->links_queue = dap_list_append(l_net_pvt->links_queue, a_client);
-    if (a_err != EDEADLK)
-        pthread_mutex_unlock(&l_net_pvt->uplinks_mutex);
+    //if (a_err != EDEADLK)
+    pthread_mutex_unlock(&l_net_pvt->uplinks_mutex);
     return !l_found;
 }
 
@@ -2475,7 +2504,7 @@ int s_net_init(const char * a_net_name, uint16_t a_acl_idx)
         l_net_pvt->seed_aliases[i] = dap_strdup(l_seed_aliases[i]);
     // randomize seed nodes list
     for (int j = l_net_pvt->seed_aliases_count - 1; j > 0; j--) {
-        int n = rand() % j;
+        short n = dap_random_uint16() % j;
         char *tmp = l_net_pvt->seed_aliases[n];
         l_net_pvt->seed_aliases[n] = l_net_pvt->seed_aliases[j];
         l_net_pvt->seed_aliases[j] = tmp;
@@ -2572,6 +2601,8 @@ int s_net_init(const char * a_net_name, uint16_t a_acl_idx)
     log_it (L_DEBUG, "Read %u aliases, %u address and %u ipv4 addresses, check them",
             l_net_pvt->seed_aliases_count,l_seed_nodes_addrs_len, l_seed_nodes_ipv4_len );
     PVT(l_net)->seed_nodes_addrs_v4 = DAP_NEW_SIZE(struct in_addr, l_net_pvt->seed_aliases_count * sizeof(struct in_addr));
+    PVT(l_net)->seed_nodes_addrs = DAP_NEW_SIZE(uint64_t, l_net_pvt->seed_aliases_count * sizeof(uint64_t));
+    PVT(l_net)->seed_nodes_ports = DAP_NEW_SIZE(uint16_t, l_net_pvt->seed_aliases_count * sizeof(uint16_t));
     // save new nodes from cfg file to db
     for ( size_t i = 0; i < PVT(l_net)->seed_aliases_count &&
                         i < l_seed_nodes_addrs_len &&
@@ -2595,6 +2626,8 @@ int s_net_init(const char * a_net_name, uint16_t a_acl_idx)
             inet_pton(AF_INET6, l_seed_nodes_ipv6[i], &l_node_info.hdr.ext_addr_v6);
         l_node_info.hdr.ext_port = l_seed_nodes_port_len && l_seed_nodes_port_len >= i ?
             strtoul(l_seed_nodes_port[i], NULL, 10) : 8079;
+        l_net_pvt->seed_nodes_ports[i] = l_node_info.hdr.ext_port;
+        l_net_pvt->seed_nodes_addrs[i] = l_seed_node_addr.uint64;
 
         if (l_seed_nodes_hostnames_len) {
             struct sockaddr l_sa = {};
@@ -2609,7 +2642,7 @@ int s_net_init(const char * a_net_name, uint16_t a_acl_idx)
                 log_it(L_ERROR, "%s", gai_strerror(l_ret_code));
             }
         }
-
+/*
         l_seed_node_addr_gdb    = dap_chain_node_alias_find(l_net, l_net_pvt->seed_aliases[i]);
         l_node_info_gdb         = l_seed_node_addr_gdb ? dap_chain_node_info_read(l_net, l_seed_node_addr_gdb) : NULL;
 
@@ -2621,12 +2654,12 @@ int s_net_init(const char * a_net_name, uint16_t a_acl_idx)
             l_node_info.hdr.ext_addr_v6.s6_addr32[0]
 #endif
         ) {
-            /* Let's check if config was altered */
+             //Let's check if config was altered
             int l_ret = l_node_info_gdb ? memcmp(&l_node_info, l_node_info_gdb, sizeof(dap_chain_node_info_t)) : 1;
             if (!l_ret) {
                 log_it(L_NOTICE,"Seed node "NODE_ADDR_FP_STR" already in list", NODE_ADDR_FP_ARGS_S(l_seed_node_addr));
             } else {
-                /* Either not yet added or must be altered */
+                // Either not yet added or must be altered
                 l_ret = dap_chain_node_info_save(l_net, &l_node_info);
                 if (!l_ret) {
                     if (dap_chain_node_alias_register(l_net,l_net_pvt->seed_aliases[i], &l_seed_node_addr))
@@ -2640,9 +2673,11 @@ int s_net_init(const char * a_net_name, uint16_t a_acl_idx)
         } else
             log_it(L_WARNING,"No address for seed node, can't populate global_db with it");
         DAP_DEL_Z(l_seed_node_addr_gdb);
-        DAP_DEL_Z(l_node_info_gdb);
+        DAP_DEL_Z(l_node_info_gdb);*/
     }
 
+    dap_chain_net_node_list_init();
+
     PVT(l_net)->bootstrap_nodes_count = 0;
     PVT(l_net)->bootstrap_nodes_addrs = DAP_NEW_SIZE(struct in_addr, l_bootstrap_nodes_len * sizeof(struct in_addr));
     PVT(l_net)->bootstrap_nodes_ports = DAP_NEW_SIZE(uint16_t, l_bootstrap_nodes_len * sizeof(uint16_t));
@@ -2703,23 +2738,16 @@ int s_net_init(const char * a_net_name, uint16_t a_acl_idx)
                     if (dap_config_get_item_bool_default(g_config,"server","enabled",false) ){
                         const char * l_ext_addr_v4 = dap_config_get_item_str_default(g_config,"server","ext_address",NULL);
                         const char * l_ext_addr_v6 = dap_config_get_item_str_default(g_config,"server","ext_address6",NULL);
-                        uint16_t l_ext_port = dap_config_get_item_uint16_default(g_config,"server","ext_port_tcp",0);
+                        uint16_t l_ext_port = dap_config_get_item_uint16_default(g_config,"server","ext_port_tcp", 8079);
                         uint16_t l_node_info_port = l_ext_port ? l_ext_port :
-                                                dap_config_get_item_uint16_default(g_config,"server","listen_port_tcp",8089);
+                                                dap_config_get_item_uint16_default(g_config,"server","listen_port_tcp",8079);
                         if (l_ext_addr_v4)
                             inet_pton(AF_INET,l_ext_addr_v4,&l_net_pvt->node_info->hdr.ext_addr_v4 );
                         if (l_ext_addr_v6)
                             inet_pton(AF_INET6,l_ext_addr_v6,&l_net_pvt->node_info->hdr.ext_addr_v6 );
                         l_net_pvt->node_info->hdr.ext_port =l_node_info_port;
-                        log_it(L_INFO,"Server is enabled on %s:%u",l_ext_addr_v4?l_ext_addr_v4:"<none>",
-                               l_node_info_port);
-                    }else
+                    } else
                         log_it(L_INFO,"Server is disabled, add only node address in nodelist");
-                    if (l_net_pvt->node_info->hdr.ext_port &&
-                            (l_net_pvt->node_info->hdr.ext_addr_v4.s_addr != INADDR_ANY ||
-                             memcmp(&l_net_pvt->node_info->hdr.ext_addr_v6, &in6addr_any, sizeof(struct in6_addr))))
-                        // Save only info with non null address & port!
-                        dap_chain_node_info_save(l_net,l_net_pvt->node_info);
                 }
                 log_it(L_NOTICE,"GDB Info: node_addr: " NODE_ADDR_FP_STR"  links: %u cell_id: 0x%016"DAP_UINT64_FORMAT_X,
                        NODE_ADDR_FP_ARGS(l_node_addr),
@@ -3009,7 +3037,7 @@ int s_net_load(dap_chain_net_t *a_net)
  */
 void dap_chain_net_deinit()
 {
-    pthread_rwlock_rdlock(&s_net_items_rwlock);
+    pthread_rwlock_wrlock(&s_net_items_rwlock);
     dap_chain_net_item_t *l_current_item, *l_tmp;
     HASH_ITER(hh, s_net_items, l_current_item, l_tmp) {
         HASH_DEL(s_net_items, l_current_item);
@@ -3700,6 +3728,29 @@ bool dap_chain_net_get_load_mode(dap_chain_net_t * a_net)
     return PVT(a_net)->load_mode;
 }
 
+void dap_chain_net_announce_addrs() {
+    if(!HASH_COUNT(s_net_items)){
+        log_it(L_ERROR, "Can't find any nets");
+        return;
+    }
+    pthread_rwlock_rdlock(&s_net_items_rwlock);
+    dap_chain_net_item_t *l_net_item = NULL, *l_tmp = NULL;
+    HASH_ITER(hh, s_net_items, l_net_item, l_tmp) {
+        dap_chain_net_pvt_t *l_net_pvt = PVT(l_net_item->chain_net);
+        if (l_net_pvt->node_info->hdr.ext_port &&
+                (l_net_pvt->node_info->hdr.ext_addr_v4.s_addr != INADDR_ANY
+                 || memcmp(&l_net_pvt->node_info->hdr.ext_addr_v6, &in6addr_any, sizeof(struct in6_addr))))
+        {
+            dap_chain_net_node_list_request(l_net_item->chain_net, l_net_pvt->node_info, false);
+            char l_node_addr_str[INET_ADDRSTRLEN] = { '\0' };
+            inet_ntop(AF_INET, &l_net_pvt->node_info->hdr.ext_addr_v4, l_node_addr_str, INET_ADDRSTRLEN);
+            log_it(L_MSG, "Announce our node address "NODE_ADDR_FP_STR" < %s:%u > in net %s",
+                   NODE_ADDR_FP_ARGS(l_net_pvt->node_addr), l_node_addr_str, l_net_pvt->node_info->hdr.ext_port, l_net_item->name);
+        }
+    }
+    pthread_rwlock_unlock(&s_net_items_rwlock);
+}
+
 char *dap_chain_net_links_dump(dap_chain_net_t *a_net) {
     dap_chain_net_pvt_t *l_net_pvt = PVT(a_net);
     pthread_mutex_lock(&l_net_pvt->uplinks_mutex);
@@ -3721,11 +3772,9 @@ char *dap_chain_net_links_dump(dap_chain_net_t *a_net) {
     pthread_rwlock_rdlock(&l_net_pvt->downlinks_lock);
     struct downlink *l_downlink = NULL, *l_downtmp = NULL;
     HASH_ITER(hh, l_net_pvt->downlinks, l_downlink, l_downtmp) {
-        if (l_downlink->addr[0]) {
-            dap_string_append_printf(l_str_downlinks, "|  ↓  |\t%zu\t|\t%s\t\t|\t%u\t|\n",
+        dap_string_append_printf(l_str_downlinks, "|  ↓  |\t%zu\t|\t%s\t\t|\t%u\t|\n",
                                      ++l_down_count,
                                      l_downlink->addr, l_downlink->port);
-        }
     }
     pthread_rwlock_unlock(&l_net_pvt->downlinks_lock);
     char *l_res_str = dap_strdup_printf("Count links: %zu\n\nUplinks: %zu\n%s\n\nDownlinks: %zu\n%s\n",
diff --git a/modules/net/dap_chain_net_balancer.c b/modules/net/dap_chain_net_balancer.c
index 9b5e456b10156b991748b4ef5dde9c7ea4dacd93..619defb2d44b1f1e6abc38d0b0b21ab5b5ea58ee 100644
--- a/modules/net/dap_chain_net_balancer.c
+++ b/modules/net/dap_chain_net_balancer.c
@@ -62,17 +62,17 @@ void dap_chain_net_balancer_free_link_list(dap_chain_net_t * a_net)
     log_it(L_DEBUG, "Balancer link list cleared");
 }
 
-static bool dap_chain_net_balancer_handshake(dap_chain_node_info_t *a_node_info,dap_chain_net_t * a_net)
+bool dap_chain_net_balancer_handshake(dap_chain_node_info_t *a_node_info,dap_chain_net_t * a_net)
 {
     dap_chain_node_client_t *l_client = dap_chain_node_client_connect_default_channels(a_net,a_node_info);
     if(!l_client) {
         return false;
     }
     // wait handshake
-    int timeout_ms = 1000;
+    int timeout_ms = 4000;
     int res = dap_chain_node_client_wait(l_client, NODE_CLIENT_STATE_ESTABLISHED, timeout_ms);
+    dap_chain_node_client_close_mt(l_client);
     if (res) {
-        dap_chain_node_client_close_mt(l_client);
         return false;
     }
     return true;
@@ -93,6 +93,10 @@ static uint64_t min_count_blocks_events(dap_global_db_obj_t * a_objs,size_t a_no
     uint64_t l_blocks_events = 0;
     for (size_t i = 0; i < a_node_count; i++) {
         dap_chain_node_info_t *l_node_cand = (dap_chain_node_info_t *)a_objs[i].value;
+        if (!l_node_cand) {
+            log_it(L_ERROR, "Invalid record, key %s", a_objs[i].key);
+            continue;
+        }
         for (dap_list_t *node_i = a_node_addr_list; node_i; node_i = node_i->next) {
             if(((struct in_addr*)node_i->data)->s_addr == l_node_cand->hdr.ext_addr_v4.s_addr) {
                 if (!l_blocks_events || l_blocks_events > l_node_cand->hdr.blocks_events)
@@ -270,7 +274,7 @@ void dap_chain_net_balancer_http_issue_link(dap_http_simple_t *a_http_simple, vo
     sscanf(a_http_simple->http_client->in_query_string, "version=%d,method=%c,needlink=%hu,net=",
                                                             &l_protocol_version, &l_issue_method, &links_need);
     if (l_protocol_version != 1 || l_issue_method != 'r') {
-        log_it(L_ERROR, "Unsupported prorocol version/method in the request to dap_chain_net_balancer module");
+        log_it(L_ERROR, "Unsupported protocol version/method in the request to dap_chain_net_balancer module");
         *l_return_code = Http_Status_MethodNotAllowed;
         return;
     }
diff --git a/modules/net/dap_chain_net_node_list.c b/modules/net/dap_chain_net_node_list.c
new file mode 100644
index 0000000000000000000000000000000000000000..ff95622939466aa6e82c17a380d3bf83cc2cb472
--- /dev/null
+++ b/modules/net/dap_chain_net_node_list.c
@@ -0,0 +1,311 @@
+/*
+* Authors:
+* Dmitriy Gerasimov <naeper@demlabs.net>
+* Cellframe       https://cellframe.net
+* DeM Labs Inc.   https://demlabs.net
+* Copyright  (c) 2017-2019
+* All rights reserved.
+
+This file is part of CellFrame SDK the open source project
+
+CellFrame SDK is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+CellFrame SDK is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with any CellFrame SDK based project.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "dap_chain_net_node_list.h"
+#include "http_status_code.h"
+#include "dap_chain_net_balancer.h"
+#include "dap_client.h"
+#include "dap_client_http.h"
+
+#define LOG_TAG "dap_chain_net_node_list"
+
+/**
+ * @brief server function, makes handshake and add node to node list
+ *
+ * @param dap_http_simple_t *a_http_simple, void *a_arg
+ * @return void
+ * send value
+ * 1 - Node addr successfully added to node list
+ * 2 - Can't add this addres to node list
+ * 3 - Can't calculate hash for addr
+ * 4 - Can't do handshake
+ * 5 - Already exists
+ */
+void dap_chain_net_node_check_http_issue_link(dap_http_simple_t *a_http_simple, void *a_arg)
+{
+    log_it(L_DEBUG,"Proc enc http request");
+    http_status_code_t *l_return_code = (http_status_code_t *)a_arg;
+
+    if (strcmp(a_http_simple->http_client->url_path, DAP_NODE_LIST_URI_HASH)) {
+        log_it(L_ERROR, "Wrong path '%s' in the request to dap_chain_net_node_list module",
+                                                            a_http_simple->http_client->url_path);
+        *l_return_code = Http_Status_BadRequest;
+        return;
+    }
+    int l_protocol_version = 0;
+    char l_issue_method = 0;
+    uint64_t addr = 0;
+    uint32_t ipv4 = 0;
+    uint16_t port = 0;
+    const char l_net_token[] = "net=";
+    sscanf(a_http_simple->http_client->in_query_string, "version=%d,method=%c,addr=%lu,ipv4=%d,port=%hu,net=",
+                                                            &l_protocol_version, &l_issue_method, &addr, &ipv4, &port);
+    if (l_protocol_version != 1 || l_issue_method != 'r') {
+        log_it(L_ERROR, "Unsupported protocol version/method in the request to dap_chain_net_node_list module");
+        *l_return_code = Http_Status_MethodNotAllowed;
+        return;
+    }
+    char *l_net_str = strstr(a_http_simple->http_client->in_query_string, l_net_token);
+    if (!l_net_str) {
+        log_it(L_ERROR, "Net name token not found in the request to dap_chain_net_node_list module");
+        *l_return_code = Http_Status_NotFound;
+        return;
+    }
+    l_net_str += strlen(l_net_token);
+    log_it(L_DEBUG, "HTTP Node check parser retrieve netname %s", l_net_str);
+
+    dap_chain_net_t *l_net = dap_chain_net_by_name(l_net_str);
+    dap_chain_node_info_t l_node_info = {
+        .hdr.address.uint64 = addr,
+        .hdr.owner_address.uint64 = dap_chain_net_get_cur_addr_int(l_net),
+        .hdr.ext_addr_v4.s_addr = ipv4,
+        .hdr.ext_port = port
+    };
+
+    uint8_t response = 0;
+    char *l_key = dap_chain_node_addr_to_hash_str(&l_node_info.hdr.address);
+    if(!l_key)
+    {
+        log_it(L_DEBUG, "Can't calculate hash for addr");
+        response = 3;
+    } else{
+        size_t node_info_size = 0;
+        dap_chain_node_info_t *l_node_inf_check;
+        l_node_inf_check = (dap_chain_node_info_t *) dap_global_db_get_sync(l_net->pub.gdb_nodes, l_key, &node_info_size, NULL, NULL);
+        if(l_node_inf_check)
+        {
+            log_it(L_DEBUG, "The node is already exists");
+            response = 5;
+            DAP_DELETE(l_node_inf_check);
+        }
+        else{
+            if(dap_chain_net_balancer_handshake(&l_node_info,l_net))
+                response = 1;
+            if(response)
+            {
+                size_t l_node_info_size = dap_chain_node_info_get_size(&l_node_info);
+                bool res = dap_global_db_set_sync(l_net->pub.gdb_nodes, l_key, (uint8_t*)&l_node_info, l_node_info_size, true) == 0;
+                if(res)
+                {
+                    char l_node_addr_str[INET_ADDRSTRLEN]={};
+                    inet_ntop(AF_INET, &l_node_info.hdr.ext_addr_v4, l_node_addr_str, INET_ADDRSTRLEN);
+                    log_it(L_DEBUG, "Add address"NODE_ADDR_FP_STR" (%s) to node list by "NODE_ADDR_FP_STR"",
+                                NODE_ADDR_FP_ARGS_S(l_node_info.hdr.address),l_node_addr_str,
+                                NODE_ADDR_FP_ARGS_S(l_node_info.hdr.owner_address));
+                    response = 1;
+                }
+                else
+                {
+                    response = 2;
+                    log_it(L_DEBUG, "Don't add this addres to node list");
+                }
+            }
+            else
+            {
+                log_it(L_DEBUG, "Can't do handshake");
+                response = 4;
+            }
+        }
+    }
+    DAP_DELETE(l_key);
+    *l_return_code = Http_Status_OK;
+    size_t l_data_send_size = sizeof(uint8_t);
+    dap_http_simple_reply(a_http_simple, &response, l_data_send_size);
+}
+
+static void s_net_node_link_prepare_success(void *a_response, size_t a_response_size, void *a_arg) {
+    struct node_link_request *l_node_list_request = (struct node_link_request *)a_arg;
+    pthread_mutex_lock(&l_node_list_request->wait_mutex);
+    l_node_list_request->response = *(uint8_t*)a_response;
+    pthread_cond_broadcast(&l_node_list_request->wait_cond);
+    pthread_mutex_unlock(&l_node_list_request->wait_mutex);
+}
+static void s_net_node_link_prepare_error(int a_error_code, void *a_arg){
+    struct node_link_request * l_node_list_request = (struct node_link_request *)a_arg;
+    dap_chain_node_info_t *l_node_info = l_node_list_request->link_info;
+    if (!l_node_info) {
+        log_it(L_WARNING, "Link prepare error, code %d", a_error_code);
+        return;
+    }
+    char l_node_addr_str[INET_ADDRSTRLEN]={};
+    inet_ntop(AF_INET, &l_node_info->hdr.ext_addr_v4, l_node_addr_str, INET_ADDRSTRLEN);
+    log_it(L_WARNING, "Link from  "NODE_ADDR_FP_STR" (%s) prepare error with code %d",
+                                NODE_ADDR_FP_ARGS_S(l_node_info->hdr.address), l_node_addr_str,a_error_code);
+}
+static struct node_link_request *s_node_list_request_init ()
+{
+    struct node_link_request *l_node_list_request = DAP_NEW_Z(struct node_link_request);
+    if(!l_node_list_request){
+        return NULL;
+    }
+    l_node_list_request->worker = dap_events_worker_get_auto();
+    l_node_list_request->from_http = true;
+    l_node_list_request->response = 0;
+
+    pthread_condattr_t attr;
+    pthread_condattr_init(&attr);
+#ifndef DAP_OS_DARWIN
+    pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
+#endif
+    pthread_cond_init(&l_node_list_request->wait_cond, &attr);
+    pthread_mutex_init(&l_node_list_request->wait_mutex, NULL);
+    return l_node_list_request;
+}
+
+static void s_node_list_request_deinit (struct node_link_request *a_node_list_request)
+{
+    pthread_cond_destroy(&a_node_list_request->wait_cond);
+    pthread_mutex_destroy(&a_node_list_request->wait_mutex);
+    DAP_DEL_Z(a_node_list_request->link_info);
+}
+static int dap_chain_net_node_list_wait(struct node_link_request *a_node_list_request, int a_timeout_ms){
+
+    int ret = -1;
+    pthread_mutex_lock(&a_node_list_request->wait_mutex);
+    if(a_node_list_request->response)
+    {
+        pthread_mutex_unlock(&a_node_list_request->wait_mutex);
+        return 0;
+    }
+    struct timespec l_cond_timeout;
+    clock_gettime(CLOCK_MONOTONIC, &l_cond_timeout);
+    l_cond_timeout.tv_sec += a_timeout_ms/1000;
+    int l_ret_wait = pthread_cond_timedwait(&a_node_list_request->wait_cond, &a_node_list_request->wait_mutex, &l_cond_timeout);
+    if(!l_ret_wait) {
+        ret = a_node_list_request->response ? 0 : -2;
+    } else if(l_ret_wait == ETIMEDOUT) {
+        log_it(L_NOTICE,"Wait for status is stopped by timeout");
+        ret = -1;
+    } else if (l_ret_wait) {
+        char l_errbuf[128];
+        l_errbuf[0] = '\0';
+        strerror_r(l_ret_wait,l_errbuf,sizeof (l_errbuf));
+        log_it(L_ERROR, "Pthread condition timed wait returned \"%s\"(code %d)", l_errbuf, l_ret_wait);
+        ret = -3;
+    }
+    pthread_mutex_unlock(&a_node_list_request->wait_mutex);
+    return ret;
+}
+
+int dap_chain_net_node_list_request (dap_chain_net_t *a_net, dap_chain_node_info_t *a_link_node_request, bool a_sync)
+{
+    dap_chain_node_info_t *l_link_node_info = dap_get_balancer_link_from_cfg(a_net);
+    if (!l_link_node_info)
+        return false;
+    char l_node_addr_str[INET_ADDRSTRLEN] = {};
+    inet_ntop(AF_INET, &l_link_node_info->hdr.ext_addr_v4, l_node_addr_str, INET_ADDRSTRLEN);
+    log_it(L_DEBUG, "Start node list HTTP request to %s", l_node_addr_str);
+    struct node_link_request *l_node_list_request = s_node_list_request_init();
+    if(!l_node_list_request){
+        log_it(L_CRITICAL, "Memory allocation error");
+        DAP_DELETE(l_link_node_info);
+        return false;
+    }
+    l_node_list_request->net = a_net;
+    l_node_list_request->link_info = l_link_node_info;
+    int ret = 0;
+
+    char *l_request = dap_strdup_printf("%s/%s?version=1,method=r,addr=%lu,ipv4=%d,port=%hu,net=%s",
+                                            DAP_UPLINK_PATH_NODE_LIST,
+                                            DAP_NODE_LIST_URI_HASH,
+                                            a_link_node_request->hdr.address.uint64,
+                                            a_link_node_request->hdr.ext_addr_v4.s_addr,
+                                            a_link_node_request->hdr.ext_port,
+                                            a_net->pub.name);
+    ret = dap_client_http_request(l_node_list_request->worker,
+                                            l_node_addr_str,
+                                            l_link_node_info->hdr.ext_port,
+                                            "GET",
+                                            "text/text",
+                                            l_request,
+                                            NULL,
+                                            0,
+                                            NULL,
+                                            s_net_node_link_prepare_success,
+                                            s_net_node_link_prepare_error,
+                                            l_node_list_request,
+                                            NULL) == NULL;
+    DAP_DELETE(l_request);
+    if (a_sync) {
+        int rc = dap_chain_net_node_list_wait(l_node_list_request, 10000);
+        ret = ret ? 6 : rc ? 0 : l_node_list_request->response;
+    } else {
+        ret = 7;
+    }
+    s_node_list_request_deinit(l_node_list_request);
+    return ret;
+}
+static void s_node_list_callback_notify(dap_global_db_context_t *a_context, dap_store_obj_t *a_obj, void *a_arg)
+{
+    if (!a_arg || !a_obj || !a_obj->key)
+        return;
+    dap_chain_net_t *l_net = (dap_chain_net_t *)a_arg;
+    assert(l_net);
+    size_t l_size_obj_need = (sizeof(dap_chain_node_info_t));
+
+    if (!dap_strcmp(a_obj->group, l_net->pub.gdb_nodes)) {
+        if (a_obj->value && a_obj->type == DAP_DB$K_OPTYPE_ADD) {
+            dap_chain_node_info_t *l_node_info = (dap_chain_node_info_t *)a_obj->value;
+
+            size_t l_size_obj = (a_obj->value_len - (l_node_info->hdr.links_number * sizeof(dap_chain_node_addr_t)));
+            if(l_size_obj_need == l_size_obj)
+            {
+                if(l_node_info->hdr.owner_address.uint64 == 0){
+                    log_it(L_NOTICE, "Node %s removed, there is not pinners", a_obj->key);
+                    dap_global_db_del_unsafe(a_context, a_obj->group, a_obj->key);
+                } else {
+                    char l_node_ipv4_str[INET_ADDRSTRLEN]={ '\0' }, l_node_ipv6_str[INET6_ADDRSTRLEN]={ '\0' };
+                    inet_ntop(AF_INET, &l_node_info->hdr.ext_addr_v4, l_node_ipv4_str, INET_ADDRSTRLEN);
+                    inet_ntop(AF_INET6, &l_node_info->hdr.ext_addr_v6, l_node_ipv6_str, INET6_ADDRSTRLEN);
+                    char l_ts[128] = { '\0' };
+                    dap_gbd_time_to_str_rfc822(l_ts, sizeof(l_ts), a_obj->timestamp);
+
+                    log_it(L_MSG, "Add node "NODE_ADDR_FP_STR" %s %s, pinned by "NODE_ADDR_FP_STR" at %s\n",
+                                             NODE_ADDR_FP_ARGS_S(l_node_info->hdr.address),
+                                             l_node_ipv4_str, dap_itoa(l_node_info->hdr.ext_port),
+                                             NODE_ADDR_FP_ARGS_S(l_node_info->hdr.owner_address),
+                                             l_ts);
+                }
+            }
+            else
+            {
+                dap_global_db_del_unsafe(a_context, a_obj->group, a_obj->key);
+                log_it(L_NOTICE, "Wrong size! data size %lu need - (%lu) %s removed ",l_size_obj,
+                       l_size_obj_need, a_obj->key);
+            }
+        }
+    }
+
+}
+
+int dap_chain_net_node_list_init()
+{
+    uint16_t l_net_count = 0;
+    dap_chain_net_t **l_net_list = dap_chain_net_list(&l_net_count);
+    for (uint16_t i = 0; i < l_net_count; i++) {
+        dap_chain_net_add_gdb_notify_callback(l_net_list[i], s_node_list_callback_notify, l_net_list[i]);
+    }
+    return 0;
+}
+
diff --git a/modules/net/dap_chain_node_cli.c b/modules/net/dap_chain_node_cli.c
index e0ebfa55966804c002321d89c724b2c7de1a8b10..bdd6861bb4de7e315e4db06b1f549f68365cbd39 100644
--- a/modules/net/dap_chain_node_cli.c
+++ b/modules/net/dap_chain_node_cli.c
@@ -97,7 +97,7 @@ int dap_chain_node_cli_init(dap_config_t * g_config)
                "mempool check -cert <priv_cert_name> -net <net_name> {-file <filename> | -hash <hash>} [-mime {<SIGNER_FILENAME,SIGNER_FILENAME_SHORT,SIGNER_FILESIZE,SIGNER_DATE,SIGNER_MIME_MAGIC> | <SIGNER_ALL_FLAGS>}]\n"
                                           );
     dap_cli_server_cmd_add("node", com_node, "Work with node",
-            "node add  -net <net_name> {-addr <node_address> | -alias <node_alias>} -port <port> -cell <cell id>  {-ipv4 <ipv4 external address> | -ipv6 <ipv6 external address>}\n\n"
+                    "node add  -net <net_name> -port <port> -ipv4 <ipv4 external address>\n\n"
                     "node del -net <net_name> {-addr <node_address> | -alias <node_alias>}\n\n"
                     "node link {add | del}  -net <net_name> {-addr <node_address> | -alias <node_alias>} -link <node_address>\n\n"
                     "node alias -addr <node_address> -alias <node_alias>\n\n"
diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c
index 6cf79190c0af2db8a537806d3ecaf090482d779c..8a1c18a8818224535c1c36dcaad62f7ff6ac7628 100644
--- a/modules/net/dap_chain_node_cli_cmd.c
+++ b/modules/net/dap_chain_node_cli_cmd.c
@@ -107,6 +107,7 @@
 #include "dap_stream_ch_chain_net_pkt.h"
 #include "dap_enc_base64.h"
 #include "dap_chain_net_srv_stake_pos_delegate.h"
+#include "dap_chain_net_node_list.h"
 
 #define LOG_TAG "chain_node_cli_cmd"
 
@@ -475,7 +476,7 @@ static int link_add_or_del_with_reply(dap_chain_net_t * a_net, dap_chain_node_in
     }
     // save edited node_info
     if(res_successful) {
-        bool res = node_info_save_and_reply(a_net, l_node_info_read, a_str_reply);
+        bool res = true;  //node_info_save_and_reply(a_net, l_node_info_read, a_str_reply);
         if(res) {
             res_successful = true;
             if(cmd_int == 1)
@@ -523,7 +524,7 @@ static int node_info_dump_with_reply(dap_chain_net_t * a_net, dap_chain_node_add
         const char *a_alias, char **a_str_reply)
 {
     int l_ret = 0;
-    dap_string_t *l_string_reply = dap_string_new("Node dump:");
+    dap_string_t *l_string_reply = dap_string_new("Node dump:\n");
 
     if ((a_addr && a_addr->uint64) || a_alias) {
         dap_chain_node_addr_t *l_addr = a_alias
@@ -544,7 +545,7 @@ static int node_info_dump_with_reply(dap_chain_net_t * a_net, dap_chain_node_add
         }
 
         // get aliases in form of string
-        dap_string_t *aliases_string = dap_string_new(NULL);
+        /*dap_string_t *aliases_string = dap_string_new(NULL);
         dap_list_t *list_aliases = get_aliases_by_name(a_net, l_addr);
         if(list_aliases)
         {
@@ -560,6 +561,8 @@ static int node_info_dump_with_reply(dap_chain_net_t * a_net, dap_chain_node_add
         else
             dap_string_append(aliases_string, "\nno aliases");
 
+
+
         const int hostlen = 128;
         char *host4 = (char*) alloca(hostlen);
         char *host6 = (char*) alloca(hostlen);
@@ -603,14 +606,11 @@ static int node_info_dump_with_reply(dap_chain_net_t * a_net, dap_chain_node_add
         dap_string_free(links_string, true);
 
         DAP_DELETE(l_addr);
-        DAP_DELETE(node_info_read);
+        DAP_DELETE(node_info_read);*/ // TODO
 
     } else { // Dump list with !a_addr && !a_alias
-        dap_global_db_obj_t *l_objs = NULL;
         size_t l_nodes_count = 0;
-        dap_string_append(l_string_reply, "\n");
-        // read all node
-        l_objs = dap_global_db_get_all_sync(a_net->pub.gdb_nodes, &l_nodes_count);
+        dap_global_db_obj_t *l_objs = dap_global_db_get_all_sync(a_net->pub.gdb_nodes, &l_nodes_count);
 
         if(!l_nodes_count || !l_objs) {
             dap_string_append_printf(l_string_reply, "No records\n");
@@ -619,18 +619,18 @@ static int node_info_dump_with_reply(dap_chain_net_t * a_net, dap_chain_node_add
             dap_global_db_objs_delete(l_objs, l_nodes_count);
             return -1;
         } else {
-            dap_string_append_printf(l_string_reply, "Got %zu records:\n", l_nodes_count);
+            dap_string_append_printf(l_string_reply, "Got %zu nodes:\n", l_nodes_count);
+            dap_string_append_printf(l_string_reply, "%-26s%-20s%-8s%-26s%s", "Address", "IPv4", "Port", "Pinner", "Timestamp\n");
             size_t l_data_size = 0;
-            // read all aliases
+
             dap_global_db_obj_t *l_aliases_objs = dap_global_db_get_all_sync(a_net->pub.gdb_nodes_aliases, &l_data_size);
-            for(size_t i = 0; i < l_nodes_count; i++) {
-                dap_chain_node_info_t *l_node_info = (dap_chain_node_info_t *)l_objs[i].value;
-                // read node
-                if ( !dap_chain_node_addr_not_null(&l_node_info->hdr.address)){
+            for (size_t i = 0; i < l_nodes_count; i++) {
+                dap_chain_node_info_t *l_node_info = (dap_chain_node_info_t*)l_objs[i].value;
+                if (!dap_chain_node_addr_not_null(&l_node_info->hdr.address)){
                     log_it(L_ERROR, "Node address is NULL");
                     continue;
                 }
-
+/*
                 dap_chain_node_info_t *l_node_info_read = node_info_read_and_reply(a_net, &l_node_info->hdr.address, NULL);
                 if (!l_node_info_read) {
                     log_it(L_ERROR, "Invalid node info object, remove it");
@@ -639,17 +639,22 @@ static int node_info_dump_with_reply(dap_chain_net_t * a_net, dap_chain_node_add
                     continue;
                 } else
                     DAP_DELETE(l_node_info_read);
-                const int hostlen = 128;
-                char *host4 = (char*) alloca(hostlen);
-                char *host6 = (char*) alloca(hostlen);
-                struct sockaddr_in sa4 = { .sin_family = AF_INET, .sin_addr = l_node_info->hdr.ext_addr_v4 };
-                const char* str_ip4 = inet_ntop(AF_INET, &(((struct sockaddr_in *) &sa4)->sin_addr), host4, hostlen);
+*/
 
-                struct sockaddr_in6 sa6 = { .sin6_family = AF_INET6, .sin6_addr = l_node_info->hdr.ext_addr_v6 };
-                const char* str_ip6 = inet_ntop(AF_INET6, &(((struct sockaddr_in6 *) &sa6)->sin6_addr), host6, hostlen);
+                char l_node_ipv4_str[INET_ADDRSTRLEN]={ '\0' }, l_node_ipv6_str[INET6_ADDRSTRLEN]={ '\0' };
+                inet_ntop(AF_INET, &l_node_info->hdr.ext_addr_v4, l_node_ipv4_str, INET_ADDRSTRLEN);
+                inet_ntop(AF_INET6, &l_node_info->hdr.ext_addr_v6, l_node_ipv6_str, INET6_ADDRSTRLEN);
+                char l_ts[128] = { '\0' };
+                dap_gbd_time_to_str_rfc822(l_ts, sizeof(l_ts), l_objs[i].timestamp);
+
+                dap_string_append_printf(l_string_reply, NODE_ADDR_FP_STR"    %-20s%-8s"NODE_ADDR_FP_STR"    %-32s\n",
+                                         NODE_ADDR_FP_ARGS_S(l_node_info->hdr.address),
+                                         l_node_ipv4_str, dap_itoa(l_node_info->hdr.ext_port),
+                                         NODE_ADDR_FP_ARGS_S(l_node_info->hdr.owner_address),
+                                         l_ts);
 
                 // get aliases in form of string
-                dap_string_t *aliases_string = dap_string_new(NULL);
+                /*dap_string_t *aliases_string = dap_string_new(NULL);
 
                 for (size_t i = 0; i < l_data_size; i++) {
                     //dap_chain_node_addr_t addr_i;
@@ -676,7 +681,7 @@ static int node_info_dump_with_reply(dap_chain_net_t * a_net, dap_chain_node_add
                 if(i)
                     dap_string_append_printf(l_string_reply, "\n");
                 char l_port_str[10];
-                sprintf(l_port_str,"%d", l_node_info->hdr.ext_port);
+                sprintf(l_port_str, "%d", l_node_info->hdr.ext_port);
                 // set short reply with node param
                 if(!a_is_full)
                     dap_string_append_printf(l_string_reply,
@@ -696,7 +701,7 @@ static int node_info_dump_with_reply(dap_chain_net_t * a_net, dap_chain_node_add
                             aliases_string->str,
                             l_node_info->hdr.links_number, links_string->str);
                 dap_string_free(aliases_string, true);
-                dap_string_free(links_string, true);
+                dap_string_free(links_string, true);*/
             }
             dap_global_db_objs_delete(l_aliases_objs, l_data_size);
         }
@@ -1211,22 +1216,54 @@ int com_node(int a_argc, char ** a_argv, char **a_str_reply)
             dap_digit_from_string(l_link_str, l_link.raw, sizeof(l_link.raw));
         }
     }
-
+    int l_ret =0;
     switch (cmd_num)
     {    
     case CMD_ADD:
-        if(!arg_index || a_argc < 8) {
-            dap_cli_server_cmd_set_reply_text(a_str_reply, "invalid parameters");
+        if(!l_port_str || !a_ipv4_str)
+        {
+            dap_cli_server_cmd_set_reply_text(a_str_reply, "node requires parameter -ipv4 and -port");
             DAP_DELETE(l_node_info);
             return -1;
         }
-        // handler of command 'node add'
-        int l_ret = node_info_add_with_reply(l_net, l_node_info, alias_str, l_cell_str, a_ipv4_str, a_ipv6_str,
-                a_str_reply);
+        dap_chain_node_info_t *l_link_node_request = DAP_NEW_Z( dap_chain_node_info_t);
+        l_link_node_request->hdr.address.uint64 = dap_chain_net_get_cur_addr_int(l_net);
+        inet_pton(AF_INET, a_ipv4_str, &(l_link_node_request->hdr.ext_addr_v4));
+        uint16_t l_node_port = 0;
+        dap_digit_from_string(l_port_str, &l_node_port, sizeof(uint16_t));
+        l_link_node_request->hdr.ext_port = l_node_port;
+        // Synchronous request, wait for reply
+        int res = dap_chain_net_node_list_request(l_net,l_link_node_request, true);
+        switch (res)
+        {
+            case 0:
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "No server");
+            break;
+            case 1:
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "Node addr successfully added to node list");
+            break;
+            case 2:
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "Didn't add your addres node to node list");
+            break;
+            case 3:
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't calculate hash for your addr");
+            break;
+            case 4:
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't do handshake for your node");
+            break;
+            case 5:
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "The node is already exists");
+            break;
+            case 6:
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't process node list HTTP request");
+            break;
+            default:
+                break;
+        }
+        DAP_DELETE(l_link_node_request);
         DAP_DELETE(l_node_info);
         return l_ret;
         //break;
-
     case CMD_DEL:
         // handler of command 'node del'
     {
@@ -2006,7 +2043,7 @@ int l_arg_index = 1, l_rc, cmd_num = CMD_NONE;
         // wallet info
         case CMD_WALLET_INFO: {
             dap_ledger_t *l_ledger = NULL;
-            if (l_wallet_name && l_addr_str || !l_wallet_name && !l_addr_str) {
+            if ((l_wallet_name && l_addr_str) || (!l_wallet_name && !l_addr_str)) {
                 dap_cli_server_cmd_set_reply_text(a_str_reply, "You should use either the -w or -addr option for the wallet info command.");
                 dap_string_free(l_string_ret, true);
                 return -1;
@@ -3541,10 +3578,12 @@ static int s_parse_additional_token_decl_arg(int a_argc, char ** a_argv, char **
             continue;
         }
         switch (l_tsd->type){
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_VALID:
+            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_VALID: {
+            uint16_t l_t = 0;
                 log_it(L_DEBUG,"== TOTAL_SIGNS_VALID: %u",
-                        dap_tsd_get_scalar(l_tsd,uint16_t) );
+                        _dap_tsd_get_scalar(l_tsd, &l_t) );
             break;
+        }
             case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_ALLOWED_ADD:
                 log_it(L_DEBUG,"== DATUM_TYPE_ALLOWED_ADD: %s",
                        dap_tsd_get_string_const(l_tsd) );
@@ -3843,10 +3882,12 @@ int com_token_decl(int a_argc, char ** a_argv, char ** a_str_reply)
                     continue;
                 }
                 switch (l_tsd->type){
-                    case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_VALID:
+                    case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_VALID: {
+                    uint16_t l_t = 0;
                         log_it(L_DEBUG,"== TOTAL_SIGNS_VALID: %u",
-                                dap_tsd_get_scalar(l_tsd, uint16_t) );
+                                _dap_tsd_get_scalar(l_tsd, &l_t) );
                     break;
+                }
                     case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_ALLOWED_ADD:
                         log_it(L_DEBUG,"== DATUM_TYPE_ALLOWED_ADD: %s",
                                dap_tsd_get_string_const(l_tsd) );
diff --git a/modules/net/dap_chain_node_cli_cmd_tx.c b/modules/net/dap_chain_node_cli_cmd_tx.c
index c876a3435da80fd65588554e885755fee880b327..88e9fdad8d17471cfaaacaba1cc1025183ffbb37 100644
--- a/modules/net/dap_chain_node_cli_cmd_tx.c
+++ b/modules/net/dap_chain_node_cli_cmd_tx.c
@@ -107,7 +107,7 @@ static bool s_dap_chain_datum_tx_out_data(dap_chain_datum_tx_t *a_datum,
     dap_chain_datum_dump_tx(a_datum, l_ticker, a_str_out, a_hash_out_type, a_tx_hash, a_ledger->net_id);
     dap_list_t *l_out_items = dap_chain_datum_tx_items_get(a_datum, TX_ITEM_TYPE_OUT_ALL, NULL);
     int l_out_idx = 0;
-    dap_string_append_printf(a_str_out, "Spenders:\r\n");
+    dap_string_append_printf(a_str_out, "Spent OUTs:\r\n");
     bool l_spent = false;
     for (dap_list_t *l_item = l_out_items; l_item; l_item = l_item->next, ++l_out_idx) {
         switch (*(dap_chain_tx_item_type_t*)l_item->data) {
@@ -115,12 +115,13 @@ static bool s_dap_chain_datum_tx_out_data(dap_chain_datum_tx_t *a_datum,
         case TX_ITEM_TYPE_OUT_OLD:
         case TX_ITEM_TYPE_OUT_EXT: {
             dap_hash_fast_t l_spender = { };
-            if ((l_spent = dap_chain_ledger_tx_hash_is_used_out_item(a_ledger, a_tx_hash, l_out_idx, &l_spender))) {
+            if (dap_chain_ledger_tx_hash_is_used_out_item(a_ledger, a_tx_hash, l_out_idx, &l_spender)) {
                 char l_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE] = { '\0' };
                 dap_hash_fast_to_str(&l_spender, l_hash_str, sizeof(l_hash_str));
                 dap_string_append_printf(a_str_out,
-                                         "\tout item %d is spent by tx %s\r\n",
+                                         "\tOUT %d is spent by tx %s\r\n",
                                          l_out_idx, l_hash_str);
+                l_spent = true;
             }
             break;
         }
@@ -128,7 +129,7 @@ static bool s_dap_chain_datum_tx_out_data(dap_chain_datum_tx_t *a_datum,
             break;
         }
     }
-    dap_string_append_printf(a_str_out, l_spent ? "\r\n\r\n" : "\tall yet unspent\r\n\r\n");
+    dap_string_append_printf(a_str_out, l_spent ? "\r\n\r\n" : "\tall OUTs yet unspent\r\n\r\n");
     return true;
 }
 
diff --git a/modules/net/include/dap_chain_net.h b/modules/net/include/dap_chain_net.h
index dc8fc580267ceb8bc76e466c2c99cc0a5ff8266a..22f3ba32a02a3fe802e0adc30ae684d3cdef28eb 100644
--- a/modules/net/include/dap_chain_net.h
+++ b/modules/net/include/dap_chain_net.h
@@ -206,6 +206,7 @@ bool dap_chain_net_get_extra_gdb_group(dap_chain_net_t *a_net, dap_chain_node_ad
 int dap_chain_net_verify_datum_for_add(dap_chain_t *a_chain, dap_chain_datum_t *a_datum, dap_hash_fast_t *a_datum_hash);
 char *dap_chain_net_verify_datum_err_code_to_str(dap_chain_datum_t *a_datum, int a_code);
 int dap_chain_net_add_downlink(dap_chain_net_t *a_net, dap_stream_worker_t *a_worker, dap_stream_ch_uuid_t a_ch_uuid, dap_events_socket_uuid_t a_esocket_uuid, char *a_addr, int a_port);
+void dap_chain_net_del_downlink(dap_stream_ch_uuid_t *a_ch_uuid);
 void dap_chain_net_add_gdb_notify_callback(dap_chain_net_t *a_net, dap_store_obj_callback_notify_t a_callback, void *a_cb_arg);
 void dap_chain_net_sync_gdb_broadcast(dap_global_db_context_t *a_context, dap_store_obj_t *a_obj, void *a_arg);
 
@@ -222,5 +223,5 @@ dap_list_t *dap_chain_datum_list(dap_chain_net_t *a_net, dap_chain_t *a_chain, d
 int dap_chain_datum_add(dap_chain_t * a_chain, dap_chain_datum_t *a_datum, size_t a_datum_size, dap_hash_fast_t *a_datum_hash);
 
 bool dap_chain_net_get_load_mode(dap_chain_net_t * a_net);
-
+void dap_chain_net_announce_addrs();
 char *dap_chain_net_links_dump(dap_chain_net_t*);
diff --git a/modules/net/include/dap_chain_net_balancer.h b/modules/net/include/dap_chain_net_balancer.h
index a2a4f9770666f492e743122383425de4873c7d2f..91162955008a7e4e4ee459f573b760ecd0f350b5 100644
--- a/modules/net/include/dap_chain_net_balancer.h
+++ b/modules/net/include/dap_chain_net_balancer.h
@@ -37,5 +37,4 @@ dap_chain_node_info_t *dap_chain_net_balancer_dns_issue_link(char *a_str);
 void dap_chain_net_balancer_prepare_list_links(const char *a_net_name,bool handshake_on);
 dap_chain_net_node_balancer_t *dap_chain_net_balancer_get_node(const char *a_net_name,uint16_t a_links_need);
 void dap_chain_net_balancer_set_link_ban(dap_chain_node_info_t *a_node_info, const char *a_net_name);
-void dap_chain_net_balancer_free_link_ban(dap_chain_net_t * a_net);
-
+bool dap_chain_net_balancer_handshake(dap_chain_node_info_t *a_node_info,dap_chain_net_t * a_net);
diff --git a/modules/net/include/dap_chain_net_node_list.h b/modules/net/include/dap_chain_net_node_list.h
new file mode 100644
index 0000000000000000000000000000000000000000..2e32bc60712f9570f5e384bc0fcc20e1a4255807
--- /dev/null
+++ b/modules/net/include/dap_chain_net_node_list.h
@@ -0,0 +1,53 @@
+/*
+* Authors:
+* Roman Khlopkov <roman.khlopkov@demlabs.net>
+* Cellframe       https://cellframe.net
+* DeM Labs Inc.   https://demlabs.net
+* Copyright  (c) 2017-2022
+* All rights reserved.
+
+This file is part of CellFrame SDK the open source project
+
+CellFrame SDK is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+CellFrame SDK is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with any CellFrame SDK based project.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#pragma once
+
+#include "dap_http_simple.h"
+#include "dap_chain_net.h"
+
+#define DAP_NODE_LIST_URI_HASH "node_list_hash"
+
+struct node_link_request {
+    dap_chain_node_info_t *link_info;
+    dap_chain_net_t *net;
+    dap_worker_t *worker;
+    bool from_http;
+    int link_replace_tries;
+    int response;
+    pthread_cond_t wait_cond;
+    pthread_mutex_t wait_mutex;
+};
+/**
+* @brief dap_chain_net_node_list_get_gdb_group
+* @param a_net
+* @return
+*/
+DAP_STATIC_INLINE char * dap_chain_net_node_list_get_gdb_group(dap_chain_net_t * a_net)
+{
+    return a_net ? dap_strdup_printf("%s.service.orders",a_net->pub.gdb_groups_prefix) : NULL;
+}
+
+void dap_chain_net_node_check_http_issue_link(dap_http_simple_t *a_http_simple, void *a_arg);
+int dap_chain_net_node_list_request (dap_chain_net_t *a_net, dap_chain_node_info_t *a_link_node_request, bool a_sync);
+int dap_chain_net_node_list_init();
diff --git a/modules/net/include/dap_chain_node.h b/modules/net/include/dap_chain_node.h
index 3d14e6d7b4fae80f630340c1c6f977b96a6bfc45..b5f8155889e7909cb4a8c33b0f69eeda9dd3070d 100644
--- a/modules/net/include/dap_chain_node.h
+++ b/modules/net/include/dap_chain_node.h
@@ -68,13 +68,14 @@ typedef struct dap_chain_node_decl{
 
 typedef struct dap_chain_node_info {
     struct {
-        dap_chain_node_addr_t address;
+        dap_chain_node_addr_t address;        
         dap_chain_cell_id_t cell_id;
         uint32_t links_number;
         struct in_addr ext_addr_v4;
         struct in6_addr ext_addr_v6;
         uint16_t ext_port; // Port thats node listening
-        char alias[248];
+        char alias[240];
+        dap_chain_node_addr_t owner_address;
         uint64_t blocks_events; /* truncated alias len */
     } DAP_ALIGN_PACKED hdr;
     dap_chain_node_addr_t links[]; // dap_chain_addr_t
diff --git a/modules/net/srv/include/dap_chain_net_srv.h b/modules/net/srv/include/dap_chain_net_srv.h
index bde2977e8998d58fccc1b0efaaf6a231ffe1ea0a..1202afa1f89da4f404ceedf6b5bbc60ac743caea 100755
--- a/modules/net/srv/include/dap_chain_net_srv.h
+++ b/modules/net/srv/include/dap_chain_net_srv.h
@@ -197,7 +197,7 @@ typedef struct dap_chain_net_srv_client_remote
     dap_stream_ch_t * ch; // Use ONLY in own context, not thread-safe
     time_t ts_created;
     dap_stream_worker_t * stream_worker;
-    int session_id;
+    uint32_t session_id;
     uint64_t bytes_received;
     uint64_t bytes_sent;
     struct dap_chain_net_srv_client_remote *prev;
diff --git a/modules/service/stake/dap_chain_net_srv_stake_lock.c b/modules/service/stake/dap_chain_net_srv_stake_lock.c
index ea265e83de2c9515e147c12259dab1404e459aa1..a0ba00a627ef9bd5e1e0ff9eb410fa6c039f7e78 100644
--- a/modules/service/stake/dap_chain_net_srv_stake_lock.c
+++ b/modules/service/stake/dap_chain_net_srv_stake_lock.c
@@ -223,8 +223,8 @@ static enum error_code s_cli_hold(int a_argc, char **a_argv, int a_arg_index, da
         return NO_DELEGATED_TOKEN_ERROR;
     }
 
-    l_tsd_section = dap_tsd_get_object(l_tsd, dap_chain_datum_token_tsd_delegate_from_stake_lock_t);
-    if (strcmp(l_ticker_str, (char *)l_tsd_section->ticker_token_from))
+    l_tsd_section = _dap_tsd_get_object(l_tsd, dap_chain_datum_token_tsd_delegate_from_stake_lock_t);
+    if (strcmp(l_ticker_str, (char*)l_tsd_section->ticker_token_from))
         return TOKEN_ERROR;
 
     if (IS_ZERO_256(l_tsd_section->emission_rate))
@@ -429,8 +429,8 @@ static enum error_code s_cli_take(int a_argc, char **a_argv, int a_arg_index, da
             return NO_DELEGATED_TOKEN_ERROR;
         }
 
-        l_tsd_section = dap_tsd_get_object(l_tsd, dap_chain_datum_token_tsd_delegate_from_stake_lock_t);
-        if (strcmp(l_ticker_str, (char *)l_tsd_section->ticker_token_from))
+        l_tsd_section = _dap_tsd_get_object(l_tsd, dap_chain_datum_token_tsd_delegate_from_stake_lock_t);
+        if (strcmp(l_ticker_str, (char*)l_tsd_section->ticker_token_from))
             return TOKEN_ERROR;
 
         if (!IS_ZERO_256(l_tsd_section->emission_rate)) {
@@ -918,7 +918,7 @@ static bool s_stake_lock_callback_verificator(dap_ledger_t *a_ledger, dap_chain_
             return false;
         }
 
-        l_tsd_section = dap_tsd_get_object(l_tsd, dap_chain_datum_token_tsd_delegate_from_stake_lock_t);
+        l_tsd_section = _dap_tsd_get_object(l_tsd, dap_chain_datum_token_tsd_delegate_from_stake_lock_t);
 
         if (!IS_ZERO_256(l_tsd_section->emission_rate)) {
             MULT_256_COIN(a_cond->header.value, l_tsd_section->emission_rate, &l_value_delegated);