diff --git a/dap-sdk b/dap-sdk
index a318ac98bc34a399b3a9f95f7b819143ed868f40..3f75cc73ff155c9ae97682059535dd5a23b0c42f 160000
--- a/dap-sdk
+++ b/dap-sdk
@@ -1 +1 @@
-Subproject commit a318ac98bc34a399b3a9f95f7b819143ed868f40
+Subproject commit 3f75cc73ff155c9ae97682059535dd5a23b0c42f
diff --git a/modules/chain/dap_chain.c b/modules/chain/dap_chain.c
index a09641236e9366f5a51718a70cb9ca72ea8b3233..20c8dfc5bc801e4014bbb9922eee78bb1ec563e1 100644
--- a/modules/chain/dap_chain.c
+++ b/modules/chain/dap_chain.c
@@ -697,7 +697,7 @@ void dap_chain_info_dump_log(dap_chain_t * a_chain)
  * @param a_callback
  * @param a_arg
  */
-void dap_chain_add_callback_notify(dap_chain_t * a_chain, dap_chain_callback_notify_t a_callback, void * a_callback_arg)
+void dap_chain_add_callback_notify(dap_chain_t *a_chain, dap_chain_callback_notify_t a_callback, dap_proc_thread_t *a_thread, void *a_callback_arg)
 {
     if(!a_chain){
         log_it(L_ERROR, "NULL chain passed to dap_chain_add_callback_notify()");
@@ -714,6 +714,7 @@ void dap_chain_add_callback_notify(dap_chain_t * a_chain, dap_chain_callback_not
     }
 
     l_notifier->callback = a_callback;
+    l_notifier->proc_thread = a_thread;
     l_notifier->arg = a_callback_arg;
     pthread_rwlock_wrlock(&a_chain->rwlock);
     a_chain->atom_notifiers = dap_list_append(a_chain->atom_notifiers, l_notifier);
@@ -845,7 +846,7 @@ void dap_chain_atom_notify(dap_chain_cell_t *a_chain_cell, dap_hash_fast_t *a_ha
             .hash = *a_hash,
             .atom = a_chain_cell->chain->is_mapped ? (byte_t*)a_atom : DAP_DUP_SIZE(a_atom, a_atom_size),
             .atom_size = a_atom_size };
-        dap_proc_thread_callback_add_pri(NULL, s_notify_atom_on_thread, l_arg, DAP_QUEUE_MSG_PRIORITY_LOW);
+        dap_proc_thread_callback_add_pri(l_notifier->proc_thread, s_notify_atom_on_thread, l_arg, DAP_QUEUE_MSG_PRIORITY_LOW);
     }
 }
 
diff --git a/modules/chain/dap_chain_cell.c b/modules/chain/dap_chain_cell.c
index 3ccbbf7771fc80bf00344f8a40ec3c98030688f3..ba76d6f8253f3d8783678bb6e3ed8b0895cd49a3 100644
--- a/modules/chain/dap_chain_cell.c
+++ b/modules/chain/dap_chain_cell.c
@@ -107,6 +107,17 @@ int dap_chain_cell_init(void)
     return  0;
 }
 
+#ifndef DAP_OS_WINDOWS
+DAP_STATIC_INLINE void s_cell_reclaim_cur_volume(dap_chain_cell_t *a_cell) {
+    if (
+#ifdef MADV_PAGEOUT
+    //madvise(a_cell->map, (size_t)(a_cell->map_end - a_cell->map), MADV_PAGEOUT) &&
+#endif
+    madvise(a_cell->map, (size_t)(a_cell->map_end - a_cell->map), MADV_DONTNEED) )
+        log_it(L_ERROR, "Unable to reclaim the previous volume, errno %d: \"%s\"", errno, dap_strerror(errno));
+}
+#endif
+
 DAP_STATIC_INLINE int s_cell_file_write_header(dap_chain_cell_t *a_cell)
 {
     dap_chain_cell_file_header_t l_hdr = {
@@ -120,7 +131,7 @@ DAP_STATIC_INLINE int s_cell_file_write_header(dap_chain_cell_t *a_cell)
     return fwrite(&l_hdr, sizeof(l_hdr), 1, a_cell->file_storage) ? fflush(a_cell->file_storage) : -1;
 }
 
-DAP_STATIC_INLINE int s_cell_map_new_volume(dap_chain_cell_t *a_cell, size_t a_fpos) {
+DAP_STATIC_INLINE int s_cell_map_new_volume(dap_chain_cell_t *a_cell, size_t a_fpos, bool a_load) {
     int l_fildes = fileno(a_cell->file_storage);
 #ifdef DAP_OS_WINDOWS
     HANDLE hSection = NULL;
@@ -135,12 +146,9 @@ DAP_STATIC_INLINE int s_cell_map_new_volume(dap_chain_cell_t *a_cell, size_t a_f
         };
         
         NTSTATUS err = pfnNtCreateSection(&hSection, SECTION_MAP_READ|SECTION_EXTEND_SIZE|SECTION_MAP_WRITE, 
-                                          NULL, &SectionSize, PAGE_READWRITE, SEC_RESERVE,
-                                          (HANDLE)_get_osfhandle(l_fildes));
-        if ( !NT_SUCCESS(err) ) {
-            log_it(L_ERROR, "NtCreateSection() failed, status %lx", err);
-            return -1;
-        }
+                                          NULL, &SectionSize, PAGE_READWRITE, SEC_RESERVE, (HANDLE)_get_osfhandle(l_fildes));
+        if ( !NT_SUCCESS(err) )
+            return log_it(L_ERROR, "NtCreateSection() failed, status %lx", err), -1;
         a_cell->map_range_bounds = dap_list_append(a_cell->map_range_bounds, hSection);
     }
 #endif
@@ -158,23 +166,17 @@ DAP_STATIC_INLINE int s_cell_map_new_volume(dap_chain_cell_t *a_cell, size_t a_f
     LARGE_INTEGER Offset = {
         .QuadPart = l_volume_start
     };
-    if ( !NT_SUCCESS ( err = pfnNtMapViewOfSection(hSection, GetCurrentProcess(), 
-                                                   (HANDLE)&a_cell->map, 0, 0, 
-                                                   &Offset, &l_map_size,
-                                                   ViewUnmap, MEM_RESERVE,
-                                                   PAGE_WRITECOPY) ) )
-    {
-        log_it(L_ERROR, "NtMapViewOfSection() failed, status %lx", err);
-        NtClose(hSection);
-        return -1;
-    }
+    err = pfnNtMapViewOfSection(hSection, GetCurrentProcess(), (HANDLE)&a_cell->map, 0, 0, 
+                                &Offset, &l_map_size, ViewUnmap, MEM_RESERVE, PAGE_WRITECOPY);
+    if ( !NT_SUCCESS(err) )
+        return NtClose(hSection), log_it(L_ERROR, "NtMapViewOfSection() failed, status %lx", err), -1;
 #else
-    if ( MAP_FAILED == (a_cell->map = mmap(NULL, l_map_size, PROT_READ|PROT_WRITE,
-                                           MAP_PRIVATE, fileno(a_cell->file_storage), l_volume_start)) ) {
-        log_it(L_ERROR, "Chain cell \"%s\" 0x%016"DAP_UINT64_FORMAT_X" cannot be mapped, errno %d",
-                        a_cell->file_storage_path, a_cell->id.uint64, errno);
-        return -1;
-    }
+    if (a_load)
+        s_cell_reclaim_cur_volume(a_cell);
+    if (( a_cell->map = mmap(NULL, l_map_size, PROT_READ|PROT_WRITE, MAP_PRIVATE,
+                             fileno(a_cell->file_storage), l_volume_start) ) == MAP_FAILED )
+        return log_it(L_ERROR, "Chain cell \"%s\" 0x%016"DAP_UINT64_FORMAT_X" cannot be mapped, errno %d",
+                                a_cell->file_storage_path, a_cell->id.uint64, errno), -1;
 #ifdef DAP_OS_DARWIN
     a_cell->cur_vol_start = l_volume_start;
 #endif
@@ -182,6 +184,10 @@ DAP_STATIC_INLINE int s_cell_map_new_volume(dap_chain_cell_t *a_cell, size_t a_f
     a_cell->map_pos = a_cell->map + l_offset;
     a_cell->map_range_bounds = dap_list_append(a_cell->map_range_bounds, a_cell->map);
     a_cell->map_range_bounds = dap_list_append(a_cell->map_range_bounds, a_cell->map_end = a_cell->map + l_map_size);
+#ifndef DAP_OS_WINDOWS    
+    if (a_load)
+        madvise(a_cell->map, l_map_size, MADV_SEQUENTIAL);
+#endif
     return 0;
 }
 
@@ -259,7 +265,7 @@ dap_chain_cell_t * dap_chain_cell_create_fill(dap_chain_t * a_chain, dap_chain_c
         fflush(l_file);
     }
 
-    if ( a_chain->is_mapped && s_cell_map_new_volume(l_cell, 0) ) {
+    if ( a_chain->is_mapped && s_cell_map_new_volume(l_cell, 0, true) ) {
         CLEANUP_AND_RET;
     }
 #undef CLEANUP_AND_RET
@@ -454,7 +460,7 @@ int dap_chain_cell_load(dap_chain_t *a_chain, dap_chain_cell_t *a_cell)
         for ( l_el_size = 0; l_pos < l_full_size; ++q, l_pos += l_el_size + sizeof(uint64_t) ) {
             l_vol_rest = (uint64_t)( a_cell->map_end - a_cell->map_pos );
             if ( l_vol_rest <= sizeof(uint64_t) || l_vol_rest - sizeof(uint64_t) <= *(uint64_t*)a_cell->map_pos)
-                if ( s_cell_map_new_volume(a_cell, l_pos) )
+                if ( s_cell_map_new_volume(a_cell, l_pos, true) )
                     break;
             if (*(uint64_t*)a_cell->map_pos > l_full_size - l_pos ) {
                 log_it(L_ERROR, "Atom size exeeds file remainder: %zu > %zu. "
@@ -469,6 +475,9 @@ int dap_chain_cell_load(dap_chain_t *a_chain, dap_chain_cell_t *a_cell)
             a_cell->map_pos += l_el_size;
             a_chain->load_progress = (int)((float)l_pos/l_full_size * 100 + 0.5);
         }
+#ifndef DAP_OS_WINDOWS
+        s_cell_reclaim_cur_volume(a_cell);
+#endif
     } else { 
         DAP_DELETE(l_hdr);
         size_t l_read = 0;
@@ -485,7 +494,7 @@ int dap_chain_cell_load(dap_chain_t *a_chain, dap_chain_cell_t *a_cell)
                 break;
             }
             l_pos += sizeof(uint64_t) + ( l_read = fread((void*)l_element, 1, l_el_size, a_cell->file_storage) );
-            a_chain->load_progress = (int)((double)l_pos/l_full_size * 100 + 0.5);
+            a_chain->load_progress = (int)((float)l_pos/l_full_size * 100 + 0.5);
             if (l_read != l_el_size) {
                 log_it(L_ERROR, "Read only %lu of %zu bytes, stop cell loading", l_read, l_el_size);
                 DAP_DELETE(l_element);
@@ -519,7 +528,7 @@ static int s_cell_file_atom_add(dap_chain_cell_t *a_cell, dap_chain_atom_ptr_t a
         debug_if (s_debug_more, L_DEBUG, "Before filling volume for atom size %ld, stream pos of %s is %lu, map pos is %lu, space left in map %lu",
                       a_atom_size, a_cell->file_storage_path, l_pos, (size_t)(a_cell->map_pos - a_cell->map), (size_t)(a_cell->map_end - a_cell->map_pos));
         if ( a_atom_size + sizeof(uint64_t) > (size_t)(a_cell->map_end - a_cell->map_pos) )
-            if ( s_cell_map_new_volume(a_cell, (size_t)l_pos) )
+            if ( s_cell_map_new_volume(a_cell, (size_t)l_pos, false) )
                 return -2;
     }
     
diff --git a/modules/chain/dap_chain_ch.c b/modules/chain/dap_chain_ch.c
index 6c71b25332bd29758646d05ce2a4b1fb115d39db..2771e6b3d14dbbdd6468b099400886b5b68d0370 100644
--- a/modules/chain/dap_chain_ch.c
+++ b/modules/chain/dap_chain_ch.c
@@ -154,39 +154,21 @@ static  dap_memstat_rec_t   s_memstat [MEMSTAT$K_NR] = {
 
 #endif
 
-static const char *s_error_type_to_string(dap_chain_ch_error_type_t a_error)
-{
-    switch (a_error) {
-    case DAP_CHAIN_CH_ERROR_SYNC_REQUEST_ALREADY_IN_PROCESS:
-        return "SYNC_REQUEST_ALREADY_IN_PROCESS";
-    case DAP_CHAIN_CH_ERROR_INCORRECT_SYNC_SEQUENCE:
-        return "INCORRECT_SYNC_SEQUENCE";
-    case DAP_CHAIN_CH_ERROR_SYNC_TIMEOUT:
-        return "SYNCHRONIZATION TIMEOUT";
-    case DAP_CHAIN_CH_ERROR_CHAIN_PKT_DATA_SIZE:
-        return "INVALID_PACKET_SIZE";
-    case DAP_CHAIN_CH_ERROR_LEGACY_PKT_DATA_SIZE:
-        return "INVALID_LEGACY_PACKET_SIZE";
-    case DAP_CHAIN_CH_ERROR_NET_INVALID_ID:
-        return "INVALID_NET_ID";
-    case DAP_CHAIN_CH_ERROR_CHAIN_NOT_FOUND:
-        return "CHAIN_NOT_FOUND";
-    case DAP_CHAIN_CH_ERROR_ATOM_NOT_FOUND:
-        return "ATOM_NOT_FOUND";
-    case DAP_CHAIN_CH_ERROR_UNKNOWN_CHAIN_PKT_TYPE:
-        return "UNKNOWN_CHAIN_PACKET_TYPE";
-    case DAP_CHAIN_CH_ERROR_GLOBAL_DB_INTERNAL_NOT_SAVED:
-        return "GLOBAL_DB_INTERNAL_SAVING_ERROR";
-    case DAP_CHAIN_CH_ERROR_NET_IS_OFFLINE:
-        return "NET_IS_OFFLINE";
-    case DAP_CHAIN_CH_ERROR_OUT_OF_MEMORY:
-        return "OUT_OF_MEMORY";
-    case DAP_CHAIN_CH_ERROR_INTERNAL:
-        return "INTERNAL_ERROR";
-    default:
-        return "UNKNOWN_ERROR";
-    }
-}
+const char* const s_error_type_to_string[] = {
+    [DAP_CHAIN_CH_ERROR_SYNC_REQUEST_ALREADY_IN_PROCESS]= "SYNC_REQUEST_ALREADY_IN_PROCESS",
+    [DAP_CHAIN_CH_ERROR_INCORRECT_SYNC_SEQUENCE]        = "INCORRECT_SYNC_SEQUENCE",
+    [DAP_CHAIN_CH_ERROR_SYNC_TIMEOUT]                   = "SYNCHRONIZATION TIMEOUT",
+    [DAP_CHAIN_CH_ERROR_CHAIN_PKT_DATA_SIZE]            = "INVALID_PACKET_SIZE",
+    [DAP_CHAIN_CH_ERROR_LEGACY_PKT_DATA_SIZE]           = "INVALID_LEGACY_PACKET_SIZE",
+    [DAP_CHAIN_CH_ERROR_NET_INVALID_ID]                 = "INVALID_NET_ID",
+    [DAP_CHAIN_CH_ERROR_CHAIN_NOT_FOUND]                = "CHAIN_NOT_FOUND",
+    [DAP_CHAIN_CH_ERROR_ATOM_NOT_FOUND]                 = "ATOM_NOT_FOUND",
+    [DAP_CHAIN_CH_ERROR_UNKNOWN_CHAIN_PKT_TYPE]         = "UNKNOWN_CHAIN_PACKET_TYPE",
+    [DAP_CHAIN_CH_ERROR_GLOBAL_DB_INTERNAL_NOT_SAVED]   = "GLOBAL_DB_INTERNAL_SAVING_ERROR",
+    [DAP_CHAIN_CH_ERROR_NET_IS_OFFLINE]                 = "NET_IS_OFFLINE",
+    [DAP_CHAIN_CH_ERROR_OUT_OF_MEMORY]                  = "OUT_OF_MEMORY",
+    [DAP_CHAIN_CH_ERROR_INTERNAL]                       = "INTERNAL_ERROR"
+};
 
 /**
  * @brief dap_chain_ch_init
@@ -618,18 +600,15 @@ static bool s_sync_in_chains_callback(void *a_arg)
         DAP_DELETE(l_args);
         return false;
     }
-    char *l_atom_hash_str = NULL;
-    l_atom_hash_str = DAP_NEW_STACK_SIZE(char, DAP_CHAIN_HASH_FAST_STR_SIZE); 
-    dap_hash_fast_t l_atom_hash = {}; 
-    dap_hash_fast(l_atom, l_atom_size, &l_atom_hash); 
-    if (s_debug_more)
-        dap_get_data_hash_str_static(l_atom, l_atom_size, l_atom_hash_str);
+    dap_hash_fast_t l_atom_hash = { }; 
+    dap_hash_fast(l_atom, l_atom_size, &l_atom_hash);
+    char *l_atom_hash_str = dap_hash_fast_to_str_static(&l_atom_hash);
     dap_chain_atom_verify_res_t l_atom_add_res = l_chain->callback_atom_add(l_chain, l_atom, l_atom_size, &l_atom_hash, false);
     bool l_ack_send = false;
     switch (l_atom_add_res) {
     case ATOM_PASS:
         debug_if(s_debug_more, L_WARNING, "Atom with hash %s for %s:%s not accepted (code ATOM_PASS, already present)",
-                                                l_atom_hash_str, l_chain->net_name, l_chain->name);
+                                          l_atom_hash_str, l_chain->net_name, l_chain->name);
         l_ack_send = true;
         break;
     case ATOM_MOVE_TO_THRESHOLD:
@@ -689,7 +668,7 @@ void dap_stream_ch_write_error_unsafe(dap_stream_ch_t *a_ch, dap_chain_net_id_t
 {
     dap_chain_ch_t *l_ch_chain = DAP_CHAIN_CH(a_ch);
     dap_return_if_fail(l_ch_chain);
-    const char *l_err_str = s_error_type_to_string(a_error);
+    const char *l_err_str = a_error < DAP_CHAIN_CH_ERROR_LAST ? s_error_type_to_string[a_error] : "UNDEFINED ERROR";
     dap_chain_ch_pkt_write_unsafe(a_ch, DAP_CHAIN_CH_PKT_TYPE_ERROR, a_net_id, a_chain_id, a_cell_id, l_err_str, strlen(l_err_str) + 1, DAP_CHAIN_CH_PKT_VERSION_LEGACY);
     s_ch_chain_go_idle(l_ch_chain);
 }
@@ -776,12 +755,9 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg)
         l_args->addr = a_ch->stream->node;
         l_args->ack_req = true;
         memcpy(l_args->data, l_chain_pkt, l_ch_pkt->hdr.data_size);
-        if (s_debug_more) {
-            char *l_atom_hash_str;
-            dap_get_data_hash_str_static(l_chain_pkt->data, l_chain_pkt_data_size, l_atom_hash_str);
-            log_it(L_INFO, "In: CHAIN pkt: atom hash %s, size %zd, net id %" DAP_UINT64_FORMAT_U ", chain id %" DAP_UINT64_FORMAT_U,
-                    l_atom_hash_str, l_chain_pkt_data_size, l_chain_pkt->hdr.net_id.uint64, l_chain_pkt->hdr.chain_id.uint64);
-        }
+        debug_if(s_debug_more, L_INFO, "In: CHAIN pkt: atom hash %s, size %zd, net id %" DAP_UINT64_FORMAT_U ", chain id %" DAP_UINT64_FORMAT_U,
+                                        dap_get_data_hash_str(l_chain_pkt->data, l_chain_pkt_data_size).s, l_chain_pkt_data_size, 
+                                        l_chain_pkt->hdr.net_id.uint64, l_chain_pkt->hdr.chain_id.uint64);
         dap_proc_thread_callback_add(a_ch->stream_worker->worker->proc_queue_input, s_sync_in_chains_callback, l_args);
     } break;
 
@@ -1498,11 +1474,8 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg)
         }
         l_chain_pkt->hdr.data_size = l_chain_pkt_data_size;
         memcpy(l_args->data, l_chain_pkt, l_ch_pkt->hdr.data_size);
-        if (s_debug_legacy) {
-            char *l_atom_hash_str;
-            dap_get_data_hash_str_static(l_chain_pkt->data, l_chain_pkt_data_size, l_atom_hash_str);
-            log_it(L_INFO, "In: CHAIN_OLD pkt: atom hash %s (size %zd)", l_atom_hash_str, l_chain_pkt_data_size);
-        }
+        debug_if(s_debug_legacy, L_INFO, "In: CHAIN_OLD pkt: atom hash %s (size %zd)",
+                                         dap_get_data_hash_str(l_chain_pkt->data, l_chain_pkt_data_size).s, l_chain_pkt_data_size);
         dap_proc_thread_callback_add(a_ch->stream_worker->worker->proc_queue_input, s_sync_in_chains_callback, l_args);
     } break;
 
@@ -1551,7 +1524,7 @@ static bool s_sync_timer_callback(void *a_arg)
     }
 
     bool l_timer_break = false;
-    const char *l_err_str = s_error_type_to_string(DAP_CHAIN_CH_ERROR_SYNC_TIMEOUT);
+    const char* l_err_str = s_error_type_to_string[DAP_CHAIN_CH_ERROR_SYNC_TIMEOUT];
     if (l_ch_chain->sync_context) {
         struct sync_context *l_context = l_ch_chain->sync_context;
         if (l_context->last_activity + s_sync_timeout <= dap_time_now()) {
diff --git a/modules/chain/dap_chain_cs.c b/modules/chain/dap_chain_cs.c
index 05f5d6549c4c1e6923bbc7596ba11fc65e29e4a0..d30576d826c3fa79d9bbaf82d98257b79354061d 100644
--- a/modules/chain/dap_chain_cs.c
+++ b/modules/chain/dap_chain_cs.c
@@ -134,11 +134,11 @@ int dap_chain_cs_create(dap_chain_t * a_chain, dap_config_t * a_chain_cfg)
         HASH_FIND_STR(s_cs_callbacks, l_consensus, l_item );
     if (l_item) {
         log_it(L_NOTICE,"Consensus \"%s\" found, prepare to parse config file",l_item->name );
-        int ret = 0;
+        int res = 0;
         if (l_item->callback_init)
-            ret = l_item->callback_init(a_chain, a_chain_cfg);
+            res = l_item->callback_init(a_chain, a_chain_cfg);
         DAP_CHAIN_PVT(a_chain)->cs_name = l_item->name;
-        return ret;
+        return res;
     } else {
         log_it(L_ERROR,"Can't find consensus \"%s\"",dap_config_get_item_str( a_chain_cfg, "chain", "consensus"));
         return -1;
diff --git a/modules/chain/include/dap_chain.h b/modules/chain/include/dap_chain.h
index e665a6ae20dbd876aec0d058b388ecf4dad22373..e8e027832c506591033c6de38a4734f08515b731 100644
--- a/modules/chain/include/dap_chain.h
+++ b/modules/chain/include/dap_chain.h
@@ -62,7 +62,10 @@ typedef struct dap_chain_datum_iter {
     size_t cur_size;
     dap_chain_hash_fast_t *cur_hash;
     dap_chain_hash_fast_t *cur_atom_hash;
+    uint32_t action;
+    dap_chain_net_srv_uid_t uid;
     int ret_code;
+    char *token_ticker;
     void *cur_item;
 } dap_chain_datum_iter_t;
 
@@ -231,8 +234,11 @@ typedef struct dap_chain {
     void * _inheritor; // inheritor object
 } dap_chain_t;
 
+typedef struct dap_proc_thread dap_proc_thread_t;
+
 typedef struct dap_chain_atom_notifier {
     dap_chain_callback_notify_t callback;
+    dap_proc_thread_t *proc_thread;
     void *arg;
 } dap_chain_atom_notifier_t;
 
@@ -274,7 +280,7 @@ dap_chain_t * dap_chain_find_by_id(dap_chain_net_id_t a_chain_net_id,dap_chain_i
 dap_chain_t *dap_chain_load_from_cfg(const char *a_chain_net_name, dap_chain_net_id_t a_chain_net_id, const char *a_chain_cfg_name);
 
 void dap_chain_delete(dap_chain_t * a_chain);
-void dap_chain_add_callback_notify(dap_chain_t * a_chain, dap_chain_callback_notify_t a_callback, void * a_arg);
+void dap_chain_add_callback_notify(dap_chain_t *a_chain, dap_chain_callback_notify_t a_callback, dap_proc_thread_t *a_thread, void *a_arg);
 void dap_chain_atom_notify(dap_chain_cell_t *a_chain_cell,  dap_hash_fast_t *a_hash, const uint8_t *a_atom, size_t a_atom_size);
 void dap_chain_atom_add_from_threshold(dap_chain_t *a_chain);
 dap_chain_atom_ptr_t dap_chain_get_atom_by_hash(dap_chain_t * a_chain, dap_chain_hash_fast_t * a_atom_hash, size_t * a_atom_size);
diff --git a/modules/chain/include/dap_chain_ch.h b/modules/chain/include/dap_chain_ch.h
index 384e5ec3d9154c784f783acb6caa0b6b06122237..da98e7e88fa5c016c40465c49b0c6884e657ba5a 100644
--- a/modules/chain/include/dap_chain_ch.h
+++ b/modules/chain/include/dap_chain_ch.h
@@ -63,7 +63,9 @@ typedef enum dap_chain_ch_error_type {
     DAP_CHAIN_CH_ERROR_INTERNAL,
 // Legacy
     DAP_CHAIN_CH_ERROR_GLOBAL_DB_INTERNAL_NOT_SAVED,
-    DAP_CHAIN_CH_ERROR_LEGACY_PKT_DATA_SIZE
+    DAP_CHAIN_CH_ERROR_LEGACY_PKT_DATA_SIZE,
+    //
+    DAP_CHAIN_CH_ERROR_LAST
 } dap_chain_ch_error_type_t;
 
 int dap_chain_ch_init(void);
diff --git a/modules/chain/tests/dap_chain_ledger_tests.c b/modules/chain/tests/dap_chain_ledger_tests.c
index 2dd5bfa8320b2d4464b8b748d2efc2ec0901852c..d842d8ecf5faceefd37049dd87224231cc16ad09 100644
--- a/modules/chain/tests/dap_chain_ledger_tests.c
+++ b/modules/chain/tests/dap_chain_ledger_tests.c
@@ -351,7 +351,7 @@ int dap_ledger_test_create_reward_decree(dap_chain_t *a_chain, dap_chain_net_id_
     dap_hash_fast_t l_decree_hash = {};
     dap_hash_fast(l_decree, l_decree_size, &l_decree_hash);
     // a_chain->callback_atom_add();
-    dap_assert_PIF(dap_chain_net_decree_apply(&l_decree_hash, l_decree, a_chain)==0, "Decree applying:");
+    dap_assert_PIF(dap_chain_net_decree_apply(&l_decree_hash, l_decree, a_chain, false)==0, "Decree applying:");
     return 0;
 }
 
@@ -491,7 +491,7 @@ int dap_ledger_test_add_new_datum (uint16_t a_datum_type, void* a_datum, size_t
 {
     dap_chain_datum_t* l_new_datum = dap_chain_datum_create(a_datum_type, a_datum, a_datum_size);
     size_t l_new_datum_size = a_datum_size + sizeof(l_new_datum->header);
-    int status = dap_chain_datum_add(a_chain, l_new_datum, l_new_datum_size, a_datum_hash);
+    int status = dap_chain_datum_add(a_chain, l_new_datum, l_new_datum_size, a_datum_hash, NULL);
     dap_assert(status == 0, "Test of transaction adding to ledger:");
     return status;
 }
@@ -531,7 +531,7 @@ void dap_ledger_test_datums_removing(dap_ledger_t *a_ledger, dap_hash_fast_t *a_
     dap_assert(l_second_tx, "Test of creating second tx:");  
     dap_chain_hash_fast_t l_second_tx_hash = {0};
     dap_hash_fast(l_second_tx, dap_chain_datum_tx_get_size(l_second_tx), &l_second_tx_hash);
-    dap_assert(!dap_ledger_tx_add(a_ledger, l_second_tx, &l_second_tx_hash, false), "Test of second transaction adding to ledger:");
+    dap_assert(!dap_ledger_tx_add(a_ledger, l_second_tx, &l_second_tx_hash, false, NULL), "Test of second transaction adding to ledger:");
     dap_ledger_test_print_balance(a_ledger, &l_addr);
 
     // try to remove spent tx
@@ -548,7 +548,7 @@ void dap_ledger_test_datums_removing(dap_ledger_t *a_ledger, dap_hash_fast_t *a_
     dap_assert_PIF(l_cond_tx, "Test of creating conditional transaction:");  
     dap_chain_hash_fast_t l_cond_tx_hash = {0};
     dap_hash_fast(l_cond_tx, dap_chain_datum_tx_get_size(l_first_tx), &l_cond_tx_hash);
-    dap_assert(!dap_ledger_tx_add(a_ledger, l_cond_tx, &l_cond_tx_hash, false), "Test of conditional transaction adding to ledger:");
+    dap_assert(!dap_ledger_tx_add(a_ledger, l_cond_tx, &l_cond_tx_hash, false, NULL), "Test of conditional transaction adding to ledger:");
     dap_ledger_test_print_balance(a_ledger, &l_addr);
     dap_assert(!dap_ledger_tx_remove(a_ledger, l_cond_tx, &l_cond_tx_hash), "Test of conditional transaction removing from ledger:");
     l_balance_after = dap_ledger_test_print_balance(a_ledger, &l_addr);
@@ -561,7 +561,7 @@ void dap_ledger_test_datums_removing(dap_ledger_t *a_ledger, dap_hash_fast_t *a_
     dap_assert_PIF(l_cond_tx, "Test of creating conditional transaction:"); 
     dap_hash_fast_t l_cond_tx_hash = {};
     dap_hash_fast(l_cond_tx, dap_chain_datum_tx_get_size(l_cond_tx), &l_cond_tx_hash);
-    dap_assert(!dap_ledger_tx_add(a_ledger, l_cond_tx, &l_cond_tx_hash, false), "Test of conditional transaction adding to ledger:");
+    dap_assert(!dap_ledger_tx_add(a_ledger, l_cond_tx, &l_cond_tx_hash, false, NULL), "Test of conditional transaction adding to ledger:");
     dap_ledger_test_print_balance(a_ledger, &l_addr);
 
     dap_cert_t *l_cond_spender_cert = dap_cert_generate_mem_with_seed("newCert", DAP_ENC_KEY_TYPE_SIG_PICNIC, "FMknbirh8*^#$RYU*q", 18);
@@ -571,7 +571,7 @@ void dap_ledger_test_datums_removing(dap_ledger_t *a_ledger, dap_hash_fast_t *a_
     dap_chain_datum_tx_t *l_cond_spendind_tx = dap_ledger_test_create_spend_tx_cond(a_from_key, &l_cond_tx_hash, l_cond_spender_cert->enc_key, dap_chain_uint256_from(1U),a_ledger);
     dap_chain_hash_fast_t l_spend_cond_tx_hash = {0};
     dap_hash_fast(l_cond_spendind_tx, dap_chain_datum_tx_get_size(l_cond_spendind_tx), &l_spend_cond_tx_hash);
-    dap_assert(!dap_ledger_tx_add(a_ledger, l_cond_spendind_tx, &l_spend_cond_tx_hash, false), "Test adding of transaction spending to a conditional transaction  to ledger:");
+    dap_assert(!dap_ledger_tx_add(a_ledger, l_cond_spendind_tx, &l_spend_cond_tx_hash, false, NULL), "Test adding of transaction spending to a conditional transaction  to ledger:");
     uint256_t l_cond_spending_balance_after = dap_ledger_test_print_balance(a_ledger, &l_cond_spender_addr);
     dap_assert(!compare256(l_cond_spending_balance_after, dap_chain_uint256_from(1U)), "Check balance after spending:");
     dap_ledger_test_print_balance(a_ledger, &l_cond_spender_addr);
@@ -588,7 +588,7 @@ void dap_ledger_test_datums_removing(dap_ledger_t *a_ledger, dap_hash_fast_t *a_
     dap_chain_datum_tx_t *l_cond_tx = dap_ledger_test_create_tx_cond(a_from_key, a_prev_hash, &l_addr_first, dap_chain_uint256_from(2U),a_ledger);
     dap_hash_fast_t l_cond_tx_hash = {};
     dap_hash_fast(l_cond_tx, dap_chain_datum_tx_get_size(l_cond_tx), &l_cond_tx_hash);
-    dap_assert(!dap_ledger_tx_add(a_ledger, l_cond_tx, &l_cond_tx_hash, false), "Adding of cond transaction to ledger is");
+    dap_assert(!dap_ledger_tx_add(a_ledger, l_cond_tx, &l_cond_tx_hash, false, NULL), "Adding of cond transaction to ledger is");
 
     dap_cert_t *l_cond_spending_cert = dap_cert_generate_mem_with_seed("newCert", DAP_ENC_KEY_TYPE_SIG_PICNIC, "FMknbirh8*^#$RYU*q", 18);
     dap_chain_addr_t l_cond_spending_addr = {0};
@@ -597,7 +597,7 @@ void dap_ledger_test_datums_removing(dap_ledger_t *a_ledger, dap_hash_fast_t *a_
     dap_chain_datum_tx_t *l_cond_returning_tx = dap_ledger_test_create_return_from_tx_cond(&l_cond_tx_hash, a_from_key ,a_ledger);
     dap_chain_hash_fast_t l_cond_returning_tx_hash = {0};
     dap_hash_fast(l_cond_returning_tx, dap_chain_datum_tx_get_size(l_cond_returning_tx), &l_cond_returning_tx_hash);
-    int err_code = dap_ledger_tx_add(a_ledger, l_cond_returning_tx, &l_cond_returning_tx_hash, false);
+    int err_code = dap_ledger_tx_add(a_ledger, l_cond_returning_tx, &l_cond_returning_tx_hash, false, NULL);
     printf("err_code = %s\n", dap_ledger_check_error_str(err_code));
     dap_assert(!err_code, "Returning of funds from cond transaction is");
     uint256_t l_cond_spending_balance_after = dap_ledger_test_print_balance(a_ledger, &l_cond_spending_addr);
@@ -617,7 +617,7 @@ void dap_ledger_test_datums_removing(dap_ledger_t *a_ledger, dap_hash_fast_t *a_
     dap_chain_datum_tx_t *l_cond_tx = dap_ledger_test_create_stake_tx_cond(a_from_key, a_prev_hash, dap_chain_uint256_from(20U), a_ledger);
     dap_hash_fast_t l_cond_tx_hash = {};
     dap_hash_fast(l_cond_tx, dap_chain_datum_tx_get_size(l_cond_tx), &l_cond_tx_hash);
-    int err_code = dap_ledger_tx_add(a_ledger, l_cond_tx, &l_cond_tx_hash, false);
+    int err_code = dap_ledger_tx_add(a_ledger, l_cond_tx, &l_cond_tx_hash, false, NULL);
     printf("err_code = %s\n", dap_ledger_check_error_str(err_code));
     dap_assert(!err_code, "Adding of stake cond transaction to ledger is");
 
@@ -632,7 +632,7 @@ void dap_ledger_test_datums_removing(dap_ledger_t *a_ledger, dap_hash_fast_t *a_
     dap_chain_datum_tx_t *l_stake_cond_tx = dap_ledger_test_create_stake_tx_cond(a_from_key, a_prev_hash, dap_chain_uint256_from(20U), a_ledger);
     dap_hash_fast_t l_stake_cond_tx_hash = {};
     dap_hash_fast(l_stake_cond_tx, dap_chain_datum_tx_get_size(l_stake_cond_tx), &l_stake_cond_tx_hash);
-    int err_code = dap_ledger_tx_add(a_ledger, l_stake_cond_tx, &l_stake_cond_tx_hash, false);
+    int err_code = dap_ledger_tx_add(a_ledger, l_stake_cond_tx, &l_stake_cond_tx_hash, false, NULL);
     printf("err_code = %s\n", dap_ledger_check_error_str(err_code));
     dap_assert(!err_code, "Adding of stake cond transaction to ledger is");
     sleep(3);
@@ -644,7 +644,7 @@ void dap_ledger_test_datums_removing(dap_ledger_t *a_ledger, dap_hash_fast_t *a_
     dap_chain_datum_tx_t *l_unstake_cond_tx = dap_ledger_test_create_unstake_tx_cond(a_from_key, &l_stake_cond_tx_hash, dap_chain_uint256_from(20U), a_ledger);
     dap_hash_fast_t l_unstake_cond_tx_hash = {};
     dap_hash_fast(l_unstake_cond_tx, dap_chain_datum_tx_get_size(l_unstake_cond_tx), &l_unstake_cond_tx_hash);
-    err_code = dap_ledger_tx_add(a_ledger, l_unstake_cond_tx, &l_unstake_cond_tx_hash, false);
+    err_code = dap_ledger_tx_add(a_ledger, l_unstake_cond_tx, &l_unstake_cond_tx_hash, false, NULL);
     printf("err_code = %s\n", dap_ledger_check_error_str(err_code));
     dap_assert(!err_code, "Adding of unstake cond transaction to ledger is");
     uint256_t l_balance_delegated_after_unstaking = dap_ledger_test_print_delegate_balance(a_ledger, &l_addr);
@@ -694,14 +694,14 @@ dap_hash_fast_t dap_ledger_test_double_spending(
     dap_assert_PIF(l_first_tx, "Can't creating base transaction.");
     dap_chain_hash_fast_t l_first_tx_hash = {0};
     dap_hash_fast(l_first_tx, dap_chain_datum_tx_get_size(l_first_tx), &l_first_tx_hash);
-    dap_assert_PIF(!dap_ledger_tx_add(a_ledger, l_first_tx, &l_first_tx_hash, false), "Can't add first transaction on ledger");
+    dap_assert_PIF(!dap_ledger_tx_add(a_ledger, l_first_tx, &l_first_tx_hash, false, NULL), "Can't add first transaction on ledger");
     //uint256_t l_balance = dap_ledger_calc_balance(a_ledger, &l_addr_first, s_token_ticker);
     // Second tx
     dap_chain_datum_tx_t *l_second_tx = dap_ledger_test_create_tx(a_from_key, a_prev_hash,
                                                                        &a_addr_to, dap_chain_uint256_from(s_standard_value_tx - s_fee));
     dap_chain_hash_fast_t l_second_tx_hash = {0};
     dap_hash_fast(l_second_tx, dap_chain_datum_tx_get_size(l_second_tx), &l_second_tx_hash);
-    dap_assert_PIF(dap_ledger_tx_add(a_ledger, l_second_tx, &l_second_tx_hash, false), "Added second transaction on ledger");
+    dap_assert_PIF(dap_ledger_tx_add(a_ledger, l_second_tx, &l_second_tx_hash, false, NULL), "Added second transaction on ledger");
     dap_pass_msg("The verification test is not able to make two normal transactions per one basic transaction.");
     return l_first_tx_hash; 
 }
@@ -831,7 +831,7 @@ void dap_ledger_test_write_back_list(dap_ledger_t *a_ledger, dap_cert_t *a_cert,
                                                                                       *l_addr_1->addr, a_cert);
         dap_hash_fast_t l_btx_addr1_hash = {0};
         dap_hash_fast(l_btx_addr1, dap_chain_datum_tx_get_size(l_btx_addr1), &l_btx_addr1_hash);
-        int l_ledger_add_code = dap_ledger_tx_add(a_ledger, l_btx_addr1, &l_btx_addr1_hash, false);
+        int l_ledger_add_code = dap_ledger_tx_add(a_ledger, l_btx_addr1, &l_btx_addr1_hash, false, NULL);
         char *l_ledger_tx_add_str = dap_strdup_printf("Can't add base tx in white address. Code: %d", l_ledger_add_code);
         dap_assert_PIF(!l_ledger_add_code, l_ledger_tx_add_str);
         DAP_DELETE(l_ledger_tx_add_str);
@@ -839,13 +839,13 @@ void dap_ledger_test_write_back_list(dap_ledger_t *a_ledger, dap_cert_t *a_cert,
         dap_chain_datum_tx_t *l_tx_to_addr4 = dap_ledger_test_create_tx(l_addr_1->enc_key, &l_btx_addr1_hash,
                                                                               l_addr_4->addr, dap_chain_uint256_from(s_total_supply-s_fee));
         dap_hash_fast(l_tx_to_addr4, dap_chain_datum_tx_get_size(l_tx_to_addr4), &l_tx_addr4_hash);
-        dap_assert_PIF(!dap_ledger_tx_add(a_ledger, l_tx_to_addr4, &l_tx_addr4_hash, false),
+        dap_assert_PIF(!dap_ledger_tx_add(a_ledger, l_tx_to_addr4, &l_tx_addr4_hash, false, NULL),
                        "Can't add transaction to address from white list in ledger");
         dap_chain_datum_tx_t *l_tx_to_addr3 = dap_ledger_test_create_tx(l_addr_4->enc_key, &l_tx_addr4_hash,
                                                                               l_addr_3->addr, dap_chain_uint256_from(s_total_supply-s_fee));
         dap_hash_fast_t l_tx_addr3_hash = {0};
         dap_hash_fast(l_tx_to_addr3, dap_chain_datum_tx_get_size(l_tx_to_addr3), &l_tx_addr3_hash);
-        int res_add_tx = dap_ledger_tx_add(a_ledger, l_tx_to_addr3, &l_tx_addr3_hash, false);
+        int res_add_tx = dap_ledger_tx_add(a_ledger, l_tx_to_addr3, &l_tx_addr3_hash, false, NULL);
         if (!res_add_tx) {
             dap_fail("It was possible to carry out a transaction to a forbidden address");
         } else {
@@ -945,20 +945,20 @@ void dap_ledger_test_write_back_list(dap_ledger_t *a_ledger, dap_cert_t *a_cert,
                                                                                        *l_addr_2->addr, a_cert);
         dap_hash_fast_t l_btx_addr2_hash = {0};
         dap_hash_fast(l_btx_addr2, dap_chain_datum_tx_get_size(l_btx_addr2), &l_btx_addr2_hash);
-        dap_assert_PIF(!dap_ledger_tx_add(a_ledger, l_btx_addr2, &l_btx_addr2_hash, false),
+        dap_assert_PIF(!dap_ledger_tx_add(a_ledger, l_btx_addr2, &l_btx_addr2_hash, false, NULL),
                        "Can't add base tx in white address");
         //Check tx in addr from block list
         dap_chain_datum_tx_t *l_tx_to_addr1 = dap_ledger_test_create_tx(l_addr_4->enc_key, &l_btx_addr2_hash,
                                                                               l_addr_1->addr, dap_chain_uint256_from(s_total_supply));
         dap_hash_fast_t l_tx_addr1_hash = {0};
         dap_hash_fast(l_tx_to_addr1, dap_chain_datum_tx_get_size(l_tx_to_addr1), &l_tx_addr1_hash);
-        dap_assert(dap_ledger_tx_add(a_ledger, l_tx_to_addr1, &l_tx_addr1_hash, false), "Transfer test to a forbidden address.");
+        dap_assert(dap_ledger_tx_add(a_ledger, l_tx_to_addr1, &l_tx_addr1_hash, false, NULL), "Transfer test to a forbidden address.");
         //Check tx in addr from list
         dap_chain_datum_tx_t *l_tx_to_addr3 = dap_ledger_test_create_tx(l_addr_4->enc_key, &l_tx_addr1_hash,
                                                                               l_addr_3->addr, dap_chain_uint256_from(s_total_supply));
         dap_hash_fast_t l_tx_addr3_hash = {0};
         dap_hash_fast(l_tx_to_addr3, dap_chain_datum_tx_get_size(l_tx_to_addr3), &l_tx_addr3_hash);
-        dap_assert(dap_ledger_tx_add(a_ledger, l_tx_to_addr3, &l_tx_addr3_hash, false), "Transfer test to a not forbidden address.");
+        dap_assert(dap_ledger_tx_add(a_ledger, l_tx_to_addr3, &l_tx_addr3_hash, false, NULL), "Transfer test to a not forbidden address.");
     }
 }
 
@@ -1041,7 +1041,7 @@ void dap_ledger_test_run(void){
     dap_hash_fast_t l_hash_btx = {0};
     dap_hash_fast(l_base_tx, l_base_tx_size, &l_hash_btx);
     dap_assert_PIF(!dap_ledger_tx_add_check(l_ledger, l_base_tx, l_base_tx_size, &l_hash_btx), "Check can added base tx in ledger");
-    dap_assert_PIF(!dap_ledger_tx_add(l_ledger, l_base_tx, &l_hash_btx, false), "Added base tx in ledger.");
+    dap_assert_PIF(!dap_ledger_tx_add(l_ledger, l_base_tx, &l_hash_btx, false, NULL), "Added base tx in ledger.");
     uint256_t l_balance_example = dap_chain_uint256_from(s_standard_value_tx);
     uint256_t l_balance = dap_ledger_calc_balance(l_ledger, &l_addr, s_token_ticker);
 	uint256_t l_fee = dap_chain_uint256_from(s_fee);
@@ -1057,7 +1057,7 @@ void dap_ledger_test_run(void){
     if (dap_ledger_tx_add_check(l_ledger, l_base_tx_second, l_base_tx_size2, &l_hash_btx_second)) {
         dap_pass_msg("Checking can added second base tx in ledger");
     }
-    if (dap_ledger_tx_add(l_ledger, l_base_tx_second, &l_hash_btx_second, false)){
+    if (dap_ledger_tx_add(l_ledger, l_base_tx_second, &l_hash_btx_second, false, NULL)){
         dap_pass_msg("Checking for a failure to add a second base transaction for the same issue to the ledger.");
     } else {
         dap_fail("Checking for a failure to add a second base transaction for the same issue to the ledger.");
diff --git a/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.c b/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.c
index 5dcf39ce43476b5d7cfbb044f9d09d58f87b382d..66822232bd32e9e6f040a1d66de7d7b5900d516b 100644
--- a/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.c
+++ b/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.c
@@ -1124,7 +1124,6 @@ static bool s_grace_period_finish(dap_chain_net_srv_grace_usage_t *a_grace_item)
         }
 
         // make receipt or tx
-        char *l_receipt_hash_str;
         dap_chain_datum_tx_receipt_t *l_receipt = NULL;
         if (l_grace->usage->receipt_next){
             l_receipt = l_grace->usage->receipt_next;
@@ -1158,8 +1157,7 @@ static bool s_grace_period_finish(dap_chain_net_srv_grace_usage_t *a_grace_item)
             log_it(L_WARNING, "Tx already in chain, but receipt is not signed by client. Finish grace and wait receipt sign responce.");
             RET_WITH_DEL_A_GRACE(DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_RECEIPT_NO_SIGN);
         }
-        dap_get_data_hash_str_static(l_receipt, l_receipt_size, l_receipt_hash_str);
-        dap_global_db_set(SRV_RECEIPTS_GDB_GROUP, l_receipt_hash_str, l_receipt, l_receipt_size, false, NULL, NULL);
+        dap_global_db_set(SRV_RECEIPTS_GDB_GROUP, dap_get_data_hash_str(l_receipt, l_receipt_size).s, l_receipt, l_receipt_size, false, NULL, NULL);
             // Form input transaction
         char *l_hash_str = dap_hash_fast_to_str_new(&l_grace->usage->tx_cond_hash);
         log_it(L_NOTICE, "Trying create input tx cond from tx %s with active receipt", l_hash_str);
@@ -1447,9 +1445,7 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t *a_ch, void *a_arg)
         }
 
         // Store receipt if any problems with transactions
-        char *l_receipt_hash_str;
-        dap_get_data_hash_str_static(l_receipt, l_receipt_size, l_receipt_hash_str);
-        dap_global_db_set(SRV_RECEIPTS_GDB_GROUP, l_receipt_hash_str, l_receipt, l_receipt_size, false, NULL, NULL);
+        dap_global_db_set(SRV_RECEIPTS_GDB_GROUP, dap_get_data_hash_str(l_receipt, l_receipt_size).s, l_receipt, l_receipt_size, false, NULL, NULL);
         size_t l_success_size;
         if (!l_usage->is_grace) {
             // Form input transaction
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 fe4c18c8626843aee823fb25758b151e16a0159a..ec9fffdf12fe254efea6d432fde89a440ddf0020 100644
--- a/modules/channel/chain-net/dap_stream_ch_chain_net.c
+++ b/modules/channel/chain-net/dap_stream_ch_chain_net.c
@@ -113,17 +113,12 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t *a_ch, void* a_arg)
     dap_stream_ch_chain_net_t * l_ch_chain_net = DAP_STREAM_CH_CHAIN_NET(a_ch);
     if(l_ch_chain_net) {
         dap_stream_ch_pkt_t *l_ch_pkt = (dap_stream_ch_pkt_t *)a_arg;
-        if (l_ch_pkt->hdr.type == DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_TEST) {
-            char *l_data_hash_str;
-            dap_get_data_hash_str_static(l_ch_pkt->data, l_ch_pkt->hdr.data_size, l_data_hash_str);
-            log_it(L_ATT, "Receive test data packet with hash %s", l_data_hash_str);
-            return false;
-        }
-        if (l_ch_pkt->hdr.data_size < sizeof(dap_stream_ch_chain_net_pkt_t)) {
-            log_it(L_WARNING, "Too small stream channel N packet size %u (header size %zu)",
-                                    l_ch_pkt->hdr.data_size, sizeof(dap_stream_ch_chain_net_pkt_t));
-            return false;
-        }
+        if (l_ch_pkt->hdr.type == DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_TEST)
+            return log_it(L_ATT, "Receive test data packet with hash %s", 
+                                 dap_get_data_hash_str(l_ch_pkt->data, l_ch_pkt->hdr.data_size).s), false;
+        if (l_ch_pkt->hdr.data_size < sizeof(dap_stream_ch_chain_net_pkt_t))
+            return log_it(L_WARNING, "Too small stream channel N packet size %u (header size %zu)",
+                                    l_ch_pkt->hdr.data_size, sizeof(dap_stream_ch_chain_net_pkt_t)), false;
         dap_stream_ch_chain_net_pkt_t *l_ch_chain_net_pkt = (dap_stream_ch_chain_net_pkt_t *)l_ch_pkt->data;
         if ((uint32_t)l_ch_chain_net_pkt->hdr.data_size + sizeof(dap_stream_ch_chain_net_pkt_t) > l_ch_pkt->hdr.data_size) {
             log_it(L_WARNING, "Too small stream channel N packet size %u (expected at least %zu)",
diff --git a/modules/common/dap_chain_datum.c b/modules/common/dap_chain_datum.c
index 6cef09e63068eeb76f2bb826c7d6f9995ebd8f0d..013cf17523ba86d30df0ee3e5b1a5281208ee210 100644
--- a/modules/common/dap_chain_datum.c
+++ b/modules/common/dap_chain_datum.c
@@ -150,7 +150,7 @@ void dap_datum_token_dump_tsd_to_json(json_object * json_obj_out, dap_chain_datu
             DAP_DEL_Z(balance);
         }continue;
         case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_ALLOWED_ADD  :
-            json_object_object_add(json_obj_out, "datum_type_allowed_add", json_object_new_string(dap_tsd_get_string_const(l_tsd)));
+                json_object_object_add(json_obj_out, "datum_type_allowed_add", json_object_new_string(dap_tsd_get_string_const(l_tsd)));
             continue;
         case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_ALLOWED_REMOVE  :
             json_object_object_add(json_obj_out, "datum_type_allowed_remove", json_object_new_string(dap_tsd_get_string_const(l_tsd)));
@@ -161,30 +161,38 @@ void dap_datum_token_dump_tsd_to_json(json_object * json_obj_out, dap_chain_datu
         case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_BLOCKED_REMOVE:
             json_object_object_add(json_obj_out, "datum_type_blocked_remove", json_object_new_string(dap_tsd_get_string_const(l_tsd)));
             continue;
-        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_ADD:
-            json_object_object_add(json_obj_out, "tx_sender_allowed_add", json_object_new_string(dap_tsd_get_string_const(l_tsd)));
-            continue;
-        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_REMOVE:
-            json_object_object_add(json_obj_out, "tx_sender_allowed_remove", json_object_new_string(dap_tsd_get_string_const(l_tsd)));
-            continue;
-        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_ADD:
-            json_object_object_add(json_obj_out, "tx_sender_blocked_add", json_object_new_string(dap_tsd_get_string_const(l_tsd)));
-            continue;
-        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_REMOVE:
-            json_object_object_add(json_obj_out, "tx_sender_blocked_remove", json_object_new_string(dap_tsd_get_string_const(l_tsd)));
-            continue;
-        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_ADD:
-            json_object_object_add(json_obj_out, "tx_receiver_allowed_add", json_object_new_string(dap_tsd_get_string_const(l_tsd)));
-            continue;
-        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_REMOVE:
-            json_object_object_add(json_obj_out, "tx_receiver_allowed", json_object_new_string(dap_tsd_get_string_const(l_tsd)));
-            continue;
-        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_ADD:
-            json_object_object_add(json_obj_out, "tx_receiver_blocked_add", json_object_new_string(dap_tsd_get_string_const(l_tsd)));
-            continue;
-        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_REMOVE:
-            json_object_object_add(json_obj_out, "tx_receiver_blocked_remove", json_object_new_string(dap_tsd_get_string_const(l_tsd)));
-            continue;
+        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_ADD: {
+                dap_chain_addr_t *l_addr = dap_tsd_get_object(l_tsd, dap_chain_addr_t);
+                json_object_object_add(json_obj_out, "tx_sender_allowed_add", json_object_new_string(dap_chain_addr_to_str_static(l_addr)));
+            } continue;
+        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_REMOVE:{
+                dap_chain_addr_t *l_addr = dap_tsd_get_object(l_tsd, dap_chain_addr_t);
+                json_object_object_add(json_obj_out, "tx_sender_allowed_remove", json_object_new_string(dap_chain_addr_to_str_static(l_addr)));
+            } continue;
+        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_ADD: {
+                dap_chain_addr_t *l_addr = dap_tsd_get_object(l_tsd, dap_chain_addr_t);
+                json_object_object_add(json_obj_out, "tx_sender_blocked_add", json_object_new_string(dap_chain_addr_to_str_static(l_addr)));
+            } continue;
+        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_REMOVE: {
+                dap_chain_addr_t *l_addr = dap_tsd_get_object(l_tsd, dap_chain_addr_t);
+                json_object_object_add(json_obj_out, "tx_sender_blocked_remove", json_object_new_string(dap_chain_addr_to_str_static(l_addr)));
+            } continue;
+        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_ADD: {
+                dap_chain_addr_t *l_addr = dap_tsd_get_object(l_tsd, dap_chain_addr_t);
+                json_object_object_add(json_obj_out, "tx_receiver_allowed_add", json_object_new_string(dap_chain_addr_to_str_static(l_addr)));
+            } continue;
+        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_REMOVE: {
+                dap_chain_addr_t *l_addr = dap_tsd_get_object(l_tsd, dap_chain_addr_t);
+                json_object_object_add(json_obj_out, "tx_receiver_allowed", json_object_new_string(dap_chain_addr_to_str_static(l_addr)));
+            } continue;
+        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_ADD: {
+                dap_chain_addr_t *l_addr = dap_tsd_get_object(l_tsd, dap_chain_addr_t);
+                json_object_object_add(json_obj_out, "tx_receiver_blocked_add", json_object_new_string(dap_chain_addr_to_str_static(l_addr)));
+            } continue;
+        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_REMOVE: {
+                dap_chain_addr_t *l_addr = dap_tsd_get_object(l_tsd, dap_chain_addr_t);
+                json_object_object_add(json_obj_out, "tx_receiver_blocked_remove", json_object_new_string(dap_chain_addr_to_str_static(l_addr)));
+            } continue;
         case DAP_CHAIN_DATUM_TOKEN_TSD_TOKEN_DESCRIPTION:
             json_object_object_add(json_obj_out, "description", json_object_new_string(dap_tsd_get_string_const(l_tsd)));
             continue;
@@ -198,313 +206,6 @@ void dap_datum_token_dump_tsd_to_json(json_object * json_obj_out, dap_chain_datu
     }
 }
 
-/**
- * @brief _dap_chain_datum_tx_out_data
- *
- * @param a_datum
- * @param a_ledger
- * @param a_str_out
- * @param a_hash_out_type
- * @param save_processed_tx
- * @param a_tx_hash_processed
- * @param l_tx_num
- */
-bool dap_chain_datum_dump_tx(dap_chain_datum_tx_t *a_datum,
-                             const char *a_ticker,
-                             dap_string_t *a_str_out,
-                             const char *a_hash_out_type,
-                             dap_hash_fast_t *a_tx_hash,
-                             dap_chain_net_id_t a_net_id)
-{
-    bool l_is_first = false;
-    dap_chain_tx_in_t *l_in_item = (dap_chain_tx_in_t *)dap_chain_datum_tx_item_get(a_datum, NULL, NULL, TX_ITEM_TYPE_IN, NULL);
-    if (l_in_item && dap_hash_fast_is_blank(&l_in_item->header.tx_prev_hash))
-        l_is_first = true;
-    char l_tmp_buf[DAP_TIME_STR_SIZE];
-    const char *l_hash_str = dap_strcmp(a_hash_out_type, "hex")
-            ? dap_enc_base58_encode_hash_to_str_static(a_tx_hash)
-            : dap_chain_hash_fast_to_str_static(a_tx_hash);
-    dap_time_to_str_rfc822(l_tmp_buf, DAP_TIME_STR_SIZE, a_datum->header.ts_created);
-    dap_string_append_printf(a_str_out, "transaction:%s hash %s\n TS Created: %s%s%s\n Items:\n",
-                             l_is_first ? " (emit)" : "", l_hash_str, l_tmp_buf,
-                             a_ticker ? " Token ticker: " : "", a_ticker ? a_ticker : "");
-    dap_hash_fast_t l_hash_tmp = { };
-    byte_t *item; size_t l_size;
-    TX_ITEM_ITER_TX(item, l_size, a_datum) {
-        switch (*item) {
-        case TX_ITEM_TYPE_IN:
-            l_hash_tmp = ((dap_chain_tx_in_t*)item)->header.tx_prev_hash;
-            l_hash_str = !dap_hash_fast_is_blank(&l_hash_tmp) 
-                ? dap_strcmp(a_hash_out_type, "hex") ? dap_enc_base58_encode_hash_to_str_static(&l_hash_tmp) : dap_chain_hash_fast_to_str_static(&l_hash_tmp)
-                : "BLANK";
-            dap_string_append_printf(a_str_out, "\t IN:\nTx_prev_hash: %s\n"
-                                                "\t\t Tx_out_prev_idx: %u\n",
-                                        l_hash_str,
-                                        ((dap_chain_tx_in_t*)item)->header.tx_out_prev_idx);
-            break;
-        case TX_ITEM_TYPE_OUT_OLD: {
-            const char *l_value_str = dap_uint256_to_char(
-                dap_chain_uint256_from(((dap_chain_tx_out_old_t*)item)->header.value), NULL );
-            dap_string_append_printf(a_str_out, "\t OUT OLD (64):\n"
-                                                "\t\t Value: %s (%"DAP_UINT64_FORMAT_U")\n"
-                                                "\t\t Address: %s\n",
-                                        l_value_str,
-                                        ((dap_chain_tx_out_old_t*)item)->header.value,
-                                        dap_chain_addr_to_str_static(&((dap_chain_tx_out_old_t*)item)->addr));
-        } break;
-        case TX_ITEM_TYPE_OUT: { // 256
-            const char *l_coins_str,
-                    *l_value_str = dap_uint256_to_char(((dap_chain_tx_out_t*)item)->header.value, &l_coins_str),
-                    *l_addr_str = dap_chain_addr_to_str_static(&((dap_chain_tx_out_t*)item)->addr);
-            dap_string_append_printf(a_str_out, "\t OUT:\n"
-                                                "\t\t Value: %s (%s)\n"
-                                                "\t\t Address: %s\n",
-                                        l_coins_str,
-                                        l_value_str,
-                                        l_addr_str);
-        } break;
-        case TX_ITEM_TYPE_IN_EMS: {
-            l_hash_tmp = ((dap_chain_tx_in_ems_t*)item)->header.token_emission_hash;
-            l_hash_str = dap_strcmp(a_hash_out_type, "hex")
-                    ? dap_enc_base58_encode_hash_to_str_static(&l_hash_tmp)
-                    : dap_chain_hash_fast_to_str_static(&l_hash_tmp);
-            dap_string_append_printf(a_str_out, "\t IN_EMS:\n"
-                                                "\t\t ticker: %s \n"
-                                                "\t\t token_emission_hash: %s\n"
-                                                "\t\t token_emission_chain_id: 0x%016"DAP_UINT64_FORMAT_x"\n",
-                                                ((dap_chain_tx_in_ems_t*)item)->header.ticker,
-                                                l_hash_str,
-                                                ((dap_chain_tx_in_ems_t*)item)->header.token_emission_chain_id.uint64);
-        } break;
-            /*
-        case TX_ITEM_TYPE_IN_EMS_EXT: {
-            l_hash_tmp = &((dap_chain_tx_in_ems_ext_t*)item)->header.ext_tx_hash;
-            l_hash_str = dap_strcmp(a_hash_out_type, "hex")
-                    ? dap_enc_base58_encode_hash_to_str(l_hash_tmp)
-                    : dap_chain_hash_fast_to_str_new(l_hash_tmp);
-            dap_string_append_printf(a_str_out, "\t IN_EMS EXT:\n"
-                                         "\t\t Version: %u\n"
-                                         "\t\t Ticker: %s\n"
-                                         "\t\t Ext chain id: 0x%016"DAP_UINT64_FORMAT_x"\n"
-                                         "\t\t Ext net id: 0x%016"DAP_UINT64_FORMAT_x"\n"
-                                         "\t\t Ext tx hash: %s\n"
-                                         "\t\t Ext tx out idx: %u\n",
-                                     ((dap_chain_tx_in_ems_ext_t*)item)->header.version,
-                                     ((dap_chain_tx_in_ems_ext_t*)item)->header.ticker,
-                                     ((dap_chain_tx_in_ems_ext_t*)item)->header.ext_chain_id.uint64,
-                                     ((dap_chain_tx_in_ems_ext_t*)item)->header.ext_net_id.uint64,
-                                     l_hash_str,
-                                     ((dap_chain_tx_in_ems_ext_t*)item)->header.ext_tx_out_idx);
-            DAP_DELETE(l_hash_str);
-        } break; */
-
-        case TX_ITEM_TYPE_IN_REWARD: {
-            l_hash_tmp = ((dap_chain_tx_in_reward_t *)item)->block_hash;
-            l_hash_str = dap_strcmp(a_hash_out_type, "hex")
-                    ? dap_enc_base58_encode_hash_to_str_static(&l_hash_tmp)
-                    : dap_chain_hash_fast_to_str_static(&l_hash_tmp);
-            dap_string_append_printf(a_str_out, "\t IN_REWARD:\n"
-                                                "\t\t block_hash: %s\n",
-                                                l_hash_str);
-        } break;
-
-        case TX_ITEM_TYPE_SIG: {
-            dap_sign_t *l_sign = dap_chain_datum_tx_item_sign_get_sig((dap_chain_tx_sig_t*)item);
-            dap_sign_get_information(l_sign, a_str_out, a_hash_out_type);
-            dap_chain_addr_t l_sender_addr;
-            dap_chain_addr_fill_from_sign(&l_sender_addr, l_sign, a_net_id);
-            dap_string_append_printf(a_str_out, "\tSender addr: %s\n", dap_chain_addr_to_str_static(&l_sender_addr));
-        } break;
-        case TX_ITEM_TYPE_RECEIPT: {
-            const char *l_coins_str, *l_value_str = dap_uint256_to_char(((dap_chain_datum_tx_receipt_t*)item)->receipt_info.value_datoshi, &l_coins_str);
-            dap_string_append_printf(a_str_out, "\t Receipt:\n"
-                                                "\t\t size: %"DAP_UINT64_FORMAT_U"\n"
-                                                "\t\t ext size: %"DAP_UINT64_FORMAT_U"\n"
-                                                "\t\t Info:"
-                                                "\t\t\t units: 0x%016"DAP_UINT64_FORMAT_x"\n"
-                                                "\t\t\t uid: 0x%016"DAP_UINT64_FORMAT_x"\n"
-                                                "\t\t\t units type: %s \n"
-                                                "\t\t\t value: %s (%s)\n",
-                                     ((dap_chain_datum_tx_receipt_t*)item)->size,
-                                     ((dap_chain_datum_tx_receipt_t*)item)->exts_size,
-                                     ((dap_chain_datum_tx_receipt_t*)item)->receipt_info.units,
-                                     ((dap_chain_datum_tx_receipt_t*)item)->receipt_info.srv_uid.uint64,
-                                     dap_chain_srv_unit_enum_to_str(((dap_chain_datum_tx_receipt_t*)item)->receipt_info.units_type.enm),
-                                     l_coins_str,
-                                     l_value_str);
-            dap_string_append_printf(a_str_out, "Exts:\n");                         
-            switch ( ((dap_chain_datum_tx_receipt_t*)item)->exts_size ) {
-            case (sizeof(dap_sign_t) * 2): {
-                dap_sign_t *l_client = DAP_CAST_PTR( dap_sign_t, ((dap_chain_datum_tx_receipt_t*)item)->exts_n_signs + sizeof(dap_sign_t) );
-                dap_string_append_printf(a_str_out, "   Client:\n");
-                dap_sign_get_information(l_client, a_str_out, a_hash_out_type);
-            }
-            case (sizeof(dap_sign_t)): {
-                dap_sign_t *l_provider = DAP_CAST_PTR( dap_sign_t, ((dap_chain_datum_tx_receipt_t*)item)->exts_n_signs );
-                dap_string_append_printf(a_str_out, "   Provider:\n");
-                dap_sign_get_information(l_provider, a_str_out, a_hash_out_type);
-                break;
-            }
-            }
-        } break;
-        case TX_ITEM_TYPE_PKEY: {
-            dap_pkey_t *l_pkey = (dap_pkey_t*)((dap_chain_tx_pkey_t*)item)->pkey;
-            dap_chain_hash_fast_t l_pkey_hash;
-            dap_hash_fast(l_pkey->pkey, l_pkey->header.size, &l_pkey_hash);
-            l_hash_str = dap_strcmp(a_hash_out_type, "hex")
-                    ? dap_enc_base58_encode_hash_to_str_static(&l_pkey_hash)
-                    : dap_chain_hash_fast_to_str_static(&l_pkey_hash);
-            dap_string_append_printf(a_str_out, "\t PKey: \n"
-                                                "\t\t SIG type: %s\n"
-                                                "\t\t SIG size: %u\n"
-                                                "\t\t Sequence number: %u \n"
-                                                "\t\t Key: \n"
-                                                "\t\t\t Type: %s\n"
-                                                "\t\t\t Size: %u\n"
-                                                "\t\t\t Hash: %s\n",
-                                     dap_sign_type_to_str(((dap_chain_tx_pkey_t*)item)->header.sig_type),
-                                     ((dap_chain_tx_pkey_t*)item)->header.sig_size,
-                                     ((dap_chain_tx_pkey_t*)item)->seq_no,
-                                     dap_pkey_type_to_str(l_pkey->header.type),
-                                     l_pkey->header.size,
-                                     l_hash_str);
-        } break;
-        case TX_ITEM_TYPE_TSD: {
-            dap_string_append_printf(a_str_out, "\t TSD data: \n"
-                                                "\t\t type: %d\n"
-                                                "\t\t size: %lu\n",
-                                     ((dap_chain_tx_tsd_t*)item)->header.type,
-                                     ((dap_chain_tx_tsd_t*)item)->header.size);
-        } break;
-        case TX_ITEM_TYPE_IN_COND:
-            l_hash_tmp = ((dap_chain_tx_in_cond_t*)item)->header.tx_prev_hash;
-            l_hash_str = dap_strcmp(a_hash_out_type, "hex")
-                    ? dap_enc_base58_encode_hash_to_str_static(&l_hash_tmp)
-                    : dap_chain_hash_fast_to_str_static(&l_hash_tmp);
-            dap_string_append_printf(a_str_out, "\t IN COND:\n\t\tReceipt_idx: %u\n"
-                                                "\t\t Tx_prev_hash: %s\n"
-                                                "\t\t Tx_out_prev_idx: %u\n",
-                                     ((dap_chain_tx_in_cond_t*)item)->header.receipt_idx,
-                                     l_hash_str,
-                                     ((dap_chain_tx_in_cond_t*)item)->header.tx_out_prev_idx);
-            break;
-        case TX_ITEM_TYPE_OUT_COND: {
-            const char *l_coins_str, *l_value_str = dap_uint256_to_char(((dap_chain_tx_out_cond_t*)item)->header.value, &l_coins_str);
-            dap_time_t l_ts_exp = ((dap_chain_tx_out_cond_t*)item)->header.ts_expires;
-            dap_time_to_str_rfc822(l_tmp_buf, DAP_TIME_STR_SIZE, l_ts_exp);
-            dap_string_append_printf(a_str_out, "\t OUT COND:\n"
-                                                "\t Header:\n"
-                                                "\t\t ts_expires: %s"
-                                                "\t\t value: %s (%s)\n"
-                                                "\t\t subtype: %s\n"
-                                                "\t\t uid: 0x%016"DAP_UINT64_FORMAT_x"\n",
-                                     l_ts_exp ? l_tmp_buf : "never\n", l_coins_str, l_value_str,
-                                     dap_chain_tx_out_cond_subtype_to_str(((dap_chain_tx_out_cond_t*)item)->header.subtype),
-                                     ((dap_chain_tx_out_cond_t*)item)->header.srv_uid.uint64);
-            switch (((dap_chain_tx_out_cond_t*)item)->header.subtype) {
-                case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY: {
-                    const char *l_coins_str, *l_value_str =
-                        dap_uint256_to_char( ((dap_chain_tx_out_cond_t*)item)->subtype.srv_pay.unit_price_max_datoshi, &l_coins_str );
-                    l_hash_tmp = ((dap_chain_tx_out_cond_t*)item)->subtype.srv_pay.pkey_hash;
-                    l_hash_str = dap_strcmp(a_hash_out_type, "hex")
-                            ? dap_enc_base58_encode_hash_to_str_static(&l_hash_tmp)
-                            : dap_chain_hash_fast_to_str_static(&l_hash_tmp);
-                    dap_string_append_printf(a_str_out, "\t\t\t unit: 0x%08x\n"
-                                                        "\t\t\t pkey: %s\n"
-                                                        "\t\t\t max price: %s (%s)\n",
-                                             ((dap_chain_tx_out_cond_t*)item)->subtype.srv_pay.unit.uint32,
-                                             l_hash_str,
-                                             l_coins_str,
-                                             l_value_str);
-                } break;
-                case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE: {
-                    dap_chain_node_addr_t *l_signer_node_addr = &((dap_chain_tx_out_cond_t*)item)->subtype.srv_stake_pos_delegate.signer_node_addr;
-                    dap_chain_addr_t *l_signing_addr = &((dap_chain_tx_out_cond_t*)item)->subtype.srv_stake_pos_delegate.signing_addr;
-                    l_hash_tmp = l_signing_addr->data.hash_fast;
-                    l_hash_str = dap_strcmp(a_hash_out_type, "hex")
-                            ? dap_enc_base58_encode_hash_to_str_static(&l_hash_tmp)
-                            : dap_chain_hash_fast_to_str_static(&l_hash_tmp);
-                    dap_string_append_printf(a_str_out, "\t\t\t signing_addr: %s\n"
-                                                        "\t\t\t with pkey hash %s\n"
-                                                        "\t\t\t signer_node_addr: "NODE_ADDR_FP_STR"\n",
-                                                        dap_chain_addr_to_str_static(l_signing_addr),
-                                                        l_hash_str,
-                                                        NODE_ADDR_FP_ARGS(l_signer_node_addr));
-                } break;
-                case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE: {
-                    const char *l_rate_str, *l_tmp_str =
-                        dap_uint256_to_char( (((dap_chain_tx_out_cond_t*)item)->subtype.srv_xchange.rate), &l_rate_str );
-                    dap_string_append_printf(a_str_out, "\t\t\t net id: 0x%016"DAP_UINT64_FORMAT_x"\n"
-                                                        "\t\t\t buy_token: %s\n"
-                                                        "\t\t\t rate: %s\n",
-                                             ((dap_chain_tx_out_cond_t*)item)->subtype.srv_xchange.buy_net_id.uint64,
-                                             ((dap_chain_tx_out_cond_t*)item)->subtype.srv_xchange.buy_token,
-                                             l_rate_str);
-                } break;
-                case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK: {
-                    dap_time_t l_ts_unlock = ((dap_chain_tx_out_cond_t*)item)->subtype.srv_stake_lock.time_unlock;
-                    dap_time_to_str_rfc822(l_tmp_buf, DAP_TIME_STR_SIZE, l_ts_unlock);
-                    dap_string_append_printf(a_str_out, "\t\t\t time_unlock %s\n", l_tmp_buf);
-                } break;
-                default: break;
-            }
-        } break;
-        case TX_ITEM_TYPE_OUT_EXT: {
-            const char *l_coins_str, *l_value_str = dap_uint256_to_char( ((dap_chain_tx_out_ext_t*)item)->header.value, &l_coins_str);
-            dap_string_append_printf(a_str_out, "\t OUT EXT:\n"
-                                                "\t\t Addr: %s\n"
-                                                "\t\t Token: %s\n"
-                                                "\t\t Value: %s (%s)\n",
-                                     dap_chain_addr_to_str_static(&((dap_chain_tx_out_ext_t*)item)->addr),
-                                     ((dap_chain_tx_out_ext_t*)item)->token,
-                                     l_coins_str,
-                                     l_value_str);
-        } break;
-        case TX_ITEM_TYPE_VOTING:{
-            size_t l_tsd_size = 0;
-            dap_chain_tx_tsd_t *l_item = (dap_chain_tx_tsd_t *)dap_chain_datum_tx_item_get(a_datum, NULL, (byte_t*)item + l_size, TX_ITEM_TYPE_TSD, &l_tsd_size);
-            if (!l_item || !l_tsd_size)
-                    break;
-            dap_chain_datum_tx_voting_params_t *l_voting_params = dap_chain_voting_parse_tsd(a_datum);
-            dap_string_append_printf(a_str_out, "\t VOTING:\n\tVoting question: %s\n\t Answer options:\n", l_voting_params->voting_question);
-            dap_list_t *l_temp = l_voting_params->answers_list;
-            uint8_t l_index = 0;
-            while (l_temp){
-                    dap_string_append_printf(a_str_out, "\t\t %i) %s\n", l_index, (char*)l_temp->data);
-                    l_index++;
-                    l_temp = l_temp->next;
-            }
-
-            if (l_voting_params->voting_expire) {
-                dap_time_to_str_rfc822(l_tmp_buf, DAP_TIME_STR_SIZE, l_voting_params->voting_expire);
-                dap_string_append_printf(a_str_out, "\t Voting expire: %s\n", l_tmp_buf);
-            }
-            if (l_voting_params->votes_max_count)
-                    dap_string_append_printf(a_str_out, "\t Votes max count: %"DAP_UINT64_FORMAT_U"\n", l_voting_params->votes_max_count);
-            dap_string_append_printf(a_str_out, "\t Changing vote is %s available.\n", l_voting_params->vote_changing_allowed ? "" : "not");
-            dap_string_append_printf(a_str_out, "\t A delegated key is%s required to participate in voting. \n",
-                                     l_voting_params->delegate_key_required ? "" : " not");
-
-            dap_list_free_full(l_voting_params->answers_list, NULL);
-            DAP_DELETE(l_voting_params->voting_question);
-            DAP_DELETE(l_voting_params);
-        } break;
-        case TX_ITEM_TYPE_VOTE:{
-            dap_chain_tx_vote_t *l_vote_item = (dap_chain_tx_vote_t *)item;
-            const char *l_hash_str = dap_chain_hash_fast_to_str_static(&l_vote_item->voting_hash);
-            dap_string_append_printf(a_str_out, "\t VOTE: \n"
-                                                "\t Voting hash: %s\n"
-                                                "\t Vote answer idx: %"DAP_UINT64_FORMAT_U"\n", l_hash_str, l_vote_item->answer_idx);
-        } break;
-        default:
-            dap_string_append_printf(a_str_out, " This transaction have unknown item type \n");
-            break;
-        }
-    }
-    dap_string_append_printf(a_str_out, "\n");
-    return true;
-}
-
 /**
  * @brief _dap_chain_datum_tx_out_data
  *
@@ -584,27 +285,6 @@ bool dap_chain_datum_dump_tx_json(json_object* a_json_arr_reply,
             sprintf(l_tmp_buff,"0x%016"DAP_UINT64_FORMAT_x"",((dap_chain_tx_in_ems_t*)item)->header.token_emission_chain_id.uint64);
             json_object_object_add(json_obj_item,"token_emission_chain_id", json_object_new_string(l_tmp_buff));
         } break;
-            /*
-        case TX_ITEM_TYPE_IN_EMS_EXT: {
-            l_hash_tmp = &((dap_chain_tx_in_ems_ext_t*)item)->header.ext_tx_hash;
-            l_hash_str = dap_strcmp(a_hash_out_type, "hex")
-                    ? dap_enc_base58_encode_hash_to_str(l_hash_tmp)
-                    : dap_chain_hash_fast_to_str_new(l_hash_tmp);
-            dap_string_append_printf(a_str_out, "\t IN_EMS EXT:\n"
-                                         "\t\t Version: %u\n"
-                                         "\t\t Ticker: %s\n"
-                                         "\t\t Ext chain id: 0x%016"DAP_UINT64_FORMAT_x"\n"
-                                         "\t\t Ext net id: 0x%016"DAP_UINT64_FORMAT_x"\n"
-                                         "\t\t Ext tx hash: %s\n"
-                                         "\t\t Ext tx out idx: %u\n",
-                                     ((dap_chain_tx_in_ems_ext_t*)item)->header.version,
-                                     ((dap_chain_tx_in_ems_ext_t*)item)->header.ticker,
-                                     ((dap_chain_tx_in_ems_ext_t*)item)->header.ext_chain_id.uint64,
-                                     ((dap_chain_tx_in_ems_ext_t*)item)->header.ext_net_id.uint64,
-                                     l_hash_str,
-                                     ((dap_chain_tx_in_ems_ext_t*)item)->header.ext_tx_out_idx);
-            DAP_DELETE(l_hash_str);
-        } break; */
 
         case TX_ITEM_TYPE_IN_REWARD: {
             l_hash_tmp = ((dap_chain_tx_in_reward_t *)item)->block_hash;
@@ -679,7 +359,7 @@ bool dap_chain_datum_dump_tx_json(json_object* a_json_arr_reply,
             l_hash_str = dap_strcmp(a_hash_out_type, "hex")
                     ? dap_enc_base58_encode_hash_to_str_static(&l_hash_tmp)
                     : dap_chain_hash_fast_to_str_static(&l_hash_tmp);
-            json_object_object_add(json_obj_item,"Receipt_idx", json_object_new_uint64(((dap_chain_tx_in_cond_t*)item)->header.receipt_idx));
+            json_object_object_add(json_obj_item,"Receipt_idx", json_object_new_int(((dap_chain_tx_in_cond_t*)item)->header.receipt_idx));
             json_object_object_add(json_obj_item,"Tx_prev_hash", json_object_new_string(l_hash_str));
             json_object_object_add(json_obj_item,"Tx_out_prev_idx", json_object_new_uint64(((dap_chain_tx_in_cond_t*)item)->header.tx_out_prev_idx));
             break;
diff --git a/modules/common/dap_chain_datum_decree.c b/modules/common/dap_chain_datum_decree.c
index 88b46cf8a273818bb0ecec160cc08876a8255a78..7a33f3351b2d08c9d6b5c9a67a1a00c5e9c1f76e 100644
--- a/modules/common/dap_chain_datum_decree.c
+++ b/modules/common/dap_chain_datum_decree.c
@@ -200,9 +200,7 @@ void dap_chain_datum_decree_dump_json(json_object *a_json_out, dap_chain_datum_d
             }
             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);
-            json_object_object_add(a_json_out, "Owner fingerprint", json_object_new_string(l_owner_pkey_str));
+            json_object_object_add(a_json_out, "Owner fingerprint", json_object_new_string(dap_get_data_hash_str(l_owner_pkey->pkey, l_owner_pkey->header.size).s));
             break;
         case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_MIN_OWNER:
             if (l_tsd->size > sizeof(uint256_t)){
diff --git a/modules/common/include/dap_chain_common.h b/modules/common/include/dap_chain_common.h
index f3c8a93b92ebc504a91ae28894983090920a8539..5d538a307df9b7a82eb7a94b260c34e1b516e013 100644
--- a/modules/common/include/dap_chain_common.h
+++ b/modules/common/include/dap_chain_common.h
@@ -75,6 +75,20 @@ typedef union dap_chain_node_role{
     uint8_t raw[DAP_CHAIN_NODE_ROLE_SIZE];
 } DAP_ALIGN_PACKED dap_chain_node_role_t;
 
+DAP_STATIC_INLINE const char *dap_chain_node_role_to_str(dap_chain_node_role_t a_node_role)
+{
+    switch (a_node_role.enums) {
+        case NODE_ROLE_ROOT_MASTER: return "NODE_ROLE_ROOT_MASTER";
+        case NODE_ROLE_ROOT: return "NODE_ROLE_ROOT";
+        case NODE_ROLE_ARCHIVE: return "NODE_ROLE_ARCHIVE";
+        case NODE_ROLE_CELL_MASTER: return "NODE_ROLE_CELL_MASTER";
+        case NODE_ROLE_MASTER: return "NODE_ROLE_MASTER";
+        case NODE_ROLE_FULL: return "NODE_ROLE_FULL";
+        case NODE_ROLE_LIGHT: return "NODE_ROLE_LIGHT";
+        default: return "UNDEFINED";
+    }
+}
+
 typedef dap_stream_node_addr_t dap_chain_node_addr_t;
 #define dap_chain_node_addr_str_check dap_stream_node_addr_str_check
 #define dap_chain_node_addr_from_str dap_stream_node_addr_from_str
diff --git a/modules/common/include/dap_chain_datum.h b/modules/common/include/dap_chain_datum.h
index 2ef80945255de74b0ddd6b240b6d35af3f39e563..db94b8a2519274ce5237715f314ec0dbc2739217 100644
--- a/modules/common/include/dap_chain_datum.h
+++ b/modules/common/include/dap_chain_datum.h
@@ -159,13 +159,6 @@ DAP_STATIC_INLINE const char *dap_chain_datum_type_id_to_str(uint16_t a_type_id)
 }
 
 void dap_datum_token_dump_tsd_to_json(json_object * json_obj_out, dap_chain_datum_token_t *a_token, size_t a_token_size, const char *a_hash_out_type);
-void dap_chain_datum_dump(dap_string_t *a_str_out, dap_chain_datum_t *a_datum, const char *a_hash_out_type, dap_chain_net_id_t a_net_id);
-bool dap_chain_datum_dump_tx(dap_chain_datum_tx_t *a_datum,
-                             const char *a_ticker,
-                             dap_string_t *a_str_out,
-                             const char *a_hash_out_type,
-                             dap_hash_fast_t *a_tx_hash,
-                             dap_chain_net_id_t a_net_id);
 bool dap_chain_datum_dump_tx_json(json_object* a_json_arr_reply,
                              dap_chain_datum_tx_t *a_datum,
                              const char *a_ticker,
diff --git a/modules/common/include/dap_chain_datum_token.h b/modules/common/include/dap_chain_datum_token.h
index 53c5ec4b30ceb0c0003cc12ba1baa598acec9364..8cbd69b20fa7d35b9a9eecc6eeabbed1c85d517a 100644
--- a/modules/common/include/dap_chain_datum_token.h
+++ b/modules/common/include/dap_chain_datum_token.h
@@ -33,6 +33,7 @@
 #include "json_object.h"
 
 
+#define DAP_CHAIN_DATUM_NONCE_SIZE                                          64
 // Token declaration
 typedef struct dap_chain_datum_token_old {
     uint16_t type;
@@ -124,8 +125,9 @@ typedef struct dap_chain_datum_token {
             uint256_t premine_supply;
             dap_chain_addr_t premine_address;
         } DAP_ALIGN_PACKED header_public;
-        byte_t header[256]; // For future changes
+        byte_t header[192]; // For future changes
     };
+    uint8_t nonce[DAP_CHAIN_DATUM_NONCE_SIZE];
     byte_t tsd_n_signs[]; // Signs and/or types-size-data sections
 } DAP_ALIGN_PACKED dap_chain_datum_token_t;
 
@@ -293,7 +295,6 @@ uint32_t dap_chain_datum_token_flag_from_str(const char *a_str);
 #define DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_REMOVE             0x0024
 #define DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_CLEAR              0x0025
 
-#define DAP_CHAIN_DATUM_NONCE_SIZE                                          64
 
 // Get delegated ticker
 DAP_STATIC_INLINE int dap_chain_datum_token_get_delegated_ticker(char *a_buf, const char *a_ticker)
diff --git a/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c b/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c
index 422e3ca3f6a1783811f1a6f719aed1f47b2ae9f5..e9eff2ad1bfca05fedcb5e31eec9a9d211a8d73d 100644
--- a/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c
+++ b/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c
@@ -57,24 +57,20 @@ typedef struct dap_chain_cs_dag_poa_presign_callback{
     void *arg;
 } dap_chain_cs_dag_poa_presign_callback_t;
 
-struct round_timer_arg {
+typedef struct dap_chain_cs_dag_poa_round_item {
+    dap_chain_hash_fast_t datum_hash;
     dap_chain_cs_dag_t *dag;
-    uint64_t round_id;
     UT_hash_handle hh;
-};
+} dap_chain_cs_dag_poa_round_item_t;
 
 typedef struct dap_chain_cs_dag_poa_pvt {
     pthread_rwlock_t rounds_rwlock;
-    struct round_timer_arg *active_rounds;
-    dap_cert_t * events_sign_cert;
-    dap_cert_t ** auth_certs;
-    char * auth_certs_prefix;
-    uint16_t auth_certs_count;
-    uint16_t auth_certs_count_verify; // Number of signatures, needed for event verification
-    bool auto_confirmation;
-    bool auto_round_complete;
-    uint32_t confirmations_timeout; // wait signs over min value (auth_certs_count_verify)
-    uint32_t wait_sync_before_complete;
+    dap_chain_cs_dag_poa_round_item_t *event_items;
+    dap_cert_t *events_sign_cert, **auth_certs;
+    char *auth_certs_prefix;
+    uint16_t auth_certs_count, auth_certs_count_verify; // Number of signatures, needed for event verification
+    bool auto_confirmation, auto_round_complete;
+    uint32_t confirmations_timeout, wait_sync_before_complete;
     dap_chain_cs_dag_poa_presign_callback_t *callback_pre_sign;
     dap_interval_timer_t mempool_timer;
 } dap_chain_cs_dag_poa_pvt_t;
@@ -83,23 +79,21 @@ typedef struct dap_chain_cs_dag_poa_pvt {
 
 static void s_callback_delete(dap_chain_cs_dag_t * a_dag);
 static int s_callback_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg);
-static void s_poa_round_clean(void *a_arg);
 static int s_callback_created(dap_chain_t * a_chain, dap_config_t *a_chain_cfg);
 static int s_callback_event_verify(dap_chain_cs_dag_t *a_dag, dap_chain_cs_dag_event_t *a_dag_event, dap_hash_fast_t *a_event_hash);
 static dap_chain_cs_dag_event_t * s_callback_event_create(dap_chain_cs_dag_t * a_dag, dap_chain_datum_t * a_datum,
                                                           dap_chain_hash_fast_t * a_hashes, size_t a_hashes_count, size_t* a_event_size);
-static bool s_callback_round_event_to_chain(struct round_timer_arg *a_arg);
+static bool s_callback_round_event_to_chain(dap_chain_cs_dag_poa_round_item_t *a_arg);
 static int s_callback_event_round_sync(dap_chain_cs_dag_t * a_dag, const char a_op_code, const char *a_group,
-                                        const char *a_key, const void *a_value, const size_t a_value_size);
+                                       const char *a_key, const void *a_value, const size_t a_value_size, bool a_by_us);
 static bool s_round_event_ready_minimum_check(dap_chain_cs_dag_t *a_dag, dap_chain_cs_dag_event_t *a_event,
                                               size_t a_event_size, char *a_event_hash_hex_str);
-static void s_round_event_cs_done(dap_chain_cs_dag_t * a_dag, uint64_t a_round_id);
+static void s_round_event_cs_done(dap_chain_cs_dag_poa_round_item_t *a_event_item, uint32_t a_timeout_s);
 
 // CLI commands
 static int s_cli_dag_poa(int argc, char ** argv, void **a_str_reply);
 
 static bool s_seed_mode = false;
-static dap_interval_timer_t s_poa_round_timer = NULL;
 static bool s_debug_more = false;
 
 /**
@@ -292,8 +286,13 @@ static int s_cli_dag_poa(int argc, char ** argv, void **a_str_reply)
                                     l_poa_pvt->events_sign_cert->name, l_event_new_hash_base58_str);
                         }
                         ret = 0;
-                        if (l_event_is_ready && l_poa_pvt->auto_round_complete) // cs done (minimum signs & verify passed)
-                            s_round_event_cs_done(l_dag, l_event->header.round_id);
+                        if (l_event_is_ready && l_poa_pvt->auto_round_complete) { // cs done (minimum signs & verify passed) 
+                            dap_chain_cs_dag_poa_round_item_t l_event_item = {
+                                .datum_hash = l_round_item->round_info.datum_hash,
+                                .dag = l_dag
+                            };
+                            s_round_event_cs_done(&l_event_item, l_poa_pvt->confirmations_timeout);
+                        }
                     } else {
                         if(!dap_strcmp(l_hash_out_type, "hex")) {
                             dap_cli_server_cmd_set_reply_text(a_str_reply,
@@ -400,15 +399,13 @@ static int s_callback_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg)
     log_it(L_NOTICE,"Initialized DAG-PoA consensus with %u/%u minimum consensus",l_poa_pvt->auth_certs_count,l_poa_pvt->auth_certs_count_verify);
     l_dag->chain->callback_created = s_callback_created;
 
-    if (!l_dag->is_add_directly && l_poa_pvt->auto_round_complete) {
-        dap_chain_net_t *l_net = dap_chain_net_by_id(a_chain->net_id);
-        dap_chain_node_role_t l_role = dap_chain_net_get_role(l_net);
-        if (l_role.enums == NODE_ROLE_ROOT_MASTER || l_role.enums == NODE_ROLE_ROOT) {
-            if (!s_poa_round_timer) {
-                s_poa_round_timer = dap_interval_timer_create(600 * 1000, s_poa_round_clean, a_chain);
-                log_it(L_MSG, "DAG-PoA: Round timer is started");
-            }
-            DAP_CHAIN_PVT(a_chain)->cs_started = true;
+    if ( !l_dag->is_add_directly && l_poa_pvt->auto_round_complete ) {
+        switch ( dap_chain_net_get_role(dap_chain_net_by_id(a_chain->net_id)).enums ) {
+            case NODE_ROLE_ROOT_MASTER:
+            case NODE_ROLE_ROOT:
+                DAP_CHAIN_PVT(a_chain)->cs_started = true;
+            default:
+                break;
         }
     }
 
@@ -424,69 +421,6 @@ static int s_callback_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg)
     return 0;
 }
 
-/**
- * @brief s_poa_round_check_callback_load_round
- * @param a_global_db_context
- * @param a_rc
- * @param a_group
- * @param a_key
- * @param a_values_total
- * @param a_values_shift
- * @param a_values_count
- * @param a_values
- * @param a_arg
- */
-static bool s_poa_round_check_callback_round_clean(dap_global_db_instance_t *a_dbi,
-                                                   int a_rc, const char *a_group,
-                                                   const size_t a_values_total, const size_t a_values_count,
-                                                   dap_global_db_obj_t *a_values, void *a_arg)
-{
-    dap_chain_cs_dag_t *l_dag = (dap_chain_cs_dag_t *)a_arg;
-    dap_chain_cs_dag_poa_t *l_poa = DAP_CHAIN_CS_DAG_POA(l_dag);
-    dap_chain_cs_dag_poa_pvt_t *l_poa_pvt = PVT(l_poa);
-
-    if (a_values_count) {
-        for (size_t i = 0; i < a_values_count; i++) {
-            if (!strcmp(DAG_ROUND_CURRENT_KEY, a_values[i].key))
-                continue;
-            if (a_values[i].value_len <= sizeof(dap_chain_cs_dag_event_round_item_t) + sizeof(dap_chain_cs_dag_event_t)) {
-                log_it(L_WARNING, "Too small round item in DAG PoA rounds GDB group");
-                dap_global_db_del_sync(a_group, a_values[i].key);
-                continue;
-            }
-            dap_chain_cs_dag_event_round_item_t *l_event_round_item = (dap_chain_cs_dag_event_round_item_t *)a_values[i].value;
-            uint64_t l_time_diff = dap_nanotime_now() - l_event_round_item->round_info.ts_update;
-            uint64_t l_timeuot = dap_nanotime_from_sec(l_poa_pvt->confirmations_timeout + l_poa_pvt->wait_sync_before_complete + 10);
-            uint64_t l_round_id = ((dap_chain_cs_dag_event_t *)l_event_round_item->event_n_signs)->header.round_id;
-            if (((int64_t)l_time_diff > 0 && l_time_diff > l_timeuot) || l_round_id <= l_dag->round_completed) {
-                pthread_rwlock_rdlock(&l_poa_pvt->rounds_rwlock);
-                struct round_timer_arg *l_arg = NULL;
-                HASH_FIND(hh, l_poa_pvt->active_rounds, &l_round_id, sizeof(uint64_t), l_arg);
-                pthread_rwlock_unlock(&l_poa_pvt->rounds_rwlock);
-                if (l_arg) {
-                    log_it(L_INFO, "Event %s is from currently active round [id %"DAP_UINT64_FORMAT_U"]", a_values[i].key, l_round_id);
-                    continue;
-                }
-                dap_global_db_del_sync(a_group, a_values[i].key);
-                log_it(L_DEBUG, "DAG-PoA: Remove event %s from round %"DAP_UINT64_FORMAT_U" %s.",
-                       a_values[i].key, l_round_id, l_time_diff > l_timeuot ? "by timer" : "owing to round completion");
-            }
-        }
-    }
-    return true;
-}
-
-/**
- * @brief Timer callback for round check
- * @param a_chain Chain object
- * @return Always true
- */
-static void s_poa_round_clean(void *a_arg)
-{
-    dap_chain_cs_dag_t *l_dag = DAP_CHAIN_CS_DAG((dap_chain_t *)a_arg);
-    dap_global_db_get_all(l_dag->gdb_group_events_round_new, 0, s_poa_round_check_callback_round_clean, l_dag);
-}
-
 static bool s_round_event_ready_minimum_check(dap_chain_cs_dag_t *a_dag, dap_chain_cs_dag_event_t *a_event,
                                               size_t a_event_size, char * a_event_hash_hex_str)
 {
@@ -605,58 +539,77 @@ static bool s_callback_round_event_to_chain_callback_get_round_item(dap_global_d
 {
     if (a_rc != DAP_GLOBAL_DB_RC_SUCCESS) 
         return false;
-    struct round_timer_arg *l_arg = (struct round_timer_arg *)a_arg;
+    dap_chain_cs_dag_poa_round_item_t *l_arg = (dap_chain_cs_dag_poa_round_item_t*)a_arg;
     dap_chain_cs_dag_t *l_dag = l_arg->dag;
-    uint64_t l_round_id = l_arg->round_id;
     dap_chain_cs_dag_poa_pvt_t *l_poa_pvt = PVT(DAP_CHAIN_CS_DAG_POA(l_dag));
     pthread_rwlock_wrlock(&l_poa_pvt->rounds_rwlock);
-    HASH_DEL(l_poa_pvt->active_rounds, l_arg);
+    HASH_DEL(l_poa_pvt->event_items, l_arg);
     pthread_rwlock_unlock(&l_poa_pvt->rounds_rwlock);
-    DAP_DELETE(a_arg);
     uint16_t l_max_signs_count = 0;
     dap_list_t *l_dups_list = NULL;
-    for (size_t i = 0; i < a_values_count; i++) {
+    size_t i, e, k;
+    const char *l_complete_keys[a_values_count], *l_expired_keys[a_values_count];
+    for (i = 0, e = 0, k = 0; i < a_values_count; i++) {
         if (!strcmp(DAG_ROUND_CURRENT_KEY, a_values[i].key))
             continue;
-        dap_chain_cs_dag_event_round_item_t *l_round_item = (dap_chain_cs_dag_event_round_item_t *)a_values[i].value;
+        if (a_values[i].value_len <= sizeof(dap_chain_cs_dag_event_round_item_t) + sizeof(dap_chain_cs_dag_event_t)) {
+            log_it(L_WARNING, "Incorrect round item size, dump it");
+            dap_global_db_del_sync(a_group, a_values[i].key);
+            continue;
+        }
+        dap_chain_cs_dag_event_round_item_t *l_round_item = (dap_chain_cs_dag_event_round_item_t*)a_values[i].value;
         dap_chain_cs_dag_event_t *l_event = (dap_chain_cs_dag_event_t *)l_round_item->event_n_signs;
-        if (l_event->header.round_id == l_round_id &&
-                l_round_item->round_info.reject_count < l_poa_pvt->auth_certs_count_verify) {
+        if ( dap_hash_fast_compare( &l_arg->datum_hash, &l_round_item->round_info.datum_hash )
+            && l_round_item->round_info.reject_count < l_poa_pvt->auth_certs_count_verify)
+        {
             l_dups_list = dap_list_append(l_dups_list, l_round_item);
             if (l_event->header.signs_count > l_max_signs_count)
                 l_max_signs_count = l_event->header.signs_count;
+            l_complete_keys[k++] = a_values[i].key;
+        }
+        else if ( dap_nanotime_from_sec(l_poa_pvt->wait_sync_before_complete + l_poa_pvt->confirmations_timeout + 10)
+                 < dap_nanotime_now() - l_round_item->round_info.ts_update )
+        {
+            l_expired_keys[e++] = a_values[i].key;
         }
     }
     dap_chain_cs_dag_event_round_item_t *l_chosen_item = s_round_event_choose_dup(l_dups_list, l_max_signs_count);
+    dap_list_free(l_dups_list);
+    char l_datum_hash_str[DAP_HASH_FAST_STR_SIZE];
+    dap_hash_fast_to_str(&l_arg->datum_hash, l_datum_hash_str, sizeof(l_datum_hash_str));
     if (l_chosen_item) {
         size_t l_event_size = l_chosen_item->event_size;
         dap_chain_cs_dag_event_t *l_new_atom = (dap_chain_cs_dag_event_t *)l_chosen_item->event_n_signs;
-        char *l_event_hash_hex_str;
-        dap_get_data_hash_str_static(l_new_atom, l_event_size, l_event_hash_hex_str);
+        dap_hash_fast_t l_atom_hash;
+        dap_hash_fast(l_new_atom, l_event_size, &l_atom_hash);
+        char l_event_hash_hex_str[DAP_HASH_FAST_STR_SIZE]; dap_hash_fast_to_str(&l_atom_hash, l_event_hash_hex_str, DAP_HASH_FAST_STR_SIZE);
         dap_chain_datum_t *l_datum = dap_chain_cs_dag_event_get_datum(l_new_atom, l_event_size);
-        l_dag->round_completed = dap_max(l_new_atom->header.round_id, l_dag->round_current);
         int l_verify_datum = dap_chain_net_verify_datum_for_add(l_dag->chain, l_datum, &l_chosen_item->round_info.datum_hash);
         if (!l_verify_datum) {
-            dap_hash_fast_t l_atom_hash = {};
-            dap_hash_fast(l_new_atom, l_event_size, &l_atom_hash);
             dap_chain_atom_verify_res_t l_res = l_dag->chain->callback_atom_add(l_dag->chain, l_new_atom, l_event_size, &l_atom_hash, true);
-            if (l_res == ATOM_ACCEPT)
-                s_poa_round_clean(l_dag->chain);
-            log_it(L_INFO, "Event %s from round %"DAP_UINT64_FORMAT_U" %s",
-                   l_event_hash_hex_str, l_round_id, dap_chain_atom_verify_res_str[l_res]);
+            if (l_res == ATOM_ACCEPT) {
+                for (; k; --k) {
+                    log_it(L_INFO, "Remove event %s with datum %s, round complete", l_complete_keys[k - 1], l_datum_hash_str);
+                    dap_global_db_del_sync(a_group, l_complete_keys[k - 1]);
+                }
+                for (; e; --e) {
+                    log_it(L_INFO, "Event %s with datum %s has expired, dump it", l_expired_keys[e - 1], l_datum_hash_str);
+                    dap_global_db_del_sync(a_group,  l_expired_keys[e - 1]);
+                }
+            }
+            log_it(L_INFO, "Event %s with datum %s is %s",
+                           l_event_hash_hex_str, l_datum_hash_str, dap_chain_atom_verify_res_str[l_res]);
         } else {
-            char l_datum_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE];
-            dap_chain_hash_fast_to_str(&l_chosen_item->round_info.datum_hash, l_datum_hash_str, DAP_CHAIN_HASH_FAST_STR_SIZE);
-            log_it(L_INFO, "Event %s from round %"DAP_UINT64_FORMAT_U" not added into chain, because the inner datum %s doesn't pass verification (%s)",
-                   l_event_hash_hex_str, l_round_id, l_datum_hash_str, dap_chain_net_verify_datum_err_code_to_str(l_datum, l_verify_datum));
+            log_it(L_ERROR, "Event %s is not chained: datum %s doesn't pass verification, error \"%s\"",
+                            l_event_hash_hex_str, l_datum_hash_str, dap_chain_net_verify_datum_err_code_to_str(l_datum, l_verify_datum));
+            for (; k; --k) {
+                log_it(L_INFO, "Remove event %s with unverified datum %s", l_complete_keys[k - 1], l_datum_hash_str);
+                dap_global_db_del_sync(a_group, l_complete_keys[k - 1]);
+            }
         }
-    } else { /* !l_chosen_item */
-        l_dag->round_completed = l_dag->round_current;
-        log_it(L_WARNING, "No candidates for round id %"DAP_UINT64_FORMAT_U, l_round_id);
-
-    }
-    dap_list_free(l_dups_list);
-    return true;
+    } else /* !l_chosen_item */
+        log_it(L_WARNING, "No valid candidates to wrap datum %s in current round", l_datum_hash_str);
+    return DAP_DELETE(l_arg), true;
 }
 
 /**
@@ -664,39 +617,25 @@ static bool s_callback_round_event_to_chain_callback_get_round_item(dap_global_d
  * @param a_callback_arg
  * @return
  */
-static bool s_callback_round_event_to_chain(struct round_timer_arg *a_callback_arg)
+static bool s_callback_round_event_to_chain(dap_chain_cs_dag_poa_round_item_t *a_callback_arg)
 {
-    dap_chain_cs_dag_t *l_dag = a_callback_arg->dag;
-    dap_global_db_get_all(l_dag->gdb_group_events_round_new, 0, s_callback_round_event_to_chain_callback_get_round_item, a_callback_arg);
-    return false;
+    return dap_global_db_get_all(a_callback_arg->dag->gdb_group_events_round_new, 0, s_callback_round_event_to_chain_callback_get_round_item, a_callback_arg),
+        false;
 }
 
-static void s_round_event_cs_done(dap_chain_cs_dag_t * a_dag, uint64_t a_round_id)
+static void s_round_event_cs_done(dap_chain_cs_dag_poa_round_item_t *a_event_item, uint32_t a_timeout_s)
 {
-    dap_chain_cs_dag_poa_t *l_poa = DAP_CHAIN_CS_DAG_POA(a_dag);
-    dap_chain_cs_dag_poa_pvt_t *l_poa_pvt = PVT(l_poa);
-    struct round_timer_arg *l_callback_arg = NULL;
+    dap_chain_cs_dag_poa_pvt_t *l_poa_pvt = PVT( DAP_CHAIN_CS_DAG_POA(a_event_item->dag) );
+    dap_chain_cs_dag_poa_round_item_t *l_event_item = NULL;
     pthread_rwlock_wrlock(&l_poa_pvt->rounds_rwlock);
-    HASH_FIND(hh, l_poa_pvt->active_rounds, &a_round_id, sizeof(uint64_t), l_callback_arg);
-    if (!l_callback_arg) {
-        l_callback_arg = DAP_NEW_Z(struct round_timer_arg);
-        if (!l_callback_arg) {
-            pthread_rwlock_unlock(&l_poa_pvt->rounds_rwlock);
-            log_it(L_CRITICAL, "%s", c_error_memory_alloc);
-            return;
-        }
-        l_callback_arg->dag = a_dag;
-        l_callback_arg->round_id = a_round_id;
-        HASH_ADD(hh, l_poa_pvt->active_rounds, round_id, sizeof(uint64_t), l_callback_arg);
-        // Placement into chain by confirmation timer
-        if (!dap_timerfd_start(PVT(l_poa)->confirmations_timeout * 1000, (dap_timerfd_callback_t)s_callback_round_event_to_chain, l_callback_arg)) {
-            HASH_DEL(l_poa_pvt->active_rounds, l_callback_arg);
-            pthread_rwlock_unlock(&l_poa_pvt->rounds_rwlock);
-            DAP_DELETE(l_callback_arg);
-            log_it(L_ERROR,"Can't run timer for round ID %"DAP_UINT64_FORMAT_U, a_round_id);
-            return;
-        }
-        log_it(L_NOTICE,"Run timer for %d sec for round ID %"DAP_UINT64_FORMAT_U, PVT(l_poa)->confirmations_timeout, a_round_id);
+    HASH_FIND(hh, l_poa_pvt->event_items, &a_event_item->datum_hash, sizeof(dap_hash_fast_t), l_event_item);
+    if (!l_event_item) {
+        l_event_item = DAP_DUP(a_event_item);
+        if ( !dap_timerfd_start(a_timeout_s * 1000, (dap_timerfd_callback_t)s_callback_round_event_to_chain, l_event_item) )
+            return DAP_DELETE(l_event_item), pthread_rwlock_unlock(&l_poa_pvt->rounds_rwlock), log_it(L_CRITICAL, "Timer creation failed");
+        HASH_ADD(hh, l_poa_pvt->event_items, datum_hash, sizeof(dap_hash_fast_t), l_event_item);
+        log_it(L_INFO, "Confirmation timer for datum %s started [%d s]",
+                       dap_chain_hash_fast_to_str_static(&l_event_item->datum_hash), a_timeout_s);
     }
     pthread_rwlock_unlock(&l_poa_pvt->rounds_rwlock);
 }
@@ -707,28 +646,32 @@ static bool s_callback_sync_all_on_start(dap_global_db_instance_t *a_dbi, int a_
 {
     for (size_t i = 0; i < a_values_count; i++)
         s_callback_event_round_sync((dap_chain_cs_dag_t *)a_arg, DAP_GLOBAL_DB_OPTYPE_ADD, a_group,
-                                    a_values[i].key, a_values[i].value, a_values[i].value_len);
+                                    a_values[i].key, a_values[i].value, a_values[i].value_len, true);
     return false;
 }
 
 static void s_round_changes_notify(dap_store_obj_t *a_obj, void *a_arg)
 {
-    dap_chain_cs_dag_t *l_dag = (dap_chain_cs_dag_t *)a_arg;
-    assert(l_dag);
+    assert(a_arg);
+    dap_chain_cs_dag_t *l_dag = (dap_chain_cs_dag_t*)a_arg;
     dap_chain_net_t *l_net = dap_chain_net_by_id(l_dag->chain->net_id);
-    log_it(L_DEBUG, "%s.%s: op_code='%c' group=\"%s\" key=\"%s\" value_size=%zu",
-        l_net->pub.name, l_dag->chain->name, dap_store_obj_get_type(a_obj), a_obj->group, a_obj->key, a_obj->value_len);
-    if (dap_store_obj_get_type(a_obj) == DAP_GLOBAL_DB_OPTYPE_ADD) {
-        if (dap_strcmp(a_obj->key, DAG_ROUND_CURRENT_KEY))  // check key for round increment, if no than process event
-            s_callback_event_round_sync(l_dag, dap_store_obj_get_type(a_obj), a_obj->group, a_obj->key, a_obj->value, a_obj->value_len);
-        else
-            log_it(L_INFO, "Global round ID: %lu", *(uint64_t*)a_obj->value);
+    dap_global_db_optype_t l_type = dap_store_obj_get_type(a_obj);
+    log_it(L_DEBUG, "%s.%s: op_code '%c', group \"%s\", key \"%s\", value_size %zu",
+        l_net->pub.name, l_dag->chain->name, l_type, a_obj->group, a_obj->key, a_obj->value_len);
+    if ( !dap_strcmp(a_obj->key, DAG_ROUND_CURRENT_KEY) )
+        return;
+    switch ( l_type ) {
+    case DAP_GLOBAL_DB_OPTYPE_ADD:
+        s_callback_event_round_sync(l_dag, l_type, a_obj->group, a_obj->key, a_obj->value, a_obj->value_len,
+                                    dap_stream_node_addr_from_sign(a_obj->sign).uint64 == g_node_addr.uint64);
+    default:
+        break;
     }
 }
 
 static void s_timer_process_callback(void *a_arg)
 {
-    dap_chain_node_mempool_process_all((dap_chain_t *)a_arg, false);
+    dap_chain_node_mempool_process_all( (dap_chain_t*)a_arg, false );
 }
 
 /**
@@ -760,19 +703,14 @@ static int s_callback_created(dap_chain_t * a_chain, dap_config_t *a_chain_net_c
     dap_global_db_cluster_add_notify_callback(l_dag_cluster, s_round_changes_notify, l_dag);
     dap_chain_net_add_auth_nodes_to_cluster(l_net, l_dag_cluster);
     dap_link_manager_add_net_associate(l_net->pub.id.uint64, l_dag_cluster->links_cluster);
-
-    byte_t *l_current_round = dap_global_db_get_sync(l_dag->gdb_group_events_round_new, DAG_ROUND_CURRENT_KEY, NULL, NULL, NULL);
-    l_dag->round_current = l_current_round ? *(uint64_t*)l_current_round : 0;
-    DAP_DELETE(l_current_round);
-    log_it(L_INFO, "Current round id %"DAP_UINT64_FORMAT_U, l_dag->round_current);
-
     PVT(l_poa)->mempool_timer = dap_interval_timer_create(15000, s_timer_process_callback, a_chain);
 
-    dap_chain_node_role_t l_role = dap_chain_net_get_role(l_net);
-    if (l_role.enums == NODE_ROLE_ROOT_MASTER || l_role.enums == NODE_ROLE_ROOT) {
-        l_dag->round_completed = l_dag->round_current++;
-        log_it(L_MSG, "Round complete ID %"DAP_UINT64_FORMAT_U", current ID %"DAP_UINT64_FORMAT_U, l_dag->round_completed, l_dag->round_current);
-        dap_global_db_get_all(l_dag->gdb_group_events_round_new, 0, s_callback_sync_all_on_start, l_dag);
+    switch ( dap_chain_net_get_role(l_net).enums ) {
+        case NODE_ROLE_ROOT_MASTER:
+        case NODE_ROLE_ROOT:
+            dap_global_db_get_all(l_dag->gdb_group_events_round_new, 0, s_callback_sync_all_on_start, l_dag);
+        default:
+            break;
     }
     return 0;
 }
@@ -784,7 +722,6 @@ static int s_callback_created(dap_chain_t * a_chain, dap_config_t *a_chain_net_c
  */
 static void s_callback_delete(dap_chain_cs_dag_t * a_dag)
 {
-    dap_interval_timer_delete(s_poa_round_timer);
     dap_chain_cs_dag_poa_t * l_poa = DAP_CHAIN_CS_DAG_POA ( a_dag );
 
     if ( l_poa->_pvt ) {
@@ -823,26 +760,19 @@ static dap_chain_cs_dag_event_t * s_callback_event_create(dap_chain_cs_dag_t * a
                                                           dap_chain_hash_fast_t * a_hashes, size_t a_hashes_count, size_t* a_event_size)
 {
     dap_return_val_if_fail(a_dag && a_dag->chain && DAP_CHAIN_CS_DAG_POA(a_dag), NULL);
-    dap_chain_cs_dag_poa_t * l_poa = DAP_CHAIN_CS_DAG_POA(a_dag);
-    if ( PVT(l_poa)->events_sign_cert == NULL){
+    dap_chain_cs_dag_poa_t *l_poa = DAP_CHAIN_CS_DAG_POA(a_dag);
+    if ( !PVT(l_poa)->events_sign_cert )
         log_it(L_ERROR, "Can't sign event with events_sign_cert in [dag-poa] section");
-        return  NULL;
-    }
-    if ( s_seed_mode || (a_hashes && a_hashes_count) ){
+    else if ( s_seed_mode || (a_hashes && a_hashes_count) ) {
         if ( !PVT(l_poa)->callback_pre_sign || !PVT(l_poa)->callback_pre_sign->callback) {
-            dap_chain_cs_dag_event_t * l_event = dap_chain_cs_dag_event_new(a_dag->chain->id, a_dag->chain->cells->id, a_dag->round_current,
-                                                                            a_datum, PVT(l_poa)->events_sign_cert->enc_key,
-                                                                            a_hashes, a_hashes_count, a_event_size);
-            return l_event;
+            return dap_chain_cs_dag_event_new(a_dag->chain->id, a_dag->chain->cells->id, a_datum,
+                                              PVT(l_poa)->events_sign_cert->enc_key,
+                                              a_hashes, a_hashes_count, a_event_size);
         } else {
-            dap_chain_cs_dag_event_t *l_event = dap_chain_cs_dag_event_new(a_dag->chain->id, a_dag->chain->cells->id, a_dag->round_current,
-                                                                           a_datum, NULL,
-                                                                           a_hashes, a_hashes_count, a_event_size);
-            int ret = PVT(l_poa)->callback_pre_sign->callback(a_dag->chain, l_event, *a_event_size, PVT(l_poa)->callback_pre_sign->arg);
-            if (ret) {
-                DAP_DELETE(l_event);
-                return NULL;
-            }
+            dap_chain_cs_dag_event_t *l_event = dap_chain_cs_dag_event_new(a_dag->chain->id, a_dag->chain->cells->id,
+                                                                           a_datum, NULL, a_hashes, a_hashes_count, a_event_size);
+            if ( PVT(l_poa)->callback_pre_sign->callback(a_dag->chain, l_event, *a_event_size, PVT(l_poa)->callback_pre_sign->arg) )
+                return DAP_DELETE(l_event), NULL;
             *a_event_size = dap_chain_cs_dag_event_sign_add(&l_event, *a_event_size, PVT(l_poa)->events_sign_cert->enc_key);
             return l_event;
         }
@@ -851,13 +781,10 @@ static dap_chain_cs_dag_event_t * s_callback_event_create(dap_chain_cs_dag_t * a
 }
 
 static int s_callback_event_round_sync(dap_chain_cs_dag_t * a_dag, const char a_op_code, const char *a_group,
-                                        const char *a_key, const void *a_value, const size_t a_value_size)
+                                       const char *a_key, const void *a_value, const size_t a_value_size, bool a_by_us)
 {
-    if (a_op_code != DAP_GLOBAL_DB_OPTYPE_ADD || !a_key || !a_value || !a_value_size)
-        return 0;
-
-    if (!strcmp(DAG_ROUND_CURRENT_KEY, a_key))
-        return 0;
+    dap_return_val_if_pass(a_op_code != DAP_GLOBAL_DB_OPTYPE_ADD || !a_key || !a_value
+                           || !a_value_size || !strcmp(DAG_ROUND_CURRENT_KEY, a_key), 0);
 
     dap_chain_cs_dag_poa_t * l_poa = DAP_CHAIN_CS_DAG_POA(a_dag);
     dap_chain_cs_dag_poa_pvt_t *l_poa_pvt = PVT(l_poa);
@@ -868,61 +795,35 @@ static int s_callback_event_round_sync(dap_chain_cs_dag_t * a_dag, const char a_
     if (!l_poa_pvt->auto_confirmation)
         return 0;
 
-    dap_chain_cs_dag_event_round_item_t *l_round_item = (dap_chain_cs_dag_event_round_item_t *)a_value;
+    dap_chain_cs_dag_event_round_item_t *l_round_item = (dap_chain_cs_dag_event_round_item_t*)a_value;
+    dap_chain_cs_dag_event_t *l_event = (dap_chain_cs_dag_event_t*)l_round_item->event_n_signs;
     size_t l_event_size = l_round_item->event_size;
-    dap_chain_cs_dag_event_t *l_event = (dap_chain_cs_dag_event_t*)DAP_DUP_SIZE(l_round_item->event_n_signs, l_event_size);
-    if (!l_event) {
-        log_it(L_CRITICAL, "Memory allocation failed");
-        return -1;
-    }
-    if (l_event->header.round_id < a_dag->round_completed) {
-        struct round_timer_arg *l_round_active = NULL;
-        uint64_t l_round_id = l_event->header.round_id;
-        pthread_rwlock_wrlock(&l_poa_pvt->rounds_rwlock);
-        HASH_FIND(hh, l_poa_pvt->active_rounds, &l_round_id, sizeof(uint64_t), l_round_active);
-        pthread_rwlock_unlock(&l_poa_pvt->rounds_rwlock);
-        if (!l_round_active) {
-            log_it(L_DEBUG, "DAG event came from too old round [last complete id %"DAP_UINT64_FORMAT_U" > %"DAP_UINT64_FORMAT_U"], skip it",
-                   a_dag->round_completed, l_event->header.round_id);
-            DAP_DELETE(l_event);
-            return -2;
+    int l_ret = 0;
+    if ( dap_chain_cs_dag_event_sign_exists(l_event, l_event_size, l_poa_pvt->events_sign_cert->enc_key) ) {
+        if (l_poa_pvt->auto_round_complete && s_round_event_ready_minimum_check(a_dag, l_event, l_event_size, (char*)a_key) ) {
+            dap_chain_cs_dag_poa_round_item_t l_event_item = { .datum_hash = l_round_item->round_info.datum_hash, .dag = a_dag };
+            return s_round_event_cs_done(&l_event_item, a_by_us ? l_poa_pvt->confirmations_timeout : 2*l_poa_pvt->confirmations_timeout), l_ret;
         }
-    }
-    if (dap_chain_cs_dag_event_sign_exists(l_event, l_event_size, l_poa_pvt->events_sign_cert->enc_key)
-            || dap_chain_cs_dag_event_round_sign_exists(l_round_item, l_poa_pvt->events_sign_cert->enc_key)) {
-        // if my sign exists
-        if (l_poa_pvt->auto_round_complete &&
-                s_round_event_ready_minimum_check(a_dag, l_event, l_event_size, (char *)a_key))
-            // cs done (minimum signs & verify passed)
-            s_round_event_cs_done(a_dag, l_event->header.round_id);
-        DAP_DELETE(l_event);
-        return 0;
-    }
-
-    size_t l_event_size_new = 0;
-    int ret = 0;
-    if (l_event->header.round_id > a_dag->round_current) {
-        log_it(L_DEBUG, "Refresh current round ID [%lu -> %lu]", a_dag->round_current, l_event->header.round_id);
-        a_dag->round_current = l_event->header.round_id;
-    }
-    if (!l_poa_pvt->callback_pre_sign || !l_poa_pvt->callback_pre_sign->callback ||
-             !(ret = l_poa_pvt->callback_pre_sign->callback(a_dag->chain, l_event, l_event_size,
-                                                      l_poa_pvt->callback_pre_sign->arg))) {
-        l_event_size_new = dap_chain_cs_dag_event_sign_add(&l_event, l_event_size, l_poa_pvt->events_sign_cert->enc_key);
-        //char *l_event_new_hash_hex_str;
-        //dap_get_data_hash_str_static(l_event, l_event_size_new, l_event_new_hash_hex_str);
-        dap_chain_cs_dag_event_gdb_set(a_dag, /*l_event_new_hash_hex_str*/ (char*)a_key, l_event, l_event_size_new, l_round_item);
-    } else { // set sign for reject
-        l_round_item = DAP_DUP_SIZE(a_value, a_value_size);
-        if (dap_chain_cs_dag_event_round_sign_add(&l_round_item, a_value_size, l_poa_pvt->events_sign_cert->enc_key)) {
-            log_it(L_NOTICE,"Can't sign event %s, because sign rejected by pre_sign callback, ret code=%d", a_key, ret);
-            l_round_item->round_info.reject_count++;
-            dap_chain_cs_dag_event_gdb_set(a_dag, (char *)a_key, l_event, l_event_size, l_round_item);
+    } else {
+        if ( !l_poa_pvt->callback_pre_sign 
+            || !l_poa_pvt->callback_pre_sign->callback
+            || !(l_ret = l_poa_pvt->callback_pre_sign->callback(a_dag->chain, l_event, l_event_size, l_poa_pvt->callback_pre_sign->arg)) 
+        ) {
+            l_event = DAP_DUP_SIZE(l_round_item->event_n_signs, l_event_size);
+            if (( l_event_size = dap_chain_cs_dag_event_sign_add(&l_event, l_event_size, l_poa_pvt->events_sign_cert->enc_key) ))
+                dap_chain_cs_dag_event_gdb_set(a_dag, (char*)a_key, l_event, l_event_size, l_round_item);
+            DAP_DELETE(l_event);
+        } else {
+            l_round_item = DAP_DUP_SIZE(a_value, a_value_size);
+            if ( dap_chain_cs_dag_event_round_sign_add(&l_round_item, a_value_size, l_poa_pvt->events_sign_cert->enc_key) ) {
+                log_it(L_NOTICE,"Can't sign event %s, because sign rejected by pre_sign callback, ret code %d", a_key, l_ret);
+                ++l_round_item->round_info.reject_count;
+                dap_chain_cs_dag_event_gdb_set(a_dag, (char*)a_key, l_event, l_event_size, l_round_item);
+            }
+            DAP_DELETE(l_round_item);
         }
-        DAP_DELETE(l_round_item);
     }
-    DAP_DELETE(l_event);
-    return 0;
+    return l_ret;
 }
 
 /**
diff --git a/modules/consensus/esbocs/dap_chain_cs_esbocs.c b/modules/consensus/esbocs/dap_chain_cs_esbocs.c
index e2de4ce9140a5755f113b3e227d988b8498c77f7..9fd9268069034d733d6b478769f5e4ee6668c7fd 100644
--- a/modules/consensus/esbocs/dap_chain_cs_esbocs.c
+++ b/modules/consensus/esbocs/dap_chain_cs_esbocs.c
@@ -206,10 +206,12 @@ void dap_chain_cs_esbocs_deinit(void)
 static int s_callback_new(dap_chain_t *a_chain, dap_config_t *a_chain_cfg)
 {
     dap_chain_cs_type_create("blocks", a_chain, a_chain_cfg);
+
 //patch for tests
 #ifdef  DAP_LEDGER_TEST
     return 0;
 #endif
+
     dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(a_chain);
     int l_ret = 0, l_inited_cert;
     dap_chain_esbocs_t *l_esbocs = NULL;
@@ -235,7 +237,6 @@ static int s_callback_new(dap_chain_t *a_chain, dap_config_t *a_chain_cfg)
     l_esbocs_pvt->new_round_delay = dap_config_get_item_uint16_default(a_chain_cfg, DAP_CHAIN_ESBOCS_CS_TYPE_STR, "new_round_delay", 10);
     l_esbocs_pvt->round_attempts_max = dap_config_get_item_uint16_default(a_chain_cfg, DAP_CHAIN_ESBOCS_CS_TYPE_STR, "round_attempts_max", 4);
     l_esbocs_pvt->round_attempt_timeout = dap_config_get_item_uint16_default(a_chain_cfg, DAP_CHAIN_ESBOCS_CS_TYPE_STR, "round_attempt_timeout", 10);
-
     l_esbocs_pvt->start_validators_min = l_esbocs_pvt->min_validators_count =
             dap_config_get_item_uint16(a_chain_cfg, DAP_CHAIN_ESBOCS_CS_TYPE_STR, "min_validators_count");
     if (!l_esbocs_pvt->min_validators_count) {
@@ -268,6 +269,8 @@ static int s_callback_new(dap_chain_t *a_chain, dap_config_t *a_chain_cfg)
                     log_it(L_ERROR, "Can't find cert \"%s\"", l_cert_name);
                 else
                     log_it(L_ERROR, "Can't find cert \"%s\" possibly for address \"%s\"", l_cert_name, l_addrs[i]);
+                l_ret = -6;
+                goto lb_err;
                 l_ret = -8;
                 goto lb_err;
             }
@@ -275,6 +278,7 @@ static int s_callback_new(dap_chain_t *a_chain, dap_config_t *a_chain_cfg)
         dap_chain_addr_t l_signing_addr;
         log_it(L_NOTICE, "Initialized auth cert \"%s\"", l_cert_name);
         l_inited_cert++;
+        l_inited_cert++;
         dap_chain_addr_fill_from_key(&l_signing_addr, l_cert_cur->enc_key, a_chain->net_id);
 
         l_esbocs_pvt->emergency_validator_addrs = dap_list_append(l_esbocs_pvt->emergency_validator_addrs,
@@ -307,6 +311,10 @@ static int s_callback_new(dap_chain_t *a_chain, dap_config_t *a_chain_cfg)
                                                  l_weight, &l_signer_node_addr);
         }
     }
+    if (!l_inited_cert) {
+        l_ret = -1;
+        goto lb_err;
+    }
     if (!l_inited_cert) {
         l_ret = -7;
         goto lb_err;
@@ -604,8 +612,9 @@ static int s_callback_created(dap_chain_t *a_chain, dap_config_t *a_chain_net_cf
         log_it(L_ERROR, "This validator is not allowed to work in emergency mode. Use special decree to supply it");
         return -5;
     }
-    dap_chain_add_callback_notify(a_chain, s_new_atom_notifier, l_session);
-    s_session_round_new(l_session);
+    dap_chain_add_callback_notify(a_chain, s_new_atom_notifier, l_session->proc_thread, l_session);
+    //s_session_round_new(l_session);
+    dap_proc_thread_callback_add(l_session->proc_thread, s_session_round_new, l_session);
 
     l_session->cs_timer = !dap_proc_thread_timer_add(l_session->proc_thread, s_session_proc_state, l_session, 1000);
     debug_if(l_esbocs_pvt->debug && l_session->cs_timer, L_MSG, "Consensus main timer is started");
@@ -1005,8 +1014,9 @@ static void s_db_calc_sync_hash(dap_chain_esbocs_session_t *a_session)
     a_session->is_actual_hash = true;
 }
 
-static void s_session_send_startsync(dap_chain_esbocs_session_t *a_session)
+static void s_session_send_startsync(void *a_arg)
 {
+    dap_chain_esbocs_session_t *a_session = (dap_chain_esbocs_session_t*)a_arg;
     if (a_session->cur_round.sync_sent)
         return;     // Sync message already was sent
     dap_chain_hash_fast_t l_last_block_hash;
@@ -1036,14 +1046,6 @@ static void s_session_send_startsync(dap_chain_esbocs_session_t *a_session)
     a_session->cur_round.sync_sent = true;
 }
 
-static bool s_session_send_startsync_on_timer(void *a_arg)
-{
-    dap_chain_esbocs_session_t *l_session = a_arg;
-    s_session_send_startsync(l_session);
-    l_session->sync_timer = NULL;
-    return false;
-}
-
 static void s_session_update_penalty(dap_chain_esbocs_session_t *a_session)
 {
     for (dap_list_t *it = a_session->cur_round.all_validators; it; it = it->next) {
@@ -1105,11 +1107,6 @@ static bool s_session_round_new(void *a_arg)
     s_session_round_clear(a_session);
     a_session->cur_round.id++;
     a_session->cur_round.sync_attempt++;
-
-    if (a_session->sync_timer) {
-        dap_timerfd_delete_mt(a_session->sync_timer->worker, a_session->sync_timer->esocket_uuid);
-        a_session->sync_timer = NULL;
-    }
     a_session->state = DAP_CHAIN_ESBOCS_SESSION_STATE_WAIT_START;
     a_session->ts_round_sync_start = 0;
     a_session->ts_stage_entry = 0;
@@ -1169,7 +1166,8 @@ static bool s_session_round_new(void *a_arg)
                     a_session->chain->net_name, a_session->chain->name,
                         a_session->cur_round.id, l_sync_send_delay);
         if (l_sync_send_delay)
-            a_session->sync_timer = dap_timerfd_start(l_sync_send_delay * 1000, s_session_send_startsync_on_timer, a_session);
+            dap_proc_thread_timer_add_pri(a_session->proc_thread, s_session_send_startsync, a_session,
+                                          l_sync_send_delay * 1000, true, DAP_QUEUE_MSG_PRIORITY_NORMAL);
         else
             s_session_send_startsync(a_session);
     }
diff --git a/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h b/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h
index e26355cf476bd50dc4a8496d4829c7c0ceedd057..e097d109a6114acb9a7e01ea5c6dc99e3323d675 100644
--- a/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h
+++ b/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h
@@ -201,7 +201,6 @@ typedef struct dap_chain_esbocs_session {
     dap_time_t ts_stage_entry; // time of current stage entrance
 
     dap_chain_esbocs_sync_item_t *sync_items;
-    dap_timerfd_t *sync_timer;
 
     dap_chain_addr_t my_signing_addr;
 
diff --git a/modules/mempool/dap_chain_mempool.c b/modules/mempool/dap_chain_mempool.c
index 8fc3ad433d34ad4c9d290455a8c7292d15091d75..7ca0d0de3b5ed30b80e0ad7cca192fe492a0b965 100644
--- a/modules/mempool/dap_chain_mempool.c
+++ b/modules/mempool/dap_chain_mempool.c
@@ -1497,9 +1497,7 @@ void dap_chain_mempool_filter(dap_chain_t *a_chain, int *a_removed){
             continue;
         }
         //Filter hash
-        char *l_hash_content_str;
-        dap_get_data_hash_str_static(l_datum->data, l_datum->header.data_size, l_hash_content_str);
-        if (dap_strcmp(l_hash_content_str, l_objs[i].key) != 0) {
+        if (dap_strcmp(dap_get_data_hash_str(l_datum->data, l_datum->header.data_size).s, l_objs[i].key) != 0) {
             l_removed++;
             log_it(L_NOTICE, "Removed datum from mempool with \"%s\" key group %s. The hash of the contents of the "
                              "datum does not match the key.", l_objs[i].key, l_gdb_group);
diff --git a/modules/net/dap_chain_ledger.c b/modules/net/dap_chain_ledger.c
index 5c1ef173ea5bb7446083f1002a4b31aab26f2f39..af0c71dcfaa156bc0d662b0b2f729584ec39d343 100644
--- a/modules/net/dap_chain_ledger.c
+++ b/modules/net/dap_chain_ledger.c
@@ -130,6 +130,7 @@ typedef struct dap_ledger_token_item {
     time_t last_update_token_time;
 
     // for auth operations
+
     dap_pkey_t ** auth_pkeys;
     dap_chain_hash_fast_t *auth_pkey_hashes;
     size_t auth_signs_total;
@@ -276,8 +277,8 @@ typedef struct dap_ledger_private {
     dap_list_t *bridged_tx_notifiers;
     dap_list_t *tx_add_notifiers;
     dap_ledger_cache_tx_check_callback_t cache_tx_check_callback;
-    // HAL
-    dap_ledger_hal_item_t *hal_items;
+    // White- and blacklist
+    dap_ledger_hal_item_t *hal_items, *hrl_items;
 } dap_ledger_private_t;
 
 #define PVT(a) ( (dap_ledger_private_t *) a->_internal )
@@ -561,6 +562,12 @@ inline static dap_ledger_hal_item_t *s_check_hal(dap_ledger_t *a_ledger, dap_has
     return ret;
 }
 
+bool dap_ledger_datum_is_blacklisted(dap_ledger_t *a_ledger, dap_hash_fast_t a_hash) {
+    dap_ledger_hal_item_t *ret = NULL;
+    HASH_FIND(hh, PVT(a_ledger)->hrl_items, &a_hash, sizeof(dap_hash_fast_t), ret);
+    return debug_if(s_debug_more && ret, L_MSG, "Datum %s is blacklisted", dap_hash_fast_to_str_static(&a_hash)), !!ret;
+}
+
 inline static dap_ledger_token_item_t *s_ledger_find_token(dap_ledger_t *a_ledger, const char *a_token_ticker)
 {
     dap_return_val_if_fail(a_ledger && a_token_ticker, NULL);
@@ -1611,7 +1618,8 @@ int dap_ledger_token_add(dap_ledger_t *a_ledger, byte_t *a_token, size_t a_token
                 .token_emissions_rwlock     = PTHREAD_RWLOCK_INITIALIZER,
                 .token_ts_updated_rwlock    = PTHREAD_RWLOCK_INITIALIZER,
                 .auth_pkeys         = DAP_NEW_Z_SIZE(dap_pkey_t*, sizeof(dap_pkey_t*) * l_token->signs_total),
-                .auth_pkey_hashes   = DAP_NEW_Z_SIZE(dap_chain_hash_fast_t, sizeof(dap_chain_hash_fast_t) * l_token->signs_total)
+                .auth_pkey_hashes   = DAP_NEW_Z_SIZE(dap_chain_hash_fast_t, sizeof(dap_chain_hash_fast_t) * l_token->signs_total),
+                .flags = 0
         };
         switch (l_token->subtype) {
         case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE:
@@ -2139,7 +2147,39 @@ json_object *s_token_item_to_json(dap_ledger_token_item_t *a_token_item)
         json_object_object_add(l_json_obj_out, "bytes", json_object_new_int(a_token_item->auth_pkeys[i]->header.size));
         json_object_array_add(l_json_arr_pkeys, l_json_obj_out);
     }
+    json_object *l_json_arr_tx_recv_allow = json_object_new_array();
+    for (size_t i = 0; i < a_token_item->tx_recv_allow_size; i++) {
+        dap_chain_addr_t l_addr = a_token_item->tx_recv_allow[i];
+        const char *l_addr_str = dap_chain_addr_to_str_static(&l_addr);
+        json_object_array_add(l_json_arr_tx_recv_allow, json_object_new_string(l_addr_str));
+    }
+    json_object *l_json_arr_tx_recv_block = json_object_new_array();
+    for (size_t i = 0; i < a_token_item->tx_recv_block_size; i++) {
+        dap_chain_addr_t l_addr = a_token_item->tx_recv_block[i];
+        const char *l_addr_str = dap_chain_addr_to_str_static(&l_addr);
+        json_object_array_add(l_json_arr_tx_recv_block, json_object_new_string(l_addr_str));
+    }
+    json_object *l_json_arr_tx_send_allow = json_object_new_array();
+    for (size_t i = 0; i < a_token_item->tx_send_allow_size; i++) {
+        dap_chain_addr_t l_addr = a_token_item->tx_send_allow[i];
+        const char *l_addr_str = dap_chain_addr_to_str_static(&l_addr);
+        json_object_array_add(l_json_arr_tx_send_allow, json_object_new_string(l_addr_str));
+    }
+    json_object *l_json_arr_tx_send_block = json_object_new_array();
+    for (size_t i = 0; i < a_token_item->tx_send_block_size; i++) {
+        dap_chain_addr_t l_addr = a_token_item->tx_send_block[i];
+        const char *l_addr_str = dap_chain_addr_to_str_static(&l_addr);
+        json_object_array_add(l_json_arr_tx_send_block, json_object_new_string(l_addr_str));
+    }
     json_object_object_add(json_obj_datum, "Signatures public keys", l_json_arr_pkeys);
+    a_token_item->tx_recv_allow_size ? json_object_object_add(json_obj_datum, "tx_recv_allow", l_json_arr_tx_recv_allow) :
+        json_object_put(l_json_arr_tx_recv_allow);
+    a_token_item->tx_recv_block_size ? json_object_object_add(json_obj_datum, "tx_recv_block", l_json_arr_tx_recv_block) :
+        json_object_put(l_json_arr_tx_recv_block);
+    a_token_item->tx_send_allow_size ? json_object_object_add(json_obj_datum, "tx_send_allow", l_json_arr_tx_send_allow) :
+        json_object_put(l_json_arr_tx_send_allow);
+    a_token_item->tx_send_block_size ? json_object_object_add(json_obj_datum, "tx_send_block", l_json_arr_tx_send_block) :
+        json_object_put(l_json_arr_tx_send_block);
     json_object_object_add(json_obj_datum, "Total emissions", json_object_new_int(HASH_COUNT(a_token_item->token_emissions)));
     return json_obj_datum;
 }
@@ -2234,7 +2274,7 @@ static void s_threshold_txs_proc( dap_ledger_t *a_ledger)
         l_success = false;
         dap_ledger_tx_item_t *l_tx_item, *l_tx_tmp;
         HASH_ITER(hh, l_ledger_pvt->threshold_txs, l_tx_item, l_tx_tmp) {
-            int l_res = dap_ledger_tx_add(a_ledger, l_tx_item->tx, &l_tx_item->tx_hash_fast, true);
+            int l_res = dap_ledger_tx_add(a_ledger, l_tx_item->tx, &l_tx_item->tx_hash_fast, true, NULL);
             if (l_res != DAP_CHAIN_CS_VERIFY_CODE_TX_NO_EMISSION &&
                     l_res != DAP_CHAIN_CS_VERIFY_CODE_TX_NO_PREVIOUS) {
                 HASH_DEL(l_ledger_pvt->threshold_txs, l_tx_item);
@@ -2557,27 +2597,24 @@ dap_ledger_t *dap_ledger_create(dap_chain_net_t *a_net, uint16_t a_flags)
         if (strlen(l_entry_name) > 4) {
             if ( strncmp (l_entry_name + strlen(l_entry_name)-4,".cfg",4) == 0 ) { // its .cfg file
                 l_entry_name [strlen(l_entry_name)-4] = 0;
-                log_it(L_DEBUG,"Open chain config \"%s\"...",l_entry_name);
+                log_it(L_DEBUG,"Open chain config \"%s.%s\"...", a_net->pub.name, l_entry_name);
                 l_chains_path = dap_strdup_printf("network/%s/%s", a_net->pub.name, l_entry_name);
                 dap_config_t * l_cfg = dap_config_open(l_chains_path);
-                uint16_t l_whitelist_size;
-                const char **l_whitelist = dap_config_get_array_str(l_cfg, "ledger", "hard_accept_list", &l_whitelist_size);
-                for (uint16_t i = 0; i < l_whitelist_size; ++i) {
-                    dap_ledger_hal_item_t *l_hal_item = DAP_NEW_Z(dap_ledger_hal_item_t);
-                    if (!l_hal_item) {
-                        log_it(L_CRITICAL, "%s", c_error_memory_alloc);
-                        DAP_DEL_Z(l_ledger_pvt);
-                        DAP_DEL_Z(l_ledger);
-                        dap_config_close(l_cfg);
-                        DAP_DELETE (l_entry_name);
-                        closedir(l_chains_dir);
-                        return NULL;
-                    }
-                    dap_chain_hash_fast_from_str(l_whitelist[i], &l_hal_item->hash);
-                    HASH_ADD(hh, l_ledger_pvt->hal_items, hash, sizeof(l_hal_item->hash), l_hal_item);
+                uint16_t l_whitelist_size, l_blacklist_size, i;
+                const char **l_whitelist = dap_config_get_array_str(l_cfg, "ledger", "hard_accept_list", &l_whitelist_size),
+                           **l_blacklist = dap_config_get_array_str(l_cfg, "ledger", "hard_reject_list", &l_blacklist_size);
+                for (i = 0; i < l_blacklist_size; ++i) {
+                    dap_ledger_hal_item_t *l_item = DAP_NEW_Z(dap_ledger_hal_item_t);
+                    dap_chain_hash_fast_from_str(l_blacklist[i], &l_item->hash);
+                    HASH_ADD(hh, l_ledger_pvt->hrl_items, hash, sizeof(dap_hash_fast_t), l_item);
+                }
+                for (i = 0; i < l_whitelist_size; ++i) {
+                    dap_ledger_hal_item_t *l_item = DAP_NEW_Z(dap_ledger_hal_item_t);
+                    dap_chain_hash_fast_from_str(l_whitelist[i], &l_item->hash);
+                    HASH_ADD(hh, l_ledger_pvt->hal_items, hash, sizeof(dap_hash_fast_t), l_item);
                 }
                 dap_config_close(l_cfg);
-                log_it(L_DEBUG, "HAL items count for chain %s : %d", l_entry_name, l_whitelist_size);
+                log_it(L_DEBUG, "Chain %s.%s has %d datums in HAL and %d datums in HRL", a_net->pub.name, l_entry_name, l_whitelist_size, l_blacklist_size);
             }
         }
         DAP_DELETE (l_entry_name);
@@ -2694,7 +2731,8 @@ int s_emission_add_check(dap_ledger_t *a_ledger, byte_t *a_token_emission, size_
     pthread_rwlock_unlock(&l_token_item->token_emissions_rwlock);
     if (l_token_emission_item) {
         debug_if(s_debug_more, L_WARNING, "Can't add token emission datum of %s %s ( %s ): already present in cache",
-                                    dap_uint256_to_char(l_emission->hdr.value, NULL), l_emission->hdr.ticker, dap_chain_hash_fast_to_str_static(a_emission_hash));
+                                    dap_uint256_to_char(l_emission->hdr.value, NULL), l_emission->hdr.ticker,
+                                    dap_chain_hash_fast_to_str_static(a_emission_hash));
         DAP_DELETE(l_emission);
         return DAP_LEDGER_CHECK_ALREADY_CACHED;
     }
@@ -4179,7 +4217,7 @@ static int s_tx_cache_check(dap_ledger_t *a_ledger,
     }
 
     if (a_main_ticker && !l_err_num)
-        dap_strncpy(a_main_ticker, l_main_ticker, DAP_CHAIN_TICKER_SIZE_MAX);
+        dap_strncpy(a_main_ticker, l_main_ticker, DAP_CHAIN_TICKER_SIZE_MAX);     
 
     HASH_ITER(hh, l_values_from_prev_tx, l_value_cur, l_tmp) {
         HASH_DEL(l_values_from_prev_tx, l_value_cur);
@@ -4273,7 +4311,7 @@ static int s_sort_ledger_tx_item(dap_ledger_tx_item_t *a, dap_ledger_tx_item_t *
  * @param a_from_threshold
  * @return return 1 OK, -1 error
  */
-int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash, bool a_from_threshold)
+int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash, bool a_from_threshold, dap_ledger_datum_iter_data_t *a_datum_index_data)
 {
     if(!a_tx) {
         debug_if(s_debug_more, L_ERROR, "NULL tx detected");
@@ -4296,7 +4334,7 @@ int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_ha
 
     if( (l_ret_check = s_tx_cache_check(a_ledger, a_tx, a_tx_hash, a_from_threshold,
                                                        &l_list_bound_items, &l_list_tx_out,
-                                                       l_main_token_ticker, &l_tag, &l_action, false))) {
+                                                       l_main_token_ticker, &l_tag, &l_action, false))) {                                                        
         if ((l_ret_check == DAP_CHAIN_CS_VERIFY_CODE_TX_NO_PREVIOUS ||
                 l_ret_check == DAP_CHAIN_CS_VERIFY_CODE_TX_NO_EMISSION) &&
                 l_ledger_pvt->threshold_enabled && !dap_chain_net_get_load_mode(a_ledger->net)) {
@@ -4309,7 +4347,7 @@ int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_ha
                 if (!l_item_tmp) {
                     if (l_threshold_txs_count >= s_threshold_txs_max) {
                         if(s_debug_more)
-                            log_it(L_WARNING, "Threshold for tranactions is overfulled (%zu max), dropping down tx %s, added nothing",
+                            log_it(L_WARNING, "Threshold for transactions is overfulled (%zu max), dropping down tx %s, added nothing",
                                        s_threshold_txs_max, l_tx_hash_str);
                     } else {
                         l_item_tmp = DAP_NEW_Z(dap_ledger_tx_item_t);
@@ -4344,7 +4382,11 @@ int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_ha
         return l_ret_check;
     }
     debug_if(s_debug_more, L_DEBUG, "dap_ledger_tx_add() check passed for tx %s", l_tx_hash_str);
-
+    if ( a_datum_index_data != NULL){
+        dap_strncpy(a_datum_index_data->token_ticker, l_main_token_ticker, DAP_CHAIN_TICKER_SIZE_MAX);
+        a_datum_index_data->action = l_action;
+        a_datum_index_data->uid = l_tag;
+    }
     // Mark 'out' items in cache if they were used & delete previous transactions from cache if it need
     // find all bound pairs 'in' and 'out'
     size_t l_outs_used = dap_list_length(l_list_bound_items);
@@ -4948,7 +4990,7 @@ FIN:
     return l_ret;
 }
 
-int dap_ledger_tx_load(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_hash_fast_t *a_tx_hash)
+int dap_ledger_tx_load(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_hash_fast_t *a_tx_hash, dap_ledger_datum_iter_data_t *a_datum_index_data)
 {
 #ifndef DAP_LEDGER_TEST
     if (dap_chain_net_get_load_mode(a_ledger->net)) {
@@ -4964,7 +5006,7 @@ int dap_ledger_tx_load(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_c
             return DAP_LEDGER_CHECK_ALREADY_CACHED;
     }
 #endif
-    return dap_ledger_tx_add(a_ledger, a_tx, a_tx_hash, false);
+    return dap_ledger_tx_add(a_ledger, a_tx, a_tx_hash, false, a_datum_index_data);
 }
 
 /**
diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c
index 86794b3d19b2ba64a095f2cb9af0f3cbab9a175d..2d481f27b80cf820c0785e139f34b6a17e640dc7 100644
--- a/modules/net/dap_chain_net.c
+++ b/modules/net/dap_chain_net.c
@@ -184,17 +184,10 @@ typedef struct dap_chain_net_pvt{
     anchor_table_t *anchors;
 } dap_chain_net_pvt_t;
 
-typedef struct dap_chain_net_item{
-    char name[DAP_CHAIN_NET_NAME_MAX + 1];
-    dap_chain_net_id_t net_id;
-    dap_chain_net_t *chain_net;
-    UT_hash_handle hh, hh2;
-} dap_chain_net_item_t;
-
 #define PVT(a) ((dap_chain_net_pvt_t *)a->pvt)
 #define PVT_S(a) ((dap_chain_net_pvt_t *)a.pvt)
 
-static dap_chain_net_item_t *s_net_items = NULL, *s_net_ids = NULL;
+static dap_chain_net_t *s_nets_by_name = NULL, *s_nets_by_id = NULL;
 static pthread_mutex_t s_net_cond_lock = PTHREAD_MUTEX_INITIALIZER;
 static pthread_cond_t s_net_cond = PTHREAD_COND_INITIALIZER;
 static uint16_t s_net_loading_count = 0;
@@ -341,13 +334,36 @@ char *dap_chain_net_get_gdb_group_acl(dap_chain_net_t *a_net)
     return NULL;
 }
 
+DAP_STATIC_INLINE struct request_link_info *s_net_resolve_host(const char *a_addr) {
+    char l_host[DAP_HOSTADDR_STRLEN + 1] = { '\0' }; uint16_t l_port = 0;
+    struct sockaddr_storage l_saddr;
+    if ( dap_net_parse_config_address(a_addr, l_host, &l_port, NULL, NULL) < 0
+        || dap_net_resolve_host(l_host, dap_itoa(l_port), false, &l_saddr, NULL) < 0 )
+        return NULL;
+    struct request_link_info *l_ret = DAP_NEW_Z(struct request_link_info);
+    l_ret->port = l_port;
+    dap_strncpy(l_ret->addr, l_host, DAP_HOSTADDR_STRLEN);
+    return l_ret;
+}
+
 static struct request_link_info *s_balancer_link_from_cfg(dap_chain_net_t *a_net)
 {
+    uint16_t l_idx;
     switch (PVT(a_net)->seed_nodes_count) {
     case 0: return log_it(L_ERROR, "No available links in net %s! Add them in net config", a_net->pub.name), NULL;
-    case 1: return PVT(a_net)->seed_nodes_info[0];
-    default: return PVT(a_net)->seed_nodes_info[dap_random_uint16() % PVT(a_net)->seed_nodes_count];
+    case 1:
+        l_idx = 0;
+    break;
+    default:
+        l_idx = dap_random_uint16() % PVT(a_net)->seed_nodes_count;
+    break;
     }
+    if ( !PVT(a_net)->seed_nodes_info[l_idx] ) {
+        // Unresolved before? Let's try again
+        const char **l_seed_nodes_hosts = dap_config_get_array_str(a_net->pub.config, "general", "seed_nodes_hosts", NULL);
+        PVT(a_net)->seed_nodes_info[l_idx] = s_net_resolve_host(l_seed_nodes_hosts[l_idx]);
+    }
+    return PVT(a_net)->seed_nodes_info[l_idx];
 }
 
 dap_chain_node_info_t *dap_chain_net_get_my_node_info(dap_chain_net_t *a_net)
@@ -371,8 +387,10 @@ dap_stream_node_addr_t *dap_chain_net_get_authorized_nodes(dap_chain_net_t *a_ne
 int dap_chain_net_link_add(dap_chain_net_t *a_net, dap_stream_node_addr_t *a_addr, const char *a_host, uint16_t a_port)
 {
     bool l_is_link_present = dap_link_manager_link_find(a_addr, a_net->pub.id.uint64);
-    if (l_is_link_present || a_addr->uint64 == g_node_addr.uint64)
+    if (l_is_link_present || a_addr->uint64 == g_node_addr.uint64) {
+        debug_if(l_is_link_present, L_DEBUG, "Link to addr "NODE_ADDR_FP_STR" is already persent in net %s", NODE_ADDR_FP_ARGS(a_addr), a_net->pub.name);
         return -3; // Link is already found for this net or link is to yourself
+    }
     if (dap_link_manager_link_create(a_addr, a_net->pub.id.uint64)) {
         log_it(L_ERROR, "Can't create link to addr " NODE_ADDR_FP_STR, NODE_ADDR_FP_ARGS(a_addr));
         return -1;
@@ -446,8 +464,10 @@ static bool s_link_manager_callback_disconnected(dap_link_t *a_link, uint64_t a_
     log_it(L_INFO, "%s."NODE_ADDR_FP_STR" can't connect for now. %s", l_net ? l_net->pub.name : "(unknown)" ,
             NODE_ADDR_FP_ARGS_S(a_link->addr),
             l_link_is_permanent ? "Setting reconnection pause for it." : "Dropping it.");
-    if (!a_links_count && l_net_pvt->state == NET_STATE_ONLINE)
+    if (!a_links_count && l_net_pvt->state != NET_STATE_OFFLINE) {
         l_net_pvt->state = NET_STATE_LINKS_PREPARE;
+        s_net_states_proc(l_net);
+    }
     return l_link_is_permanent;
 }
 
@@ -495,11 +515,15 @@ int s_link_manager_link_request(uint64_t a_net_id)
     if (l_net_pvt->state == NET_STATE_LINKS_PREPARE)
         l_net_pvt->state = NET_STATE_LINKS_CONNECTING;
     struct request_link_info *l_balancer_link = s_balancer_link_from_cfg(l_net);
-    if (!l_balancer_link) {
-        log_it(L_ERROR, "Can't process balancer link %s request in nte %s", dap_chain_net_balancer_type_to_str(PVT(l_net)->balancer_type), l_net->pub.name);
-        return -5;
-    }
-    return dap_chain_net_balancer_request(l_net, l_balancer_link->addr,  l_balancer_link->port, PVT(l_net)->balancer_type);
+    if (!l_balancer_link)
+        return log_it(L_ERROR, "Can't process balancer link %s request in net %s", 
+                        dap_chain_net_balancer_type_to_str(PVT(l_net)->balancer_type), l_net->pub.name), -5;
+    dap_balancer_link_request_t *l_arg = DAP_NEW_Z(dap_balancer_link_request_t);
+    l_arg->net = l_net;
+    l_arg->host_addr = (const char*)l_balancer_link->addr;
+    l_arg->host_port = l_balancer_link->port;
+    l_arg->type = PVT(l_net)->balancer_type;
+    return dap_worker_exec_callback_on(dap_worker_get_auto(), dap_chain_net_balancer_request, l_arg), 0;
 }
 
 int s_link_manager_fill_net_info(dap_link_t *a_link)
@@ -507,15 +531,15 @@ int s_link_manager_fill_net_info(dap_link_t *a_link)
 // sanity check
     dap_return_val_if_pass(!a_link, -1);
 // func work
-    dap_chain_net_item_t *l_net_item = NULL, *l_tmp = NULL;
     dap_chain_node_info_t *l_node_info = NULL;
-    HASH_ITER(hh, s_net_items, l_net_item, l_tmp)
-        if ((l_node_info = dap_chain_node_info_read(l_net_item->chain_net, &a_link->addr)))
+    for (dap_chain_net_t *net = s_nets_by_name; net; net = net->hh.next) {
+        if (( l_node_info = dap_chain_node_info_read(net, &a_link->addr) ))
             break;
+    }
     if (!l_node_info)
         return -3;
     a_link->uplink.ready = true;
-    if (dap_link_manager_link_update(&a_link->addr, l_node_info->ext_host, l_node_info->ext_port))
+    if ( dap_link_manager_link_update(&a_link->addr, l_node_info->ext_host, l_node_info->ext_port) )
         a_link->uplink.ready = true;
     DAP_DELETE(l_node_info);
     return 0;
@@ -618,18 +642,35 @@ dap_chain_node_role_t dap_chain_net_get_role(dap_chain_net_t * a_net)
  * @param a_node_role
  * @return dap_chain_net_t*
  */
-static dap_chain_net_t *s_net_new(dap_chain_net_id_t *a_id, const char *a_name,
-                                  const char *a_native_ticker, const char *a_node_role)
+static dap_chain_net_t *s_net_new(const char *a_net_name, dap_config_t *a_cfg)
 {
-// sanity check
-    dap_return_val_if_pass(!a_id || !a_name || !a_native_ticker || !a_node_role, NULL);
+    dap_return_val_if_fail(a_cfg, NULL);
     dap_chain_net_t *l_ret = NULL;
-// memory alloc
+    const char  *l_net_name_str = dap_config_get_item_str_default(a_cfg, "general", "name", a_net_name),
+                *l_net_id_str   = dap_config_get_item_str(a_cfg, "general", "id"),
+                *a_node_role    = dap_config_get_item_str(a_cfg, "general", "node-role" ),
+                *a_native_ticker= dap_config_get_item_str(a_cfg, "general", "native_ticker");
+    dap_chain_net_id_t l_net_id;
+
+    if(!l_net_name_str || !l_net_id_str || dap_chain_net_id_parse(l_net_id_str, &l_net_id))
+        return log_it(L_ERROR, "Can't create l_net, can't read name or ID config"), NULL;
+
+    dap_chain_net_t *l_net_sought = NULL;
+    HASH_FIND_STR(s_nets_by_name, l_net_name_str, l_net_sought);
+    if (!l_net_sought)
+        HASH_FIND(hh2, s_nets_by_id, &l_net_id, sizeof(l_net_id), l_net_sought);
+    if (l_net_sought) {
+        log_it(L_ERROR, "Can't create net %s ID %"DAP_UINT64_FORMAT_U", an already existent net "
+                        "%s ID %"DAP_UINT64_FORMAT_U" has the same name or ID.\n"\
+                        "Please, fix your configs and restart node",
+                        l_net_name_str, l_net_id.uint64, l_net_sought->pub.name,
+                        l_net_sought->pub.id.uint64);
+        return NULL;
+    }
     DAP_NEW_Z_SIZE_RET_VAL(l_ret, dap_chain_net_t, sizeof(dap_chain_net_t) + sizeof(dap_chain_net_pvt_t), NULL, NULL);
     DAP_NEW_Z_SIZE_RET_VAL(PVT(l_ret)->node_info, dap_chain_node_info_t, sizeof(dap_chain_node_info_t) + DAP_HOSTADDR_STRLEN + 1, NULL, l_ret);
-// func work
-    l_ret->pub.id.uint64 = a_id->uint64;
 
+    l_ret->pub.id = l_net_id;
     if (strcmp (a_node_role, "root_master")==0){
         PVT(l_ret)->node_role.enums = NODE_ROLE_ROOT_MASTER;
     } else if (strcmp( a_node_role,"root") == 0){
@@ -645,18 +686,49 @@ static dap_chain_net_t *s_net_new(dap_chain_net_id_t *a_id, const char *a_name,
     }else if (strcmp( a_node_role,"light") == 0){
         PVT(l_ret)->node_role.enums = NODE_ROLE_LIGHT;
     }else{
-        log_it(L_ERROR,"Unknown node role \"%s\" for network '%s'", a_node_role, a_name);
+        log_it(L_ERROR,"Unknown node role \"%s\" for network '%s'", a_node_role, l_net_name_str);
         DAP_DELETE(l_ret);
         return NULL;
     }
-
-    if (!(l_ret->pub.name = dap_strdup(a_name)) ||
-        !(l_ret->pub.native_ticker = dap_strdup( a_native_ticker )))
-            DAP_DEL_MULTY(l_ret->pub.name, l_ret->pub.native_ticker, l_ret);
-    log_it (L_NOTICE, "Node role \"%s\" selected for network '%s'", a_node_role, a_name);
+    if (!( l_net_name_str ))
+        return DAP_DELETE(l_ret), log_it(L_ERROR, "Invalid net name, check [general] \"name\" in netconfig"), NULL;
+    dap_strncpy(l_ret->pub.name, l_net_name_str, sizeof(l_ret->pub.name));
+    if (!( l_ret->pub.native_ticker = a_native_ticker ))
+        return DAP_DEL_MULTY(l_ret->pub.name, l_ret),
+               log_it(L_ERROR, "Invalid native ticker, check [general] \"native_ticker\" in %s.cfg",
+                                l_net_name_str),
+                NULL;
+    log_it (L_NOTICE, "Node role \"%s\" selected for network '%s'", a_node_role, l_net_name_str);
+    l_ret->pub.config = a_cfg;
+    l_ret->pub.gdb_groups_prefix
+        = dap_config_get_item_str_default( a_cfg, "general", "gdb_groups_prefix", dap_config_get_item_str(a_cfg, "general", "name") );
+    HASH_ADD_STR(s_nets_by_name, pub.name, l_ret);
+    HASH_ADD(hh2, s_nets_by_id, pub.id, sizeof(dap_chain_net_id_t), l_ret);
     return l_ret;
 }
 
+bool s_net_disk_load_notify_callback(UNUSED_ARG void *a_arg) {
+    json_object *json_obj = json_object_new_object();
+    json_object_object_add(json_obj, "class", json_object_new_string("nets_init"));
+    json_object *l_jobj_nets = json_object_new_object();
+    for (dap_chain_net_t *net = s_nets_by_name; net; net = net->hh.next) {
+        json_object *json_chains = json_object_new_object();
+        for (dap_chain_t *l_chain = net->pub.chains; l_chain; l_chain = l_chain->next) {
+            json_object *l_jobj_chain_info = json_object_new_object();
+            json_object_object_add(l_jobj_chain_info, "count_atoms", json_object_new_int(l_chain->callback_count_atom(l_chain)));
+            json_object_object_add(l_jobj_chain_info, "load_process", json_object_new_int(l_chain->load_progress));
+            json_object_object_add(json_chains, l_chain->name, l_jobj_chain_info);
+            log_it(L_DEBUG, "Loading net \"%s\", chain \"%s\", ID 0x%016"DAP_UINT64_FORMAT_x " [%d%%]",
+                            net->pub.name, l_chain->name, l_chain->id.uint64, l_chain->load_progress);
+        }
+        json_object_object_add(l_jobj_nets, net->pub.name, json_chains);
+    }
+    json_object_object_add(json_obj, "nets", l_jobj_nets);
+    dap_notify_server_send_mt(json_object_get_string(json_obj));
+    json_object_put(json_obj);
+    return true;
+}
+
 /**
  * @brief
  * load network config settings
@@ -664,35 +736,33 @@ static dap_chain_net_t *s_net_new(dap_chain_net_id_t *a_id, const char *a_name,
 void dap_chain_net_load_all()
 {
     pthread_mutex_lock(&s_net_cond_lock);
-    s_net_loading_count = HASH_COUNT(s_net_items);
+    s_net_loading_count = HASH_COUNT(s_nets_by_name);
     if (!s_net_loading_count) {
         log_it(L_ERROR, "Can't find any nets");
         pthread_mutex_unlock(&s_net_cond_lock);
         return;
     }
-    dap_chain_net_item_t *l_net_items_current = NULL, *l_net_items_tmp = NULL;
-    HASH_ITER(hh, s_net_items, l_net_items_current, l_net_items_tmp)
-        dap_proc_thread_callback_add(NULL, s_net_load, l_net_items_current->chain_net);
+    dap_timerfd_t *l_load_notify_timer = dap_timerfd_start(5000, (dap_timerfd_callback_t)s_net_disk_load_notify_callback, NULL);
+    for (dap_chain_net_t *net = s_nets_by_name; net; net = net->hh.next)
+        dap_proc_thread_callback_add(NULL, s_net_load, net);
     while (s_net_loading_count)
         pthread_cond_wait(&s_net_cond, &s_net_cond_lock);
     pthread_mutex_unlock(&s_net_cond_lock);
+    dap_timerfd_delete_mt(l_load_notify_timer->worker, l_load_notify_timer->esocket_uuid);
 }
 
 dap_string_t* dap_cli_list_net()
 {
-    dap_chain_net_item_t * l_net_item, *l_net_item_tmp;
     dap_string_t *l_string_ret = dap_string_new("");
     dap_chain_net_t * l_net = NULL;
-    int l_net_i = 0;
-    dap_string_append(l_string_ret,"Available networks and chains:\n");
-    HASH_ITER(hh, s_net_items, l_net_item, l_net_item_tmp){
-        l_net = l_net_item->chain_net;
-        dap_string_append_printf(l_string_ret, "\t%s:\n", l_net_item->name);
-        l_net_i++;
-
-        dap_chain_t * l_chain = l_net->pub.chains;
+    unsigned l_net_i = 0;
+    dap_string_append(l_string_ret, "Available networks and chains:\n");
+    for (dap_chain_net_t *net = s_nets_by_name; net; net = net->hh.next) {
+        dap_string_append_printf(l_string_ret, "\t%s:\n", l_net->pub.name);
+        ++l_net_i;
+        dap_chain_t *l_chain = l_net->pub.chains;
         while (l_chain) {
-            dap_string_append_printf(l_string_ret, "\t\t%s\n", l_chain->name );
+            dap_string_append_printf( l_string_ret, "\t\t%s\n", l_chain->name );
             l_chain = l_chain->next;
         }
     }
@@ -945,13 +1015,11 @@ static int s_cli_net(int argc, char **argv, void **reply)
                 json_object_object_add(l_jobj_return, "net", l_jobj_net_name);
                 json_object_object_add(l_jobj_return, "chains", l_jobj_chains);
             }else{
-                dap_chain_net_item_t * l_net_item, *l_net_item_tmp;
                 json_object *l_jobj_networks = json_object_new_array();
-                HASH_ITER(hh, s_net_items, l_net_item, l_net_item_tmp){
+                for (dap_chain_net_t *l_net = s_nets_by_name; l_net; l_net = l_net->hh.next) {
                     json_object *l_jobj_network = json_object_new_object();
                     json_object *l_jobj_chains = json_object_new_array();
-                    l_net = l_net_item->chain_net;
-                    json_object *l_jobj_network_name = json_object_new_string(l_net_item->name);
+                    json_object *l_jobj_network_name = json_object_new_string(l_net->pub.name);
                     if (!l_jobj_network || !l_jobj_chains || !l_jobj_network_name) {
                         json_object_put(l_jobj_return);
                         json_object_put(l_jobj_network);
@@ -1023,9 +1091,8 @@ static int s_cli_net(int argc, char **argv, void **reply)
 
             json_object *l_jobj_networks = json_object_new_array();
             // show list of nets
-            dap_chain_net_item_t * l_net_item, *l_net_item_tmp;
-            HASH_ITER(hh, s_net_items, l_net_item, l_net_item_tmp){
-                json_object *l_jobj_network_name = json_object_new_string(l_net_item->name);
+            for (dap_chain_net_t *l_net = s_nets_by_name; l_net; l_net = l_net->hh.next) {
+                json_object *l_jobj_network_name = json_object_new_string(l_net->pub.name);
                 json_object_array_add(l_jobj_networks, l_jobj_network_name);
             }
             json_object_object_add(l_jobj_return, "networks", l_jobj_networks);
@@ -1644,11 +1711,11 @@ void dap_chain_net_deinit()
 {
     dap_link_manager_deinit();
     dap_chain_net_balancer_deinit();
-    dap_chain_net_item_t *l_current_item, *l_tmp;
-    HASH_ITER(hh, s_net_ids, l_current_item, l_tmp)
-        HASH_DELETE(hh2, s_net_ids, l_current_item);
-    HASH_ITER(hh, s_net_items, l_current_item, l_tmp) {
-        dap_chain_net_delete(l_current_item->chain_net);
+    dap_chain_net_t *l_net, *l_tmp;
+    HASH_ITER(hh2, s_nets_by_id, l_net, l_tmp) {
+        HASH_DEL(s_nets_by_name, l_net);
+        HASH_DELETE(hh2, s_nets_by_id, l_net);
+        dap_chain_net_delete(l_net);
     }
     dap_http_ban_list_client_deinit();
 }
@@ -1674,15 +1741,8 @@ void dap_chain_net_delete(dap_chain_net_t *a_net)
     dap_global_db_cluster_delete(PVT(a_net)->nodes_states);
     dap_global_db_cluster_delete(PVT(a_net)->common_orders);
 
-    dap_chain_net_item_t *l_net_item = NULL;
-    HASH_FIND(hh, s_net_items, a_net->pub.name, strlen(a_net->pub.name), l_net_item);
-    if (l_net_item) {
-        HASH_DEL(s_net_items, l_net_item);
-        HASH_DELETE(hh2, s_net_ids, l_net_item);
-        DAP_DELETE(l_net_item);
-    }
-    DAP_DEL_Z(PVT(a_net)->authorized_nodes_addrs);
-    DAP_DEL_Z(PVT(a_net)->node_info);
+    DAP_DELETE(PVT(a_net)->authorized_nodes_addrs);
+    DAP_DELETE(PVT(a_net)->node_info);
     if (a_net->pub.ledger) {
         dap_ledger_purge(a_net->pub.ledger, true);
         dap_ledger_handle_free(a_net->pub.ledger);
@@ -1693,22 +1753,15 @@ void dap_chain_net_delete(dap_chain_net_t *a_net)
 #ifdef DAP_LEDGER_TEST
 int dap_chain_net_test_init()
 {
-    dap_chain_net_id_t l_iddn = {0};
-    sscanf("0xFA0", "0x%16"DAP_UINT64_FORMAT_x, &l_iddn.uint64);
-    dap_chain_net_t *l_net = s_net_new(&l_iddn, "Snet", "TestCoin", "root");
-    
-    
-    // l_net->pub.id.uint64 = l_iddn.uint64;
-    // l_net->pub.native_ticker = "TestCoin";
-    // l_net->pub.name = "Snet";
-
-    dap_chain_net_item_t *l_net_item = DAP_NEW_Z(dap_chain_net_item_t);
-    dap_strncpy(l_net_item->name, "Snet", DAP_CHAIN_NET_NAME_MAX);
-    l_net_item->chain_net = l_net;
-    l_net_item->net_id.uint64 = l_net->pub.id.uint64;
-
-    HASH_ADD(hh2, s_net_ids, net_id, sizeof(l_net_item->net_id), l_net_item);
-
+    dap_chain_net_t *l_net = DAP_NEW_Z_SIZE( dap_chain_net_t, sizeof(dap_chain_net_t) + sizeof(dap_chain_net_pvt_t) );
+    PVT(l_net)->node_info = DAP_NEW_Z_SIZE(dap_chain_net_t, sizeof(dap_chain_node_info_t) + DAP_HOSTADDR_STRLEN + 1 );
+    l_net->pub.id.uint64 = 0xFA0;
+    strcpy(l_net->pub.name, "Snet");
+    l_net->pub.gdb_groups_prefix = (const char*)l_net->pub.name;
+    l_net->pub.native_ticker = "TestCoin";
+    PVT(l_net)->node_role.enums = NODE_ROLE_ROOT;
+    HASH_ADD(hh2, s_nets_by_id, pub.id, sizeof(dap_chain_net_id_t), l_net);
+    HASH_ADD_STR(s_nets_by_name, pub.name, l_net);
     return 0;
 }
 #endif
@@ -1725,76 +1778,36 @@ int s_net_init(const char *a_net_name, uint16_t a_acl_idx)
 {
     char *l_cfg_path = dap_strdup_printf("network/%s", a_net_name);
     dap_config_t *l_cfg = dap_config_open(l_cfg_path);
-    if (!l_cfg) {
-        log_it(L_ERROR,"Can't open default network config %s", l_cfg_path);
-        DAP_DEL_Z(l_cfg_path);
-        return -1;
-    }
     DAP_DELETE(l_cfg_path);
+    if ( !l_cfg )
+        return log_it(L_ERROR,"Can't open default network config %s", l_cfg_path), -1;
 
-    const char *l_net_name_str = dap_config_get_item_str(l_cfg , "general", "name");
-    const char *l_net_id_str = dap_config_get_item_str(l_cfg , "general", "id");
-    dap_chain_net_id_t l_net_id;
-    if(!l_net_name_str || !l_net_id_str || dap_chain_net_id_parse(l_net_id_str, &l_net_id)) {
-        log_it(L_ERROR,"Can't create l_net, can't read name or ID config");
-        return -1;
-    }
-
-    dap_chain_net_item_t *l_net_item_finded = NULL;
-    HASH_FIND_STR(s_net_items, l_net_name_str, l_net_item_finded);
-    if (!l_net_item_finded)
-        HASH_FIND(hh2, s_net_ids, &l_net_id, sizeof(l_net_id), l_net_item_finded);
-    if (l_net_item_finded) {
-        log_it(L_ERROR,"Can't create net %s ID %"DAP_UINT64_FORMAT_U", existed net %s ID %"DAP_UINT64_FORMAT_U" has the same name or ID.\n"\
-                "Please, fix your configs and restart node",
-                l_net_name_str, l_net_id.uint64, l_net_item_finded->name,
-                l_net_item_finded->net_id.uint64);
-        dap_config_close(l_cfg);
-        return -2;
-    }
-
-    dap_chain_net_t *l_net = s_net_new(
-                                        &l_net_id,
-                                        dap_config_get_item_str(l_cfg , "general" , "name" ),
-                                        dap_config_get_item_str(l_cfg , "general" , "native_ticker"),
-                                        dap_config_get_item_str(l_cfg , "general" , "node-role" )
-                                       );
-    if(!l_net) {
-        log_it(L_ERROR,"Can't create l_net");
-        dap_config_close(l_cfg);
-        return -1;
-    }
+    dap_chain_net_t *l_net = s_net_new(a_net_name, l_cfg);
+    if ( !l_net ) 
+        return log_it(L_ERROR,"Can't create net \"%s\"", a_net_name), dap_config_close(l_cfg), -1;
 
-    l_net->pub.gdb_groups_prefix = dap_strdup(
-                dap_config_get_item_str_default(l_cfg, "general", "gdb_groups_prefix",
-                                                dap_config_get_item_str(l_cfg, "general", "name")));
     dap_chain_net_pvt_t *l_net_pvt = PVT(l_net);
     l_net_pvt->load_mode = true;
     l_net_pvt->acl_idx = a_acl_idx;
-    // Bridged netwoks allowed to send transactions to
+    // Transaction can be sent to bridged networks
     uint16_t l_net_ids_count = 0;
     const char **l_bridged_net_ids = dap_config_get_array_str(l_cfg, "general", "bridged_network_ids", &l_net_ids_count);
-    for (uint16_t i = 0; i < l_net_ids_count; i++) {
-        dap_chain_net_id_t l_id;
-        if (dap_chain_net_id_parse(l_bridged_net_ids[i], &l_id) != 0)
-            continue;
-        l_net->pub.bridged_networks = dap_list_append(l_net->pub.bridged_networks, DAP_DUP(&l_id));
-    }
-
-    // Add network to the list
-    dap_chain_net_item_t *l_net_item = DAP_NEW_Z(dap_chain_net_item_t);
-    if (!l_net_item) {
-        log_it(L_CRITICAL, "%s", c_error_memory_alloc);
-        dap_chain_net_delete(l_net);
-        dap_config_close(l_cfg);
-        return -4;
+    if (l_net_ids_count) {
+        l_net->pub.bridged_networks = DAP_NEW_Z_COUNT(dap_chain_net_id_t, l_net_ids_count);
+        unsigned i, j;
+        for (i = 0, j = 0; i < l_net_ids_count; ++i) {
+            if (dap_chain_net_id_parse(l_bridged_net_ids[i], &l_net->pub.bridged_networks[j]) != 0) {
+                log_it(L_ERROR, "Can't add invalid net id \"%s\" to bridged net list of \"%s\"",
+                                l_bridged_net_ids[i], a_net_name);
+                continue;
+            }   
+            ++j;
+        }
+        l_net->pub.bridged_networks = j && j < i
+            ? DAP_REALLOC_COUNT(l_net->pub.bridged_networks, j)
+            : ( DAP_DELETE(l_net->pub.bridged_networks), NULL );
+        l_net->pub.bridged_networks_count = j;
     }
-    dap_strncpy(l_net_item->name, dap_config_get_item_str(l_cfg, "general", "name"), DAP_CHAIN_NET_NAME_MAX);
-    l_net_item->chain_net = l_net;
-    l_net_item->net_id.uint64 = l_net->pub.id.uint64;
-    
-    HASH_ADD_STR(s_net_items, name, l_net_item);
-    HASH_ADD(hh2, s_net_ids, net_id, sizeof(l_net_item->net_id), l_net_item);
 
     const char **l_permanent_nodes_addrs = dap_config_get_array_str(l_cfg, "general", "permanent_nodes_addrs", &l_net_pvt->permanent_links_count);
     if (l_net_pvt->permanent_links_count) {
@@ -1824,27 +1837,25 @@ int s_net_init(const char *a_net_name, uint16_t a_acl_idx)
     uint16_t l_permalink_hosts_count = 0, i, e;
     const char **l_permanent_links_hosts = dap_config_get_array_str(l_cfg, "general", "permanent_nodes_hosts", &l_permalink_hosts_count);
     for (i = 0, e = 0; i < dap_min(l_permalink_hosts_count, l_net_pvt->permanent_links_count); ++i) {
-        char l_host[DAP_HOSTADDR_STRLEN + 1] = { '\0' }; uint16_t l_port = 0;
-        struct sockaddr_storage l_saddr;
-        if ( dap_net_parse_config_address(l_permanent_links_hosts[i], l_host, &l_port, NULL, NULL) < 0
-            || dap_net_resolve_host(l_host, dap_itoa(l_port), false, &l_saddr, NULL) < 0 )
-        {
+        struct request_link_info *l_tmp = s_net_resolve_host( l_permanent_links_hosts[i] );
+        if ( !l_tmp ) {
             log_it(L_ERROR, "Incorrect address \"%s\", fix \"%s\" network config"
                             "or check internet connection and restart node",
                             a_net_name, l_permanent_links_hosts[i]);
             ++e;
             continue;
         }
-        l_net_pvt->permanent_links[i]->uplink_port = l_port;
-        dap_strncpy(l_net_pvt->permanent_links[i]->uplink_addr, l_host, DAP_HOSTADDR_STRLEN);
+        l_net_pvt->permanent_links[i]->uplink_port = l_tmp->port;
+        dap_strncpy(l_net_pvt->permanent_links[i]->uplink_addr, l_tmp->addr, DAP_HOSTADDR_STRLEN);
+        DAP_DELETE(l_tmp);
     }
     if ( i && (e == i) ) {
         log_it(L_ERROR, "%d / %d permanent links are invalid or can't be accessed, fix \"%s\""
                         "network config or check internet connection and restart node",
                         e, i, a_net_name);
-        dap_chain_net_delete(l_net);
-        dap_config_close(l_cfg);
-        return -16;
+        //dap_chain_net_delete(l_net);
+        //dap_config_close(l_cfg);
+        //return -16;
     }
 
     const char **l_authorized_nodes_addrs = dap_config_get_array_str(l_cfg, "general", "authorized_nodes_addrs", &l_net_pvt->authorized_nodes_count);
@@ -1867,41 +1878,28 @@ int s_net_init(const char *a_net_name, uint16_t a_acl_idx)
          l_seed_nodes_hosts  = dap_config_get_array_str(l_cfg, "general", "bootstrap_hosts", &l_net_pvt->seed_nodes_count);
     if (!l_net_pvt->seed_nodes_count)
         log_it(L_WARNING, "Can't read seed nodes addresses, work with local balancer only");
-    else if (!(l_net_pvt->seed_nodes_info = DAP_NEW_Z_COUNT(struct request_link_info *, l_net_pvt->seed_nodes_count))) {
+    else if (!( l_net_pvt->seed_nodes_info = DAP_NEW_Z_COUNT(struct request_link_info*, l_net_pvt->seed_nodes_count) )) {
         log_it(L_CRITICAL, "%s", c_error_memory_alloc);
         dap_chain_net_delete(l_net);
         dap_config_close(l_cfg);
         return -4;
     }
     for (i = 0, e = 0; i < l_net_pvt->seed_nodes_count; ++i) {
-        char l_host[DAP_HOSTADDR_STRLEN + 1] = { '\0' }; uint16_t l_port = 0;
-        struct sockaddr_storage l_saddr;
-        if ( dap_net_parse_config_address(l_seed_nodes_hosts[i], l_host, &l_port, NULL, NULL) < 0
-            || dap_net_resolve_host(l_host, dap_itoa(l_port), false, &l_saddr, NULL) < 0)
-        {
+        if (!( l_net_pvt->seed_nodes_info[i] = s_net_resolve_host(l_seed_nodes_hosts[i]) )) {
             log_it(L_ERROR, "Incorrect address \"%s\", fix \"%s\" network config"
                             "or check internet connection and restart node",
                             a_net_name, l_seed_nodes_hosts[i]);
             ++e;
             continue;
         }
-        l_net_pvt->seed_nodes_info[i] = DAP_NEW_Z(struct request_link_info);
-        if (!l_net_pvt->seed_nodes_info[i]) {
-            log_it(L_CRITICAL, "%s", c_error_memory_alloc);
-            dap_chain_net_delete(l_net);
-            dap_config_close(l_cfg);
-            return -4;
-        }
-        l_net_pvt->seed_nodes_info[i]->port = l_port;
-        dap_strncpy(l_net_pvt->seed_nodes_info[i]->addr, l_host, DAP_HOSTADDR_STRLEN);
     }
     if ( i && (e == i) ) {
         log_it(L_ERROR, "%d / %d seed links are invalid or can't be accessed, fix \"%s\""
                         "network config or check internet connection and restart node",
                         e, i, a_net_name);
-        dap_chain_net_delete(l_net);
-        dap_config_close(l_cfg);
-        return -16;
+        //dap_chain_net_delete(l_net);
+        //dap_config_close(l_cfg);
+        //return -16;
     }
 
     /* *** Chains init by configs *** */
@@ -2027,7 +2025,6 @@ int s_net_init(const char *a_net_name, uint16_t a_acl_idx)
     l_net->pub.ledger = dap_ledger_create(l_net, l_ledger_flags);
     // Decrees initializing
     dap_chain_net_decree_init(l_net);
-    l_net->pub.config = l_cfg;
     return 0;
 }
 
@@ -2199,7 +2196,7 @@ bool s_net_load(void *a_arg)
                                                         DAP_CLUSTER_TYPE_EMBEDDED);
     DAP_DELETE(l_gdb_groups_mask);
     // Nodes and its aliases cluster
-    l_net->pub.gdb_nodes = dap_strdup_printf("%s.nodes.list",l_net->pub.gdb_groups_prefix);
+    snprintf(l_net->pub.gdb_nodes, sizeof(l_net->pub.gdb_nodes), "%s.%s", l_net->pub.gdb_groups_prefix, s_gdb_nodes_postfix);
     l_net_pvt->nodes_cluster = dap_global_db_cluster_add(dap_global_db_instance_get_default(),
                                                          l_net->pub.name, dap_guuid_compose(l_net->pub.id.uint64, 0),
                                                          l_net->pub.gdb_nodes, 0, true,
@@ -2355,22 +2352,15 @@ bool dap_chain_net_remove_validator_from_clusters(dap_chain_t *a_chain, dap_stre
 }
 
 size_t dap_chain_net_count() {
-    return HASH_COUNT(s_net_items);
+    return HASH_COUNT(s_nets_by_name);
 }
 
 dap_chain_net_t *dap_chain_net_iter_start() {
-    dap_return_val_if_pass(!s_net_items, NULL);
-    return s_net_items->chain_net;
+    return s_nets_by_name;
 }
 
 dap_chain_net_t *dap_chain_net_iter_next(dap_chain_net_t *a_it) {
-    if (!a_it)
-        return NULL;
-    dap_chain_net_item_t *l_net_sought = NULL;
-    HASH_FIND_STR(s_net_items, a_it->pub.name, l_net_sought);
-    return l_net_sought && l_net_sought->hh.next
-        ? ((dap_chain_net_item_t*)l_net_sought->hh.next)->chain_net 
-        : NULL;
+    return a_it ? a_it->hh.next : NULL;
 }
 
 /**
@@ -2380,10 +2370,10 @@ dap_chain_net_t *dap_chain_net_iter_next(dap_chain_net_t *a_it) {
  */
 dap_chain_net_t *dap_chain_net_by_name(const char *a_name)
 {
-    dap_chain_net_item_t *l_net_item = NULL;
+    dap_chain_net_t *l_net = NULL;
     if (a_name)
-        HASH_FIND(hh, s_net_items, a_name, strlen(a_name), l_net_item);
-    return l_net_item ? l_net_item->chain_net : NULL;
+        HASH_FIND_STR(s_nets_by_name, a_name, l_net);
+    return l_net;
 }
 
 /**
@@ -2404,9 +2394,9 @@ dap_ledger_t * dap_ledger_by_net_name( const char * a_net_name)
  */
 dap_chain_net_t *dap_chain_net_by_id(dap_chain_net_id_t a_id)
 {
-    dap_chain_net_item_t *l_net_item = NULL;
-    HASH_FIND(hh2, s_net_ids, &a_id, sizeof(a_id), l_net_item);
-    return l_net_item ? l_net_item->chain_net : NULL;
+    dap_chain_net_t *l_net = NULL;
+    HASH_FIND(hh2, s_nets_by_id, &a_id, sizeof(a_id), l_net);
+    return l_net;
 }
 
 /**
@@ -2697,14 +2687,13 @@ static bool s_net_check_acl(dap_chain_net_t *a_net, dap_chain_hash_fast_t *a_pke
  */
 static uint8_t *s_net_set_acl(dap_chain_hash_fast_t *a_pkey_hash)
 {
-    if (!HASH_COUNT(s_net_items))
+    uint16_t l_cnt = HASH_COUNT(s_nets_by_name);
+    if ( !l_cnt )
         return NULL;
-    uint8_t *l_ret = DAP_NEW_Z_SIZE(uint8_t, HASH_COUNT(s_net_items));
+    uint8_t *l_ret = DAP_NEW_Z_COUNT(uint8_t, l_cnt);
     unsigned i = 0;
-    dap_chain_net_item_t *l_net_cur = NULL, *l_net_tmp = NULL;
-    HASH_ITER(hh, s_net_items, l_net_cur, l_net_tmp) {
-        l_ret[i++] = s_net_check_acl(l_net_cur->chain_net, a_pkey_hash);
-    }
+    for (dap_chain_net_t *l_net = s_nets_by_name; l_net; l_net = l_net->hh.next)
+        l_ret[i++] = s_net_check_acl(l_net, a_pkey_hash);
     return l_ret;
 }
 
@@ -2783,7 +2772,7 @@ dap_list_t* dap_chain_datum_list(dap_chain_net_t *a_net, dap_chain_t *a_chain, d
  * @param a_datum_size
  * @return
  */
-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)
+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, void *a_datum_index_data)
 {
     size_t l_datum_data_size = a_datum->header.data_size;
     if (a_datum_size < l_datum_data_size + sizeof(a_datum->header)) {
@@ -2792,6 +2781,8 @@ int dap_chain_datum_add(dap_chain_t *a_chain, dap_chain_datum_t *a_datum, size_t
         return -101;
     }
     dap_ledger_t *l_ledger = dap_chain_net_by_id(a_chain->net_id)->pub.ledger;
+    if ( dap_ledger_datum_is_blacklisted(l_ledger, *a_datum_hash) )
+        return log_it(L_ERROR, "Datum is blackilsted"), -100;
     switch (a_datum->header.type_id) {
         case DAP_CHAIN_DATUM_DECREE: {
             dap_chain_datum_decree_t *l_decree = (dap_chain_datum_decree_t *)a_datum->data;
@@ -2823,8 +2814,8 @@ int dap_chain_datum_add(dap_chain_t *a_chain, dap_chain_datum_t *a_datum, size_t
             if (l_tx_size != l_datum_data_size) {
                 log_it(L_WARNING, "Corrupted transaction, datum size %zd is not equal to size of TX %zd", l_datum_data_size, l_tx_size);
                 return -102;
-            }
-            return dap_ledger_tx_load(l_ledger, l_tx, a_datum_hash);
+            }            
+            return dap_ledger_tx_load(l_ledger, l_tx, a_datum_hash, (dap_ledger_datum_iter_data_t*)a_datum_index_data);
         }
         case DAP_CHAIN_DATUM_CA:
             return dap_cert_chain_file_save(a_datum, a_chain->net_name);
@@ -2935,8 +2926,8 @@ uint256_t dap_chain_net_get_reward(dap_chain_net_t *a_net, uint64_t a_block_num)
 
 void dap_chain_net_announce_addr_all()
 {
-    for (dap_chain_net_item_t *it = s_net_items; it; it = it->hh.next)
-        dap_chain_net_announce_addr(it->chain_net);
+    for (dap_chain_net_t *net = s_nets_by_name; net; net = net->hh.next)
+        dap_chain_net_announce_addr(net);
 }
 
 void dap_chain_net_announce_addr(dap_chain_net_t *a_net)
@@ -2944,11 +2935,12 @@ void dap_chain_net_announce_addr(dap_chain_net_t *a_net)
     dap_return_if_fail(a_net);
     dap_chain_net_pvt_t *l_net_pvt = PVT(a_net);
     if ( l_net_pvt->node_info->ext_port ) {
-        dap_chain_net_node_list_request(a_net, l_net_pvt->node_info->ext_port, false, 'a');
         log_it(L_INFO, "Announce our node address "NODE_ADDR_FP_STR" [ %s : %u ] in net %s",
                NODE_ADDR_FP_ARGS_S(g_node_addr),
                l_net_pvt->node_info->ext_host,
                l_net_pvt->node_info->ext_port, a_net->pub.name);
+        dap_chain_net_node_list_request(a_net, l_net_pvt->node_info->ext_port, true, 'a');
+        
     }
 }
 
@@ -2998,19 +2990,15 @@ static int s_net_try_online(dap_chain_net_t *a_net)
 void dap_chain_net_try_online_all() {
     int32_t l_ret = 0;
 
-    if(!HASH_COUNT(s_net_items)){
-        log_it(L_ERROR, "Can't find any nets");
-        return;
-    }
-    if (!dap_config_get_item_bool_default(g_config ,"general", "auto_online", false)) {
-        log_it(L_DEBUG, "Auto online is off in config");
-        return;
-    }
-    dap_chain_net_item_t *l_net_items_current = NULL, *l_net_items_tmp = NULL;
-    HASH_ITER(hh, s_net_items, l_net_items_current, l_net_items_tmp) {
-        if( (l_ret = s_net_try_online(l_net_items_current->chain_net)) ) {
-            log_it(L_ERROR, "Can't try online state for net %s.  Finished with (%d) error code.", l_net_items_current->name, l_ret);
-        }
+    if( !HASH_COUNT(s_nets_by_name) )
+        return log_it(L_ERROR, "Can't find any nets");
+
+    if ( !dap_config_get_item_bool_default(g_config ,"general", "auto_online", false) )
+        return log_it(L_DEBUG, "Auto online is off in config");
+
+    for (dap_chain_net_t *net = s_nets_by_name; net; net = net->hh.next) {
+        if (( l_ret = s_net_try_online(net) ))
+            log_it(L_ERROR, "Can't try online state for net %s.  Finished with (%d) error code.", net, l_ret);
     }
 }
 
@@ -3063,9 +3051,10 @@ static void s_ch_in_pkt_callback(dap_stream_ch_t *a_ch, uint8_t a_type, const vo
         if (!dap_hash_fast_compare(&l_miss_info->missed_hash, &l_net_pvt->sync_context.requested_atom_hash)) {
             char l_missed_hash_str[DAP_HASH_FAST_STR_SIZE];
             dap_hash_fast_to_str(&l_miss_info->missed_hash, l_missed_hash_str, DAP_HASH_FAST_STR_SIZE);
-            log_it(L_WARNING, "Get irrelevant chain sync MISSED packet with missed hash %s, but requested hash is %s",
+            log_it(L_WARNING, "Get irrelevant chain sync MISSED packet with missed hash %s, but requested hash is %s. Net %s chain %s",
                                                                         l_missed_hash_str,
-                                                                        dap_hash_fast_to_str_static(&l_net_pvt->sync_context.requested_atom_hash));
+                                                                        dap_hash_fast_to_str_static(&l_net_pvt->sync_context.requested_atom_hash),
+                                                                        l_net->pub.name, l_net_pvt->sync_context.cur_chain->name);
             dap_stream_ch_write_error_unsafe(a_ch, l_net->pub.id,
                                              l_net_pvt->sync_context.cur_chain->id,
                                              l_net_pvt->sync_context.cur_cell
@@ -3132,10 +3121,11 @@ static void s_ch_in_pkt_callback(dap_stream_ch_t *a_ch, uint8_t a_type, const vo
 
 static void s_ch_out_pkt_callback(dap_stream_ch_t *a_ch, uint8_t a_type, const void *a_data, size_t a_data_size, void *a_arg)
 {
-    debug_if(s_debug_more, L_DEBUG, "Sent OUT sync packet type %hhu size %zu to addr " NODE_ADDR_FP_STR,
-                                                           a_type, a_data_size, NODE_ADDR_FP_ARGS_S(a_ch->stream->node));
+    
     dap_chain_net_t *l_net = a_arg;
     dap_chain_net_pvt_t *l_net_pvt = PVT(l_net);
+    if (!l_net_pvt->sync_context.cur_chain)
+        return;
     switch (a_type) {
     case DAP_CHAIN_CH_PKT_TYPE_ERROR:
         l_net_pvt->sync_context.cur_chain->state = CHAIN_SYNC_STATE_ERROR;
@@ -3144,6 +3134,8 @@ static void s_ch_out_pkt_callback(dap_stream_ch_t *a_ch, uint8_t a_type, const v
         break;
     }
     l_net_pvt->sync_context.stage_last_activity = dap_time_now();
+    debug_if(s_debug_more, L_DEBUG, "Sent OUT sync packet type %hhu size %zu to addr " NODE_ADDR_FP_STR,
+                                    a_type, a_data_size, NODE_ADDR_FP_ARGS_S(a_ch->stream->node));
 }
 
 
@@ -3251,6 +3243,12 @@ static void s_sync_timer_callback(void *a_arg)
         l_net_pvt->sync_context.cur_chain->state = CHAIN_SYNC_STATE_SYNCED;
         return;
     }
+    // if sync more than 3 mins after online state, change state to SYNC
+    if (l_net_pvt->state == NET_STATE_ONLINE && l_net_pvt->sync_context.state == CHAIN_SYNC_STATE_WAITING &&
+        dap_time_now() - l_net_pvt->sync_context.stage_last_activity > l_net_pvt->sync_context.sync_idle_time ) {
+        l_net_pvt->state = NET_STATE_SYNC_CHAINS;
+        s_net_states_proc(l_net);
+    }
 
     l_net_pvt->sync_context.cur_cell = l_net_pvt->sync_context.cur_chain->cells;
     l_net_pvt->sync_context.cur_chain->state = CHAIN_SYNC_STATE_WAITING;
@@ -3365,6 +3363,20 @@ int dap_chain_net_state_go_to(dap_chain_net_t *a_net, dap_chain_net_state_t a_ne
         dap_link_manager_set_net_condition(a_net->pub.id.uint64, true);
         for (uint16_t i = 0; i < PVT(a_net)->permanent_links_count; ++i) {
             dap_link_info_t *l_permalink_info = PVT(a_net)->permanent_links[i];
+            if ( !*l_permalink_info->uplink_addr ) {
+                // Unresolved before? Let's try again
+                const char **l_permanent_nodes_addrs = dap_config_get_array_str(a_net->pub.config, "general", "permanent_nodes_addrs", NULL);
+                struct request_link_info *l_tmp = s_net_resolve_host(l_permanent_nodes_addrs[i]);
+                if (l_tmp) {
+                    l_permalink_info->uplink_port = l_tmp->port;
+                    dap_strncpy(l_permalink_info->uplink_addr, l_tmp->addr, DAP_HOSTADDR_STRLEN);
+                    DAP_DELETE(l_tmp);
+                } else {
+                    log_it(L_ERROR, "Can't resolve permanent link address %s for net %s, possibly an internet connection issue",
+                                    l_permanent_nodes_addrs[i], a_net->pub.name);
+                    continue;
+                }
+            }
             if (dap_chain_net_link_add(a_net, &l_permalink_info->node_addr, l_permalink_info->uplink_addr, l_permalink_info->uplink_port)) {
                 log_it(L_ERROR, "Can't create permanent link to addr " NODE_ADDR_FP_STR, NODE_ADDR_FP_ARGS_S(l_permalink_info->node_addr));
                 continue;
@@ -3386,4 +3398,4 @@ DAP_INLINE dap_chain_net_state_t dap_chain_net_get_target_state(dap_chain_net_t
     return PVT(a_net)->state_target;
 }
 
-/*------------------------------------State machine block end---------------------------------*/
+/*------------------------------------State machine block end---------------------------------*/
\ No newline at end of file
diff --git a/modules/net/dap_chain_net_anchor.c b/modules/net/dap_chain_net_anchor.c
index 5b710283932c645bf0fef6bd8888d2943798753c..84984130f327ab2764950032315e9062643e77d2 100644
--- a/modules/net/dap_chain_net_anchor.c
+++ b/modules/net/dap_chain_net_anchor.c
@@ -168,7 +168,7 @@ int dap_chain_net_anchor_load(dap_chain_datum_anchor_t * a_anchor, dap_chain_t *
         return -109;
     }
 
-    if ((ret_val = dap_chain_net_decree_apply(&l_hash, NULL, a_chain)) != 0){
+    if ((ret_val = dap_chain_net_decree_apply(&l_hash, NULL, a_chain, true)) != 0){
         debug_if(s_debug_more, L_WARNING, "Decree applying failed");
         return ret_val;
     }
@@ -315,7 +315,7 @@ int dap_chain_net_anchor_unload(dap_chain_datum_anchor_t * a_anchor, dap_chain_t
                         return -109;
                     }
 
-                    if((ret_val = dap_chain_net_decree_apply(&l_hash, NULL, a_chain))!=0){
+                    if((ret_val = dap_chain_net_decree_apply(&l_hash, NULL, a_chain, true))!=0){
                         log_it(L_WARNING,"Decree applying failed");
                         return ret_val;
                     }
@@ -351,7 +351,7 @@ int dap_chain_net_anchor_unload(dap_chain_datum_anchor_t * a_anchor, dap_chain_t
                         log_it(L_WARNING,"Can not find datum hash in anchor data");
                         return -109;
                     }
-                    if((ret_val = dap_chain_net_decree_apply(&l_hash, NULL, a_chain))!=0){
+                    if((ret_val = dap_chain_net_decree_apply(&l_hash, NULL, a_chain, true))!=0){
                         log_it(L_WARNING,"Decree applying failed");
                         return ret_val;
                     }
@@ -368,7 +368,7 @@ int dap_chain_net_anchor_unload(dap_chain_datum_anchor_t * a_anchor, dap_chain_t
                         log_it(L_WARNING,"Can not find datum hash in anchor data");
                         return -109;
                     }
-                    if((ret_val = dap_chain_net_decree_apply(&l_hash, NULL, a_chain))!=0){
+                    if((ret_val = dap_chain_net_decree_apply(&l_hash, NULL, a_chain, true))!=0){
                         log_it(L_WARNING,"Decree applying failed");
                         return ret_val;
                     }
@@ -389,7 +389,7 @@ int dap_chain_net_anchor_unload(dap_chain_datum_anchor_t * a_anchor, dap_chain_t
                         return -109;
                     }
 
-                    if((ret_val = dap_chain_net_decree_apply(&l_hash, NULL, a_chain))!=0){
+                    if((ret_val = dap_chain_net_decree_apply(&l_hash, NULL, a_chain, true))!=0){
                         log_it(L_WARNING,"Decree applying failed");
                         return ret_val;
                     }
diff --git a/modules/net/dap_chain_net_balancer.c b/modules/net/dap_chain_net_balancer.c
index 1460bce84e96d0110971b376ba051e6a47e98653..02dd26c1ad252ccc30f28083cc55c8505ee605c8 100644
--- a/modules/net/dap_chain_net_balancer.c
+++ b/modules/net/dap_chain_net_balancer.c
@@ -44,18 +44,8 @@ typedef struct dap_balancer_request_info {
     UT_hash_handle hh;
 } dap_balancer_request_info_t;
 
-typedef struct dap_balancer_link_request {
-    const char* host_addr;
-    uint16_t host_port;
-    dap_chain_net_t *net;
-    dap_worker_t *worker;
-    uint16_t required_links_count;
-    dap_balancer_request_info_t *request_info;
-} dap_balancer_link_request_t;
-
 static_assert(sizeof(dap_chain_net_links_t) + sizeof(dap_chain_node_info_old_t) < DAP_BALANCER_MAX_REPLY_SIZE, "DAP_BALANCER_MAX_REPLY_SIZE cannot accommodate information minimum about 1 link");
 static const size_t s_max_links_response_count = (DAP_BALANCER_MAX_REPLY_SIZE - sizeof(dap_chain_net_links_t)) / sizeof(dap_chain_node_info_old_t);
-static const dap_time_t s_request_period = 5; // sec
 static dap_balancer_request_info_t* s_request_info_items = NULL;
 
 /**
@@ -87,22 +77,30 @@ static dap_chain_net_links_t *s_get_ignored_node_addrs(dap_chain_net_t *a_net, s
     size_t
         l_size = 0,
         l_uplinks_count = 0,
+        l_downlinks_count = 0,
+        l_links_count = 0,
         l_low_availability_count = 0;
     const dap_stream_node_addr_t
         *l_curr_addr = &dap_chain_net_get_my_node_info(a_net)->address,
-        *l_uplinks = dap_link_manager_get_net_links_addrs(a_net->pub.id.uint64, &l_uplinks_count, NULL, true),
+        *l_links = dap_link_manager_get_net_links_addrs(a_net->pub.id.uint64, &l_uplinks_count, &l_downlinks_count, false),
         *l_low_availability = dap_link_manager_get_ignored_addrs(&l_low_availability_count, a_net->pub.id.uint64);
-    if(!l_curr_addr->uint64 && !l_uplinks && !l_low_availability) {
+        l_links_count = l_uplinks_count + l_downlinks_count;
+    if(!l_curr_addr->uint64 && !l_links && !l_low_availability) {
         log_it(L_WARNING, "Error forming ignore list in net %s, please check, should be minimum self addr", a_net->pub.name);
         return NULL;
     }
+    l_size = sizeof(dap_chain_net_links_t) + sizeof(dap_stream_node_addr_t) * (l_links_count + l_low_availability_count + 1);
+    // memory alloc
+    dap_chain_net_links_t *l_ret = NULL;
+    DAP_NEW_Z_SIZE_RET_VAL(l_ret, dap_chain_net_links_t, l_size, NULL, l_links, l_low_availability);
+    l_ret->count_node = l_links_count + l_low_availability_count + 1;
     if (dap_log_level_get() <= L_DEBUG ) {
         char *l_ignored_str = NULL;
-        DAP_NEW_Z_SIZE_RET_VAL(l_ignored_str, char, 50 * (l_uplinks_count + l_low_availability_count + 1) + 200 + strlen(a_net->pub.name), NULL, l_uplinks, l_low_availability);
-        sprintf(l_ignored_str + strlen(l_ignored_str), "Second %zu nodes will be ignored in balancer links preparing in net %s:\n\tSelf:\n\t\t"NODE_ADDR_FP_STR"\n", l_uplinks_count + l_low_availability_count + 1, a_net->pub.name, NODE_ADDR_FP_ARGS(l_curr_addr));
-        sprintf(l_ignored_str + strlen(l_ignored_str), "\tUplinks (%zu):\n", l_uplinks_count);
-        for (size_t i = 0; i < l_uplinks_count; ++i) {
-            sprintf(l_ignored_str + strlen(l_ignored_str), "\t\t"NODE_ADDR_FP_STR"\n", NODE_ADDR_FP_ARGS(l_uplinks + i));
+        DAP_NEW_Z_SIZE_RET_VAL(l_ignored_str, char, 50 * (l_ret->count_node) + 200 + strlen(a_net->pub.name), NULL, l_links, l_low_availability);
+        sprintf(l_ignored_str + strlen(l_ignored_str), "Second %zu nodes will be ignored in balancer links preparing in net %s:\n\tSelf:\n\t\t"NODE_ADDR_FP_STR"\n", l_ret->count_node, a_net->pub.name, NODE_ADDR_FP_ARGS(l_curr_addr));
+        sprintf(l_ignored_str + strlen(l_ignored_str), "\tActive links (%zu):\n", l_links_count);
+        for (size_t i = 0; i < l_links_count; ++i) {
+            sprintf(l_ignored_str + strlen(l_ignored_str), "\t\t"NODE_ADDR_FP_STR"\n", NODE_ADDR_FP_ARGS(l_links + i));
         }
         sprintf(l_ignored_str + strlen(l_ignored_str), "\tCooling (%zu):\n", l_low_availability_count);
         for (size_t i = 0; i < l_low_availability_count; ++i) {
@@ -111,20 +109,15 @@ static dap_chain_net_links_t *s_get_ignored_node_addrs(dap_chain_net_t *a_net, s
         log_it(L_DEBUG, "%s", l_ignored_str);
         DAP_DELETE(l_ignored_str);
     }
-    l_size = sizeof(dap_chain_net_links_t) + sizeof(dap_stream_node_addr_t) * (l_uplinks_count + l_low_availability_count + 1);
-// memory alloc
-    dap_chain_net_links_t *l_ret = NULL;
-    DAP_NEW_Z_SIZE_RET_VAL(l_ret, dap_chain_net_links_t, l_size, NULL, l_uplinks, l_low_availability);
 // func work
     memcpy(l_ret->nodes_info, l_curr_addr, sizeof(dap_stream_node_addr_t));
-    if(l_uplinks)
-        memcpy(l_ret->nodes_info + sizeof(dap_stream_node_addr_t), l_uplinks, l_uplinks_count * sizeof(dap_stream_node_addr_t));
+    if(l_links)
+        memcpy(l_ret->nodes_info + sizeof(dap_stream_node_addr_t), l_links, l_links_count * sizeof(dap_stream_node_addr_t));
     if(l_low_availability)
-        memcpy(l_ret->nodes_info + (l_uplinks_count + 1) * sizeof(dap_stream_node_addr_t), l_low_availability, l_low_availability_count * sizeof(dap_stream_node_addr_t));
-    l_ret->count_node = l_uplinks_count + l_low_availability_count + 1;
+        memcpy(l_ret->nodes_info + (l_links_count + 1) * sizeof(dap_stream_node_addr_t), l_low_availability, l_low_availability_count * sizeof(dap_stream_node_addr_t));
     if (a_size)
         *a_size = l_size;
-    DAP_DEL_MULTY(l_uplinks, l_low_availability);
+    DAP_DEL_MULTY(l_links, l_low_availability);
     return l_ret;
 }
 
@@ -465,66 +458,53 @@ dap_link_info_t *dap_chain_net_balancer_dns_issue_link(const char *a_net_name)
  * @param a_balancer_type - http or DNS
  * @return if ok 0, error - other
  */
-int dap_chain_net_balancer_request(dap_chain_net_t *a_net, const char *a_host_addr, uint16_t a_host_port, int a_balancer_type)
+void dap_chain_net_balancer_request(void *a_arg)
 {
 // sanity check
-    dap_return_val_if_pass(!a_net, -1);
+    dap_return_if_fail(a_arg);
+    dap_balancer_link_request_t *l_arg = (dap_balancer_link_request_t*)a_arg;
 // period request check
     dap_balancer_request_info_t *l_item = NULL;
-    HASH_FIND(hh, s_request_info_items, &a_net->pub.id, sizeof(a_net->pub.id), l_item);
+    HASH_FIND(hh, s_request_info_items, &l_arg->net->pub.id, sizeof(l_arg->net->pub.id), l_item);
     if (!l_item) {
-        DAP_NEW_Z_RET_VAL(l_item, dap_balancer_request_info_t, -2, NULL);
-        l_item->net_id = a_net->pub.id;
+        DAP_NEW_Z_RET(l_item, dap_balancer_request_info_t, NULL);
+        l_item->net_id = l_arg->net->pub.id;
         HASH_ADD(hh, s_request_info_items, net_id, sizeof(l_item->net_id), l_item);
     }
-    if (l_item->request_time + DAP_CHAIN_NET_BALANCER_REQUEST_DELAY > dap_time_now()) {
-        log_it(L_DEBUG, "Who understands life, he is in no hurry. Dear %s, please wait few seconds", a_net->pub.name);
-        return 0;
-    }
+    if (l_item->request_time + DAP_CHAIN_NET_BALANCER_REQUEST_DELAY > dap_time_now())
+        return log_it(L_DEBUG, "Who understands life, he is in no hurry. Dear %s, please wait few seconds", l_arg->net->pub.name);
 // preparing to request
     size_t
         l_ignored_addrs_size = 0,
-        l_required_links_count = dap_link_manager_needed_links_count(a_net->pub.id.uint64);
+        l_required_links_count = dap_link_manager_needed_links_count(l_arg->net->pub.id.uint64);
     dap_chain_net_links_t
-        *l_ignored_addrs = s_get_ignored_node_addrs(a_net, &l_ignored_addrs_size),
-        *l_links = s_get_node_addrs(a_net, l_required_links_count, l_ignored_addrs, false);
+        *l_ignored_addrs = s_get_ignored_node_addrs(l_arg->net, &l_ignored_addrs_size),
+        *l_links = s_get_node_addrs(l_arg->net, l_required_links_count, l_ignored_addrs, false);
 // links from local GDB
     if (l_links) {
-        log_it(L_INFO, "%"DAP_UINT64_FORMAT_U" links successful prepared from global-db in net %s", l_links->count_node, a_net->pub.name);
-        s_balancer_link_prepare_success(a_net, l_links, NULL, 0);
-        if (l_links->count_node >= l_required_links_count) {
-            DAP_DEL_MULTY(l_ignored_addrs, l_links);
-            return 0;
-        }
+        log_it(L_INFO, "%"DAP_UINT64_FORMAT_U" links successful prepared from global-db in net %s", l_links->count_node, l_arg->net->pub.name);
+        s_balancer_link_prepare_success(l_arg->net, l_links, NULL, 0);
+        if (l_links->count_node >= l_required_links_count)
+            return DAP_DEL_MULTY(l_ignored_addrs, l_links);
         l_required_links_count -= l_links->count_node;
         DAP_DELETE(l_links);
     }
 // links from http balancer request
-    if (!a_host_addr || !a_host_port) {
-        log_it(L_INFO, "Can't read seed nodes addresses in net %s, work with local balancer only", a_net->pub.name);
-        DAP_DEL_Z(l_ignored_addrs);
-        return 0;
-    }
-    dap_balancer_link_request_t *l_balancer_request = NULL;
-    DAP_NEW_Z_RET_VAL(l_balancer_request, dap_balancer_link_request_t, -4, NULL);
-    *l_balancer_request = (dap_balancer_link_request_t) {
-        .host_addr = a_host_addr,
-        .host_port = a_host_port,
-        .net = a_net,
-        .worker = dap_worker_get_current(),
-        .required_links_count = l_required_links_count,
-        .request_info = l_item
-    };
+    if (!l_arg->host_addr || !*l_arg->host_addr || !l_arg->host_port)
+        return DAP_DELETE(l_ignored_addrs), log_it(L_INFO, "Can't read seed nodes addresses in net %s, work with local balancer only",
+                                                            l_arg->net->pub.name);
+    l_arg->worker = dap_worker_get_current();
+    l_arg->required_links_count = l_required_links_count;
+    l_arg->request_info = l_item;
     log_it(L_DEBUG, "Start balancer %s request to %s:%u in net %s",
-           dap_chain_net_balancer_type_to_str(a_balancer_type), l_balancer_request->host_addr, l_balancer_request->host_port, a_net->pub.name);
+                    dap_chain_net_balancer_type_to_str(l_arg->type), l_arg->host_addr, l_arg->host_port, l_arg->net->pub.name);
     
-    int ret;
-    if (a_balancer_type == DAP_CHAIN_NET_BALANCER_TYPE_HTTP) {
+    if (l_arg->type == DAP_CHAIN_NET_BALANCER_TYPE_HTTP) {
         char *l_ignored_addrs_str = NULL;
         if (l_ignored_addrs) {
-            DAP_NEW_Z_SIZE_RET_VAL(
+            DAP_NEW_Z_SIZE_RET(
                 l_ignored_addrs_str, char, DAP_ENC_BASE64_ENCODE_SIZE(l_ignored_addrs_size) + 1,
-                -7, l_ignored_addrs, l_balancer_request);
+                l_ignored_addrs, l_arg);
             dap_enc_base64_encode(l_ignored_addrs, l_ignored_addrs_size, l_ignored_addrs_str, DAP_ENC_DATA_TYPE_B64);
             DAP_DELETE(l_ignored_addrs);
         }
@@ -534,38 +514,28 @@ int dap_chain_net_balancer_request(dap_chain_net_t *a_net, const char *a_host_ad
                                                 DAP_BALANCER_URI_HASH,
                                                 DAP_BALANCER_PROTOCOL_VERSION,
                                                 (int)l_required_links_count,
-                                                a_net->pub.name,
+                                                l_arg->net->pub.name,
                                                 l_ignored_addrs_str ? l_ignored_addrs_str : "");
-        ret = dap_client_http_request(l_balancer_request->worker,
-                                                l_balancer_request->host_addr,
-                                                l_balancer_request->host_port,
-                                                "GET",
-                                                "text/text",
-                                                l_request,
-                                                NULL,
-                                                0,
-                                                NULL,
-                                                s_http_balancer_link_prepare_success,
-                                                s_http_balancer_link_prepare_error,
-                                                l_balancer_request,
-                                                NULL) == NULL;
+        if (! dap_client_http_request(l_arg->worker, l_arg->host_addr, l_arg->host_port,
+                                       "GET", "text/text", l_request, NULL, 0, NULL,
+                                       s_http_balancer_link_prepare_success, s_http_balancer_link_prepare_error,
+                                       l_arg, NULL) )
+        {
+            log_it(L_ERROR, "Can't process balancer link %s request in net %s",
+                            dap_chain_net_balancer_type_to_str(l_arg->type), l_arg->net->pub.name);
+        }
         DAP_DEL_MULTY(l_ignored_addrs_str, l_request);
     } else {
-        l_balancer_request->host_port = DNS_LISTEN_PORT;
+        l_arg->host_port = DNS_LISTEN_PORT;
         // TODO: change signature and implementation
-        ret = /* dap_chain_node_info_dns_request(l_balancer_request->worker,
-                                                l_link_node_info->hdr.ext_addr_v4,
-                                                l_link_node_info->hdr.ext_port,
-                                                a_net->pub.name,
-                                                s_dns_balancer_link_prepare_success,
-                                                s_dns_balancer_link_prepare_error,
-                                                l_balancer_request); */ -1;
-    }
-    if (ret) {
-        log_it(L_ERROR, "Can't process balancer link %s request in net %s", dap_chain_net_balancer_type_to_str(a_balancer_type), a_net->pub.name);
-        return -6;
+        /* dap_chain_node_info_dns_request(l_balancer_request->worker,
+                                            l_link_node_info->hdr.ext_addr_v4,
+                                            l_link_node_info->hdr.ext_port,
+                                            a_net->pub.name,
+                                            s_dns_balancer_link_prepare_success,
+                                            s_dns_balancer_link_prepare_error,
+                                            l_balancer_request); */
     }
-    return 0;
 }
 
 /**
diff --git a/modules/net/dap_chain_net_decree.c b/modules/net/dap_chain_net_decree.c
index 6aafb2826aa07cfe23cf92ab5e583c71c95ed2af..28fbef933c7df9828f47ba14f32b60fbf6cf9a01 100644
--- a/modules/net/dap_chain_net_decree.c
+++ b/modules/net/dap_chain_net_decree.c
@@ -52,7 +52,7 @@ typedef struct decree_table {
 
 // Private fuctions prototype
 static bool s_verify_pkey (dap_sign_t *a_sign, dap_chain_net_t *a_net);
-static int s_common_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain_net_t *a_net, bool a_apply, bool a_load_mode);
+static int s_common_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain_net_t *a_net, bool a_apply, bool a_anchored);
 static int s_service_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain_net_t *a_net, bool a_apply);
 
 static bool s_debug_more = false;
@@ -119,7 +119,7 @@ void dap_chain_net_decree_purge(dap_chain_net_t *a_net)
     dap_chain_net_decree_init(a_net);
 }
 
-static int s_decree_verify(dap_chain_net_t *a_net, dap_chain_datum_decree_t *a_decree, size_t a_data_size, dap_chain_hash_fast_t *a_decree_hash, bool a_load_mode)
+static int s_decree_verify(dap_chain_net_t *a_net, dap_chain_datum_decree_t *a_decree, size_t a_data_size, dap_chain_hash_fast_t *a_decree_hash, bool a_anchored)
 {
     if (a_data_size < sizeof(dap_chain_datum_decree_t)) {
         log_it(L_WARNING, "Decree size is too small");
@@ -205,7 +205,7 @@ static int s_decree_verify(dap_chain_net_t *a_net, dap_chain_datum_decree_t *a_d
     int l_ret = 0;
     switch(a_decree->header.type) {
     case DAP_CHAIN_DATUM_DECREE_TYPE_COMMON:
-        l_ret = s_common_decree_handler(a_decree, a_net, false, a_load_mode);
+        l_ret = s_common_decree_handler(a_decree, a_net, false, a_anchored);
         break;
     case DAP_CHAIN_DATUM_DECREE_TYPE_SERVICE:
         l_ret = s_service_decree_handler(a_decree, a_net, false);
@@ -227,7 +227,7 @@ int dap_chain_net_decree_verify(dap_chain_net_t *a_net, dap_chain_datum_decree_t
     return s_decree_verify(a_net, a_decree, a_data_size, a_decree_hash, false);
 }
 
-int dap_chain_net_decree_apply(dap_hash_fast_t *a_decree_hash, dap_chain_datum_decree_t *a_decree, dap_chain_t *a_chain)
+int dap_chain_net_decree_apply(dap_hash_fast_t *a_decree_hash, dap_chain_datum_decree_t *a_decree, dap_chain_t *a_chain, bool a_anchored)
 {
     int ret_val = 0;
     dap_chain_net_t *l_net = NULL;
@@ -282,7 +282,7 @@ int dap_chain_net_decree_apply(dap_hash_fast_t *a_decree_hash, dap_chain_datum_d
     // Process decree
     switch(l_new_decree->decree->header.type) {
     case DAP_CHAIN_DATUM_DECREE_TYPE_COMMON:
-        ret_val = s_common_decree_handler(l_new_decree->decree, l_net, true, false);
+        ret_val = s_common_decree_handler(l_new_decree->decree, l_net, true, a_anchored);
         break;
     case DAP_CHAIN_DATUM_DECREE_TYPE_SERVICE:
         ret_val = s_service_decree_handler(l_new_decree->decree, l_net, true);
@@ -318,12 +318,12 @@ int dap_chain_net_decree_load(dap_chain_datum_decree_t * a_decree, dap_chain_t *
 
     size_t l_data_size = dap_chain_datum_decree_get_size(a_decree);
 
-    if ((ret_val = s_decree_verify(l_net, a_decree, l_data_size, a_decree_hash, true)) != 0) {
+    if ((ret_val = s_decree_verify(l_net, a_decree, l_data_size, a_decree_hash, false)) != 0) {
         //log_it(L_ERROR, "Decree verification failed!");
         return ret_val;
     }
 
-    return dap_chain_net_decree_apply(a_decree_hash, a_decree, a_chain);
+    return dap_chain_net_decree_apply(a_decree_hash, a_decree, a_chain, false);
 }
 
 int dap_chain_net_decree_reset_applied(dap_chain_net_t *a_net, dap_chain_hash_fast_t *a_decree_hash)
@@ -356,7 +356,7 @@ static bool s_verify_pkey (dap_sign_t *a_sign, dap_chain_net_t *a_net)
     return false;
 }
 
-static int s_common_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain_net_t *a_net, bool a_apply, bool a_load_mode)
+static int s_common_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain_net_t *a_net, bool a_apply, bool a_anchored)
 {
     uint256_t l_value;
     uint32_t l_sign_type;
@@ -433,10 +433,8 @@ static int s_common_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain
                 log_it(L_WARNING,"Can't get signer node address from decree.");
                 return -108;
             }
-            if (a_load_mode) {
-                assert(!a_apply);
+            if (!a_anchored)
                 break;
-            }
             if (dap_chain_net_srv_stake_verify_key_and_node(&l_addr, &l_node_addr)) {
                 debug_if(s_debug_more, L_WARNING, "Key and node verification error");
                 return -109;
@@ -485,6 +483,8 @@ static int s_common_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain
                 log_it(L_WARNING, "Can't apply this decree to specified chain");
                 return -115;
             }
+            if (!a_anchored)
+                break;
             uint16_t l_decree_count = (uint16_t)dap_chain_uint256_to(l_value);
             uint16_t l_current_count = dap_chain_net_srv_stake_get_total_keys(a_net->pub.id, NULL);
             if (l_decree_count > l_current_count) {
diff --git a/modules/net/dap_chain_node.c b/modules/net/dap_chain_node.c
index d530ede2b7aee567857a50e890a89168210073f2..48b64cbbe4be9dc8f9fe58d49e9c7997d949c87e 100644
--- a/modules/net/dap_chain_node.c
+++ b/modules/net/dap_chain_node.c
@@ -47,8 +47,12 @@
 #include "dap_chain_ledger.h"
 
 #define LOG_TAG "dap_chain_node"
+#define DAP_CHAIN_NODE_NET_STATES_INFO_CURRENT_VERSION 2
 
 typedef struct dap_chain_node_net_states_info {
+    uint16_t version_info;
+    char version_node[16];
+    dap_chain_node_role_t role;
     dap_chain_node_addr_t address;
     uint64_t events_count;
     uint64_t atoms_count;
@@ -62,6 +66,8 @@ static const uint64_t s_cmp_delta_event = 0;
 static const uint64_t s_cmp_delta_atom = 10;
 static const uint64_t s_timer_update_states_info = 10 /*sec*/ * 1000;
 static const char s_states_group[] = ".nodes.states";
+ // only add in version up, not change!!!
+static const uint16_t s_states_version_size[DAP_CHAIN_NODE_NET_STATES_INFO_CURRENT_VERSION] = { 32, 54 };
 
 /**
  * @brief get states info about current
@@ -69,6 +75,10 @@ static const char s_states_group[] = ".nodes.states";
  */
 static void s_update_node_states_info(UNUSED_ARG void *a_arg)
 {
+#ifndef DAP_VERSION
+#pragma message "[!WRN!] DAP_VERSION IS NOT DEFINED. Manual override engaged."
+#define DAP_VERSION "0.9-15"
+#endif
     for (dap_chain_net_t *l_net = dap_chain_net_iter_start(); l_net; l_net = dap_chain_net_iter_next(l_net)) {
         if(dap_chain_net_get_state(l_net) != NET_STATE_OFFLINE) {
             size_t
@@ -76,19 +86,22 @@ static void s_update_node_states_info(UNUSED_ARG void *a_arg)
                 l_downlinks_count = 0,
                 l_info_size = 0;
         // memory alloc first
-            dap_stream_node_addr_t *l_linked_node_addrs = dap_link_manager_get_net_links_addrs(l_net->pub.id.uint64, &l_uplinks_count, &l_downlinks_count, false);
+            dap_stream_node_addr_t *l_linked_node_addrs = dap_link_manager_get_net_links_addrs(l_net->pub.id.uint64, &l_uplinks_count, &l_downlinks_count, true);
             dap_chain_node_net_states_info_t *l_info = NULL;
             l_info_size = sizeof(dap_chain_node_net_states_info_t) + (l_uplinks_count + l_downlinks_count) * sizeof(dap_chain_node_addr_t);
             DAP_NEW_Z_SIZE_RET(l_info, dap_chain_node_net_states_info_t, l_info_size, l_linked_node_addrs);
         // func work
             // data preparing
+            l_info->version_info = DAP_CHAIN_NODE_NET_STATES_INFO_CURRENT_VERSION;
+            dap_strncpy(l_info->version_node, DAP_VERSION, sizeof(l_info->version_node) - 1);
+            l_info->role = dap_chain_net_get_role(l_net);
             l_info->address.uint64 = g_node_addr.uint64;
             l_info->uplinks_count = l_uplinks_count;
             l_info->downlinks_count = l_downlinks_count;
 
             dap_chain_t *l_chain = dap_chain_find_by_id(l_net->pub.id, (dap_chain_id_t){ .uint64 = 0 });  // zerochain
             l_info->events_count = (l_chain && l_chain->callback_count_atom) ? l_chain->callback_count_atom(l_chain) : 0;
-            l_chain =dap_chain_find_by_id(l_net->pub.id, (dap_chain_id_t){ .uint64 = 1 });  // mainchain
+            l_chain = l_chain ? l_chain->next : NULL;  // mainchain
             l_info->atoms_count = (l_chain && l_chain->callback_count_atom) ? l_chain->callback_count_atom(l_chain) : 0;
             
             memcpy(l_info->links_addrs, l_linked_node_addrs, (l_info->uplinks_count + l_info->downlinks_count) * sizeof(dap_chain_node_addr_t));
@@ -110,16 +123,18 @@ static void s_states_info_to_str(dap_chain_net_t *a_net, const char *a_node_addr
     size_t l_data_size = 0;
     char *l_gdb_group = dap_strdup_printf("%s%s", a_net->pub.gdb_groups_prefix, s_states_group);
     dap_chain_node_net_states_info_t *l_store_obj = (dap_chain_node_net_states_info_t *)dap_global_db_get_sync(l_gdb_group, a_node_addr_str, &l_data_size, NULL, &l_timestamp);
-    if (!l_store_obj || l_data_size != sizeof(dap_chain_node_net_states_info_t) + (l_store_obj->uplinks_count + l_store_obj->downlinks_count) * sizeof(dap_chain_node_addr_t)) {
-        log_it(L_ERROR, "Can't find state about %s node", a_node_addr_str);
+    if (!l_store_obj || l_store_obj->version_info != DAP_CHAIN_NODE_NET_STATES_INFO_CURRENT_VERSION ||
+         l_data_size != s_states_version_size[DAP_CHAIN_NODE_NET_STATES_INFO_CURRENT_VERSION - 1] + (l_store_obj->uplinks_count + l_store_obj->downlinks_count) * sizeof(dap_chain_node_addr_t))
+    {
+        log_it(L_ERROR, "Can't find state about %s node in net %s", a_node_addr_str, a_net->pub.name);
         DAP_DELETE(l_gdb_group);
         return;
     }
     char l_ts[80] = { '\0' };
     dap_nanotime_to_str_rfc822(l_ts, sizeof(l_ts), l_timestamp);
     dap_string_append_printf(l_info_str,
-        "Record timestamp: %s\nNode addr: %s\nNet: %s\nEvents count: %"DAP_UINT64_FORMAT_U"\nAtoms count: %"DAP_UINT64_FORMAT_U"\nUplinks count: %u\nDownlinks count: %u\n",
-        l_ts, a_node_addr_str, a_net->pub.name, l_store_obj->events_count, l_store_obj->atoms_count, l_store_obj->uplinks_count, l_store_obj->downlinks_count);
+        "Record timestamp: %s\nRecord version: %u\nNode version: %s\nNode addr: %s\nNet: %s\nRole: %s\nEvents count: %"DAP_UINT64_FORMAT_U"\nAtoms count: %"DAP_UINT64_FORMAT_U"\nUplinks count: %u\nDownlinks count: %u\n",
+        l_ts, l_store_obj->version_info, l_store_obj->version_node,a_node_addr_str, a_net->pub.name, dap_chain_node_role_to_str(l_store_obj->role), l_store_obj->events_count, l_store_obj->atoms_count, l_store_obj->uplinks_count, l_store_obj->downlinks_count);
     size_t l_max_links = dap_max(l_store_obj->uplinks_count, l_store_obj->downlinks_count);
     if(l_max_links) {
         dap_string_append_printf(l_info_str,
@@ -422,6 +437,8 @@ static int s_node_states_info_cmp(dap_list_t *a_first, dap_list_t *a_second)
   if(b->events_count > a->events_count && b->events_count - a->events_count > s_cmp_delta_event) return 1;
   if(a->atoms_count > b->atoms_count && a->atoms_count - b->atoms_count > s_cmp_delta_atom) return -1;
   if(b->atoms_count > a->atoms_count && b->atoms_count - a->atoms_count > s_cmp_delta_atom) return 1;
+  if(a->role.enums == NODE_ROLE_ROOT) return 1;
+  if(b->role.enums == NODE_ROLE_ROOT) return -1;
   if(a->downlinks_count < b->downlinks_count) return -1;
   if(b->downlinks_count < a->downlinks_count) return 1;
   return 0;
@@ -473,10 +490,15 @@ dap_list_t *dap_chain_node_get_states_list_sort(dap_chain_net_t *a_net, dap_chai
         if (!l_state_store_obj) {
             log_it(L_DEBUG, "Can't find state about %s node, apply low priority", l_objs[i].key);
             l_item->downlinks_count = (uint32_t)(-1);
-        } else if (l_data_size != sizeof(dap_chain_node_net_states_info_t) + (l_state_store_obj->uplinks_count + l_state_store_obj->downlinks_count) * sizeof(dap_chain_node_addr_t)) {
-            log_it(L_DEBUG, "Wrong %s node state record size, expected %zu, get %zu. Apply low priority", l_objs[i].key, sizeof(dap_chain_node_net_states_info_t) + (l_state_store_obj->uplinks_count + l_state_store_obj->downlinks_count) * sizeof(dap_chain_node_addr_t), l_data_size);
+        } else if (
+                l_state_store_obj->version_info != DAP_CHAIN_NODE_NET_STATES_INFO_CURRENT_VERSION ||
+                l_data_size != s_states_version_size[DAP_CHAIN_NODE_NET_STATES_INFO_CURRENT_VERSION - 1] + (l_state_store_obj->uplinks_count + l_state_store_obj->downlinks_count) * sizeof(dap_chain_node_addr_t)
+            ) {
+            log_it(L_DEBUG, "Wrong %s node state record size to state version %u, expected %zu, get %zu. Apply low priority", l_objs[i].key, l_state_store_obj->version_info, sizeof(dap_chain_node_net_states_info_t) + (l_state_store_obj->uplinks_count + l_state_store_obj->downlinks_count) * sizeof(dap_chain_node_addr_t), l_data_size);
+            l_item->role.enums = NODE_ROLE_ROOT;
             l_item->downlinks_count = (uint32_t)(-1);
         } else {
+            l_item->role.enums = l_state_store_obj->role.enums;
             l_item->atoms_count = l_state_store_obj->atoms_count;
             l_item->events_count = l_state_store_obj->events_count;
             l_item->downlinks_count = l_state_store_obj->downlinks_count;
diff --git a/modules/net/dap_chain_node_cli.c b/modules/net/dap_chain_node_cli.c
index fc9938129e8442762cb38687604be7115051f449..c871d5975814db41eb21ec6e54ce516a9e3f3ce2 100644
--- a/modules/net/dap_chain_node_cli.c
+++ b/modules/net/dap_chain_node_cli.c
@@ -218,9 +218,9 @@ int dap_chain_node_cli_init(dap_config_t * g_config)
             "\n"
             );
 
-    dap_cli_server_cmd_add("token_update_sign", com_token_decl_sign, "Token update add sign and new sign",
-                                        "token_update_sign -net <net_name> [-chain <chain_name>] -datum <datum_hash> -certs <certs list> -new_certs <certs list>\n"
-                                        "\t Sign existent <datum hash> in mempool with <certs list>\n"
+    dap_cli_server_cmd_add("token_update_sign", com_token_decl_sign, "Token update add sign to datum",
+                                        "token_update_sign -net <net_name> [-chain <chain_name>] -datum <datum_hash> -certs <cert_list>\n"
+                                        "\t Sign existent <datum hash> in mempool with <certs_list>\n"
     );
     // Token commands
 
@@ -285,8 +285,9 @@ int dap_chain_node_cli_init(dap_config_t * g_config)
 
     // Transaction history
     dap_cli_server_cmd_add("tx_history", com_tx_history, "Transaction history (for address or by hash)",
-            "tx_history  {-addr <addr> | -w <wallet_name> | -tx <tx_hash>} [-net <net_name>] [-chain <chain_name>] [-limit] [-offset]\n"
-            "tx_history -all -net <net_name> [-chain <chain_name>] [-limit] [-offset]\n");
+            "tx_history  {-addr <addr> | -w <wallet_name> | -tx <tx_hash>} [-net <net_name>] [-chain <chain_name>] [-limit] [-offset] [-head]\n"
+            "tx_history -all -net <net_name> [-chain <chain_name>] [-limit] [-offset] [-head]\n"
+            "tx_history -count -net <net_name>\n");
 
 	// Ledger info
     dap_cli_server_cmd_add("ledger", com_ledger, "Ledger information",
diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c
index 1ba566feb505dc0786454b930914e13a237c4903..3d4fee8dff31e24b91a510aba89b4782ccb79811 100644
--- a/modules/net/dap_chain_node_cli_cmd.c
+++ b/modules/net/dap_chain_node_cli_cmd.c
@@ -566,8 +566,6 @@ int com_global_db(int a_argc, char ** a_argv, void **a_str_reply)
         switch (l_subcmd) {
             case SUMCMD_GET: // Get value
             {
-                char *l_hash_str;
-                dap_get_data_hash_str_static(l_value, l_value_len, l_hash_str);
                 char *l_value_str = DAP_NEW_Z_SIZE(char, l_value_len * 2 + 2);
                 if(!l_value_str) {
                     log_it(L_CRITICAL, "%s", c_error_memory_alloc);
@@ -580,7 +578,7 @@ int com_global_db(int a_argc, char ** a_argv, void **a_str_reply)
                 size_t ret = dap_bin2hex(l_value_str, l_value, l_value_len);
                 json_object_object_add(json_obj_rec, "command status", json_object_new_string("Record found"));
                 json_object_object_add(json_obj_rec, "lenght(byte)", json_object_new_uint64(l_value_len));
-                json_object_object_add(json_obj_rec, "hash", json_object_new_string(l_hash_str));
+                json_object_object_add(json_obj_rec, "hash", json_object_new_string(dap_get_data_hash_str(l_value, l_value_len).s));
                 json_object_object_add(json_obj_rec, "pinned", l_is_pinned ? json_object_new_string("Yes") : json_object_new_string("No") );
                 json_object_object_add(json_obj_rec, "value", json_object_new_string(l_value_str));
                 DAP_DELETE(l_value_str);
@@ -2199,7 +2197,7 @@ int l_arg_index = 1, l_rc, cmd_num = CMD_NONE;
                                                       "sig_multi_chained. You must specify at least two more "
                                                       "signatures other than sig_multi_chained.\n"
                                                       "After sig_multi_chained, you must specify two more signatures "
-                                                      "from the list: %s", dap_cert_get_str_recommended_sign());
+                                                      "from the list:\n%s", dap_cert_get_str_recommended_sign());
                                 json_object_put(json_arr_out);
                                 return DAP_CHAIN_NODE_CLI_COM_TX_WALLET_UNKNOWN_SIGN_ERR;
                             }
@@ -2625,9 +2623,15 @@ int com_token_decl_sign(int a_argc, char **a_argv, void **a_str_reply)
                 size_t l_data_size = l_tsd_size + l_signs_size;
                 l_datum_token = s_sign_cert_in_cycle(l_certs, l_datum_token, l_certs_count, &l_data_size,
                                                             &l_sign_counter);
+                log_it(L_DEBUG, "Apply %zu signs to datum %s", l_sign_counter, l_datum_hash_hex_str);
+                if (!l_sign_counter) {
+                    dap_cli_server_cmd_set_reply_text(a_str_reply, "Error! Used certs not valid");
+                    DAP_DEL_MULTY(l_datum_token, l_datum_hash_hex_str, l_datum_hash_base58_str, l_gdb_group_mempool);
+                    return -9;
+                }
                 l_datum_token->signs_total += l_sign_counter;
                 size_t l_token_size = sizeof(*l_datum_token) + l_data_size;
-                dap_chain_datum_t * l_datum = dap_chain_datum_create(DAP_CHAIN_DATUM_TOKEN,
+                l_datum = dap_chain_datum_create(DAP_CHAIN_DATUM_TOKEN,
                                                                      l_datum_token, l_token_size);
                 DAP_DELETE(l_datum_token);
                 // Calc datum's hash
@@ -2644,8 +2648,8 @@ int com_token_decl_sign(int a_argc, char **a_argv, void **a_str_reply)
                     char* l_hash_str = l_datum_hash_hex_str;
                     // Remove old datum from pool
                     if( dap_global_db_del_sync(l_gdb_group_mempool, l_hash_str ) == 0) {
-                        dap_cli_server_cmd_set_reply_text(a_str_reply, "Datum %s is replacing the %s in datum pool",
-                                l_key_out_str, l_datum_hash_out_str);
+                        dap_cli_server_cmd_set_reply_text(a_str_reply, "Datum was replaced in datum pool:\n\tOld: %s\n\tNew: %s",
+                                l_datum_hash_out_str, l_key_out_str);
                     } else {
                         dap_cli_server_cmd_set_reply_text(a_str_reply,
                                 "Warning! Can't remove old datum %s ( new datum %s added normaly in datum pool)",
@@ -2658,11 +2662,7 @@ int com_token_decl_sign(int a_argc, char **a_argv, void **a_str_reply)
                             l_key_out_str, l_datum_hash_out_str);
                     rc = -2;
                 }
-                DAP_DELETE(l_key_str);
-                DAP_DELETE(l_datum_hash_hex_str);
-                DAP_DELETE(l_datum_hash_base58_str);
-                DAP_DELETE(l_datum);
-                DAP_DELETE(l_gdb_group_mempool);
+                DAP_DEL_MULTY(l_key_str, l_datum_hash_hex_str, l_datum_hash_base58_str, l_datum, l_gdb_group_mempool);
                 return rc;
             } else {
                 dap_cli_server_cmd_set_reply_text(a_str_reply,
@@ -2675,8 +2675,7 @@ int com_token_decl_sign(int a_argc, char **a_argv, void **a_str_reply)
                     l_chain?l_chain->name:"<undefined>");
             return -5;
         }
-        DAP_DELETE(l_datum_hash_hex_str);
-        DAP_DELETE(l_datum_hash_base58_str);
+        DAP_DEL_MULTY(l_datum_hash_hex_str, l_datum_hash_base58_str);
     } else {
         dap_cli_server_cmd_set_reply_text(a_str_reply, "token_decl_sign need -datum <datum hash> argument");
         return -2;
@@ -3600,7 +3599,7 @@ int _cmd_mempool_proc(dap_chain_net_t *a_net, dap_chain_t *a_chain, const char *
         dap_json_rpc_allocation_error(*a_json_arr_reply);
         return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED;
     }
-    int l_verify_datum = dap_chain_net_verify_datum_for_add(a_chain, l_datum, &l_datum_hash);
+    int l_verify_datum = dap_chain_net_verify_datum_for_add(l_chain, l_datum, &l_datum_hash);
     if (l_verify_datum){
         json_object *l_jobj_verify_err = json_object_new_string(dap_chain_net_verify_datum_err_code_to_str(l_datum, l_verify_datum));
         json_object *l_jobj_verify_status = json_object_new_boolean(FALSE);
@@ -3616,8 +3615,8 @@ int _cmd_mempool_proc(dap_chain_net_t *a_net, dap_chain_t *a_chain, const char *
         json_object_object_add(l_jobj_verify, "error", l_jobj_verify_err);
         ret = DAP_COM_MEMPOOL_PROC_LIST_ERROR_FALSE_VERIFY;
     } else {
-        if (a_chain->callback_add_datums) {
-            if (a_chain->callback_add_datums(a_chain, &l_datum, 1) == 0) {
+        if (l_chain->callback_add_datums) {
+            if (l_chain->callback_add_datums(l_chain, &l_datum, 1) == 0) {
                 json_object *l_jobj_verify_status = json_object_new_boolean(FALSE);
                 if (!l_jobj_verify_status) {
                     json_object_put(l_jobj_verify_status);
@@ -4056,7 +4055,6 @@ typedef struct _dap_cli_token_additional_params {
     uint16_t    parsed_flags;
     size_t      tsd_total_size;
     byte_t      *parsed_tsd;
-    size_t      parsed_tsd_size;
 } dap_cli_token_additional_params;
 
 typedef struct _dap_sdk_cli_params {
@@ -4210,7 +4208,6 @@ static int s_parse_additional_token_decl_arg(int a_argc, char ** a_argv, void **
     size_t l_tsd_total_size = 0;
     uint16_t l_flags = 0;
     char ** l_str_flags = NULL;
-    a_params->ext.parsed_tsd_size = 0;
 
     if (!a_update_token) {
         if (a_params->ext.flags){   // Flags
@@ -4225,7 +4222,6 @@ static int s_parse_additional_token_decl_arg(int a_argc, char ** a_argv, void **
                 l_str_flags++;
             }
         }
-        a_params->ext.parsed_flags = l_flags;
     } else {
         const char *l_set_flags = NULL;
         const char *l_unset_flags = NULL;
@@ -4246,7 +4242,6 @@ static int s_parse_additional_token_decl_arg(int a_argc, char ** a_argv, void **
             l_flags = 0;
             l_tsd_list = dap_list_append(l_tsd_list, l_flag_set_tsd);
             l_tsd_total_size += dap_tsd_size(l_flag_set_tsd);
-            a_params->ext.parsed_tsd_size += dap_tsd_size(l_flag_set_tsd);
         }
         if (l_unset_flags) {
             l_str_flags = dap_strsplit(l_unset_flags,",",0xffff );
@@ -4263,10 +4258,41 @@ static int s_parse_additional_token_decl_arg(int a_argc, char ** a_argv, void **
             l_flags = 0;
             l_tsd_list = dap_list_append(l_tsd_list, l_flag_unset_tsd);
             l_tsd_total_size += dap_tsd_size(l_flag_unset_tsd);
-            a_params->ext.parsed_tsd_size += dap_tsd_size(l_flag_unset_tsd);
         }
     }
 
+    if (a_params->ext.total_signs_valid){ // Signs valid
+        uint16_t l_param_value = (uint16_t)atoi(a_params->ext.total_signs_valid);
+        dap_tsd_t * l_tsd = dap_tsd_create_scalar(
+                                                DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_VALID, l_param_value);
+        l_tsd_list = dap_list_append(l_tsd_list, l_tsd);
+        l_tsd_total_size+= dap_tsd_size(l_tsd);
+    }
+    if (a_params->ext.datum_type_allowed){
+        dap_tsd_t * l_tsd = dap_tsd_create_string(
+                                                DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_ALLOWED_ADD, a_params->ext.datum_type_allowed);
+        l_tsd_list = dap_list_append(l_tsd_list, l_tsd);
+        l_tsd_total_size+= dap_tsd_size(l_tsd);
+    }
+    if (a_params->ext.datum_type_blocked){
+        dap_tsd_t * l_tsd = dap_tsd_create_string(
+                                                DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_BLOCKED_ADD, a_params->ext.datum_type_blocked);
+        l_tsd_list = dap_list_append(l_tsd_list, l_tsd);
+        l_tsd_total_size+= dap_tsd_size(l_tsd);
+    }
+    if (a_params->ext.tx_receiver_allowed)
+        l_tsd_list = s_parse_wallet_addresses(a_params->ext.tx_receiver_allowed, l_tsd_list, &l_tsd_total_size, DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_ADD);
+
+    if (a_params->ext.tx_receiver_blocked)
+        l_tsd_list = s_parse_wallet_addresses(a_params->ext.tx_receiver_blocked, l_tsd_list, &l_tsd_total_size, DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_ADD);
+
+    if (a_params->ext.tx_sender_allowed)
+        l_tsd_list = s_parse_wallet_addresses(a_params->ext.tx_sender_allowed, l_tsd_list, &l_tsd_total_size, DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_ADD);
+
+    if (a_params->ext.tx_sender_blocked)
+        l_tsd_list = s_parse_wallet_addresses(a_params->ext.tx_sender_blocked, l_tsd_list, &l_tsd_total_size, DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_ADD);
+
+
     const char* l_new_certs_str = NULL;
     const char* l_remove_signs = NULL;
     dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-new_certs", &l_new_certs_str);
@@ -4316,7 +4342,6 @@ static int s_parse_additional_token_decl_arg(int a_argc, char ** a_argv, void **
         dap_tsd_t *l_desc_token = dap_tsd_create_string(DAP_CHAIN_DATUM_TOKEN_TSD_TOKEN_DESCRIPTION, l_description);
         l_tsd_list = dap_list_append(l_tsd_list, l_desc_token);
         l_tsd_total_size += dap_tsd_size(l_desc_token);
-        a_params->ext.parsed_tsd_size += dap_tsd_size(l_desc_token);
     }
     size_t l_tsd_offset = 0;
     a_params->ext.parsed_tsd = DAP_NEW_SIZE(byte_t, l_tsd_total_size);
@@ -4493,24 +4518,9 @@ int com_token_decl(int a_argc, char ** a_argv, void **a_str_reply)
         case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE:
 		{ // 256
             dap_list_t *l_tsd_list = NULL;
-            size_t l_tsd_total_size = 0;
-            uint16_t l_flags = 0;
-            char ** l_str_flags = NULL;
-
-            if (l_params->ext.flags){   // Flags
-                 l_str_flags = dap_strsplit(l_params->ext.flags,",",0xffff );
-                 while (l_str_flags && *l_str_flags){
-                     uint16_t l_flag = dap_chain_datum_token_flag_from_str(*l_str_flags);
-                     if (l_flag == DAP_CHAIN_DATUM_TOKEN_FLAG_UNDEFINED ){
-                         dap_cli_server_cmd_set_reply_text(a_str_reply, "Flag can't be \"%s\"",*l_str_flags);
-                         DAP_DEL_Z(l_params);
-                         return -20;
-                     }
-                     l_flags |= l_flag; // if we have multiple flags
-                     l_str_flags++;
-                }
-            }
-			if (l_params->ext.delegated_token_from){
+            size_t l_tsd_local_list_size = 0;
+
+            if (l_params->ext.delegated_token_from){
 				dap_chain_datum_token_t *l_delegated_token_from;
 				if (NULL == (l_delegated_token_from = dap_ledger_token_ticker_check(l_net->pub.ledger, l_params->ext.delegated_token_from))) {
                     dap_cli_server_cmd_set_reply_text(a_str_reply,"To create a delegated token %s, can't find token by ticket %s", l_ticker, l_params->ext.delegated_token_from);
@@ -4530,42 +4540,19 @@ int com_token_decl(int a_argc, char ** a_argv, void **a_str_reply)
 				dap_tsd_t * l_tsd = dap_tsd_create_scalar(
 														DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DELEGATE_EMISSION_FROM_STAKE_LOCK, l_tsd_section);
 				l_tsd_list = dap_list_append(l_tsd_list, l_tsd);
-				l_tsd_total_size+= dap_tsd_size(l_tsd);
+				l_tsd_local_list_size += dap_tsd_size(l_tsd);
 			}
-            if (l_params->ext.total_signs_valid){ // Signs valid
-                uint16_t l_param_value = (uint16_t)atoi(l_params->ext.total_signs_valid);
-                l_signs_total = l_param_value;
-                dap_tsd_t * l_tsd = dap_tsd_create_scalar(
-                                                        DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_VALID, l_param_value);
-                l_tsd_list = dap_list_append(l_tsd_list, l_tsd);
-                l_tsd_total_size+= dap_tsd_size(l_tsd);
-            }
-            if (l_params->ext.datum_type_allowed){
-                dap_tsd_t * l_tsd = dap_tsd_create_string(
-                                                        DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_ALLOWED_ADD, l_params->ext.datum_type_allowed);
-                l_tsd_list = dap_list_append(l_tsd_list, l_tsd);
-                l_tsd_total_size+= dap_tsd_size(l_tsd);
-            }
-            if (l_params->ext.datum_type_blocked){
-                dap_tsd_t * l_tsd = dap_tsd_create_string(
-                                                        DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_BLOCKED_ADD, l_params->ext.datum_type_blocked);
-                l_tsd_list = dap_list_append(l_tsd_list, l_tsd);
-                l_tsd_total_size+= dap_tsd_size(l_tsd);
+
+            if (l_params->ext.total_signs_valid) {
+                l_signs_total = (uint16_t)atoi(l_params->ext.total_signs_valid);
             }
-            if (l_params->ext.tx_receiver_allowed)
-                l_tsd_list = s_parse_wallet_addresses(l_params->ext.tx_receiver_allowed, l_tsd_list, &l_tsd_total_size, DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_ADD);
 
-            if (l_params->ext.tx_receiver_blocked)
-                l_tsd_list = s_parse_wallet_addresses(l_params->ext.tx_receiver_blocked, l_tsd_list, &l_tsd_total_size, DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_ADD);
 
-            if (l_params->ext.tx_sender_allowed)
-                l_tsd_list = s_parse_wallet_addresses(l_params->ext.tx_sender_allowed, l_tsd_list, &l_tsd_total_size, DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_ADD);
+            size_t l_tsd_total_size = l_tsd_local_list_size + l_params->ext.tsd_total_size;
 
-            if (l_params->ext.tx_sender_blocked)
-                l_tsd_list = s_parse_wallet_addresses(l_params->ext.tx_sender_blocked, l_tsd_list, &l_tsd_total_size, DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_ADD);
 
-            if (l_params->ext.parsed_tsd)
-                l_tsd_total_size += l_params->ext.parsed_tsd_size;
+            // if (l_params->ext.parsed_tsd)
+                // l_tsd_total_size += l_params->ext.parsed_tsd_size;
 
 
             // Create new datum token
@@ -4585,7 +4572,7 @@ int com_token_decl(int a_argc, char ** a_argv, void **a_str_reply)
                 l_datum_token->header_private_decl.flags = l_params->ext.parsed_flags;
                 l_datum_token->total_supply = l_total_supply;
                 l_datum_token->signs_valid = l_signs_emission;
-                l_datum_token->header_private_decl.tsd_total_size = l_tsd_total_size;
+                l_datum_token->header_private_decl.tsd_total_size = l_tsd_local_list_size + l_params->ext.tsd_total_size;
                 l_datum_token->header_private_decl.decimals = atoi(l_params->decimals_str);
             } else { //DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL
                 log_it(L_DEBUG,"Prepared TSD sections for CF20 token on %zd total size", l_tsd_total_size);
@@ -4682,6 +4669,7 @@ int com_token_decl(int a_argc, char ** a_argv, void **a_str_reply)
             DAP_DEL_Z(l_params);
             return -8;
     }
+    dap_uuid_generate_nonce(&l_datum_token->nonce, DAP_CHAIN_DATUM_NONCE_SIZE);
     // If we have more certs than we need signs - use only first part of the list
     if(l_certs_count > l_signs_total)
         l_certs_count = l_signs_total;
@@ -4862,7 +4850,7 @@ int com_token_update(int a_argc, char ** a_argv, void **a_str_reply)
             // Add TSD sections in the end
             // Add TSD sections in the end
             if (l_params->ext.tsd_total_size) {
-                memcpy(l_datum_token->tsd_n_signs, l_params->ext.parsed_tsd, l_params->ext.parsed_tsd_size);
+                memcpy(l_datum_token->tsd_n_signs, l_params->ext.parsed_tsd, l_params->ext.tsd_total_size);
                 DAP_DELETE(l_params->ext.parsed_tsd);
             }
             log_it(L_DEBUG, "%s token declaration update '%s' initialized", (	l_params->subtype == DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE)	?
@@ -4888,6 +4876,7 @@ int com_token_update(int a_argc, char ** a_argv, void **a_str_reply)
                                               "Unknown token type");
             return -8;
     }
+    dap_uuid_generate_nonce(&l_datum_token->nonce, DAP_CHAIN_DATUM_NONCE_SIZE);
     // If we have more certs than we need signs - use only first part of the list
     if(l_certs_count > l_signs_total)
         l_certs_count = l_signs_total;
@@ -6824,9 +6813,8 @@ int com_tx_create_json(int a_argc, char ** a_argv, void **a_json_arr_reply)
 
     // Add transaction to mempool
     char *l_gdb_group_mempool_base_tx = dap_chain_net_get_gdb_group_mempool_new(l_chain);// get group name for mempool
-    char *l_tx_hash_str;
-    dap_get_data_hash_str_static(l_datum_tx->data, l_datum_tx->header.data_size, l_tx_hash_str);
-    bool l_placed = !dap_global_db_set(l_gdb_group_mempool_base_tx,l_tx_hash_str, l_datum_tx, l_datum_tx_size, false, NULL, NULL);
+    char *l_tx_hash_str = dap_get_data_hash_str(l_datum_tx->data, l_datum_tx->header.data_size).s;
+    bool l_placed = !dap_global_db_set(l_gdb_group_mempool_base_tx, l_tx_hash_str, l_datum_tx, l_datum_tx_size, false, NULL, NULL);
 
     DAP_DEL_Z(l_datum_tx);
     DAP_DELETE(l_gdb_group_mempool_base_tx);
@@ -7082,8 +7070,9 @@ int com_tx_create(int a_argc, char **a_argv, void **a_json_arr_reply)
 
     if (l_addr_to->net_id.uint64 != l_net->pub.id.uint64 && !dap_chain_addr_is_blank(l_addr_to)) {
         bool l_found = false;
-        for (dap_list_t *it = l_net->pub.bridged_networks; it; it = it->next) {
-            if (((dap_chain_net_id_t *)it->data)->uint64 == l_addr_to->net_id.uint64) {
+        int i;
+        for (i = 0; i < l_net->pub.bridged_networks_count; ++i) {
+            if (l_net->pub.bridged_networks[i].uint64 == l_addr_to->net_id.uint64) {
                 l_found = true;
                 break;
             }
@@ -7091,8 +7080,8 @@ int com_tx_create(int a_argc, char **a_argv, void **a_json_arr_reply)
         if (!l_found) {
             dap_string_t *l_allowed_list = dap_string_new("");
             dap_string_append_printf(l_allowed_list, "0x%016"DAP_UINT64_FORMAT_X, l_net->pub.id.uint64);
-            for (dap_list_t *it = l_net->pub.bridged_networks; it; it = it->next)
-                dap_string_append_printf(l_allowed_list, ", 0x%016"DAP_UINT64_FORMAT_X, ((dap_chain_net_id_t *)it->data)->uint64);
+            for (i = 0; i < l_net->pub.bridged_networks_count; ++i)
+                dap_string_append_printf(l_allowed_list, ", 0x%016"DAP_UINT64_FORMAT_X, l_net->pub.bridged_networks[i].uint64);
             dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_TX_CREATE_DESTINATION_NETWORK_IS_UNREACHEBLE,
                                    "Destination network ID=0x%"DAP_UINT64_FORMAT_x
                                    " is unreachable. List of available network IDs:\n%s"
@@ -7277,8 +7266,9 @@ int com_tx_history(int a_argc, char ** a_argv, void **a_str_reply)
     bool l_brief = (dap_cli_server_cmd_check_option(a_argv, arg_index, a_argc, "-brief") != -1) ? true : false;
 
     bool l_is_tx_all = dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-all", NULL);
+    bool l_is_tx_count = dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-count", NULL);
 
-    if (!l_addr_base58 && !l_wallet_name && !l_tx_hash_str && !l_is_tx_all) {
+    if (!l_addr_base58 && !l_wallet_name && !l_tx_hash_str && !l_is_tx_all && !l_is_tx_count) {
         dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_PARAM_ERR,
                                 "tx_history requires parameter '-addr' or '-w' or '-tx'");
         return DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_PARAM_ERR;
@@ -7417,6 +7407,11 @@ int com_tx_history(int a_argc, char ** a_argv, void **a_str_reply)
         json_object_array_add(*a_json_arr_reply, json_arr_history_all);
         json_object_array_add(*a_json_arr_reply, json_obj_summary);
         return DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_OK;
+    } else if (l_is_tx_count) {
+        json_object * json_count_obj= json_object_new_object();
+        json_object_object_add(json_count_obj, "Number of transaction", json_object_new_uint64(l_chain->callback_count_tx(l_chain)));
+        json_object_array_add(*a_json_arr_reply, json_count_obj);
+        return DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_OK;
     }
 
     if (json_obj_out) {
@@ -8262,46 +8257,26 @@ static int s_signer_cmd(int a_arg_index, int a_argc, char **a_argv, void **a_str
         dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, l_opts_signer[i].name, (const char **) &l_opts_sign[i]);
     }
 
-    if (!l_opts_sign[OPT_CERT]) {
-        dap_cli_server_cmd_set_reply_text(a_str_reply, "%s need to be selected", l_opts_signer[OPT_CERT].name);
-        return -1;
-    }
+    if (!l_opts_sign[OPT_CERT])
+        return dap_cli_server_cmd_set_reply_text(a_str_reply, "%s need to be selected", l_opts_signer[OPT_CERT].name), -1;
 
     dap_chain_net_t *l_network = dap_chain_net_by_name(l_opts_sign[OPT_NET]);
-    if (!l_network) {
-        dap_cli_server_cmd_set_reply_text(a_str_reply, "%s network not found", l_opts_sign[OPT_NET]);
-        return -1;
-    }
+    if ( !l_network )
+        return dap_cli_server_cmd_set_reply_text(a_str_reply, "%s network not found", l_opts_sign[OPT_NET]), -1;
 
     dap_chain_t *l_chain = dap_chain_net_get_chain_by_name(l_network, l_opts_sign[OPT_CHAIN]);
-    if (!l_chain) {
-        dap_cli_server_cmd_set_reply_text(a_str_reply, "%s chain not found", l_opts_sign[OPT_CHAIN]);
-        return -1;
-    }
+    if (!l_chain)
+        return dap_cli_server_cmd_set_reply_text(a_str_reply, "%s chain not found", l_opts_sign[OPT_CHAIN]), -1;
 
-    int l_ret = 0;
     dap_sign_t *l_sign = NULL;
-    dap_chain_datum_t *l_datum = NULL;
-
-    l_ret = s_get_key_from_file(l_opts_sign[OPT_FILE], l_opts_sign[OPT_MIME], l_opts_sign[OPT_CERT], &l_sign);
-    if (!l_ret) {
-        dap_cli_server_cmd_set_reply_text(a_str_reply, "%s cert not found", l_opts_sign[OPT_CERT]);
-        return -1;
-    }
-
-    l_datum = dap_chain_datum_create(DAP_CHAIN_DATUM_SIGNER, l_sign->pkey_n_sign, l_sign->header.sign_size);
-    if (!l_datum) {
-        dap_cli_server_cmd_set_reply_text(a_str_reply, "not created datum");
-        return -1;
-    }
-
-    l_ret = l_chain->callback_add_datums(l_chain, &l_datum, 1);
-
-    char *l_key_str;
-    dap_get_data_hash_str_static(l_datum->data, l_datum->header.data_size, l_key_str);
-    dap_cli_server_cmd_set_reply_text(a_str_reply, "hash: %s", l_key_str);
-    DAP_DELETE(l_datum);
-    return l_ret;
+    if ( !s_get_key_from_file(l_opts_sign[OPT_FILE], l_opts_sign[OPT_MIME], l_opts_sign[OPT_CERT], &l_sign) )
+        return dap_cli_server_cmd_set_reply_text(a_str_reply, "%s cert not found", l_opts_sign[OPT_CERT]), -1;
+
+    dap_chain_datum_t * l_datum = dap_chain_datum_create(DAP_CHAIN_DATUM_SIGNER, l_sign->pkey_n_sign, l_sign->header.sign_size);
+    if (!l_datum)
+        return dap_cli_server_cmd_set_reply_text(a_str_reply, "not created datum"), -1;
+    dap_cli_server_cmd_set_reply_text(a_str_reply, "hash: %s", dap_get_data_hash_str(l_datum->data, l_datum->header.data_size).s);
+    return DAP_DELETE(l_datum), l_chain->callback_add_datums(l_chain, &l_datum, 1);
 }
 
 
diff --git a/modules/net/dap_chain_node_cli_cmd_tx.c b/modules/net/dap_chain_node_cli_cmd_tx.c
index 5c7781893d0f514cd1d56bd503756982664a6232..c8e234b3ffa68953e022e89e4a3a6249f558b312 100644
--- a/modules/net/dap_chain_node_cli_cmd_tx.c
+++ b/modules/net/dap_chain_node_cli_cmd_tx.c
@@ -130,7 +130,7 @@ json_object * dap_db_tx_history_to_json(json_object* a_json_arr_reply,
                                         dap_chain_datum_tx_t * l_tx,
                                         dap_chain_t * a_chain, 
                                         const char *a_hash_out_type, 
-                                        dap_chain_net_t * l_net,
+                                        dap_chain_datum_iter_t *a_datum_iter,
                                         int l_ret_code,
                                         bool *accepted_tx,
                                         bool brief_out)
@@ -143,7 +143,8 @@ json_object * dap_db_tx_history_to_json(json_object* a_json_arr_reply,
     }
 
     dap_ledger_t *l_ledger = dap_chain_net_by_id(a_chain->net_id)->pub.ledger;
-    l_tx_token_ticker = dap_ledger_tx_get_token_ticker_by_hash(l_ledger, a_tx_hash);
+    l_tx_token_ticker = a_datum_iter ? a_datum_iter->token_ticker
+                                     : dap_ledger_tx_get_token_ticker_by_hash(l_ledger, a_tx_hash);
     if (l_tx_token_ticker) {
         json_object_object_add(json_obj_datum, "status", json_object_new_string("ACCEPTED"));
         l_tx_token_description = dap_ledger_get_description_by_ticker(l_ledger, l_tx_token_ticker);
@@ -176,15 +177,18 @@ json_object * dap_db_tx_history_to_json(json_object* a_json_arr_reply,
     dap_chain_net_srv_uid_t uid;
     char *service_name;
     dap_chain_tx_tag_action_type_t action;
+    bool srv_found = a_datum_iter ? a_datum_iter->uid.uint64 ? true : false
+                                  : dap_ledger_tx_service_info(l_ledger, a_tx_hash, &uid, &service_name, &action);
+    if (a_datum_iter)action = a_datum_iter->action;
 
-    if (dap_ledger_tx_service_info(l_ledger, a_tx_hash, &uid, &service_name, &action))
+    if (srv_found)
     {
-        json_object_object_add(json_obj_datum, "service", json_object_new_string(service_name));
+        //json_object_object_add(json_obj_datum, "service", json_object_new_string(service_name));
         json_object_object_add(json_obj_datum, "action", json_object_new_string(dap_ledger_tx_action_str(action)));
     }
     else
     {   
-        json_object_object_add(json_obj_datum, "service", json_object_new_string("UNKNOWN"));
+        //json_object_object_add(json_obj_datum, "service", json_object_new_string("UNKNOWN"));
         json_object_object_add(json_obj_datum, "action", json_object_new_string("UNKNOWN"));
     }
 
@@ -222,7 +226,7 @@ json_object * dap_db_history_tx(json_object* a_json_arr_reply,
                                  (dap_chain_datum_tx_t *)l_datum->data : NULL;
 
     if (l_tx) {
-        return dap_db_tx_history_to_json(a_json_arr_reply, a_tx_hash, &l_atom_hash,l_tx, a_chain, a_hash_out_type, l_net, l_ret_code, &accepted_tx, false);
+        return dap_db_tx_history_to_json(a_json_arr_reply, a_tx_hash, &l_atom_hash,l_tx, a_chain, a_hash_out_type, NULL, l_ret_code, &accepted_tx, false);
     } else {
         const char *l_tx_hash_str = dap_strcmp(a_hash_out_type, "hex")
                 ? dap_enc_base58_encode_hash_to_str_static(a_tx_hash)
@@ -233,9 +237,9 @@ json_object * dap_db_history_tx(json_object* a_json_arr_reply,
 }
 
 static void s_tx_header_print(json_object* json_obj_datum, dap_chain_tx_hash_processed_ht_t **a_tx_data_ht,
-                              dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_atom_hash,
+                              dap_chain_datum_tx_t *a_tx, dap_chain_datum_iter_t *a_datum_iter,
                               const char *a_hash_out_type, dap_ledger_t *a_ledger,
-                              dap_chain_hash_fast_t *a_tx_hash, int a_ret_code)
+                              dap_chain_hash_fast_t *a_tx_hash)
 {
     bool l_declined = false;
     // transaction time
@@ -254,37 +258,40 @@ static void s_tx_header_print(json_object* json_obj_datum, dap_chain_tx_hash_pro
         }
         l_tx_data->hash = *a_tx_hash;
         HASH_ADD(hh, *a_tx_data_ht, hash, sizeof(*a_tx_hash), l_tx_data);
-        const char *l_token_ticker = dap_ledger_tx_get_token_ticker_by_hash(a_ledger, a_tx_hash);
+        const char *l_token_ticker = a_datum_iter->token_ticker;        
         if (!l_token_ticker)
             l_declined = true;
     }
     char *l_tx_hash_str, *l_atom_hash_str;
     if (!dap_strcmp(a_hash_out_type, "hex")) {
         l_tx_hash_str = dap_chain_hash_fast_to_str_new(a_tx_hash);
-        l_atom_hash_str = dap_chain_hash_fast_to_str_new(a_atom_hash);
+        l_atom_hash_str = dap_chain_hash_fast_to_str_new(a_datum_iter->cur_atom_hash);
     } else {
         l_tx_hash_str = dap_enc_base58_encode_hash_to_str(a_tx_hash);
-        l_atom_hash_str = dap_enc_base58_encode_hash_to_str(a_atom_hash);
+        l_atom_hash_str = dap_enc_base58_encode_hash_to_str(a_datum_iter->cur_atom_hash);
     }
     json_object_object_add(json_obj_datum, "status", json_object_new_string(l_declined ? "DECLINED" : "ACCEPTED"));
     json_object_object_add(json_obj_datum, "hash", json_object_new_string(l_tx_hash_str));
     json_object_object_add(json_obj_datum, "atom_hash", json_object_new_string(l_atom_hash_str));
-    json_object_object_add(json_obj_datum, "ret_code", json_object_new_int(a_ret_code));
-    json_object_object_add(json_obj_datum, "ret_code_str", json_object_new_string(dap_ledger_check_error_str(a_ret_code)));
+    json_object_object_add(json_obj_datum, "ret_code", json_object_new_int(a_datum_iter->ret_code));
+    json_object_object_add(json_obj_datum, "ret_code_str", json_object_new_string(dap_ledger_check_error_str(a_datum_iter->ret_code)));
 
 
     dap_chain_net_srv_uid_t uid;
     char *service_name;
     dap_chain_tx_tag_action_type_t action;
+    bool srv_found = a_datum_iter->uid.uint64 ? true : false;
+    action = a_datum_iter->action;
     
-    if (dap_ledger_tx_service_info(a_ledger, a_tx_hash, &uid, &service_name, &action))
+    //if (dap_ledger_tx_service_info(a_ledger, a_tx_hash, &uid, &service_name, &action))
+    if (srv_found)
     {
-        json_object_object_add(json_obj_datum, "service", json_object_new_string(service_name));
+        //json_object_object_add(json_obj_datum, "service", json_object_new_string(service_name));
         json_object_object_add(json_obj_datum, "action", json_object_new_string(dap_ledger_tx_action_str(action)));
     }
     else
     {
-        json_object_object_add(json_obj_datum, "service", json_object_new_string("UNKNOWN"));
+        //json_object_object_add(json_obj_datum, "service", json_object_new_string("UNKNOWN"));
         json_object_object_add(json_obj_datum, "action", json_object_new_string("UNKNOWN"));
     }
 
@@ -339,13 +346,10 @@ json_object* dap_db_history_addr(json_object* a_json_arr_reply, dap_chain_addr_t
 
     dap_chain_addr_t  l_net_fee_addr = {};
     bool l_net_fee_used = dap_chain_net_tx_get_fee(l_net->pub.id, NULL, &l_net_fee_addr);
-    bool l_is_need_correction = false;
-    bool l_continue = false;
-    uint256_t l_corr_value = {}, l_unstake_value = {};    
     bool look_for_unknown_service = (a_srv && strcmp(a_srv,"unknown") == 0);
     size_t l_arr_start = 0;
     size_t l_arr_end = 0;
-    s_set_offset_limit_json(json_obj_datum, &l_arr_start, &l_arr_end, a_limit, a_offset, a_chain->callback_count_atom(a_chain));
+    s_set_offset_limit_json(json_obj_datum, &l_arr_start, &l_arr_end, a_limit, a_offset, a_chain->callback_count_tx(a_chain));
     
     size_t i_tmp = 0;
     size_t
@@ -368,12 +372,15 @@ json_object* dap_db_history_addr(json_object* a_json_arr_reply, dap_chain_addr_t
     {
         if (i_tmp >= l_arr_end)
             break;
-        json_object *l_corr_object = NULL;
         if (l_datum->header.type_id != DAP_CHAIN_DATUM_TX)
             // go to next datum
             continue;        
         // it's a transaction        
-        bool l_is_unstake = false;
+        bool l_is_need_correction = false;
+        bool l_continue = false;
+        uint256_t l_corr_value = {}, l_cond_value = {};
+        bool l_recv_from_cond = false, l_send_to_same_cond = false;
+        json_object *l_corr_object = NULL, *l_cond_recv_object = NULL, *l_cond_send_object = NULL;
         dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t *)l_datum->data;
         dap_list_t *l_list_in_items = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_IN_ALL, NULL);
         if (!l_list_in_items) // a bad tx
@@ -385,7 +392,8 @@ json_object* dap_db_history_addr(json_object* a_json_arr_reply, dap_chain_addr_t
         const char *l_noaddr_token = NULL;
 
         dap_hash_fast_t l_tx_hash = *l_datum_iter->cur_hash;
-        const char *l_src_token = dap_ledger_tx_get_token_ticker_by_hash(l_ledger, &l_tx_hash);
+        const char *l_src_token = l_datum_iter->token_ticker;
+        //const char *l_src_token = dap_ledger_tx_get_token_ticker_by_hash(l_ledger, &l_tx_hash);
 
         int l_src_subtype = DAP_CHAIN_TX_OUT_COND_SUBTYPE_UNDEFINED;
         for (dap_list_t *it = l_list_in_items; it; it = it->next) {
@@ -436,10 +444,8 @@ json_object* dap_db_history_addr(json_object* a_json_arr_reply, dap_chain_addr_t
                     if (l_cond_prev->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE)
                         l_noaddr_token = l_native_ticker;
                     else {
-                        if (l_cond_prev->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK) {
-                            l_is_unstake = true;
-                            l_unstake_value = l_cond_prev->header.value;
-                        }
+                        l_recv_from_cond = true;
+                        l_cond_value = l_cond_prev->header.value;
                         l_noaddr_token = l_src_token;
                     }
                 } break;
@@ -487,6 +493,7 @@ json_object* dap_db_history_addr(json_object* a_json_arr_reply, dap_chain_addr_t
             if (!l_dst_addr_present)
             {
                 json_object_put(j_arr_data);
+                j_arr_data = NULL;
                 json_object_put(j_obj_tx);
                 dap_list_free(l_list_out_items);
                 continue;
@@ -529,25 +536,20 @@ json_object* dap_db_history_addr(json_object* a_json_arr_reply, dap_chain_addr_t
                 SUM_256_256(l_fee_sum, l_value, &l_fee_sum);
             
             //tag
-            char *service_name = NULL;
+            const char *l_service_name = NULL;
             dap_chain_tx_tag_action_type_t l_action;
-            bool srv_found = dap_ledger_tx_service_info(l_ledger, &l_tx_hash, NULL, &service_name, &l_action);
+            bool srv_found = l_datum_iter->uid.uint64 ? true : false;
+            l_action = l_datum_iter->action;
+            l_service_name = dap_ledger_tx_action_str(l_action);
             if (!(l_action & a_action))
                 continue;
-
-            if (a_srv)
-            {
-              
+            if (a_srv) {
                 //skip if looking for UNKNOWN + it is known
-                if (look_for_unknown_service && srv_found) {
-                    continue;
-                }
-                            
+                if (look_for_unknown_service && srv_found)
+                    continue;                    
                 //skip if search condition provided, it not UNKNOWN and found name not match
-                if (!look_for_unknown_service && (!srv_found || strcmp(service_name, a_srv) != 0))
-                {
+                if (!look_for_unknown_service && (!srv_found || strcmp(l_service_name, a_srv) != 0))
                     continue;
-                }
             }
 
             if (l_dst_addr && dap_chain_addr_compare(l_dst_addr, a_addr)) {  
@@ -557,8 +559,8 @@ json_object* dap_db_history_addr(json_object* a_json_arr_reply, dap_chain_addr_t
                     break;
                 }             
                 if (!l_header_printed) {               
-                    s_tx_header_print(j_obj_tx, &l_tx_data_ht, l_tx, l_datum_iter->cur_atom_hash,
-                                      a_hash_out_type, l_ledger, &l_tx_hash, l_datum_iter->ret_code);
+                    s_tx_header_print(j_obj_tx, &l_tx_data_ht, l_tx, l_datum_iter,
+                                      a_hash_out_type, l_ledger, &l_tx_hash);
                     l_header_printed = true;
                     l_count++;
                     i_tmp++;
@@ -571,8 +573,8 @@ json_object* dap_db_history_addr(json_object* a_json_arr_reply, dap_chain_addr_t
                     l_src_str = dap_chain_addr_to_str_static(l_src_addr);
                 else
                     l_src_str = dap_chain_tx_out_cond_subtype_to_str(l_src_subtype);
-                if (l_is_unstake)
-                    l_value = l_unstake_value;
+                if (l_recv_from_cond)
+                    l_value = l_cond_value;
                 else if (!dap_strcmp(l_native_ticker, l_noaddr_token)) {
                     l_is_need_correction = true;
                     l_corr_value = l_value;
@@ -592,10 +594,12 @@ json_object* dap_db_history_addr(json_object* a_json_arr_reply, dap_chain_addr_t
                 json_object_object_add(j_obj_data, "token", l_dst_token ? json_object_new_string(l_dst_token)
                                                                             : json_object_new_string("UNKNOWN"));
                 json_object_object_add(j_obj_data, "source_address", json_object_new_string(l_src_str));
-                if (l_is_need_correction)
-                    l_corr_object = j_obj_data;
+                if (l_recv_from_cond && !l_cond_recv_object)
+                    l_cond_recv_object = j_obj_data;
                 else
                     json_object_array_add(j_arr_data, j_obj_data);
+                if (l_is_need_correction)
+                    l_corr_object = j_obj_data;
                 
             } else if (!l_src_addr || dap_chain_addr_compare(l_src_addr, a_addr)) {
                 if (!l_dst_addr && ((dap_chain_tx_out_cond_t *)it->data)->header.subtype == l_src_subtype && l_src_subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE)
@@ -608,17 +612,23 @@ json_object* dap_db_history_addr(json_object* a_json_arr_reply, dap_chain_addr_t
                     break;
                 }                                
                 if (!l_header_printed) {                    
-                    s_tx_header_print(j_obj_tx, &l_tx_data_ht, l_tx, l_datum_iter->cur_atom_hash,
-                                      a_hash_out_type, l_ledger, &l_tx_hash, l_datum_iter->ret_code);
+                    s_tx_header_print(j_obj_tx, &l_tx_data_ht, l_tx, l_datum_iter,
+                                      a_hash_out_type, l_ledger, &l_tx_hash);
                     l_header_printed = true;
                     l_count++;
                     i_tmp++;
                     l_src_token ? l_tx_ledger_accepted++ : l_tx_ledger_rejected++;
                 }
 
-                const char *l_dst_addr_str = l_dst_addr ? dap_chain_addr_to_str_static(l_dst_addr)
-                                                        : dap_chain_tx_out_cond_subtype_to_str(
-                                                              ((dap_chain_tx_out_cond_t *)it->data)->header.subtype);
+                const char *l_dst_addr_str = NULL;
+                if (l_dst_addr)
+                    l_dst_addr_str = dap_chain_addr_to_str_static(l_dst_addr);
+                else {
+                    dap_chain_tx_out_cond_subtype_t l_dst_subtype = ((dap_chain_tx_out_cond_t *)it->data)->header.subtype;
+                    l_dst_addr_str = dap_chain_tx_out_cond_subtype_to_str(l_dst_subtype);
+                    if (l_recv_from_cond && l_dst_subtype != DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE && l_dst_subtype == l_src_subtype)
+                        l_send_to_same_cond = true;
+                }
                 const char *l_coins_str, *l_value_str = dap_uint256_to_char(l_value, &l_coins_str);
                                 
                 json_object * j_obj_data = json_object_new_object();
@@ -634,13 +644,45 @@ json_object* dap_db_history_addr(json_object* a_json_arr_reply, dap_chain_addr_t
                 json_object_object_add(j_obj_data, "token", l_dst_token ? json_object_new_string(l_dst_token)
                                                                         : json_object_new_string("UNKNOWN"));
                 json_object_object_add(j_obj_data, "destination_address", json_object_new_string(l_dst_addr_str));
-                json_object_array_add(j_arr_data, j_obj_data);                
+                if (l_send_to_same_cond && !l_cond_send_object)
+                    l_cond_send_object = j_obj_data;
+                else
+                    json_object_array_add(j_arr_data, j_obj_data);
             }
         }  
-        if (l_continue){
-            l_continue = false;
+        if (l_continue)
             continue;
+
+        if (l_is_need_correction) {
+            SUM_256_256(l_corr_value, l_fee_sum, &l_corr_value);
+            const char *l_coins_str, *l_value_str = dap_uint256_to_char(l_corr_value, &l_coins_str);
+            json_object_object_add(l_corr_object, "recv_coins", json_object_new_string(l_coins_str));
+            json_object_object_add(l_corr_object, "recv_datoshi", json_object_new_string(l_value_str));
         }
+        if (l_send_to_same_cond) {
+            json_object *l_cond_recv_value_obj = json_object_object_get(l_cond_recv_object, "recv_datoshi");
+            const char *l_cond_recv_value_str = json_object_get_string(l_cond_recv_value_obj);
+            uint256_t l_cond_recv_value = dap_uint256_scan_uninteger(l_cond_recv_value_str);
+            json_object *l_cond_send_value_obj = json_object_object_get(l_cond_send_object, "send_datoshi");
+            const char *l_cond_send_value_str = json_object_get_string(l_cond_send_value_obj);
+            uint256_t l_cond_send_value = dap_uint256_scan_uninteger(l_cond_send_value_str);
+            assert(!IS_ZERO_256(l_cond_recv_value) && !IS_ZERO_256(l_cond_send_value));
+            int l_direction = compare256(l_cond_recv_value, l_cond_send_value);
+            if (l_direction > 0) {
+                SUBTRACT_256_256(l_cond_recv_value, l_cond_send_value, &l_cond_recv_value);
+                const char *l_coins_str, *l_value_str = dap_uint256_to_char(l_cond_recv_value, &l_coins_str);
+                json_object_object_add(l_cond_recv_object, "recv_coins", json_object_new_string(l_coins_str));
+                json_object_object_add(l_cond_recv_object, "recv_datoshi", json_object_new_string(l_value_str));
+                json_object_array_add(j_arr_data, l_cond_recv_object);
+            } else if (l_direction < 0) {
+                SUBTRACT_256_256(l_cond_send_value, l_cond_recv_value, &l_cond_send_value);
+                const char *l_coins_str, *l_value_str = dap_uint256_to_char(l_cond_send_value, &l_coins_str);
+                json_object_object_add(l_cond_send_object, "send_coins", json_object_new_string(l_coins_str));
+                json_object_object_add(l_cond_send_object, "send_datoshi", json_object_new_string(l_value_str));
+                json_object_array_add(j_arr_data, l_cond_send_object);
+            }
+        } else if (l_recv_from_cond)
+            json_object_array_add(j_arr_data, l_cond_recv_object);
 
         if (json_object_array_length(j_arr_data) > 0) {
             json_object_object_add(j_obj_tx, "data", j_arr_data);
@@ -651,16 +693,6 @@ json_object* dap_db_history_addr(json_object* a_json_arr_reply, dap_chain_addr_t
             json_object_put(j_obj_tx);
         }
         dap_list_free(l_list_out_items);
-        if (l_is_need_correction && l_corr_object) {
-            SUM_256_256(l_corr_value, l_fee_sum, &l_corr_value);
-            const char *l_coins_str, *l_value_str = dap_uint256_to_char(l_corr_value, &l_coins_str);
-            json_object_object_add(l_corr_object, "recv_coins", json_object_new_string(l_coins_str));
-            json_object_object_add(l_corr_object, "recv_datoshi", json_object_new_string(l_value_str));
-            json_object * j_arr_correct = json_object_new_object();            
-            json_object_object_add(j_arr_correct, "correction", l_corr_object);
-            json_object_array_add(json_obj_datum, j_arr_correct);
-            l_is_need_correction = false;
-        }
     }
     a_chain->callback_datum_iter_delete(l_datum_iter);
     // delete hashes
@@ -685,7 +717,8 @@ json_object* dap_db_history_addr(json_object* a_json_arr_reply, dap_chain_addr_t
     return json_obj_datum;
 }
 
-static int s_json_tx_history_pack(json_object* a_json_arr_reply, json_object** a_json_obj_datum, dap_chain_datum_t * a_datum,  dap_chain_net_t *a_net,
+static int s_json_tx_history_pack(json_object* a_json_arr_reply, json_object** a_json_obj_datum, dap_chain_datum_iter_t *a_datum_iter,
+                                  dap_chain_datum_t * a_datum,
                                   dap_chain_t *a_chain, dap_chain_tx_tag_action_type_t a_action,
                                   const char *a_hash_out_type, bool a_out_brief, size_t* a_accepted,
                                   size_t* a_rejected, bool a_look_for_unknown_service, const char *a_srv)
@@ -694,19 +727,18 @@ static int s_json_tx_history_pack(json_object* a_json_arr_reply, json_object** a
     dap_hash_fast_t l_ttx_hash = {0};
     dap_hash_fast(l_tx, a_datum->header.data_size, &l_ttx_hash);
 
-    char *service_name = NULL;
+    const char *service_name = NULL;
     dap_chain_tx_tag_action_type_t l_action = DAP_CHAIN_TX_TAG_ACTION_UNKNOWN;
-
-    dap_ledger_t *l_ledger = a_net->pub.ledger;
-    bool srv_found = dap_ledger_tx_service_info(l_ledger, &l_ttx_hash, NULL, &service_name, &l_action);
+    //bool srv_found = a_datum_iter->uid.uint64 ? true : false;
+    l_action = a_datum_iter->action;
+    service_name = dap_ledger_tx_action_str(l_action);
 
     if (!(l_action & a_action))
         return 1;
 
     if (a_srv)
     {
-        char *service_name = NULL;
-        bool srv_found = dap_ledger_tx_service_info(l_ledger, &l_ttx_hash, NULL, &service_name, NULL);
+        bool srv_found = a_datum_iter->uid.uint64 ? true : false;
         //skip if looking for UNKNOWN + it is known
         if (a_look_for_unknown_service && srv_found) {
             return 1;
@@ -720,7 +752,7 @@ static int s_json_tx_history_pack(json_object* a_json_arr_reply, json_object** a
     }
 
     bool accepted_tx;
-    *a_json_obj_datum = dap_db_tx_history_to_json(a_json_arr_reply, &l_ttx_hash, NULL, l_tx, a_chain, a_hash_out_type, a_net, 0, &accepted_tx, a_out_brief);
+    *a_json_obj_datum = dap_db_tx_history_to_json(a_json_arr_reply, &l_ttx_hash, NULL, l_tx, a_chain, a_hash_out_type, a_datum_iter, 0, &accepted_tx, a_out_brief);
     if (!*a_json_obj_datum) {
         log_it(L_CRITICAL, "%s", c_error_memory_alloc);
         return 2;
@@ -744,94 +776,55 @@ json_object *dap_db_history_tx_all(json_object* a_json_arr_reply, dap_chain_t *a
             l_tx_ledger_accepted = 0,
             l_tx_ledger_rejected = 0,
             l_count = 0,
-            l_count_tx = 0;
-        int res = 0;
-        dap_chain_cell_t    *l_cell = NULL,
-                            *l_cell_tmp = NULL;
-        dap_chain_atom_iter_t *l_iter = NULL;
+            i_tmp = 0;
+        int res = 0;        
         json_object * json_arr_out = json_object_new_array();
         json_object * json_tx_history = NULL;        
         size_t l_arr_start = 0;
         size_t l_arr_end = 0;
-        s_set_offset_limit_json(json_arr_out, &l_arr_start, &l_arr_end, a_limit, a_offset, a_chain->callback_count_atom(a_chain));
+        s_set_offset_limit_json(json_arr_out, &l_arr_start, &l_arr_end, a_limit, a_offset, a_chain->callback_count_tx(a_chain));
         
         bool look_for_unknown_service = (a_srv && strcmp(a_srv,"unknown") == 0);
-        if(a_head)
-            HASH_ITER(hh, a_chain->cells, l_cell, l_cell_tmp) {            
-                if ((l_count_tx >= l_arr_end)&&(l_arr_end))
-                    break;
-                l_iter = a_chain->callback_atom_iter_create(a_chain, l_cell->id, NULL);
-                size_t l_atom_size = 0;
-                dap_chain_atom_ptr_t l_ptr = a_chain->callback_atom_iter_get(l_iter, DAP_CHAIN_ITER_OP_FIRST, &l_atom_size);
-                while (l_ptr && l_atom_size && ((l_count_tx < l_arr_end)||(!l_arr_end))) {
-                    size_t l_datums_count = 0;
-                    dap_chain_datum_t **l_datums = l_cell->chain->callback_atom_get_datums(l_ptr, l_atom_size, &l_datums_count);
-                    for (size_t i = 0; i < l_datums_count && ((l_count_tx < l_arr_end)||(!l_arr_end)); i++) {
-                        if (l_datums[i]->header.type_id == DAP_CHAIN_DATUM_TX) { 
-                            if (l_count_tx < l_arr_start) {
-                                l_count_tx++;
-                                continue;
-                            }
-                            res = s_json_tx_history_pack(a_json_arr_reply, &json_tx_history, l_datums[i], a_net, a_chain, a_action, a_hash_out_type, out_brief, 
-                                                        &l_tx_ledger_accepted, &l_tx_ledger_rejected, look_for_unknown_service, a_srv); 
-                            if (res == 1)
-                                continue;
-                            else if (res == 2)
-                            {
-                                json_object_put(json_arr_out);
-                                return NULL;
-                            }
-                            json_object_object_add(json_tx_history, "tx number", json_object_new_uint64(l_count+1));                     
-                            json_object_array_add(json_arr_out, json_tx_history);
-                            ++l_count_tx;
-                            l_count++;
-                        }
-                    }
-                    DAP_DEL_Z(l_datums);
-                    l_ptr = a_chain->callback_atom_iter_get(l_iter, DAP_CHAIN_ITER_OP_NEXT, &l_atom_size);
-                }
-                l_cell->chain->callback_atom_iter_delete(l_iter);
-            }
-        else 
+        // load transactions
+        dap_chain_datum_iter_t *l_datum_iter = a_chain->callback_datum_iter_create(a_chain);
+        
+        dap_chain_datum_callback_iters  iter_begin;
+        dap_chain_datum_callback_iters  iter_direc;
+        iter_begin = a_head ? a_chain->callback_datum_iter_get_first
+                            : a_chain->callback_datum_iter_get_last;
+        iter_direc = a_head ? a_chain->callback_datum_iter_get_next
+                            : a_chain->callback_datum_iter_get_prev;
+        
+        for (dap_chain_datum_t *l_datum = iter_begin(l_datum_iter);
+                                l_datum;
+                                l_datum = iter_direc(l_datum_iter))
         {
-            l_cell_tmp = HASH_LAST(a_chain->cells);
-            for(; l_cell_tmp; l_cell_tmp = l_cell_tmp->hh.prev){
-                if ((l_count_tx >= l_arr_end)&&(l_arr_end))
-                    break;
-                l_iter = a_chain->callback_atom_iter_create(a_chain, l_cell_tmp->id, NULL);
-                size_t l_atom_size = 0;
-                dap_chain_atom_ptr_t l_ptr = a_chain->callback_atom_iter_get(l_iter, DAP_CHAIN_ITER_OP_LAST, &l_atom_size);
-                while (l_ptr && l_atom_size && ((l_count_tx < l_arr_end)||(!l_arr_end))) {
-                    size_t l_datums_count = 0;
-                    dap_chain_datum_t **l_datums = l_cell_tmp->chain->callback_atom_get_datums(l_ptr, l_atom_size, &l_datums_count);
-                    for (size_t i = l_datums_count; i && ((l_count_tx < l_arr_end)||(!l_arr_end)); i--) {
-                        if (l_datums[i-1]->header.type_id == DAP_CHAIN_DATUM_TX) {
-                            if (l_count_tx < l_arr_start) {
-                                l_count_tx++;
-                                continue;
-                            }
-                            res = s_json_tx_history_pack(a_json_arr_reply, &json_tx_history, l_datums[i-1], a_net, a_chain, a_action, a_hash_out_type, out_brief, 
-                                                        &l_tx_ledger_accepted, &l_tx_ledger_rejected, look_for_unknown_service, a_srv); 
-                            if (res == 1)
-                                continue;
-                            else if (res == 2)
-                            {
-                                json_object_put(json_arr_out);
-                                return NULL;
-                            }
-                            json_object_object_add(json_tx_history, "tx number", json_object_new_uint64(l_count+1));                     
-                            json_object_array_add(json_arr_out, json_tx_history);
-                            ++l_count_tx;
-                            l_count++;
-                        }
-                    }
-                    DAP_DEL_Z(l_datums);
-                    l_ptr = a_chain->callback_atom_iter_get(l_iter, DAP_CHAIN_ITER_OP_PREV, &l_atom_size);
-                }
-                l_cell_tmp->chain->callback_atom_iter_delete(l_iter);
+            if (i_tmp >= l_arr_end)
+                break;
+            if (l_datum->header.type_id != DAP_CHAIN_DATUM_TX)
+                // go to next datum
+                continue;
+            
+            if (i_tmp < l_arr_start) {
+                i_tmp++;
+                continue;
             }
-        }
+            res = s_json_tx_history_pack(a_json_arr_reply, &json_tx_history, l_datum_iter, l_datum, a_chain, a_action, a_hash_out_type, out_brief,
+                                        &l_tx_ledger_accepted, &l_tx_ledger_rejected, look_for_unknown_service, a_srv);
+            if (res == 1)
+                continue;
+            else if (res == 2)
+            {
+                json_object_put(json_arr_out);
+                return NULL;
+            }
+            json_object_object_add(json_tx_history, "tx number", json_object_new_uint64(l_count+1));                     
+            json_object_array_add(json_arr_out, json_tx_history);
+            ++i_tmp;
+            l_count++;            
+        }        
         log_it(L_DEBUG, "END getting tx from chain");
+        a_chain->callback_datum_iter_delete(l_datum_iter);
 
         json_object_object_add(json_obj_summary, "network", json_object_new_string(a_net->pub.name));
         json_object_object_add(json_obj_summary, "chain", json_object_new_string(a_chain->name));
diff --git a/modules/net/include/dap_chain_ledger.h b/modules/net/include/dap_chain_ledger.h
index 9074e4dcf58da3255a763fcbac0d874c7d7c9c5e..88bde9717b40dbe9cad1153e0ca45228882317da 100644
--- a/modules/net/include/dap_chain_ledger.h
+++ b/modules/net/include/dap_chain_ledger.h
@@ -200,6 +200,12 @@ typedef struct dap_ledger_datum_iter {
     void *cur_ledger_tx_item;
 } dap_ledger_datum_iter_t;
 
+typedef struct dap_ledger_datum_iter_data {
+    char token_ticker[DAP_CHAIN_TICKER_SIZE_MAX];
+    uint32_t action;
+    dap_chain_net_srv_uid_t uid;
+} dap_ledger_datum_iter_data_t;
+
 typedef int (*dap_ledger_verificator_callback_t)(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_t *a_tx_out_cond, dap_chain_datum_tx_t *a_tx_in, bool a_owner);
 typedef void (*dap_ledger_updater_callback_t)(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx_in, dap_hash_fast_t *a_tx_in_hash, dap_chain_tx_out_cond_t *a_prev_cond);
 typedef void (*dap_ledger_delete_callback_t)(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx_in, dap_chain_tx_out_cond_t *a_prev_cond);
@@ -271,8 +277,8 @@ DAP_STATIC_INLINE char *dap_ledger_get_gdb_group(dap_ledger_t *a_ledger, const c
  *
  * return 1 OK, -1 error
  */
-int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash, bool a_from_threshold);
-int dap_ledger_tx_load(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_hash_fast_t *a_tx_hash);
+int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash, bool a_from_threshold, dap_ledger_datum_iter_data_t *a_datum_index_data);
+int dap_ledger_tx_load(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_hash_fast_t *a_tx_hash, dap_ledger_datum_iter_data_t *a_datum_index_data);
 int dap_ledger_tx_remove(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash);
 
 int dap_ledger_tx_add_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, size_t a_datum_size, dap_hash_fast_t *a_datum_hash);
@@ -451,6 +457,7 @@ dap_chain_datum_tx_t *dap_ledger_datum_iter_get_last(dap_ledger_datum_iter_t *a_
 void dap_ledger_tx_add_notify(dap_ledger_t *a_ledger, dap_ledger_tx_add_notify_t a_callback, void *a_arg);
 void dap_ledger_bridged_tx_notify_add(dap_ledger_t *a_ledger, dap_ledger_bridged_tx_notify_t a_callback, void *a_arg);
 
+bool dap_ledger_datum_is_blacklisted(dap_ledger_t *a_ledger, dap_hash_fast_t a_hash);
 
 bool dap_ledger_cache_enabled(dap_ledger_t *a_ledger);
 void dap_ledger_set_cache_tx_check_callback(dap_ledger_t *a_ledger, dap_ledger_cache_tx_check_callback_t a_callback);
diff --git a/modules/net/include/dap_chain_net.h b/modules/net/include/dap_chain_net.h
index 74cff108864d8dd81e5f7d1390e8a9a0f5fd162f..ca991e0d43c20462f6612cb9fa81b5448055e3d1 100644
--- a/modules/net/include/dap_chain_net.h
+++ b/modules/net/include/dap_chain_net.h
@@ -54,26 +54,24 @@ typedef enum dap_chain_net_state {
     NET_STATE_ONLINE
 } dap_chain_net_state_t;
 
+static const char s_gdb_nodes_postfix[] = ".nodes.list";
+
 typedef struct dap_chain_net {
     struct {
         dap_chain_net_id_t id;
-        char * name;
-        char * gdb_groups_prefix;
-        char * gdb_nodes;
-
+        char name[DAP_CHAIN_NET_NAME_MAX + 1], gdb_nodes[DAP_CHAIN_NET_NAME_MAX + sizeof(s_gdb_nodes_postfix) + 1];
+        const char *gdb_groups_prefix, *native_ticker;
         dap_list_t *keys;               // List of PoA certs for net
-
-        bool mempool_autoproc;
-
-        dap_chain_t *chains; // double-linked list of chains
-        const char *native_ticker;
+        dap_chain_t *chains;            // double-linked list of chains
         dap_ledger_t *ledger;
-        // Net fee
-        uint256_t fee_value;
+        uint256_t fee_value;            // Net fee
         dap_chain_addr_t fee_addr;
-        dap_list_t *bridged_networks;   // List of bridged network ID's allowed to cross-network TX
+        dap_chain_net_id_t *bridged_networks;   // List of bridged network ID's allowed to cross-network TX
+        uint16_t bridged_networks_count;
         dap_config_t *config;
+        bool mempool_autoproc;
     } pub;
+    UT_hash_handle hh, hh2;
     uint8_t pvt[];
 } dap_chain_net_t;
 
@@ -196,7 +194,7 @@ void dap_chain_net_srv_order_add_notify_callback(dap_chain_net_t *a_net, dap_sto
  */
 dap_list_t *dap_chain_datum_list(dap_chain_net_t *a_net, dap_chain_t *a_chain, dap_chain_datum_filter_func_t *a_filter_func, void *a_filter_func_param);
 
-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);
+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, void *a_datum_index_data);
 int dap_chain_datum_remove(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);
diff --git a/modules/net/include/dap_chain_net_balancer.h b/modules/net/include/dap_chain_net_balancer.h
index b5e1d0bd26bf0d06335676b698f41256e79895e7..ccada8e10d97086f34654e607c3113a8a5bde7c2 100644
--- a/modules/net/include/dap_chain_net_balancer.h
+++ b/modules/net/include/dap_chain_net_balancer.h
@@ -30,6 +30,8 @@ along with any CellFrame SDK based project.  If not, see <http://www.gnu.org/lic
 #define DAP_BALANCER_PROTOCOL_VERSION 2
 #define DAP_BALANCER_MAX_REPLY_SIZE 2048
 
+typedef struct dap_balancer_request_info dap_balancer_request_info_t;
+
 typedef struct dap_chain_net_links {
     uint64_t count_node;
     byte_t nodes_info[];
@@ -40,6 +42,15 @@ typedef enum dap_balancer_type {
     DAP_CHAIN_NET_BALANCER_TYPE_DNS
 } dap_balancer_type_t;
 
+typedef struct dap_balancer_link_request {
+    const char* host_addr;
+    uint16_t host_port;
+    dap_chain_net_t *net;
+    dap_worker_t *worker;
+    uint16_t required_links_count;
+    dap_balancer_request_info_t *request_info;
+    dap_balancer_type_t type;
+} dap_balancer_link_request_t;
 
 DAP_STATIC_INLINE const char *dap_chain_net_balancer_type_to_str(dap_balancer_type_t a_type)
 {
@@ -54,4 +65,4 @@ void dap_chain_net_balancer_http_issue_link(dap_http_simple_t *a_http_simple, vo
 dap_link_info_t *dap_chain_net_balancer_dns_issue_link(const char *a_net_name);
 int dap_chain_net_balancer_handshake(dap_chain_node_info_t *a_node_info, dap_chain_net_t * a_net);
 dap_string_t *dap_chain_net_balancer_get_node_str(dap_chain_net_t *a_net);
-int dap_chain_net_balancer_request(dap_chain_net_t *a_net, const char *a_host_addr, uint16_t a_host_port, int a_balancer_type);
\ No newline at end of file
+void dap_chain_net_balancer_request(void *a_arg);
\ No newline at end of file
diff --git a/modules/net/include/dap_chain_net_decree.h b/modules/net/include/dap_chain_net_decree.h
index 270db17d7677121195c387e3b85eced5c8c7bb23..6cf2e6eff0b9f651d0826fb6b678d18a25ac5f2d 100644
--- a/modules/net/include/dap_chain_net_decree.h
+++ b/modules/net/include/dap_chain_net_decree.h
@@ -36,7 +36,7 @@ int dap_chain_net_decree_deinit(dap_chain_net_t *a_net);
 
 void dap_chain_net_decree_purge(dap_chain_net_t *a_net);
 
-int dap_chain_net_decree_apply(dap_hash_fast_t *a_decree_hash, dap_chain_datum_decree_t * a_decree, dap_chain_t *a_chain);
+int dap_chain_net_decree_apply(dap_hash_fast_t *a_decree_hash, dap_chain_datum_decree_t * a_decree, dap_chain_t *a_chain, bool a_anchored);
 int dap_chain_net_decree_verify(dap_chain_net_t *a_net, dap_chain_datum_decree_t *a_decree, size_t a_data_size, dap_chain_hash_fast_t *a_decree_hash);
 int dap_chain_net_decree_load(dap_chain_datum_decree_t * a_decree, dap_chain_t *a_chain, dap_chain_hash_fast_t *a_decree_hash);
 dap_chain_datum_decree_t *dap_chain_net_decree_get_by_hash(dap_chain_net_t *a_net, dap_hash_fast_t *a_hash, bool *is_applied);
diff --git a/modules/net/include/dap_chain_node.h b/modules/net/include/dap_chain_node.h
index 6aa06cce6f52db16434e987487561e8153b4837a..320748529e2f4747b4e5d5d46f30379baa4b87a4 100644
--- a/modules/net/include/dap_chain_node.h
+++ b/modules/net/include/dap_chain_node.h
@@ -56,6 +56,7 @@ typedef struct dap_chain_node_info {
 // using to easy sorting and formin in balancer
 typedef struct dap_chain_node_states_info {
     dap_link_info_t link_info;
+    dap_chain_node_role_t role;
     uint64_t events_count;
     uint64_t atoms_count;
     uint32_t downlinks_count;
diff --git a/modules/net/include/dap_chain_node_cli_cmd_tx.h b/modules/net/include/dap_chain_node_cli_cmd_tx.h
index cc045075434421469ecb70ff25f68e1567888097..442f895e7edd3ad5173681ecfd8903cb0741744b 100644
--- a/modules/net/include/dap_chain_node_cli_cmd_tx.h
+++ b/modules/net/include/dap_chain_node_cli_cmd_tx.h
@@ -51,7 +51,7 @@ json_object * dap_db_tx_history_to_json(json_object* a_json_arr_reply,
                                         dap_chain_datum_tx_t * l_tx,
                                         dap_chain_t * a_chain, 
                                         const char *a_hash_out_type, 
-                                        dap_chain_net_t * l_net,
+                                        dap_chain_datum_iter_t *a_datum_iter,
                                         int l_ret_code,
                                         bool *accepted_tx,
                                         bool out_brief);
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 eceb9a2296f6b8c1b7cc52c51998300eac599931..84ee2e167286c8cbfe14bdbe29dce38215cf5351 100644
--- a/modules/service/stake/dap_chain_net_srv_stake_lock.c
+++ b/modules/service/stake/dap_chain_net_srv_stake_lock.c
@@ -1043,10 +1043,8 @@ static int s_stake_lock_callback_verificator(dap_ledger_t *a_ledger, dap_chain_t
             if (!l_burning_tx) {
                 char l_burning_tx_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE] = { '\0' };
                 dap_hash_fast_to_str(&l_burning_tx_hash, l_burning_tx_hash_str, DAP_CHAIN_HASH_FAST_STR_SIZE);
-                char *l_take_tx_hash_str;
-                dap_get_data_hash_str_static(a_tx_in, dap_chain_datum_tx_get_size(a_tx_in), l_take_tx_hash_str);
                 debug_if(s_debug_more, L_ERROR, "[Legacy] Can't find burning tx with hash %s, obtained from the receipt of take tx %s",
-                       l_burning_tx_hash_str, l_take_tx_hash_str);
+                                                l_burning_tx_hash_str, dap_get_data_hash_str(a_tx_in, dap_chain_datum_tx_get_size(a_tx_in)).s);
                 return -10;
             }
         } else
diff --git a/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c b/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c
index 6b1c08f6d9078a36286110738aed9efd0c92de13..283f78856f8622a16833a82f823d5e8b57d281d1 100644
--- a/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c
+++ b/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c
@@ -497,10 +497,10 @@ void dap_chain_net_srv_stake_key_update(dap_chain_addr_t *a_signing_addr, uint25
     if (!l_stake)
         return; // It's update for non delegated key, it's OK
     HASH_DELETE(ht, l_srv_stake->tx_itemlist, l_stake);
+    char *l_old_value_str = dap_chain_balance_to_coins(l_stake->locked_value);
     l_stake->locked_value = l_stake->value = a_new_value;
     l_stake->tx_hash = *a_new_tx_hash;
     HASH_ADD(ht, l_srv_stake->tx_itemlist, tx_hash, sizeof(dap_hash_fast_t), l_stake);
-    char *l_old_value_str = dap_chain_balance_to_coins(l_stake->locked_value);
     const char *l_new_value_str; dap_uint256_to_char(a_new_value, &l_new_value_str);
     log_it(L_NOTICE, "Updated key with fingerprint %s and locked value %s to new locked value %s for node " NODE_ADDR_FP_STR,
                             dap_chain_hash_fast_to_str_static(&a_signing_addr->data.hash_fast), l_old_value_str,
diff --git a/modules/service/xchange/dap_chain_net_srv_xchange.c b/modules/service/xchange/dap_chain_net_srv_xchange.c
index bc9878fc5c1ad6a3becd01ee500de1ba64d070b2..bd3fb71ccbde0dae3e710a756d36264af3a8aac8 100644
--- a/modules/service/xchange/dap_chain_net_srv_xchange.c
+++ b/modules/service/xchange/dap_chain_net_srv_xchange.c
@@ -1775,7 +1775,6 @@ static bool s_string_append_tx_cond_info( dap_string_t * a_reply_str,
                                          tx_opt_status_t a_filter_by_status,
                                          bool a_print_prev_hash, bool a_print_status, bool a_print_ts)
 {
-    enum{TX_TYPE_NONE, TX_TYPE_ORDER, TX_TYPE_EXCHANGE, TX_TYPE_INVALIDATE};
     size_t l_tx_size = dap_chain_datum_tx_get_size(a_tx);
 
     dap_hash_fast_t l_tx_hash = {0};
diff --git a/modules/type/blocks/dap_chain_cs_blocks.c b/modules/type/blocks/dap_chain_cs_blocks.c
index 5e2e7be22d37749bb9db28d5f7265e8206499229..521468c0b8baeaa5785cd9f0c07c527e0e4ba0f2 100644
--- a/modules/type/blocks/dap_chain_cs_blocks.c
+++ b/modules/type/blocks/dap_chain_cs_blocks.c
@@ -42,6 +42,9 @@ typedef struct dap_chain_block_datum_index {
     time_t ts_added;
     dap_chain_block_cache_t *block_cache;
     size_t datum_index;
+    char token_ticker[DAP_CHAIN_TICKER_SIZE_MAX];
+    dap_chain_net_srv_uid_t service_uid;
+    dap_chain_tx_tag_action_type_t action;
     UT_hash_handle hh;
 } dap_chain_block_datum_index_t;
 
@@ -189,7 +192,7 @@ int dap_chain_cs_blocks_init()
             "block -net <net_name> [-chain <chain_name>] dump <block_hash>\n"
                 "\t\tDump block info\n\n"
 
-            "block -net <net_name> [-chain <chain_name>] list [{signed | first_signed}] [-limit] [-offset]"
+            "block -net <net_name> [-chain <chain_name>] list [{signed | first_signed}] [-limit] [-offset] [-head]"
             " [-from_hash <block_hash>] [-to_hash <block_hash>] [-from_date <YYMMDD>] [-to_date <YYMMDD>]"
             " [{-cert <signing_cert_name> | -pkey_hash <signing_cert_pkey_hash>}] [-unspent]]\n"
                 "\t\t List blocks\n\n"
@@ -210,11 +213,10 @@ int dap_chain_cs_blocks_init()
 
         "Reward for block signs:\n"
             "block -net <net_name> [-chain <chain_name>] reward set"
-            " -cert <poa_cert_name> -value <value>\n"
+            " -poa_cert <poa_cert_name> -value <value>\n"
                 "\t\t Set base reward for sign for one block at one minute\n\n"
 
-            "block -net <net_name> [-chain <chain_name>] reward show"
-            " -cert <poa_cert_name> -value <value>\n"
+            "block -net <net_name> [-chain <chain_name>] reward show\n"
                 "\t\t Show base reward for sign for one block at one minute\n\n"
 
             "block -net <net_name> [-chain <chain_name>] reward collect"
@@ -473,7 +475,7 @@ static void s_cli_meta_hex_print(json_object* a_json_obj_out, const char * a_met
 {
     int l_len = a_meta->hdr.data_size * 2 + 5;
     char *l_str = DAP_NEW_STACK_SIZE(char, l_len);
-    snprintf(l_str, 2, "0x");
+    strcpy(l_str, "0x");
     dap_bin2hex(l_str + 2, a_meta->data, a_meta->hdr.data_size);
     json_object_object_add(a_json_obj_out, a_meta_title, json_object_new_string(l_str));
 }
@@ -530,6 +532,22 @@ static void s_print_autocollect_table(dap_chain_net_t *a_net, json_object *a_jso
     DAP_DEL_MULTY(l_key, l_val);
 }
 
+
+
+static int block_list_sort_by_date(const void *a, const void *b)
+{
+    struct json_object *obj_a = *(struct json_object **)a;
+    struct json_object *obj_b = *(struct json_object **)b;
+
+    struct json_object *timestamp_a = json_object_object_get(obj_a, "timestamp");
+    struct json_object *timestamp_b = json_object_object_get(obj_b, "timestamp");
+
+    int64_t time_a = json_object_get_int64(timestamp_a);
+    int64_t time_b = json_object_get_int64(timestamp_b);
+
+    return time_a - time_b;
+}
+
 /**
  * @brief s_cli_blocks
  * @param argc
@@ -756,7 +774,7 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply)
                     json_object_object_add(json_obj_meta, "# -", json_object_new_string(l_hexbuf));
                     int l_len = l_meta->hdr.data_size * 2 + 5;
                     char *l_data_hex = DAP_NEW_STACK_SIZE(char, l_len);
-                    snprintf(l_data_hex, 2, "0x");
+                    strcpy(l_data_hex, "0x");
                     dap_bin2hex(l_data_hex + 2, l_meta->data, l_meta->hdr.data_size);
                     json_object_object_add(json_obj_meta, "Data hex - ", json_object_new_string(l_data_hex)); }
                 }
@@ -976,15 +994,27 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply)
                 char l_buf[DAP_TIME_STR_SIZE];
                 json_object* json_obj_bl_cache = json_object_new_object();
                 dap_time_to_str_rfc822(l_buf, DAP_TIME_STR_SIZE, l_ts);
-                json_object_object_add(json_obj_bl_cache, "block",json_object_new_uint64(i_tmp));
+                json_object_object_add(json_obj_bl_cache, "#",json_object_new_uint64(i_tmp));
+                json_object_object_add(json_obj_bl_cache, "block number",json_object_new_uint64(l_block_cache->block_number));
                 json_object_object_add(json_obj_bl_cache, "hash",json_object_new_string(l_block_cache->block_hash_str));
+                json_object_object_add(json_obj_bl_cache, "timestamp", json_object_new_uint64(l_ts));
                 json_object_object_add(json_obj_bl_cache, "ts_create",json_object_new_string(l_buf));
                 json_object_array_add(json_arr_bl_cache_out, json_obj_bl_cache);
                 if (l_to_hash_str && dap_hash_fast_compare(&l_to_hash, &l_block_cache->block_hash))
                     break;
             }
             pthread_rwlock_unlock(&PVT(l_blocks)->rwlock);
-            json_object_array_add(*a_json_arr_reply, json_arr_bl_cache_out);
+            //sort by time
+            json_object_array_sort(json_arr_bl_cache_out, block_list_sort_by_date);
+            // Remove the timestamp and change block num
+            size_t l_length = json_object_array_length(json_arr_bl_cache_out);
+            for (size_t i = 0; i < l_length; i++) {
+                struct json_object *obj = json_object_array_get_idx(json_arr_bl_cache_out, i);
+                json_object_object_del(obj, "timestamp");
+                if (json_object_object_get_ex(obj, "block", NULL)) 
+                    json_object_object_add(obj, "block", json_object_new_uint64(i));
+            }
+            json_object_array_add(*json_arr_reply, json_arr_bl_cache_out);
 
             char *l_filtered_criteria = "none";
             json_object* json_obj_out = json_object_new_object();
@@ -1181,8 +1211,9 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply)
                 : dap_chain_mempool_tx_reward_create(l_blocks, l_cert->enc_key, l_addr, l_block_list, l_fee_value, l_hash_out_type);
             if (l_hash_tx) {
                 json_object* json_obj_out = json_object_new_object();
-                char *l_val = dap_strdup_printf(l_val, "TX for %s collection created successfully, hash = %s\n", l_subcmd_str, l_hash_tx);
-                json_object_object_add(json_obj_out, "status", json_object_new_string(l_val));
+                char *l_val = dap_strdup_printf("TX for %s collection created successfully, hash = %s\n", l_subcmd_str, l_hash_tx);
+                DAP_DELETE(l_hash_tx);
+                json_object_object_add(json_obj_out, "status", json_object_new_string(l_val ? l_val : "(null)"));
                 DAP_DELETE(l_val);
                 json_object_array_add(*a_json_arr_reply, json_obj_out);
                 DAP_DELETE(l_hash_tx);
@@ -1478,10 +1509,12 @@ static int s_add_atom_datums(dap_chain_cs_blocks_t *a_blocks, dap_chain_block_ca
             break;
         }
         dap_hash_fast_t *l_datum_hash = a_block_cache->datum_hash + i;
-        int l_res = dap_chain_datum_add(a_blocks->chain, l_datum, l_datum_size, l_datum_hash);
+        dap_ledger_datum_iter_data_t l_datum_index_data = { .token_ticker = "0", .action = DAP_CHAIN_TX_TAG_ACTION_UNKNOWN , .uid.uint64 = 0 };
+
+        int l_res = dap_chain_datum_add(a_blocks->chain, l_datum, l_datum_size, l_datum_hash, &l_datum_index_data);
         l_ret++;
         if (l_datum->header.type_id == DAP_CHAIN_DATUM_TX)
-            PVT(a_blocks)->tx_count++;
+            PVT(a_blocks)->tx_count++;  
         // Save datum hash -> block_hash link in hash table
         dap_chain_block_datum_index_t *l_datum_index = DAP_NEW_Z(dap_chain_block_datum_index_t);
         if (!l_datum_index) {
@@ -1493,6 +1526,9 @@ static int s_add_atom_datums(dap_chain_cs_blocks_t *a_blocks, dap_chain_block_ca
         l_datum_index->datum_hash = *l_datum_hash;
         l_datum_index->ret_code = l_res;
         l_datum_index->datum_index = i;
+        l_datum_index->action = l_datum_index_data.action;
+        l_datum_index->service_uid = l_datum_index_data.uid;
+        dap_strncpy(l_datum_index->token_ticker, l_datum_index_data.token_ticker, DAP_CHAIN_TICKER_SIZE_MAX);
         pthread_rwlock_wrlock(&PVT(a_blocks)->datums_rwlock);
         HASH_ADD(hh, PVT(a_blocks)->datum_index, datum_hash, sizeof(*l_datum_hash), l_datum_index);
         pthread_rwlock_unlock(&PVT(a_blocks)->datums_rwlock);
@@ -2212,12 +2248,18 @@ static void s_datum_iter_fill(dap_chain_datum_iter_t *a_datum_iter, dap_chain_bl
         a_datum_iter->cur_hash = &a_datum_index->datum_hash;
         a_datum_iter->cur_atom_hash = &a_datum_index->block_cache->block_hash;
         a_datum_iter->ret_code = a_datum_index->ret_code;
+        a_datum_iter->action = a_datum_index->action;
+        a_datum_iter->uid = a_datum_index->service_uid;    
+        a_datum_iter->token_ticker = dap_strcmp(a_datum_index->token_ticker, "0") ? a_datum_index->token_ticker : NULL;
     } else {
         a_datum_iter->cur = NULL;
         a_datum_iter->cur_hash = NULL;
         a_datum_iter->cur_atom_hash = NULL;
         a_datum_iter->cur_size = 0;
         a_datum_iter->ret_code = 0;
+        a_datum_iter->token_ticker = NULL;
+        a_datum_iter->action = 0;
+        a_datum_iter->uid.uint64 = 0;
     }
     debug_if(a_datum_index && !a_datum_index->block_cache->datum, L_ERROR, "Chains was deleted with errors");
 }
diff --git a/modules/type/dag/dap_chain_cs_dag.c b/modules/type/dag/dap_chain_cs_dag.c
index 969ea0f217e7eca582225410a7ed7c923574e737..2ed4ade008364f8bc4ee883ccea668fbcf78403d 100644
--- a/modules/type/dag/dap_chain_cs_dag.c
+++ b/modules/type/dag/dap_chain_cs_dag.c
@@ -407,7 +407,7 @@ static int s_dap_chain_add_atom_to_events_table(dap_chain_cs_dag_t *a_dag, dap_c
     }
     dap_hash_fast_t l_datum_hash;
     dap_chain_datum_calc_hash(l_datum, &l_datum_hash);
-    int l_ret = dap_chain_datum_add(a_dag->chain, l_datum, l_datum_size, &l_datum_hash);
+    int l_ret = dap_chain_datum_add(a_dag->chain, l_datum, l_datum_size, &l_datum_hash, NULL);
     if (l_datum->header.type_id == DAP_CHAIN_DATUM_TX)  // && l_ret == 0
         PVT(a_dag)->tx_count++;
     a_event_item->datum_hash = l_datum_hash;
@@ -458,11 +458,7 @@ static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_cha
     dap_chain_cs_dag_event_t * l_event = (dap_chain_cs_dag_event_t *) a_atom;
 
     dap_chain_hash_fast_t l_event_hash = *a_atom_hash;
-    if(s_debug_more) {
-        char l_event_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE] = { '\0' };
-        dap_chain_hash_fast_to_str(&l_event_hash, l_event_hash_str, sizeof(l_event_hash_str));
-        log_it(L_DEBUG, "Processing event: %s ... (size %zd)", l_event_hash_str,a_atom_size);
-    }
+    debug_if(s_debug_more, L_DEBUG, "Processing event: %s ... (size %zd)",  dap_chain_hash_fast_to_str_static(&l_event_hash), a_atom_size);
     pthread_mutex_lock(&PVT(l_dag)->events_mutex);
     // check if we already have this event
     dap_chain_atom_verify_res_t ret = s_dap_chain_check_if_event_is_present(PVT(l_dag)->events, &l_event_hash) ||
@@ -683,11 +679,6 @@ static bool s_chain_callback_datums_pool_proc(dap_chain_t *a_chain, dap_chain_da
      * or we have successfully chosen the hash(es) to link with.
      * No additional conditions required.
     */
-    byte_t *l_current_round_bytes = dap_global_db_get_sync(l_dag->gdb_group_events_round_new, DAG_ROUND_CURRENT_KEY, NULL, NULL, NULL);
-    uint64_t l_current_round = l_current_round_bytes ? *(uint64_t*)l_current_round_bytes : 0;
-    DAP_DEL_Z(l_current_round_bytes);
-    l_dag->round_completed = l_current_round++;
-    l_dag->round_current = l_current_round;
     uint64_t l_event_size = 0;
     dap_chain_cs_dag_event_t * l_event = l_dag->callback_cs_event_create
             ? l_dag->callback_cs_event_create(l_dag, a_datum, l_hashes, l_hashes_linked, &l_event_size)
@@ -708,18 +699,15 @@ static bool s_chain_callback_datums_pool_proc(dap_chain_t *a_chain, dap_chain_da
         } else
             return true;
     }
-
-    dap_global_db_set_sync(l_dag->gdb_group_events_round_new, DAG_ROUND_CURRENT_KEY,
-                      &l_current_round, sizeof(uint64_t), false);
     dap_chain_cs_dag_event_round_item_t l_round_item = { .round_info.datum_hash = l_datum_hash };
-    char *l_event_hash_hex_str = DAP_NEW_STACK_SIZE(char, DAP_CHAIN_HASH_FAST_STR_SIZE);
+    char l_event_hash_hex_str[DAP_CHAIN_HASH_FAST_STR_SIZE];
     dap_chain_hash_fast_to_str(&l_event_hash, l_event_hash_hex_str, DAP_CHAIN_HASH_FAST_STR_SIZE);
     l_res = dap_chain_cs_dag_event_gdb_set(l_dag, l_event_hash_hex_str, l_event, l_event_size, &l_round_item);
     DAP_DELETE(l_event);
     log_it(l_res ? L_INFO : L_ERROR,
-           l_res ? "Event %s placed in the new forming round [id %"DAP_UINT64_FORMAT_U"]"
-                 : "Can't add new event [%s] to the new events round [id %"DAP_UINT64_FORMAT_U"]",
-           l_event_hash_hex_str, l_current_round);
+           l_res ? "Event %s placed into new forming round"
+                 : "Can't add new event %s to new events round",
+           l_event_hash_hex_str);
     return l_res;
 }
 
@@ -815,12 +803,8 @@ static dap_chain_atom_verify_res_t s_chain_callback_atom_verify(dap_chain_t *a_c
         HASH_FIND(hh, PVT(l_dag)->events ,l_hash ,sizeof (*l_hash),  l_event_search);
         pthread_mutex_unlock(l_events_mutex);
         if (l_event_search == NULL) {
-            if(s_debug_more) {
-                char l_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE];
-                dap_chain_hash_fast_to_str(l_hash, l_hash_str, sizeof(l_hash_str));
-                log_it(L_WARNING, "Hash %s wasn't in hashtable of previously parsed, event %s goes to threshold",
-                                        l_hash_str, dap_hash_fast_to_str_static(a_atom_hash));
-            }
+            debug_if(s_debug_more, L_WARNING, "Hash %s wasn't in hashtable of previously parsed, event %s goes to threshold",
+                                              dap_hash_fast_to_str_static(l_hash), dap_hash_fast_to_str_static(a_atom_hash));
             res = ATOM_MOVE_TO_THRESHOLD;
             break;
         }
@@ -1285,13 +1269,10 @@ static dap_chain_datum_t *s_chain_callback_datum_iter_get_next(dap_chain_datum_i
     return a_datum_iter->cur;
 }
 
-static bool s_json_dag_pack_round(json_object * a_json_out, dap_global_db_obj_t * a_objs, int i){
-    json_object * json_obj_event_i = json_object_new_object();
-    if (!strcmp(DAG_ROUND_CURRENT_KEY, a_objs[i].key)) {
-        json_object_object_add(json_obj_event_i, a_objs[i].key, json_object_new_uint64(*(uint64_t *)a_objs[i].value));
-        json_object_array_add(a_json_out, json_obj_event_i);
+static bool s_json_dag_pack_round(json_object * a_json_out, dap_global_db_obj_t * a_objs, int i) {
+    if ( !strcmp(DAG_ROUND_CURRENT_KEY, a_objs[i].key) )
         return true;
-    }
+    json_object * json_obj_event_i = json_object_new_object();
     dap_chain_cs_dag_event_t * l_event = (dap_chain_cs_dag_event_t *)
                     ((dap_chain_cs_dag_event_round_item_t *)a_objs[i].value)->event_n_signs;
     char buf[DAP_TIME_STR_SIZE];
@@ -1307,7 +1288,8 @@ static void s_json_dag_pack_event(json_object * a_json_out, dap_chain_cs_dag_eve
     json_object * json_obj_event_i = json_object_new_object();                            
     char buf[DAP_TIME_STR_SIZE];
     dap_time_to_str_rfc822(buf, DAP_TIME_STR_SIZE, a_event_item->event->header.ts_created);
-    json_object_object_add(json_obj_event_i, "event", json_object_new_string(dap_itoa(i)));
+    json_object_object_add(json_obj_event_i, "#", json_object_new_string(dap_itoa(i)));
+    json_object_object_add(json_obj_event_i, "event number", json_object_new_uint64(a_event_item->event_number));
     json_object_object_add(json_obj_event_i, "hash", json_object_new_string(dap_chain_hash_fast_to_str_static(&a_event_item->hash)));
     json_object_object_add(json_obj_event_i, "ts_create", json_object_new_string(buf));
     json_object_array_add(a_json_out, json_obj_event_i);
diff --git a/modules/type/dag/dap_chain_cs_dag_event.c b/modules/type/dag/dap_chain_cs_dag_event.c
index 8e4fc060129010fbf0010edf8a07953441c6aec9..c9d769f044cff34697e19f80266e5d095de84779 100644
--- a/modules/type/dag/dap_chain_cs_dag_event.c
+++ b/modules/type/dag/dap_chain_cs_dag_event.c
@@ -43,51 +43,43 @@
  * @param a_hashes_count
  * @return
  */
-dap_chain_cs_dag_event_t *dap_chain_cs_dag_event_new(dap_chain_id_t a_chain_id, dap_chain_cell_id_t a_cell_id, uint64_t a_round_id,
-                                                     dap_chain_datum_t *a_datum, dap_enc_key_t *a_key,
-                                                     dap_chain_hash_fast_t *a_hashes, size_t a_hashes_count, size_t *a_event_size)
+dap_chain_cs_dag_event_t *dap_chain_cs_dag_event_new(dap_chain_id_t a_chain_id, dap_chain_cell_id_t a_cell_id,
+                                                     dap_chain_datum_t *a_datum, dap_enc_key_t *a_key, dap_chain_hash_fast_t *a_hashes,
+                                                     size_t a_hashes_count, size_t *a_event_size)
 {
     assert(a_event_size);
-    size_t l_hashes_size = sizeof(*a_hashes)*a_hashes_count;
-    size_t l_datum_size =  dap_chain_datum_size(a_datum);
-    dap_chain_cs_dag_event_t * l_event_new = NULL;
-    size_t l_event_size = sizeof(l_event_new->header)
-            + l_hashes_size
-            + l_datum_size;
-    l_event_new = DAP_NEW_Z_SIZE(dap_chain_cs_dag_event_t, l_event_size);
-    l_event_new->header.ts_created = dap_time_now();
-    l_event_new->header.cell_id.uint64 = a_cell_id.uint64;
-    l_event_new->header.chain_id.uint64 = a_chain_id.uint64;
-    l_event_new->header.hash_count = a_hashes_count;
-    l_event_new->header.round_id = a_round_id;
-
-    if ( l_hashes_size ){
-        memcpy(l_event_new->hashes_n_datum_n_signs, a_hashes, l_hashes_size );
-    }
+    size_t l_hashes_size = sizeof(*a_hashes) * a_hashes_count,
+        l_datum_size = dap_chain_datum_size(a_datum),
+        l_event_size = sizeof(dap_chain_class_dag_event_hdr_t) + l_hashes_size + l_datum_size;
+    dap_chain_cs_dag_event_t *l_event_new = DAP_NEW_Z_SIZE(dap_chain_cs_dag_event_t, l_event_size);
+    *l_event_new = (dap_chain_cs_dag_event_t) {
+        {
+            .ts_created = dap_time_now(),
+            .chain_id = a_chain_id,
+            .cell_id = a_cell_id,
+            .hash_count = a_hashes_count
+        }
+    };
 
-    memcpy(l_event_new->hashes_n_datum_n_signs+l_hashes_size, a_datum,l_datum_size );
+    if ( l_hashes_size )
+        memcpy( l_event_new->hashes_n_datum_n_signs, a_hashes, l_hashes_size );
+    memcpy( l_event_new->hashes_n_datum_n_signs + l_hashes_size, a_datum,l_datum_size );
 
     if ( a_key ){
-        dap_sign_t * l_sign = dap_sign_create(a_key, l_event_new, l_event_size, 0);
-        if ( l_sign ){
-            size_t l_sign_size = dap_sign_get_size(l_sign);
-            l_event_size += l_sign_size;
-            l_event_new = (dap_chain_cs_dag_event_t *)DAP_REALLOC(l_event_new, l_event_size);
-            if (!l_event_new) {
-                log_it(L_CRITICAL, "Not enough memeory");
-                DAP_DELETE(l_sign);
-                return NULL;
-            }
-            memcpy(l_event_new->hashes_n_datum_n_signs + l_hashes_size + l_datum_size, l_sign, l_sign_size);
-            l_event_new->header.signs_count++;
-            log_it(L_INFO,"Created event size %zd, signed with sign size %zd", l_event_size, l_sign_size);
-            DAP_DELETE(l_sign);
-        }else {
-            log_it(L_ERROR,"Can't sign dag event!");
-            DAP_DELETE(l_event_new);
-            return NULL;
-        }
-    }else {
+        dap_sign_t *l_sign = dap_sign_create(a_key, l_event_new, l_event_size, 0);
+        if ( !l_sign )
+            return DAP_DELETE(l_event_new), log_it(L_ERROR,"Can't sign dag event!"), NULL;
+        size_t l_sign_size = dap_sign_get_size(l_sign);
+        l_event_size += l_sign_size;
+        dap_chain_cs_dag_event_t *l_event_newer = (dap_chain_cs_dag_event_t*)DAP_REALLOC(l_event_new, l_event_size);
+        if (!l_event_newer) 
+            return DAP_DEL_MULTY(l_event_new, l_sign), log_it(L_CRITICAL, "Not enough memeory"), NULL;
+        l_event_new = l_event_newer;
+        memcpy(l_event_new->hashes_n_datum_n_signs + l_hashes_size + l_datum_size, l_sign, l_sign_size);
+        l_event_new->header.signs_count++;
+        log_it(L_INFO,"Created event size %zd, signed with sign size %zd", l_event_size, l_sign_size);
+        DAP_DELETE(l_sign);
+    } else {
         log_it(L_NOTICE, "Created unsigned dag event");
     }
     if (a_event_size)
@@ -110,9 +102,7 @@ uint64_t dap_chain_cs_dag_event_calc_size_excl_signs(dap_chain_cs_dag_event_t *a
         return 0;
     dap_chain_datum_t *l_datum = (dap_chain_datum_t *)(a_event->hashes_n_datum_n_signs + l_hashes_size);
     uint64_t l_ret = dap_chain_datum_size(l_datum) + l_hashes_size + sizeof(a_event->header);
-    if (a_limit_size && a_limit_size < l_ret)
-        return 0;
-    return l_ret;
+    return a_limit_size && a_limit_size < l_ret ? 0 : l_ret;
 }
 
 /**
@@ -159,22 +149,18 @@ size_t dap_chain_cs_dag_event_sign_add(dap_chain_cs_dag_event_t **a_event_ptr, s
     if (dap_chain_cs_dag_event_sign_exists(l_event, a_event_size, a_key)) {
         size_t l_pub_key_size = 0;
         uint8_t *l_pub_key = dap_enc_key_serialize_pub_key(a_key, &l_pub_key_size);
-        dap_hash_fast_t l_pkey_hash = {};
-        dap_hash_fast(l_pub_key, l_pub_key_size, &l_pkey_hash);
-        DAP_DELETE(l_pub_key);
-        char l_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE];
-        dap_hash_fast_to_str(&l_pkey_hash, l_hash_str, DAP_CHAIN_HASH_FAST_STR_SIZE);
-        log_it(L_DEBUG, "Sign from this key exists: %s", l_hash_str);
-        return 0;
+        return log_it(L_DEBUG, "Already signed with pkey %s", dap_get_data_hash_str(l_pub_key, l_pub_key_size).s), DAP_DELETE(l_pub_key), 0;
     }
     size_t l_event_size_excl_sign = dap_chain_cs_dag_event_calc_size_excl_signs(l_event, a_event_size);
     dap_sign_t *l_sign = dap_sign_create(a_key, l_event, l_event_size_excl_sign, 0);
     size_t l_sign_size = dap_sign_get_size(l_sign);
-    *a_event_ptr = l_event = DAP_REALLOC(l_event, a_event_size + l_sign_size);
+    if (! (l_event = DAP_REALLOC(*a_event_ptr, a_event_size + l_sign_size) ))
+        return log_it(L_CRITICAL, "Memory allocation error"), DAP_DELETE(l_sign), a_event_size;
     size_t l_event_size = a_event_size - sizeof(l_event->header);
     memcpy(l_event->hashes_n_datum_n_signs + l_event_size, l_sign, l_sign_size);
     l_event->header.signs_count++;
     DAP_DELETE(l_sign);
+    *a_event_ptr = l_event;
     return a_event_size + l_sign_size;
 }
 
@@ -202,18 +188,18 @@ static bool s_sign_exists(uint8_t *a_pos, size_t a_len, dap_enc_key_t *a_key)
 
 bool dap_chain_cs_dag_event_sign_exists(dap_chain_cs_dag_event_t *a_event, size_t a_event_size, dap_enc_key_t *a_key)
 {
-    size_t l_hashes_size = a_event->header.hash_count*sizeof(dap_chain_hash_fast_t);
-    dap_chain_datum_t * l_datum = (dap_chain_datum_t*)(a_event->hashes_n_datum_n_signs + l_hashes_size);
-    size_t l_datum_size =  dap_chain_datum_size(l_datum);
-    uint8_t *l_offset = a_event->hashes_n_datum_n_signs + l_hashes_size + l_datum_size;
-    size_t l_signs_size = a_event_size - sizeof(a_event->header) - l_hashes_size - l_datum_size;
-    return s_sign_exists(l_offset, l_signs_size, a_key);
+    size_t l_hashes_size = a_event->header.hash_count * sizeof(dap_chain_hash_fast_t);
+    dap_chain_datum_t *l_datum = (dap_chain_datum_t*)(a_event->hashes_n_datum_n_signs + l_hashes_size);
+    size_t l_datum_size = dap_chain_datum_size(l_datum);
+    return s_sign_exists(a_event->hashes_n_datum_n_signs + l_hashes_size + l_datum_size,
+                        a_event_size - sizeof(a_event->header) - l_hashes_size - l_datum_size,
+                        a_key);
 }
 
 bool dap_chain_cs_dag_event_round_sign_exists(dap_chain_cs_dag_event_round_item_t *a_round_item, dap_enc_key_t *a_key) {
-    uint8_t *l_offset = a_round_item->event_n_signs + (size_t)a_round_item->event_size;
-    size_t l_signs_size = (size_t)a_round_item->data_size - (size_t)a_round_item->event_size;
-    return s_sign_exists(l_offset, l_signs_size, a_key);
+    return s_sign_exists(a_round_item->event_n_signs + a_round_item->event_size,
+                        (size_t)(a_round_item->data_size - a_round_item->event_size),
+                        a_key); 
 }
 
 /**
@@ -253,12 +239,14 @@ size_t dap_chain_cs_dag_event_round_sign_add(dap_chain_cs_dag_event_round_item_t
         return 0;
     dap_sign_t * l_sign = dap_sign_create(a_key, &l_round_item->round_info.datum_hash, sizeof(dap_chain_hash_fast_t), 0);
     size_t l_sign_size = dap_sign_get_size(l_sign);
-    size_t l_offset = (size_t)l_round_item->data_size;
-    *a_round_item_ptr = l_round_item = DAP_REALLOC(l_round_item, a_round_item_size+l_sign_size);
-    memcpy(l_round_item->event_n_signs+l_offset, l_sign, l_sign_size);
+    size_t l_offset = l_round_item->data_size;
+    if (! (l_round_item = DAP_REALLOC(*a_round_item_ptr, a_round_item_size + l_sign_size)) )
+        return log_it(L_CRITICAL, "Memory allocaton error"), DAP_DELETE(l_sign), a_round_item_size;
+    memcpy(l_round_item->event_n_signs + l_offset, l_sign, l_sign_size);
     DAP_DELETE(l_sign);
     l_round_item->data_size += (uint32_t)l_sign_size;
-    return a_round_item_size+l_sign_size;
+    *a_round_item_ptr = l_round_item;
+    return a_round_item_size + l_sign_size;
 }
 
 /**
diff --git a/modules/type/dag/include/dap_chain_cs_dag.h b/modules/type/dag/include/dap_chain_cs_dag.h
index 1020634067194f1684b3fb16e7197d3690456880..f28f7baf3c6e91287fe49be29591cd1d4a99bde8 100644
--- a/modules/type/dag/include/dap_chain_cs_dag.h
+++ b/modules/type/dag/include/dap_chain_cs_dag.h
@@ -61,8 +61,6 @@ typedef struct dap_chain_cs_dag
     dap_chain_hash_fast_t static_genesis_event_hash;
     dap_chain_cs_dag_hal_item_t *hal;
 
-    atomic_uint_fast64_t round_current, round_completed;
-
     uint16_t datum_add_hashes_count;
     char * gdb_group_events_round_new;
 
diff --git a/modules/type/dag/include/dap_chain_cs_dag_event.h b/modules/type/dag/include/dap_chain_cs_dag_event.h
index 4de1d9055b8eca61d05ca961d6fd6cfcd5a003cc..b56f5ae9b36aa274a0989c0377fb276051cabb9d 100644
--- a/modules/type/dag/include/dap_chain_cs_dag_event.h
+++ b/modules/type/dag/include/dap_chain_cs_dag_event.h
@@ -60,9 +60,8 @@ typedef struct dap_chain_cs_dag_event_round_item {
     uint8_t event_n_signs[]; // event // dap_chain_cs_dag_event_t
 } DAP_ALIGN_PACKED dap_chain_cs_dag_event_round_item_t;
 
-dap_chain_cs_dag_event_t *dap_chain_cs_dag_event_new(dap_chain_id_t a_chain_id, dap_chain_cell_id_t a_cell_id, uint64_t a_round_id,
-                                                     dap_chain_datum_t *a_datum, dap_enc_key_t *a_key,
-                                                     dap_chain_hash_fast_t *a_hashes, size_t a_hashes_count, size_t *a_event_size);
+dap_chain_cs_dag_event_t *dap_chain_cs_dag_event_new(dap_chain_id_t a_chain_id, dap_chain_cell_id_t a_cell_id, dap_chain_datum_t *a_datum,
+                                                     dap_enc_key_t *a_key, dap_chain_hash_fast_t *a_hashes, size_t a_hashes_count, size_t *a_event_size);
 
 /**
  * @brief dap_chain_cs_dag_event_get_datum
diff --git a/modules/type/none/dap_chain_cs_none.c b/modules/type/none/dap_chain_cs_none.c
index 25124d12a4636f168a753953f34e0700ae9dbd40..046eeef125ac5167411d904dd0247bb6f8d23145 100644
--- a/modules/type/none/dap_chain_cs_none.c
+++ b/modules/type/none/dap_chain_cs_none.c
@@ -318,7 +318,7 @@ static dap_chain_atom_verify_res_t s_nonconsensus_callback_atom_add(dap_chain_t
     dap_nonconsensus_private_t *l_nochain_priv = PVT(l_nochain);
     dap_chain_datum_t *l_datum = (dap_chain_datum_t*) a_atom;
     dap_hash_fast_t l_datum_hash = *a_atom_hash;
-    if(dap_chain_datum_add(a_chain, l_datum, a_atom_size, &l_datum_hash))
+    if(dap_chain_datum_add(a_chain, l_datum, a_atom_size, &l_datum_hash, NULL))
         return ATOM_REJECT;
 
     dap_nonconsensus_datum_hash_item_t * l_hash_item = DAP_NEW_Z(dap_nonconsensus_datum_hash_item_t);