diff --git a/CMakeLists.txt b/CMakeLists.txt
index de5b86f2655056eb73e1eff34e01e2ec3fce1067..87f693ce8f15040dec97208f3d0ec55173b55224 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -18,7 +18,7 @@ endif()
 if(NOT DEFINED CELLFRAME_MODULES)
     include (dap-sdk/cmake/OS_Detection.cmake)
 
-    set(CELLFRAME_MODULES "core chains mining network srv cs-dag-poa cs-block-poa cs-dag-pos cs-block-pos cs-esbocs cs-none srv-app srv-app-db srv-datum srv-stake srv-xchange")
+    set(CELLFRAME_MODULES "core chains mining network srv cs-dag-poa cs-block-poa cs-dag-pos cs-block-pos cs-esbocs cs-none srv-app srv-app-db srv-datum srv-stake srv-voting srv-bridge srv-xchange")
 
     if(LINUX OR DARWIN)
         set(CELLFRAME_MODULES "${CELLFRAME_MODULES} srv-vpn")
@@ -183,6 +183,19 @@ if (CELLFRAME_MODULES MATCHES "srv-stake")
     set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_chain_net_srv_stake)
 endif()
 
+
+# Enable service bridge
+if (CELLFRAME_MODULES MATCHES "srv-bridge")
+    message("[+] Module 'srv-bridge'")
+    set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_chain_net_srv_bridge)
+endif()
+
+# Enable service voting
+if (CELLFRAME_MODULES MATCHES "srv-voting")
+    message("[+] Module 'srv-voting'")
+    set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_chain_net_srv_voting)
+endif()
+
 # Enable service for dynamic modules
 if (CELLFRAME_MODULES MATCHES "modules-dynamic")
     message("[+] Module 'dap_modules_dynamic_cdb'")
diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt
index 1aca3bdd4b20b06554a6cc296a9731a0bcbd42e9..3b4079665a1c524cb670301839d79682a042ca25 100644
--- a/modules/CMakeLists.txt
+++ b/modules/CMakeLists.txt
@@ -20,7 +20,6 @@ if (CELLFRAME_MODULES MATCHES "network")
     add_subdirectory(mempool)
     add_subdirectory(net)
     add_subdirectory(net/srv)
-    add_subdirectory(json_rpc)
     # Stream channels
     add_subdirectory(channel/chain-net)
 endif()
@@ -110,7 +109,12 @@ if (CELLFRAME_MODULES MATCHES "srv-stake")
     add_subdirectory(service/stake)
 endif()
 
-# Unit tests
-if( BUILD_TESTS)
-    add_subdirectory(test)
+# Service for polls and voting
+if (CELLFRAME_MODULES MATCHES "srv-voting")
+    add_subdirectory(service/voting)
+endif()
+
+# Service for bridge
+if (CELLFRAME_MODULES MATCHES "srv-bridge")
+    add_subdirectory(service/bridge)
 endif()
diff --git a/modules/chain/dap_chain.c b/modules/chain/dap_chain.c
index e6bef0653720859c136c9b607a419afa3f017c95..e8450ad2d2ef98a5ef9ad78bdc3fb00dc347d5ec 100644
--- a/modules/chain/dap_chain.c
+++ b/modules/chain/dap_chain.c
@@ -248,7 +248,7 @@ static dap_chain_type_t s_chain_type_from_str(const char *a_type_str)
         return CHAIN_TYPE_DECREE;
     if (!dap_strcmp(a_type_str, "anchor"))
         return CHAIN_TYPE_ANCHOR;
-    return CHAIN_TYPE_LAST;
+    return CHAIN_TYPE_INVALID;
 }
 
 /**
@@ -445,7 +445,7 @@ dap_chain_t *dap_chain_load_from_cfg(const char *a_chain_net_name, dap_chain_net
 					for (uint16_t i = 0; i < l_datum_types_count; i++)
 					{
 						dap_chain_type_t l_chain_type = s_chain_type_from_str(l_datum_types[i]);
-						if (l_chain_type != CHAIN_TYPE_LAST)
+						if (l_chain_type != CHAIN_TYPE_INVALID)
 						{
 							l_chain->datum_types[l_count_recognized] = l_chain_type;
 							l_count_recognized++;
@@ -470,7 +470,7 @@ dap_chain_t *dap_chain_load_from_cfg(const char *a_chain_net_name, dap_chain_net
 					for (uint16_t i = 0; i < l_default_datum_types_count; i++)
 					{
 						dap_chain_type_t l_chain_type = s_chain_type_from_str(l_default_datum_types[i]);
-						if (l_chain_type != CHAIN_TYPE_LAST
+						if (l_chain_type != CHAIN_TYPE_INVALID
 						&& s_chain_in_chain_types(l_chain_type, l_chain->datum_types, l_chain->datum_types_count))// <<--- check this chain_type in readed datum_types
 						{
 							l_chain->default_datum_types[l_count_recognized] = l_chain_type;
@@ -542,6 +542,21 @@ bool dap_chain_has_file_store(dap_chain_t * a_chain)
 }
 
 
+/**
+ * @brief get type of chain
+ *
+ * @param l_chain
+ * @return char*
+ */
+const char *dap_chain_get_cs_type(dap_chain_t *l_chain)
+{
+    if (!l_chain){
+        log_it(L_DEBUG, "dap_get_chain_type. Chain object is 0");
+        return NULL;
+    }
+    return (const char *)DAP_CHAIN_PVT(l_chain)->cs_name;
+}
+
 /**
  * @brief dap_chain_save_all
  * @param l_chain
@@ -723,8 +738,9 @@ ssize_t dap_chain_atom_save(dap_chain_cell_t *a_chain_cell, const uint8_t *a_ato
         dap_cluster_t *l_net_cluster = dap_cluster_find(dap_guuid_compose(l_chain->net_id.uint64, 0));
         if (l_net_cluster) {
             size_t l_pkt_size = a_atom_size + sizeof(dap_chain_ch_pkt_t);
-            dap_chain_ch_pkt_t *l_pkt = dap_chain_ch_pkt_new(l_chain->net_id.uint64, l_chain->id.uint64,
-                                                             a_chain_cell->id.uint64, a_atom, a_atom_size);
+            dap_chain_ch_pkt_t *l_pkt = dap_chain_ch_pkt_new(l_chain->net_id, l_chain->id,
+                                                             a_chain_cell->id, a_atom, a_atom_size,
+                                                             DAP_CHAIN_CH_PKT_VERSION_CURRENT);
             if (l_pkt) {
                 dap_gossip_msg_issue(l_net_cluster, DAP_CHAIN_CH_ID, l_pkt, l_pkt_size, a_new_atom_hash);
                 DAP_DELETE(l_pkt);
@@ -738,7 +754,7 @@ ssize_t dap_chain_atom_save(dap_chain_cell_t *a_chain_cell, const uint8_t *a_ato
             dap_chain_atom_notifier_t *l_notifier = (dap_chain_atom_notifier_t*)l_iter->data;
             struct chain_thread_notifier *l_arg = DAP_NEW_Z(struct chain_thread_notifier);
             if (!l_arg) {
-                log_it(L_CRITICAL, g_error_memory_alloc);
+                log_it(L_CRITICAL, "%s", g_error_memory_alloc);
                 continue;
             }
             *l_arg = (struct chain_thread_notifier) { .callback = l_notifier->callback, .callback_arg = l_notifier->arg,
@@ -746,7 +762,7 @@ ssize_t dap_chain_atom_save(dap_chain_cell_t *a_chain_cell, const uint8_t *a_ato
             l_arg->atom = DAP_DUP_SIZE(a_atom, a_atom_size);
             if (!l_arg->atom) {
                 DAP_DELETE(l_arg);
-                log_it(L_CRITICAL, g_error_memory_alloc);
+                log_it(L_CRITICAL, "%s", g_error_memory_alloc);
                 continue;
             }
             dap_proc_thread_callback_add_pri(NULL, s_notify_atom_on_thread, l_arg, DAP_QUEUE_MSG_PRIORITY_LOW);
@@ -808,3 +824,25 @@ const char* dap_chain_get_path(dap_chain_t *a_chain)
     return DAP_CHAIN_PVT(a_chain)->file_storage_dir;
 }
 
+const char *dap_chain_type_to_str(const dap_chain_type_t a_default_chain_type) {
+    switch (a_default_chain_type)
+    {
+        case CHAIN_TYPE_INVALID:
+            return "invalid";
+        case CHAIN_TYPE_TOKEN:
+            return "token";
+        case CHAIN_TYPE_EMISSION:
+            return "emission";
+        case CHAIN_TYPE_TX:
+            return "transaction";
+        case CHAIN_TYPE_CA:
+            return "ca";
+        case CHAIN_TYPE_SIGNER:
+            return "signer";
+        case CHAIN_TYPE_DECREE:
+            return "decree";
+        case CHAIN_TYPE_ANCHOR:
+            return "anchor";
+    }
+    return "invalid";
+}
diff --git a/modules/chain/dap_chain_ch.c b/modules/chain/dap_chain_ch.c
index 2a8d8a77d79f1d099acf73b71a559a94bcf0f3af..171fbd1bf6b0c6359037d0c670151cd4da1d21ba 100644
--- a/modules/chain/dap_chain_ch.c
+++ b/modules/chain/dap_chain_ch.c
@@ -23,41 +23,17 @@
  along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <stdint.h>
-
-#ifdef WIN32
-#include <winsock2.h>
-#include <windows.h>
-#include <mswsock.h>
-#include <ws2tcpip.h>
-#include <io.h>
-#include <pthread.h>
-#endif
-
 #include "dap_common.h"
-#include "dap_strfuncs.h"
 #include "dap_list.h"
 #include "dap_config.h"
 #include "dap_hash.h"
 #include "dap_time.h"
-#include "utlist.h"
-
 #include "dap_worker.h"
-#include "dap_events.h"
 #include "dap_proc_thread.h"
-#include "dap_client_pvt.h"
-
 #include "dap_chain.h"
-#include "dap_chain_datum.h"
-#include "dap_chain_cs.h"
 #include "dap_chain_cell.h"
-
-#include "dap_global_db.h"
-
+#include "dap_global_db_legacy.h"
+#include "dap_global_db_ch.h"
 #include "dap_stream.h"
 #include "dap_stream_pkt.h"
 #include "dap_stream_worker.h"
@@ -70,30 +46,7 @@
 
 #define LOG_TAG "dap_chain_ch"
 
-struct sync_request
-{
-    dap_worker_t * worker;
-    dap_stream_ch_uuid_t ch_uuid;
-    dap_chain_ch_sync_request_old_t request;
-    dap_chain_ch_pkt_hdr_t request_hdr;
-    dap_chain_pkt_item_t pkt;
-
-    dap_chain_ch_hash_item_t *remote_atoms; // Remote atoms
-    dap_chain_ch_hash_item_t *remote_gdbs; // Remote gdbs
-
-    uint64_t stats_request_elemets_processed;
-    int last_err;
-    union{
-        struct{
-            //dap_db_log_list_t *db_log; //  db log
-            dap_list_t *db_iter;
-            char *sync_group;
-        } gdb;
-        struct{
-            dap_chain_atom_iter_t *request_atom_iter;
-        } chain;
-    };
-};
+#define DAP_CHAIN_PKT_EXPECT_SIZE   DAP_STREAM_PKT_FRAGMENT_SIZE
 
 enum sync_context_state {
     SYNC_STATE_IDLE,
@@ -114,45 +67,83 @@ struct sync_context {
     dap_time_t last_activity;
 };
 
-static void s_ch_chain_go_idle(dap_chain_ch_t *a_ch_chain);
-static inline bool s_ch_chain_get_idle(dap_chain_ch_t *a_ch_chain) { return a_ch_chain->state == DAP_CHAIN_CH_STATE_IDLE; }
+typedef struct dap_chain_ch_hash_item {
+    dap_hash_fast_t hash;
+    uint32_t size;
+    UT_hash_handle hh;
+} dap_chain_ch_hash_item_t;
 
-static void s_stream_ch_new(dap_stream_ch_t* a_ch, void* a_arg);
-static void s_stream_ch_delete(dap_stream_ch_t* a_ch, void* a_arg);
-static bool s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg);
-static bool s_stream_ch_packet_out(dap_stream_ch_t* a_ch, void* a_arg);
-static void s_stream_ch_io_complete(dap_events_socket_t *a_es, void *a_arg);
+struct legacy_sync_context {
+    dap_stream_worker_t *worker;
+    dap_stream_ch_uuid_t ch_uuid;
+    dap_stream_node_addr_t remote_addr;
+    dap_chain_ch_pkt_hdr_t request_hdr;
 
-static bool s_sync_out_chains_proc_callback(void *a_arg);
-static void s_sync_out_chains_last_worker_callback(dap_worker_t *a_worker, void *a_arg);
-static void s_sync_out_chains_first_worker_callback(dap_worker_t *a_worker, void *a_arg);
+    _Atomic(dap_chain_ch_state_t) state;
+    dap_chain_ch_error_type_t last_error;
+
+    bool is_type_of_gdb;
+    union {
+        struct {
+            dap_chain_ch_hash_item_t *remote_atoms;     // Remote atoms
+            dap_chain_atom_iter_t *atom_iter;           // Atom iterator
+            uint64_t stats_request_atoms_processed;     // Atoms statictic
+        };
+        struct {
+            dap_chain_ch_hash_item_t *remote_gdbs;      // Remote gdbs
+            dap_global_db_legacy_list_t *db_list;       // DB iterator
+            uint64_t stats_request_gdbs_processed;      // DB statictic
+        };
+    };
 
-static bool s_sync_out_gdb_proc_callback(void *a_arg);
+    dap_time_t last_activity;
+    dap_chain_ch_state_t prev_state;
+    size_t enqueued_data_size;
+};
 
-static bool s_sync_in_chains_callback(void *a_arg);
+typedef struct dap_chain_ch {
+    void *_inheritor;
+    dap_timerfd_t *sync_timer;
+    struct sync_context *sync_context;
+
+    // Legacy section //
+    dap_timerfd_t *activity_timer;
+    uint32_t timer_shots;
+    int sent_breaks;
+    struct legacy_sync_context *legacy_sync_context;
+} dap_chain_ch_t;
+
+#define DAP_CHAIN_CH(a) ((dap_chain_ch_t *) ((a)->internal) )
+#define DAP_STREAM_CH(a) ((dap_stream_ch_t *)((a)->_inheritor))
+
+static void s_ch_chain_go_idle(dap_chain_ch_t *a_ch_chain);
+
+static void s_stream_ch_new(dap_stream_ch_t *a_ch, void *a_arg);
+static void s_stream_ch_delete(dap_stream_ch_t *a_ch, void *a_arg);
+static bool s_stream_ch_packet_in(dap_stream_ch_t * a_ch, void *a_arg);
+static void s_stream_ch_io_complete(dap_events_socket_t *a_es, void *a_arg);
 
+static bool s_sync_in_chains_callback(void *a_arg);
+static bool s_sync_out_chains_proc_callback(void *a_arg);
 static bool s_gdb_in_pkt_proc_callback(void *a_arg);
-static bool s_gdb_in_pkt_proc_set_raw_callback(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_store_obj_t *a_values, void *a_arg);
-static void s_gdb_in_pkt_error_worker_callback(dap_worker_t *a_thread, void *a_arg);
+static bool s_sync_out_gdb_proc_callback(void *a_arg);
 
 static void s_stream_ch_chain_pkt_write(dap_stream_ch_t *a_ch, uint8_t a_type, uint64_t a_net_id,
                                         uint64_t a_chain_id, uint64_t a_cell_id,
                                         const void * a_data, size_t a_data_size);
+
 static void s_gossip_payload_callback(void *a_payload, size_t a_payload_size, dap_stream_node_addr_t a_sender_addr);
 static bool s_chain_iter_callback(void *a_arg);
 static bool s_chain_iter_delete_callback(void *a_arg);
 static bool s_sync_timer_callback(void *a_arg);
 
-static bool s_debug_more = false;
+static bool s_debug_more = false, s_debug_legacy = false;
 static uint32_t s_sync_timeout = 30;
 static uint32_t s_sync_packets_per_thread_call = 10;
 static uint32_t s_sync_ack_window_size = 100; // atoms
 
-static uint_fast16_t s_update_pack_size=100; // Number of hashes packed into the one packet
-static uint_fast16_t s_skip_in_reactor_count=50; // Number of hashes packed to skip in one reactor loop callback out packet
+// Legacy
+static uint_fast16_t s_update_pack_size = 100; // Number of hashes packed into the one packet
 
 #ifdef  DAP_SYS_DEBUG
 
@@ -170,8 +161,12 @@ static const char *s_error_type_to_string(dap_chain_ch_error_type_t a_error)
         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 "IVALID_PACKET_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:
@@ -200,12 +195,12 @@ static const char *s_error_type_to_string(dap_chain_ch_error_type_t a_error)
 int dap_chain_ch_init()
 {
     log_it(L_NOTICE, "Chains exchange channel initialized");
-    dap_stream_ch_proc_add(DAP_CHAIN_CH_ID, s_stream_ch_new, s_stream_ch_delete, s_stream_ch_packet_in,
-            s_stream_ch_packet_out);
+    dap_stream_ch_proc_add(DAP_CHAIN_CH_ID, s_stream_ch_new, s_stream_ch_delete, s_stream_ch_packet_in, NULL);
     s_sync_timeout = dap_config_get_item_uint32_default(g_config, "chain", "sync_timeout", s_sync_timeout);
     s_sync_ack_window_size = dap_config_get_item_uint32_default(g_config, "chain", "sync_ack_window_size", s_sync_ack_window_size);
     s_sync_packets_per_thread_call = dap_config_get_item_int16_default(g_config, "chain", "pack_size", s_sync_packets_per_thread_call);
     s_debug_more = dap_config_get_item_bool_default(g_config, "chain", "debug_more", false);
+    s_debug_legacy = dap_config_get_item_bool_default(g_config, "chain", "debug_legacy", false);
 #ifdef  DAP_SYS_DEBUG
     for (int i = 0; i < MEMSTAT$K_NR; i++)
         dap_memstat_reg(&s_memstat[i]);
@@ -226,7 +221,7 @@ void dap_chain_ch_deinit()
  * @param a_ch
  * @param arg
  */
-void s_stream_ch_new(dap_stream_ch_t* a_ch, void* a_arg)
+void s_stream_ch_new(dap_stream_ch_t *a_ch, void *a_arg)
 {
     UNUSED(a_arg);
     if (!(a_ch->internal = DAP_NEW_Z(dap_chain_ch_t))) {
@@ -235,7 +230,6 @@ void s_stream_ch_new(dap_stream_ch_t* a_ch, void* a_arg)
     };
     dap_chain_ch_t *l_ch_chain = DAP_CHAIN_CH(a_ch);
     l_ch_chain->_inheritor = a_ch;
-    a_ch->stream->esocket->callbacks.write_finished_callback = s_stream_ch_io_complete;
 
 #ifdef  DAP_SYS_DEBUG
     atomic_fetch_add(&s_memstat[MEMSTAT$K_STM_CH_CHAIN].alloc_nr, 1);
@@ -261,313 +255,342 @@ static void s_stream_ch_delete(dap_stream_ch_t *a_ch, void *a_arg)
 #endif
 }
 
+// *** Legacy support code *** //
+
 /**
- * @brief s_stream_ch_chain_delete
+ * @brief dap_chain_ch_create_sync_request_gdb
  * @param a_ch_chain
+ * @param a_net
  */
-static void s_sync_request_delete(struct sync_request * a_sync_request)
+struct legacy_sync_context *s_legacy_sync_context_create(dap_chain_ch_pkt_t *a_chain_pkt, dap_stream_ch_t *a_ch)
 {
-    if (!a_sync_request) {
-        //already NULL'ed
-        return;
-    }
-    if (a_sync_request->pkt.pkt_data) {
-        DAP_DEL_Z(a_sync_request->pkt.pkt_data);
-    }
+    dap_chain_ch_t * l_ch_chain = DAP_CHAIN_CH(a_ch);
+    dap_return_val_if_fail(l_ch_chain, NULL);
 
-    if (a_sync_request->gdb.db_iter) {
-        a_sync_request->gdb.db_iter = dap_list_first( a_sync_request->gdb.db_iter);
-        dap_list_free_full( a_sync_request->gdb.db_iter, NULL);
-        a_sync_request->gdb.db_iter = NULL;
+    struct legacy_sync_context *l_context;
+    DAP_NEW_Z_RET_VAL(l_context, struct legacy_sync_context, NULL, NULL);
+
+    *l_context = (struct legacy_sync_context) {
+            .worker         = a_ch->stream_worker,
+            .ch_uuid        = a_ch->uuid,
+            .remote_addr    = *(dap_stream_node_addr_t *)a_chain_pkt->data,
+            .request_hdr    = a_chain_pkt->hdr,
+            .state          = DAP_CHAIN_CH_STATE_IDLE,
+            .last_activity  = dap_time_now()
+        };
+    dap_stream_ch_uuid_t *l_uuid = DAP_DUP(&a_ch->uuid);
+    if (!l_uuid) {
+        log_it(L_CRITICAL, "%s", g_error_memory_alloc);
+        DAP_DELETE(l_context);
+        return NULL;
     }
-    DAP_DEL_Z(a_sync_request);
+    l_ch_chain->sync_timer = dap_timerfd_start_on_worker(a_ch->stream_worker->worker, 1000, s_sync_timer_callback, l_uuid);
+    a_ch->stream->esocket->callbacks.write_finished_callback = s_stream_ch_io_complete;
+    a_ch->stream->esocket->callbacks.arg = l_context;
+    if (l_context->worker->worker->_inheritor != a_ch->stream_worker)
+        log_it(L_CRITICAL, "Corrupted stream worker %p", a_ch->stream_worker);
+    return l_context;
 }
 
 /**
- * @brief s_sync_out_chains_worker_callback
- * @param a_worker
- * @param a_arg
+ * @brief s_stream_ch_chain_delete
+ * @param a_ch_chain
  */
-static void s_sync_out_chains_first_worker_callback(dap_worker_t *a_worker, void *a_arg)
+static void s_legacy_sync_context_delete(void *a_arg)
 {
-    struct sync_request * l_sync_request = (struct sync_request *) a_arg;
-    dap_stream_ch_t *l_ch = dap_stream_ch_find_by_uuid_unsafe( DAP_STREAM_WORKER(a_worker) , l_sync_request->ch_uuid);
-    if( l_ch == NULL ){
-        log_it(L_INFO,"Client disconnected before we sent the reply");
-        s_sync_request_delete(l_sync_request);
-        return;
-    }
+    struct legacy_sync_context *l_context = a_arg;
+    dap_return_if_fail(l_context);
 
-    dap_chain_ch_t * l_ch_chain = DAP_CHAIN_CH(l_ch);
-    if (!l_ch_chain) {
-        log_it(L_CRITICAL, "Channel without chain, dump it");
-        s_sync_request_delete(l_sync_request);
-        return;
-    }
-    if (l_ch_chain->state != DAP_CHAIN_CH_STATE_UPDATE_CHAINS_REMOTE) {
-        log_it(L_INFO, "Timeout fired before we sent the reply");
-        s_sync_request_delete(l_sync_request);
-        return;
-    }
+    dap_chain_ch_hash_item_t *l_hash_item, *l_tmp;
 
-    l_ch_chain->state = DAP_CHAIN_CH_STATE_SYNC_CHAINS;
-    l_ch_chain->request_atom_iter = l_sync_request->chain.request_atom_iter;
+    if (l_context->is_type_of_gdb) {
+        HASH_ITER(hh, l_context->remote_gdbs, l_hash_item, l_tmp) {
+            // Clang bug at this, l_hash_item should change at every loop cycle
+            HASH_DEL(l_context->remote_gdbs, l_hash_item);
+            DAP_DELETE(l_hash_item);
+        }
+        l_context->remote_atoms = NULL;
+
+        if (l_context->db_list)
+            dap_global_db_legacy_list_delete(l_context->db_list);
+    } else {
+        HASH_ITER(hh, l_context->remote_atoms, l_hash_item, l_tmp) {
+            // Clang bug at this, l_hash_item should change at every loop cycle
+            HASH_DEL(l_context->remote_atoms, l_hash_item);
+            DAP_DELETE(l_hash_item);
+        }
+        l_context->remote_gdbs = NULL;
 
-    if (s_debug_more )
-        log_it(L_INFO,"Out: DAP_CHAIN_CH_PKT_TYPE_FIRST_CHAIN");
+        if (l_context->atom_iter)
+            l_context->atom_iter->chain->callback_atom_iter_delete(l_context->atom_iter);
+    }
 
-    dap_chain_ch_pkt_write_unsafe(l_ch, DAP_CHAIN_CH_PKT_TYPE_FIRST_CHAIN,
-            l_ch_chain->request_hdr.net_id.uint64, l_ch_chain->request_hdr.chain_id.uint64,
-            l_ch_chain->request_hdr.cell_id.uint64, &g_node_addr, sizeof(dap_chain_node_addr_t));
-    DAP_DELETE(l_sync_request);
+    dap_stream_ch_t *l_ch = dap_stream_ch_find_by_uuid_unsafe(l_context->worker, l_context->ch_uuid);
+    if (l_ch) {
+        DAP_CHAIN_CH(l_ch)->legacy_sync_context = NULL;
+        l_ch->stream->esocket->callbacks.write_finished_callback = NULL;
+        l_ch->stream->esocket->callbacks.arg = NULL;
+    }
 
+    DAP_DELETE(l_context);
 }
 
-/**
- * @brief s_sync_out_chains_last_worker_callback
- * @param a_worker
- * @param a_arg
- */
-static void s_sync_out_chains_last_worker_callback(dap_worker_t *a_worker, void *a_arg)
+static bool s_sync_out_gdb_proc_callback(void *a_arg)
 {
-    struct sync_request * l_sync_request = (struct sync_request *) a_arg;
-    dap_stream_ch_t *l_ch = dap_stream_ch_find_by_uuid_unsafe(DAP_STREAM_WORKER(a_worker), l_sync_request->ch_uuid);
-    if( l_ch == NULL ){
-        log_it(L_INFO,"Client disconnected before we sent the reply");
-        s_sync_request_delete(l_sync_request);
-        return;
+    struct legacy_sync_context *l_context = a_arg;
+    dap_chain_ch_state_t l_cur_state = l_context->state;
+    if (l_cur_state != DAP_CHAIN_CH_STATE_UPDATE_GLOBAL_DB && l_cur_state != DAP_CHAIN_CH_STATE_SYNC_GLOBAL_DB) {
+        // Illegal context
+        assert(l_cur_state == DAP_CHAIN_CH_STATE_IDLE);
+        goto context_delete;
+    }
+    dap_list_t *l_list_out = dap_global_db_legacy_list_get_multiple(l_context->db_list, s_update_pack_size);
+    if (!l_list_out) {
+        dap_chain_ch_sync_request_old_t l_payload = { .node_addr = g_node_addr };
+        uint8_t l_type = l_cur_state == DAP_CHAIN_CH_STATE_UPDATE_GLOBAL_DB ? DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_END
+                                                                            : DAP_CHAIN_CH_PKT_TYPE_SYNCED_GLOBAL_DB;
+        debug_if(s_debug_legacy, L_INFO, "Out: %s", dap_chain_ch_pkt_type_to_str(l_type));
+        dap_chain_ch_pkt_write_mt(l_context->worker, l_context->ch_uuid, l_type,
+                                  l_context->request_hdr.net_id, l_context->request_hdr.chain_id, l_context->request_hdr.cell_id,
+                                  &l_payload, sizeof(l_payload), DAP_CHAIN_CH_PKT_VERSION_LEGACY);
+        if (l_cur_state == DAP_CHAIN_CH_STATE_SYNC_GLOBAL_DB) {
+            log_it(L_INFO, "Synchronized database: items synchronized %" DAP_UINT64_FORMAT_U " from %zu",
+                                             l_context->stats_request_gdbs_processed, l_context->db_list->items_number);
+            l_context->state = DAP_CHAIN_CH_STATE_IDLE;
+            goto context_delete;
+        }
+        dap_global_db_legacy_list_rewind(l_context->db_list);
+        if (atomic_compare_exchange_strong(&l_context->state, &l_cur_state, DAP_CHAIN_CH_STATE_SYNC_GLOBAL_DB_REMOTE))
+            return false;
+        goto context_delete;
     }
 
-    dap_chain_ch_t * l_ch_chain = DAP_CHAIN_CH(l_ch);
-    if (!l_ch_chain) {
-        log_it(L_CRITICAL, "Channel without chain, dump it");
-        s_sync_request_delete(l_sync_request);
-        return;
+    void *l_data = NULL;
+    size_t l_data_size = 0;
+    uint8_t l_type = DAP_CHAIN_CH_PKT_TYPE_GLOBAL_DB;
+    if (l_cur_state == DAP_CHAIN_CH_STATE_UPDATE_GLOBAL_DB) {
+        l_type = DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB;
+        l_data_size = dap_list_length(l_list_out) * sizeof(dap_chain_ch_update_element_t);
+        l_data = DAP_NEW_Z_SIZE(dap_chain_ch_update_element_t, l_data_size);
+        if (!l_data) {
+            log_it(L_CRITICAL, "%s", g_error_memory_alloc);
+            l_context->state = DAP_CHAIN_CH_STATE_ERROR;
+            goto context_delete;
+        }
     }
-    l_ch_chain->request_atom_iter = l_sync_request->chain.request_atom_iter;
-    // last packet
-    dap_chain_ch_sync_request_old_t l_request = {};
-    if (s_debug_more )
-        log_it(L_INFO,"Out: DAP_CHAIN_CH_PKT_TYPE_SYNCED_CHAINS");
-    dap_chain_ch_pkt_write_unsafe(l_ch, DAP_CHAIN_CH_PKT_TYPE_SYNCED_CHAINS,
-            l_sync_request->request_hdr.net_id.uint64, l_sync_request->request_hdr.chain_id.uint64,
-            l_sync_request->request_hdr.cell_id.uint64, &l_request, sizeof(l_request));
-    s_ch_chain_go_idle(l_ch_chain);
-    DAP_DELETE(l_sync_request);
-}
-/**
- * @brief s_sync_chains_callback
- * @param a_thread
- * @param a_arg
- * @return
- */
-static bool s_sync_out_chains_proc_callback(void *a_arg)
-{
-    struct sync_request * l_sync_request = (struct sync_request *) a_arg;
-
-    dap_chain_t * l_chain = dap_chain_find_by_id(l_sync_request->request_hdr.net_id, l_sync_request->request_hdr.chain_id);
-    assert(l_chain);
-    l_sync_request->chain.request_atom_iter = l_chain->callback_atom_iter_create(l_chain, l_sync_request->request_hdr.cell_id, NULL, false);
-    size_t l_first_size = 0;
-    dap_chain_atom_ptr_t l_atom = l_chain->callback_atom_iter_get(l_sync_request->chain.request_atom_iter, DAP_CHAIN_ITER_OP_FIRST, &l_first_size);
-    if (l_atom && l_first_size) {
-        // first packet
-        dap_chain_hash_fast_t l_hash_from = l_sync_request->request.hash_from;
-        if (!dap_hash_fast_is_blank(&l_hash_from)) {
-            (void ) l_chain->callback_atom_find_by_hash(l_sync_request->chain.request_atom_iter,
-                                                          &l_hash_from, &l_first_size);
-        }
-         dap_worker_exec_callback_on(dap_events_worker_get(l_sync_request->worker->id), s_sync_out_chains_first_worker_callback, l_sync_request );
-    } else {
-         dap_worker_exec_callback_on(dap_events_worker_get(l_sync_request->worker->id),s_sync_out_chains_last_worker_callback, l_sync_request );
+    bool l_go_wait = false;
+    size_t i = 0;
+    for (dap_list_t *it = l_list_out; it; it = it->next, i++) {
+        dap_global_db_pkt_old_t *l_pkt = it->data;
+        if (l_context->db_list->items_rest)
+            --l_context->db_list->items_rest;
+        dap_hash_t l_pkt_hash;
+        dap_hash_fast(l_pkt->data, l_pkt->data_size, &l_pkt_hash);
+        if (l_cur_state == DAP_CHAIN_CH_STATE_UPDATE_GLOBAL_DB) {
+            dap_chain_ch_update_element_t *l_hashes = l_data;
+            l_hashes[i].hash = l_pkt_hash;
+            l_hashes[i].size = l_pkt->data_size;
+        } else { // l_cur_state == DAP_CHAIN_CH_STATE_SYNC_GLOBAL_DB
+            dap_chain_ch_hash_item_t *l_hash_item = NULL;
+            HASH_FIND(hh, l_context->remote_gdbs, &l_pkt_hash, sizeof(dap_hash_fast_t), l_hash_item);
+            if (!l_hash_item) {
+                dap_global_db_pkt_old_t *l_pkt_pack = l_data;
+                size_t l_cur_size = l_pkt_pack ? l_pkt_pack->data_size : 0;
+                if (l_cur_size + sizeof(dap_global_db_pkt_old_t) + l_pkt->data_size >= DAP_CHAIN_PKT_EXPECT_SIZE) {
+                    l_context->enqueued_data_size += l_data_size;
+                    if (!l_go_wait && l_context->enqueued_data_size > DAP_EVENTS_SOCKET_BUF_SIZE / 2) {
+                        if (!atomic_compare_exchange_strong(&l_context->state, &l_cur_state, DAP_CHAIN_CH_STATE_WAITING))
+                            goto context_delete;
+                        l_context->prev_state = l_cur_state;
+                        l_go_wait = true;
+                    }
+                    dap_chain_ch_pkt_write_mt(l_context->worker, l_context->ch_uuid, l_type,
+                                              l_context->request_hdr.net_id, l_context->request_hdr.chain_id, l_context->request_hdr.cell_id,
+                                              l_data, l_data_size, DAP_CHAIN_CH_PKT_VERSION_LEGACY);
+                    debug_if(s_debug_legacy, L_INFO, "Send one global_db packet len=%zu (rest=%zu/%zu items)", l_data_size,
+                                                l_context->db_list->items_rest, l_context->db_list->items_number);
+                    l_context->last_activity = dap_time_now();
+                    DAP_DEL_Z(l_pkt_pack);
+                    l_cur_size = 0;
+                }
+                l_pkt_pack = dap_global_db_pkt_pack_old(l_pkt_pack, l_pkt);
+                if (!l_pkt_pack || l_cur_size == l_pkt_pack->data_size) {
+                    log_it(L_CRITICAL, "%s", g_error_memory_alloc);
+                    l_context->state = DAP_CHAIN_CH_STATE_ERROR;
+                    goto context_delete;
+                }
+                l_context->stats_request_gdbs_processed++;
+                l_data = l_pkt_pack;
+                l_data_size = sizeof(dap_global_db_pkt_old_t) + l_pkt_pack->data_size;
+            } /* else       // Over-extended debug
+                debug_if(s_debug_legacy, L_DEBUG, "Skip GDB hash %s because its already present in remote GDB hash table",
+                                                dap_hash_fast_to_str_static(&l_pkt_hash));
+            */
+        }
+    }
+    dap_list_free_full(l_list_out, NULL);
+
+    if (l_data && l_data_size) {
+        dap_chain_ch_pkt_write_mt(l_context->worker, l_context->ch_uuid, l_type,
+                                  l_context->request_hdr.net_id, l_context->request_hdr.chain_id, l_context->request_hdr.cell_id,
+                                  l_data, l_data_size, DAP_CHAIN_CH_PKT_VERSION_LEGACY);
+        if (l_cur_state == DAP_CHAIN_CH_STATE_UPDATE_GLOBAL_DB)
+            debug_if(s_debug_legacy, L_INFO, "Out: %s, %zu records", dap_chain_ch_pkt_type_to_str(l_type), i);
+        else
+            debug_if(s_debug_legacy, L_INFO, "Send one global_db packet len=%zu (rest=%zu/%zu items)", l_data_size,
+                                            l_context->db_list->items_rest, l_context->db_list->items_number);
+        l_context->last_activity = dap_time_now();
+        DAP_DELETE(l_data);
+    } else if (l_context->last_activity + 3 < dap_time_now()) {
+        l_context->last_activity = dap_time_now();
+        debug_if(s_debug_more, L_INFO, "Send one GlobalDB no freeze packet");
+        dap_chain_ch_pkt_write_mt(l_context->worker, l_context->ch_uuid, DAP_CHAIN_CH_PKT_TYPE_GLOBAL_DB_NO_FREEZE,
+                                             l_context->request_hdr.net_id, l_context->request_hdr.chain_id,
+                                             l_context->request_hdr.cell_id, NULL, 0, DAP_CHAIN_CH_PKT_VERSION_LEGACY);
     }
+    if (!l_go_wait)
+        return true;
+    return false;
+context_delete:
+    dap_worker_exec_callback_on(l_context->worker->worker, s_legacy_sync_context_delete, l_context);
     return false;
 }
 
+struct record_processing_args {
+    dap_stream_worker_t *worker;
+    dap_stream_ch_uuid_t uuid;
+    dap_chain_ch_pkt_hdr_t hdr;
+    dap_global_db_pkt_old_t *pkt;
+    bool new;
+};
 
-/**
- * @brief s_sync_out_gdb_first_gdb_worker_callback
- * @param a_worker
- * @param a_arg
- */
-static void s_sync_out_gdb_first_worker_callback(dap_worker_t *a_worker, void *a_arg)
+static bool s_gdb_in_pkt_proc_callback(void *a_arg)
 {
-    struct sync_request *l_sync_request = (struct sync_request *) a_arg;
-
-    dap_stream_ch_t *l_ch = dap_stream_ch_find_by_uuid_unsafe(DAP_STREAM_WORKER(l_sync_request->worker), l_sync_request->ch_uuid);
-    if( l_ch == NULL ){
-        log_it(L_INFO,"Client disconnected before we sent the reply");
-        s_sync_request_delete(l_sync_request);
-        return;
-    }
-
-    dap_chain_ch_t *l_ch_chain = DAP_CHAIN_CH( l_ch );
-
-    if (!l_ch_chain) {
-        log_it(L_CRITICAL, "Channel without chain, dump it");
-        s_sync_request_delete(l_sync_request);
-        return;
-    }
-
-    if (l_ch_chain->state != DAP_CHAIN_CH_STATE_UPDATE_GLOBAL_DB_REMOTE) {
-        log_it(L_INFO, "Timeout fired before we sent the reply");
-        s_sync_request_delete(l_sync_request);
-        return;
-    }
-
-    // Add it to outgoing list
-    l_ch_chain->state = DAP_CHAIN_CH_STATE_SYNC_GLOBAL_DB;
-    if (s_debug_more )
-        log_it(L_INFO,"Out: DAP_CHAIN_CH_PKT_TYPE_FIRST_GLOBAL_DB");
-    dap_chain_ch_pkt_write_unsafe(DAP_STREAM_CH(l_ch_chain), DAP_CHAIN_CH_PKT_TYPE_FIRST_GLOBAL_DB,
-            l_ch_chain->request_hdr.net_id.uint64, l_ch_chain->request_hdr.chain_id.uint64,
-            l_ch_chain->request_hdr.cell_id.uint64, &g_node_addr, sizeof(dap_chain_node_addr_t));
-
-    if( a_worker){ // We send NULL to prevent delete
-        s_sync_request_delete(l_sync_request);
+    struct record_processing_args *l_args = a_arg;
+    size_t l_objs_count = 0;
+    dap_store_obj_t *l_objs = dap_global_db_pkt_deserialize_old(l_args->pkt, &l_objs_count);
+    DAP_DELETE(l_args->pkt);
+    if (!l_objs || !l_objs_count) {
+        log_it(L_WARNING, "Deserialization of legacy global DB packet failed");
+        DAP_DELETE(l_args);
+        return false;
     }
+    bool l_success = false;
+    dap_stream_node_addr_t l_blank_addr = { .uint64 = 0 };
+    for (uint32_t i = 0; i < l_objs_count; i++)
+        if (!(l_success = dap_global_db_ch_check_store_obj(l_objs + i, &l_blank_addr)))
+            break;
+    if (l_args->new && l_objs_count == 1)
+        l_objs[0].flags |= DAP_GLOBAL_DB_RECORD_NEW;
+    if (l_success)
+        dap_global_db_set_raw_sync(l_objs, l_objs_count);
+    dap_store_obj_free(l_objs, l_objs_count);
+    DAP_DELETE(l_args);
+    return false;
 }
 
-/**
- * @brief s_sync_out_gdb_synced_data_worker_callback
- * @param a_worker
- * @param a_arg
- */
-static void s_sync_out_gdb_last_worker_callback(dap_worker_t *a_worker, void *a_arg)
+static bool s_sync_out_chains_proc_callback(void *a_arg)
 {
-    struct sync_request * l_sync_request = (struct sync_request *) a_arg;
-    dap_stream_ch_t *l_ch = dap_stream_ch_find_by_uuid_unsafe(DAP_STREAM_WORKER(a_worker), l_sync_request->ch_uuid);
-    if( l_ch == NULL ){
-        log_it(L_INFO,"Client disconnected before we sent the reply");
-        s_sync_request_delete(l_sync_request);
-        return;
-    }
-
-    dap_chain_ch_t *l_ch_chain = DAP_CHAIN_CH( l_ch );
-    if (!l_ch_chain) {
-        log_it(L_CRITICAL, "Channel without chain, dump it");
-        s_sync_request_delete(l_sync_request);
-        return;
+    struct legacy_sync_context *l_context = a_arg;
+    dap_chain_ch_state_t l_cur_state = l_context->state;
+    if (l_cur_state != DAP_CHAIN_CH_STATE_UPDATE_CHAINS && l_cur_state != DAP_CHAIN_CH_STATE_SYNC_CHAINS) {
+        // Illegal context
+        assert(l_cur_state == DAP_CHAIN_CH_STATE_IDLE);
+        goto context_delete;
     }
-    s_sync_out_gdb_first_worker_callback(NULL,a_arg); // NULL to say callback not to delete request
-
-    if (s_debug_more )
-        log_it(L_INFO,"Out: DAP_CHAIN_CH_PKT_TYPE_SYNCED_GLOBAL_DB");
-    dap_chain_ch_pkt_write_unsafe(DAP_STREAM_CH(l_ch_chain), DAP_CHAIN_CH_PKT_TYPE_SYNCED_GLOBAL_DB,
-                                         l_ch_chain->request_hdr.net_id.uint64, l_ch_chain->request_hdr.chain_id.uint64,
-                                         l_ch_chain->request_hdr.cell_id.uint64, NULL, 0);
-    s_ch_chain_go_idle(l_ch_chain);
-    s_sync_request_delete(l_sync_request);
-}
 
-/**
- * @brief s_sync_out_gdb_callback
- * @param a_thread
- * @param a_arg
- * @return
- */
-static bool s_sync_out_gdb_proc_callback(void *a_arg)
-{
-    /*
-    struct sync_request *l_sync_request = (struct sync_request *)a_arg;
-    dap_chain_net_t *l_net = dap_chain_net_by_id(l_sync_request->request_hdr.net_id);
-    dap_stream_ch_t *l_ch = dap_stream_ch_find_by_uuid_unsafe(DAP_STREAM_WORKER(l_sync_request->worker), l_sync_request->ch_uuid);
-    if (l_ch == NULL) {
-        log_it(L_INFO, "Client disconnected before we sent the reply");
-        s_sync_request_delete(l_sync_request);
-        return true;
+    dap_chain_ch_update_element_t *l_hashes = NULL;
+    if (l_cur_state == DAP_CHAIN_CH_STATE_UPDATE_CHAINS) {
+        l_hashes = DAP_NEW_Z_SIZE(dap_chain_ch_update_element_t, s_update_pack_size * sizeof(dap_chain_ch_update_element_t));
+        if (!l_hashes) {
+            log_it(L_CRITICAL, "%s", g_error_memory_alloc);
+            l_context->state = DAP_CHAIN_CH_STATE_ERROR;
+            goto context_delete;
+        }
     }
-    dap_chain_ch_t *l_ch_chain = DAP_CHAIN_CH(l_ch);
-    if (!l_ch_chain) {
-        log_it(L_CRITICAL, "Channel without chain, dump it");
-        s_sync_request_delete(l_sync_request);
-        return true;
+    size_t l_data_size = 0;
+    bool l_chain_end = false, l_go_wait = false;
+    for (uint_fast16_t i = 0; i < s_update_pack_size; i++) {
+        if (!l_context->atom_iter->cur || !l_context->atom_iter->cur_size) {
+            l_chain_end = true;
+            break;
+        }
+        if (l_cur_state == DAP_CHAIN_CH_STATE_UPDATE_CHAINS) {
+            l_hashes[i].hash = *l_context->atom_iter->cur_hash;
+            l_hashes[i].size = l_context->atom_iter->cur_size;
+            l_data_size += sizeof(dap_chain_ch_update_element_t);
+        } else { // l_cur_state == DAP_CHAIN_CH_STATE_SYNC_CHAINS
+            dap_chain_ch_hash_item_t *l_hash_item = NULL;
+            HASH_FIND(hh, l_context->remote_atoms, l_context->atom_iter->cur_hash, sizeof(dap_hash_fast_t), l_hash_item);
+            if (!l_hash_item) {
+                l_context->enqueued_data_size += l_context->atom_iter->cur_size;
+                if (l_context->enqueued_data_size > DAP_EVENTS_SOCKET_BUF_SIZE / 2) {
+                    if (!atomic_compare_exchange_strong(&l_context->state, &l_cur_state, DAP_CHAIN_CH_STATE_WAITING))
+                        goto context_delete;
+                    l_context->prev_state = l_cur_state;
+                    l_go_wait = true;
+                }
+                dap_chain_ch_pkt_write_mt(l_context->worker, l_context->ch_uuid, DAP_CHAIN_CH_PKT_TYPE_CHAIN_OLD,
+                                          l_context->request_hdr.net_id, l_context->request_hdr.chain_id, l_context->request_hdr.cell_id,
+                                          l_context->atom_iter->cur, l_context->atom_iter->cur_size, DAP_CHAIN_CH_PKT_VERSION_LEGACY);
+                debug_if(s_debug_legacy, L_INFO, "Out CHAIN pkt: atom hash %s (size %zd)", dap_hash_fast_to_str_static(l_context->atom_iter->cur_hash),
+                                                                                           l_context->atom_iter->cur_size);
+                l_context->last_activity = dap_time_now();
+                l_context->stats_request_atoms_processed++;
+            } /* else       // Over-extended debug
+                debug_if(s_debug_legacy, L_DEBUG, "Skip atom hash %s because its already present in remote atoms hash table",
+                                                dap_hash_fast_to_str_static(&l_context->atom_iter->cur_hash));
+            */
+        }
+        l_context->atom_iter->chain->callback_atom_iter_get(l_context->atom_iter, DAP_CHAIN_ITER_OP_NEXT, NULL);
+        if (l_go_wait)
+            break;
     }
-    int l_flags = 0;
-    if (dap_chain_net_get_extra_gdb_group(l_net, l_sync_request->request.node_addr))
-        l_flags |= F_DB_LOG_ADD_EXTRA_GROUPS;
-    if (!l_sync_request->request.id_start)
-        l_flags |= F_DB_LOG_SYNC_FROM_ZERO;
-    if (l_ch_chain->request_db_log != NULL)
-        dap_db_log_list_delete(l_ch_chain->request_db_log);
-    l_ch_chain->request_db_log = dap_db_log_list_start(l_net->pub.name, l_sync_request->request.node_addr.uint64, l_flags);
-
-    if (l_ch_chain->request_db_log) {
-        if (s_debug_more)
-            log_it(L_DEBUG, "Sync out gdb proc, requested %"DAP_UINT64_FORMAT_U" records from address "NODE_ADDR_FP_STR,
-                             l_ch_chain->request_db_log->items_number, NODE_ADDR_FP_ARGS_S(l_sync_request->request.node_addr));
-        l_sync_request->gdb.db_log = l_ch_chain->request_db_log;
-         dap_worker_exec_callback_on(dap_events_worker_get(l_sync_request->worker->id), s_sync_out_gdb_first_worker_callback, l_sync_request );
-    } else {
-         dap_worker_exec_callback_on(dap_events_worker_get(l_sync_request->worker->id), s_sync_out_gdb_last_worker_callback, l_sync_request );
-    } */
-    return false;
-}
-
-static void s_sync_update_gdb_start_worker_callback(dap_worker_t *a_worker, void *a_arg)
-{
-    struct sync_request *l_sync_request = (struct sync_request *) a_arg;
 
-    dap_stream_ch_t *l_ch = dap_stream_ch_find_by_uuid_unsafe(DAP_STREAM_WORKER(a_worker), l_sync_request->ch_uuid);
-    if( l_ch == NULL ){
-        log_it(L_INFO,"Client disconnected before we sent the reply");
-        s_sync_request_delete(l_sync_request);
-        return;
+    if (l_hashes) {
+        dap_chain_ch_pkt_write_mt(l_context->worker, l_context->ch_uuid, DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS,
+                                  l_context->request_hdr.net_id, l_context->request_hdr.chain_id, l_context->request_hdr.cell_id,
+                                  l_hashes, l_data_size, DAP_CHAIN_CH_PKT_VERSION_LEGACY);
+        debug_if(s_debug_legacy, L_INFO, "Out: DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS, %zu records", l_data_size / sizeof(dap_chain_ch_update_element_t));
+        DAP_DELETE(l_hashes);
+    } else if (l_context->last_activity + 3 < dap_time_now()) {
+        l_context->last_activity = dap_time_now();
+        debug_if(s_debug_more, L_INFO, "Send one chain no freeze packet");
+        dap_chain_ch_pkt_write_mt(l_context->worker, l_context->ch_uuid, DAP_CHAIN_CH_PKT_TYPE_CHAINS_NO_FREEZE,
+                                        l_context->request_hdr.net_id, l_context->request_hdr.chain_id,
+                                        l_context->request_hdr.cell_id, NULL, 0, DAP_CHAIN_CH_PKT_VERSION_LEGACY);
     }
-    dap_chain_ch_pkt_write_unsafe(l_ch, DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_START,
-                                         l_sync_request->request_hdr.net_id.uint64, l_sync_request->request_hdr.chain_id.uint64,
-                                         l_sync_request->request_hdr.cell_id.uint64, NULL, 0);
-    if (s_debug_more)
-        log_it(L_INFO, "Out: DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_START for net_id 0x%016"DAP_UINT64_FORMAT_x" "
-                       "chain_id 0x%016"DAP_UINT64_FORMAT_x" cell_id 0x%016"DAP_UINT64_FORMAT_x"",
-                       l_sync_request->request_hdr.net_id.uint64, l_sync_request->request_hdr.chain_id.uint64, l_sync_request->request_hdr.cell_id.uint64);
-    DAP_DELETE(l_sync_request);
-}
 
-static bool s_sync_update_gdb_proc_callback(void *a_arg)
-{
-    /*
-    struct sync_request *l_sync_request = (struct sync_request *)a_arg;
-    log_it(L_DEBUG, "Prepare request to gdb sync from %s", l_sync_request->request.id_start ? "last sync" : "zero");
-    dap_chain_net_t *l_net = dap_chain_net_by_id(l_sync_request->request_hdr.net_id);
-    if (!l_net) {
-        log_it(L_ERROR, "Network ID 0x%016"DAP_UINT64_FORMAT_x" not found", l_sync_request->request_hdr.net_id.uint64);
-        DAP_DELETE(l_sync_request);
-        return true;
+    if (l_chain_end) {
+        dap_chain_ch_sync_request_old_t l_payload = { .node_addr = g_node_addr };
+        uint8_t l_type = l_cur_state == DAP_CHAIN_CH_STATE_UPDATE_CHAINS ? DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_END
+                                                                         : DAP_CHAIN_CH_PKT_TYPE_SYNCED_CHAINS;
+        debug_if(s_debug_legacy, L_INFO, "Out: %s", dap_chain_ch_pkt_type_to_str(l_type));
+        dap_chain_ch_pkt_write_mt(l_context->worker, l_context->ch_uuid, l_type,
+                                  l_context->request_hdr.net_id, l_context->request_hdr.chain_id, l_context->request_hdr.cell_id,
+                                  &l_payload, sizeof(l_payload), DAP_CHAIN_CH_PKT_VERSION_LEGACY);
+        debug_if(l_cur_state == DAP_CHAIN_CH_STATE_UPDATE_CHAINS, L_INFO,
+                    "Synchronized chain: items synchronized %" DAP_UINT64_FORMAT_U, l_context->stats_request_atoms_processed);
+        if (l_cur_state == DAP_CHAIN_CH_STATE_SYNC_CHAINS) {
+            l_context->state = DAP_CHAIN_CH_STATE_IDLE;
+            goto context_delete;
+        }
+        l_context->atom_iter->chain->callback_atom_iter_get(l_context->atom_iter, DAP_CHAIN_ITER_OP_FIRST, NULL);
+        if (atomic_compare_exchange_strong(&l_context->state, &l_cur_state, DAP_CHAIN_CH_STATE_SYNC_CHAINS_REMOTE))
+            return false;
+        goto context_delete;
     }
-    dap_stream_ch_t *l_ch = dap_stream_ch_find_by_uuid_unsafe(DAP_STREAM_WORKER(l_sync_request->worker), l_sync_request->ch_uuid);
-    if (!l_ch) {
-        log_it(L_INFO, "Client disconnected before we sent the reply");
-        DAP_DELETE(l_sync_request);
+    if (!l_go_wait)
         return true;
-    } else if (!DAP_CHAIN_CH(l_ch)) {
-        log_it(L_CRITICAL, "Channel without chain, dump it");
-        DAP_DELETE(l_sync_request);
-        return true;
-    }
-
-    dap_chain_ch_t *l_ch_chain = DAP_CHAIN_CH(l_ch);
-    int l_flags = 0;
-    if (dap_chain_net_get_extra_gdb_group(l_net, l_sync_request->request.node_addr))
-        l_flags |= F_DB_LOG_ADD_EXTRA_GROUPS;
-    if (!l_sync_request->request.id_start)
-        l_flags |= F_DB_LOG_SYNC_FROM_ZERO;
-    if (l_ch_chain->request_db_log != NULL)
-        dap_db_log_list_delete(l_ch_chain->request_db_log);
-    l_ch_chain->request_db_log = dap_db_log_list_start(l_net->pub.name, l_sync_request->request.node_addr.uint64, l_flags);
-    l_ch_chain->state = DAP_CHAIN_CH_STATE_UPDATE_GLOBAL_DB;
-    l_sync_request->gdb.db_log = l_ch_chain->request_db_log;
-    l_sync_request->request.node_addr.uint64 = dap_chain_net_get_cur_addr_int(l_net);
-     dap_worker_exec_callback_on(dap_events_worker_get(l_sync_request->worker->id), s_sync_update_gdb_start_worker_callback, l_sync_request);
-     */
     return false;
-}
-
-static bool s_gdb_in_pkt_proc_callback(void *a_arg)
-{
+context_delete:
+    dap_worker_exec_callback_on(l_context->worker->worker, s_legacy_sync_context_delete, l_context);
     return false;
 }
 
+// *** End of legacy support code *** //
+
+
 struct atom_processing_args {
     dap_stream_node_addr_t addr;
     bool ack_req;
@@ -615,7 +638,7 @@ static bool s_sync_in_chains_callback(void *a_arg)
         debug_if(s_debug_more, L_INFO, "Thresholded atom with hash %s for %s:%s", l_atom_hash_str, l_chain->net_name, l_chain->name);
         break;
     case ATOM_ACCEPT:
-        debug_if(s_debug_more, L_INFO,"Accepted atom with hash %s for %s:%s", l_atom_hash_str, l_chain->net_name, l_chain->name);
+        debug_if(s_debug_more, L_INFO, "Accepted atom with hash %s for %s:%s", l_atom_hash_str, l_chain->net_name, l_chain->name);
         if (dap_chain_atom_save(l_chain->cells, l_atom, l_atom_size, NULL) < 0)
             log_it(L_ERROR, "Can't save atom %s to the file", l_atom_hash_str);
         else
@@ -639,8 +662,8 @@ static bool s_sync_in_chains_callback(void *a_arg)
     }
     if (l_ack_send && l_args->ack_req) {
         uint64_t l_ack_num = (l_chain_pkt->hdr.num_hi << 16) | l_chain_pkt->hdr.num_lo;
-        dap_chain_ch_pkt_t *l_pkt = dap_chain_ch_pkt_new(l_chain_pkt->hdr.net_id.uint64, l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64,
-                                                         &l_ack_num, sizeof(uint64_t));
+        dap_chain_ch_pkt_t *l_pkt = dap_chain_ch_pkt_new(l_chain_pkt->hdr.net_id, l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
+                                                         &l_ack_num, sizeof(uint64_t), DAP_CHAIN_CH_PKT_VERSION_CURRENT);
         dap_stream_ch_pkt_send_by_addr(&l_args->addr, DAP_CHAIN_CH_ID, DAP_CHAIN_CH_PKT_TYPE_CHAIN_ACK, l_pkt, dap_chain_ch_pkt_get_size(l_pkt));
         DAP_DELETE(l_pkt);
         debug_if(s_debug_more, L_DEBUG, "Out: CHAIN_ACK %s for net %s to destination " NODE_ADDR_FP_STR " with num %" DAP_UINT64_FORMAT_U,
@@ -664,7 +687,7 @@ static void s_gossip_payload_callback(void *a_payload, size_t a_payload_size, da
     }
     struct atom_processing_args *l_args = DAP_NEW_SIZE(struct atom_processing_args, a_payload_size + sizeof(struct atom_processing_args));
     if (!l_args) {
-        log_it(L_CRITICAL, g_error_memory_alloc);
+        log_it(L_CRITICAL, "%s", g_error_memory_alloc);
         return;
     }
     l_args->addr = a_sender_addr;
@@ -673,116 +696,13 @@ static void s_gossip_payload_callback(void *a_payload, size_t a_payload_size, da
     dap_proc_thread_callback_add(NULL, s_sync_in_chains_callback, l_args);
 }
 
-/**
- * @brief s_gdb_in_pkt_error_worker_callback
- * @param a_thread
- * @param a_arg
- */
-static void s_gdb_in_pkt_error_worker_callback(dap_worker_t *a_worker, void *a_arg)
-{
-    struct sync_request *l_sync_request = (struct sync_request *) a_arg;
-
-    dap_stream_ch_t *l_ch = dap_stream_ch_find_by_uuid_unsafe(DAP_STREAM_WORKER(a_worker), l_sync_request->ch_uuid);
-    if (l_ch == NULL)
-        log_it(L_INFO,"Client disconnected before we sent the reply");
-    else
-        dap_stream_ch_write_error_unsafe(l_ch, l_sync_request->request_hdr.net_id.uint64,
-                                           l_sync_request->request_hdr.chain_id.uint64,
-                                           l_sync_request->request_hdr.cell_id.uint64,
-                                           DAP_CHAIN_CH_ERROR_GLOBAL_DB_INTERNAL_NOT_SAVED);
-    DAP_DELETE(l_sync_request);
-}
-
-/**
- * @brief dap_chain_ch_create_sync_request_gdb
- * @param a_ch_chain
- * @param a_net
- */
-struct sync_request *dap_chain_ch_create_sync_request(dap_chain_ch_pkt_t *a_chain_pkt, dap_stream_ch_t* a_ch)
-{
-    dap_chain_ch_t * l_ch_chain = DAP_CHAIN_CH(a_ch);
-    if (!l_ch_chain) {
-        log_it(L_CRITICAL, "Channel without chain, dump it");
-        return NULL;
-    }
-    struct sync_request *l_sync_request = DAP_NEW_Z(struct sync_request);
-    if (!l_sync_request) {
-        log_it(L_CRITICAL, "%s", g_error_memory_alloc);
-        return NULL;
-    }
-    *l_sync_request = (struct sync_request) {
-            .worker         = a_ch->stream_worker->worker,
-            .ch_uuid        = a_ch->uuid,
-            .request        = l_ch_chain->request,
-            .request_hdr    = a_chain_pkt->hdr,
-            .remote_atoms   = l_ch_chain->remote_atoms,
-            .remote_gdbs    = l_ch_chain->remote_gdbs };
-    return l_sync_request;
-}
-
-void dap_stream_ch_write_error_unsafe(dap_stream_ch_t *a_ch, uint64_t a_net_id, uint64_t a_chain_id, uint64_t a_cell_id, dap_chain_ch_error_type_t a_error)
+void dap_stream_ch_write_error_unsafe(dap_stream_ch_t *a_ch, dap_chain_net_id_t a_net_id, dap_chain_id_t a_chain_id, dap_chain_cell_id_t a_cell_id, dap_chain_ch_error_type_t a_error)
 {
     dap_chain_ch_t *l_ch_chain = DAP_CHAIN_CH(a_ch);
-    if (!l_ch_chain) {
-        log_it(L_CRITICAL, "Channel without chain, dump it");
-        return;
-    }
+    dap_return_if_fail(l_ch_chain);
+    const char *l_err_str = s_error_type_to_string(a_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);
-    dap_chain_ch_pkt_write_error_unsafe(a_ch, a_net_id, a_chain_id, a_cell_id, "%s", s_error_type_to_string(a_error));
-}
-
-static bool s_chain_timer_callback(void *a_arg)
-{
-    dap_worker_t *l_worker = dap_worker_get_current();
-    dap_stream_ch_t *l_ch = dap_stream_ch_find_by_uuid_unsafe(DAP_STREAM_WORKER(l_worker), *(dap_stream_ch_uuid_t*)a_arg);
-    if (!l_ch) {
-        DAP_DELETE(a_arg);
-        return false;
-    }
-    dap_chain_ch_t *l_ch_chain = DAP_CHAIN_CH(l_ch);
-    if (!l_ch_chain) {
-        log_it(L_CRITICAL, "Channel without chain, dump it");
-        DAP_DELETE(a_arg);
-        return false;
-    }
-    if (l_ch_chain->timer_shots++ >= DAP_SYNC_TICKS_PER_SECOND * s_sync_timeout) {
-        if (!s_ch_chain_get_idle(l_ch_chain))
-            s_ch_chain_go_idle(l_ch_chain);
-        DAP_DELETE(a_arg);
-        l_ch_chain->activity_timer = NULL;
-        return false;
-    }
-    if (l_ch_chain->state != DAP_CHAIN_CH_STATE_WAITING && l_ch_chain->sent_breaks) {
-        s_stream_ch_packet_out(l_ch, a_arg);
-        if (l_ch_chain->activity_timer == NULL)
-            return false;
-    }
-    // Sending dumb packet with nothing to inform remote thats we're just skiping atoms of GDB's, nothing freezed
-    if (l_ch_chain->state == DAP_CHAIN_CH_STATE_SYNC_CHAINS && l_ch_chain->sent_breaks >= 3 * DAP_SYNC_TICKS_PER_SECOND) {
-        debug_if(s_debug_more, L_INFO, "Send one chain TSD packet");
-        dap_chain_ch_pkt_write_unsafe(l_ch, DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_TSD,
-                                             l_ch_chain->request_hdr.net_id.uint64, l_ch_chain->request_hdr.chain_id.uint64,
-                                             l_ch_chain->request_hdr.cell_id.uint64, NULL, 0);
-        l_ch_chain->sent_breaks = 0;
-        l_ch_chain->timer_shots = 0;
-    }
-    return true;
-}
-
-static void s_chain_timer_reset(dap_chain_ch_t *a_ch_chain)
-{
-    a_ch_chain->timer_shots = 0;
-    if (!a_ch_chain->activity_timer)
-        dap_chain_ch_timer_start(a_ch_chain);
-}
-
-void dap_chain_ch_timer_start(dap_chain_ch_t *a_ch_chain)
-{
-    dap_stream_ch_uuid_t *l_uuid = DAP_DUP(&DAP_STREAM_CH(a_ch_chain)->uuid);
-    a_ch_chain->activity_timer = dap_timerfd_start_on_worker(DAP_STREAM_CH(a_ch_chain)->stream_worker->worker,
-                                                             1000 / DAP_SYNC_TICKS_PER_SECOND,
-                                                             s_chain_timer_callback, (void *)l_uuid);
-    a_ch_chain->sent_breaks = 0;
 }
 
 /**
@@ -807,41 +727,49 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg)
     dap_chain_ch_pkt_t *l_chain_pkt = (dap_chain_ch_pkt_t *)l_ch_pkt->data;
     size_t l_chain_pkt_data_size = l_ch_pkt->hdr.data_size - sizeof(l_chain_pkt->hdr);
 
-    if (l_chain_pkt->hdr.version > DAP_CHAIN_CH_PKT_VERSION) {
+    if (!l_chain_pkt->hdr.version || l_chain_pkt->hdr.version > DAP_CHAIN_CH_PKT_VERSION_CURRENT) {
         debug_if(s_debug_more, L_ATT, "Unsupported protocol version %d, current version %d",
-                 l_chain_pkt->hdr.version, DAP_CHAIN_CH_PKT_VERSION);
+                 l_chain_pkt->hdr.version, DAP_CHAIN_CH_PKT_VERSION_CURRENT);
         return false;
     }
-    if (l_chain_pkt->hdr.version >= 2 &&
+    if (l_chain_pkt->hdr.version > DAP_CHAIN_CH_PKT_VERSION_LEGACY &&
                 l_chain_pkt_data_size != l_chain_pkt->hdr.data_size) {
         log_it(L_WARNING, "Incorrect chain packet size %zu, expected %u",
                             l_chain_pkt_data_size, l_chain_pkt->hdr.data_size);
         return false;
     }
 
-    s_chain_timer_reset(l_ch_chain);
-
     switch (l_ch_pkt->hdr.type) {
 
     /* *** New synchronization protocol *** */
 
-    case DAP_CHAIN_CH_PKT_TYPE_ERROR:{
-        char * l_error_str = (char*)l_chain_pkt->data;
-        if(l_chain_pkt_data_size>1)
-            l_error_str[l_chain_pkt_data_size-1]='\0'; // To be sure that nobody sends us garbage
-                                                       // without trailing zero
-        log_it(L_WARNING, "In: from remote addr %s chain id 0x%016"DAP_UINT64_FORMAT_x" got error on his side: '%s'",
+    case DAP_CHAIN_CH_PKT_TYPE_ERROR: {
+        if (!l_chain_pkt_data_size || l_chain_pkt->data[l_chain_pkt_data_size - 1] != 0) {
+            log_it(L_WARNING, "Incorrect format with data size %zu in packet %s", l_chain_pkt_data_size,
+                                                    dap_chain_ch_pkt_type_to_str(l_ch_pkt->hdr.type));
+            return false;
+        }
+        log_it(L_WARNING, "In: from remote addr %s chain id 0x%016" DAP_UINT64_FORMAT_x " got error on his side: '%s'",
                DAP_STREAM_CH(l_ch_chain)->stream->esocket->remote_addr_str,
-               l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt_data_size ? l_error_str : "<empty>");
+               l_chain_pkt->hdr.chain_id.uint64, (char *)l_chain_pkt->data);
+        s_ch_chain_go_idle(l_ch_chain);
     } break;
 
     case DAP_CHAIN_CH_PKT_TYPE_CHAIN: {
+        if (!l_chain_pkt_data_size) {
+            log_it(L_WARNING, "Incorrect data size %zu in packet %s", l_chain_pkt_data_size,
+                                                    dap_chain_ch_pkt_type_to_str(l_ch_pkt->hdr.type));
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                    l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
+                    DAP_CHAIN_CH_ERROR_CHAIN_PKT_DATA_SIZE);
+            return false;
+        }
         dap_cluster_t *l_cluster = dap_cluster_find(dap_guuid_compose(l_chain_pkt->hdr.net_id.uint64, 0));
         if (!l_cluster) {
             log_it(L_WARNING, "Can't find cluster with ID 0x%" DAP_UINT64_FORMAT_X, l_chain_pkt->hdr.net_id.uint64);
-            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id.uint64,
-                    l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64,
-                    DAP_CHAIN_CH_ERROR_CHAIN_NOT_FOUND);
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                    l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
+                    DAP_CHAIN_CH_ERROR_CHAIN_PKT_DATA_SIZE);
             return false;
         }
         dap_cluster_member_t *l_check = dap_cluster_member_find_unsafe(l_cluster, &a_ch->stream->node);
@@ -852,13 +780,11 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg)
         }
         struct atom_processing_args *l_args = DAP_NEW_SIZE(struct atom_processing_args, l_ch_pkt->hdr.data_size + sizeof(struct atom_processing_args));
         if (!l_args) {
-            log_it(L_CRITICAL, g_error_memory_alloc);
+            log_it(L_CRITICAL, "%s", g_error_memory_alloc);
             break;
         }
         l_args->addr = a_ch->stream->node;
         l_args->ack_req = true;
-        if (l_chain_pkt->hdr.version < 2)
-            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_more) {
             char *l_atom_hash_str;
@@ -872,8 +798,8 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg)
         if (l_chain_pkt_data_size != sizeof(dap_chain_ch_sync_request_t)) {
             log_it(L_WARNING, "DAP_CHAIN_CH_PKT_TYPE_CHAIN_REQ: Wrong chain packet size %zd when expected %zd",
                                                                             l_chain_pkt_data_size, sizeof(dap_chain_ch_sync_request_t));
-            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id.uint64,
-                    l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64,
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                    l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
                     DAP_CHAIN_CH_ERROR_CHAIN_PKT_DATA_SIZE);
             return false;
         }
@@ -883,35 +809,35 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg)
                             " cell 0x%016" DAP_UINT64_FORMAT_x ", hash from %s, num from %" DAP_UINT64_FORMAT_U,
                             l_chain_pkt->hdr.net_id.uint64, l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64,
                             dap_hash_fast_to_str_static(&l_request->hash_from), l_request->num_from);
-        if (l_ch_chain->sync_context) {
-            log_it(L_WARNING, "Can't process CHAIN_REQ request cause already busy with syncronization");
-            dap_chain_ch_pkt_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id.uint64,
-                    l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64,
+        if (l_ch_chain->sync_context || l_ch_chain->legacy_sync_context) {
+            log_it(L_WARNING, "Can't process CHAIN_REQ request cause already busy with synchronization");
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                    l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
                     DAP_CHAIN_CH_ERROR_SYNC_REQUEST_ALREADY_IN_PROCESS);
-            return false;
+            break;
         }
         dap_chain_t *l_chain = dap_chain_find_by_id(l_chain_pkt->hdr.net_id, l_chain_pkt->hdr.chain_id);
-        if (!l_chain) {
-            log_it(L_WARNING, "Not found chain id 0x%016" DAP_UINT64_FORMAT_x " with net id 0x%016" DAP_UINT64_FORMAT_x,
+        if (!l_chain || l_chain->callback_load_from_gdb) {
+            log_it(L_WARNING, "Not found valid chain with id 0x%016" DAP_UINT64_FORMAT_x " and net id 0x%016" DAP_UINT64_FORMAT_x,
                                                         l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.net_id.uint64);
-            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id.uint64,
-                    l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64,
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                    l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
                     DAP_CHAIN_CH_ERROR_CHAIN_NOT_FOUND);
-            return false;
+            break;
         }
         if (!dap_link_manager_get_net_condition(l_chain_pkt->hdr.net_id.uint64)) {
             log_it(L_WARNING, "Net id 0x%016" DAP_UINT64_FORMAT_x " is offline", l_chain_pkt->hdr.net_id.uint64);
-            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id.uint64,
-                    l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64,
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                    l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
                     DAP_CHAIN_CH_ERROR_NET_IS_OFFLINE);
-            return false;
+            break;
         }
         bool l_sync_from_begin = dap_hash_fast_is_blank(&l_request->hash_from);
         dap_chain_atom_iter_t *l_iter = l_chain->callback_atom_iter_create(l_chain, l_chain_pkt->hdr.cell_id, l_sync_from_begin
                                                                            ? NULL : &l_request->hash_from, false);
         if (!l_iter) {
-            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id.uint64,
-                    l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64,
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                    l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
                     DAP_CHAIN_CH_ERROR_OUT_OF_MEMORY);
             break;
         }
@@ -925,12 +851,11 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg)
                     l_last_num > l_iter->cur_num)) {
                 dap_chain_ch_summary_t l_sum = { .num_cur = l_iter->cur_num, .num_last = l_last_num };
                 dap_chain_ch_pkt_write_unsafe(a_ch, DAP_CHAIN_CH_PKT_TYPE_CHAIN_SUMMARY,
-                                                l_chain_pkt->hdr.net_id.uint64, l_chain_pkt->hdr.chain_id.uint64,
-                                                l_chain_pkt->hdr.cell_id.uint64, &l_sum, sizeof(l_sum));
+                                                l_chain_pkt->hdr.net_id, l_chain_pkt->hdr.chain_id,
+                                                l_chain_pkt->hdr.cell_id, &l_sum, sizeof(l_sum),
+                                                DAP_CHAIN_CH_PKT_VERSION_CURRENT);
                 debug_if(s_debug_more, L_DEBUG, "Out: CHAIN_SUMMARY %s for net %s to destination " NODE_ADDR_FP_STR,
-                                        l_chain ? l_chain->name : "(null)",
-                                                    l_chain ? l_chain->net_name : "(null)",
-                                                                    NODE_ADDR_FP_ARGS_S(a_ch->stream->node));
+                                                        l_chain->name, l_chain->net_name, NODE_ADDR_FP_ARGS_S(a_ch->stream->node));
                 struct sync_context *l_context = DAP_NEW_Z(struct sync_context);
                 l_context->addr = a_ch->stream->node;
                 l_context->iter = l_iter;
@@ -941,9 +866,15 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg)
                 l_context->last_activity = dap_time_now();
                 atomic_store_explicit(&l_context->state, SYNC_STATE_READY, memory_order_relaxed);
                 atomic_store(&l_context->allowed_num, l_sum.num_cur + s_sync_ack_window_size);
-                dap_proc_thread_callback_add(a_ch->stream_worker->worker->proc_queue_input, s_chain_iter_callback, l_context);
+                dap_stream_ch_uuid_t *l_uuid = DAP_DUP(&a_ch->uuid);
+                if (!l_uuid) {
+                    log_it(L_CRITICAL, "%s", g_error_memory_alloc);
+                    DAP_DELETE(l_context);
+                    break;
+                }
                 l_ch_chain->sync_context = l_context;
-                l_ch_chain->sync_timer = dap_timerfd_start_on_worker(a_ch->stream_worker->worker, 1000, s_sync_timer_callback, l_ch_chain);
+                dap_proc_thread_callback_add(a_ch->stream_worker->worker->proc_queue_input, s_chain_iter_callback, l_context);
+                l_ch_chain->sync_timer = dap_timerfd_start_on_worker(a_ch->stream_worker->worker, 1000, s_sync_timer_callback, l_uuid);
                 break;
             }
             if (l_request->num_from < l_iter->cur_num || l_last_num > l_iter->cur_num)
@@ -958,8 +889,9 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg)
                                                      .last_hash = *l_iter->cur_hash,
                                                      .last_num = l_iter->cur_num };
             dap_chain_ch_pkt_write_unsafe(a_ch, DAP_CHAIN_CH_PKT_TYPE_CHAIN_MISS,
-                                          l_chain_pkt->hdr.net_id.uint64, l_chain_pkt->hdr.chain_id.uint64,
-                                          l_chain_pkt->hdr.cell_id.uint64, &l_miss_info, sizeof(l_miss_info));
+                                          l_chain_pkt->hdr.net_id, l_chain_pkt->hdr.chain_id,
+                                          l_chain_pkt->hdr.cell_id, &l_miss_info, sizeof(l_miss_info),
+                                          DAP_CHAIN_CH_PKT_VERSION_CURRENT);
             if (s_debug_more) {
                 char l_last_hash_str[DAP_HASH_FAST_STR_SIZE];
                 dap_hash_fast_to_str(&l_miss_info.last_hash, l_last_hash_str, DAP_HASH_FAST_STR_SIZE);
@@ -974,8 +906,9 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg)
             }
         } else {
             dap_chain_ch_pkt_write_unsafe(a_ch, DAP_CHAIN_CH_PKT_TYPE_SYNCED_CHAIN,
-                                          l_chain_pkt->hdr.net_id.uint64, l_chain_pkt->hdr.chain_id.uint64,
-                                          l_chain_pkt->hdr.cell_id.uint64, NULL, 0);
+                                          l_chain_pkt->hdr.net_id, l_chain_pkt->hdr.chain_id,
+                                          l_chain_pkt->hdr.cell_id, NULL, 0,
+                                          DAP_CHAIN_CH_PKT_VERSION_CURRENT);
             debug_if(s_debug_more, L_DEBUG, "Out: SYNCED_CHAIN %s for net %s to destination " NODE_ADDR_FP_STR,
                                     l_chain ? l_chain->name : "(null)",
                                                 l_chain ? l_chain->net_name : "(null)",
@@ -988,8 +921,8 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg)
         if (l_chain_pkt_data_size != sizeof(dap_chain_ch_summary_t)) {
             log_it(L_WARNING, "DAP_CHAIN_CH_PKT_TYPE_CHAIN_SUMMARY: Wrong chain packet size %zd when expected %zd",
                                                                             l_chain_pkt_data_size, sizeof(dap_chain_ch_summary_t));
-            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id.uint64,
-                    l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64,
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                    l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
                     DAP_CHAIN_CH_ERROR_CHAIN_PKT_DATA_SIZE);
             return false;
         }
@@ -1007,8 +940,8 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg)
         if (l_chain_pkt_data_size != sizeof(uint64_t)) {
             log_it(L_WARNING, "DAP_CHAIN_CH_PKT_TYPE_CHAIN_ACK: Wrong chain packet size %zd when expected %zd",
                                                                             l_chain_pkt_data_size, sizeof(uint64_t));
-            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id.uint64,
-                    l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64,
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                    l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
                     DAP_CHAIN_CH_ERROR_CHAIN_PKT_DATA_SIZE);
             return false;
         }
@@ -1022,15 +955,16 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg)
         struct sync_context *l_context = l_ch_chain->sync_context;
         if (!l_context) {
             log_it(L_WARNING, "CHAIN_ACK: No active sync context");
-            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id.uint64,
-                    l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64,
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                    l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
                     DAP_CHAIN_CH_ERROR_INCORRECT_SYNC_SEQUENCE);
             break;
         }
         if (l_context->num_last == l_ack_num) {
             dap_chain_ch_pkt_write_unsafe(a_ch, DAP_CHAIN_CH_PKT_TYPE_SYNCED_CHAIN,
-                                                 l_chain_pkt->hdr.net_id.uint64, l_chain_pkt->hdr.chain_id.uint64,
-                                                 l_chain_pkt->hdr.cell_id.uint64, NULL, 0);
+                                                l_chain_pkt->hdr.net_id, l_chain_pkt->hdr.chain_id,
+                                                l_chain_pkt->hdr.cell_id, NULL, 0,
+                                                DAP_CHAIN_CH_PKT_VERSION_CURRENT);
             s_ch_chain_go_idle(l_ch_chain);
             break;
         }
@@ -1056,8 +990,8 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg)
         if (l_chain_pkt_data_size != sizeof(dap_chain_ch_miss_info_t)) {
             log_it(L_WARNING, "DAP_CHAIN_CH_PKT_TYPE_CHAIN_MISS: Wrong chain packet size %zd when expected %zd",
                                                                             l_chain_pkt_data_size, sizeof(dap_chain_ch_miss_info_t));
-            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id.uint64,
-                    l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64,
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                    l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
                     DAP_CHAIN_CH_ERROR_CHAIN_PKT_DATA_SIZE);
             return false;
         }
@@ -1079,8 +1013,8 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg)
     } break;
 
     default:
-        dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id.uint64,
-                                            l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64,
+        dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                                            l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
                                             DAP_CHAIN_CH_ERROR_UNKNOWN_CHAIN_PKT_TYPE);
         return false;
 
@@ -1089,371 +1023,566 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg)
 
     /* *** Legacy *** */
 
-        /// --- GDB update ---
-        // Request for gdbs list update
-        case DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_REQ:{
-            if(l_ch_chain->state != DAP_CHAIN_CH_STATE_IDLE){
-                log_it(L_WARNING, "Can't process UPDATE_GLOBAL_DB_REQ request because its already busy with syncronization");
-                dap_chain_ch_pkt_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id.uint64,
-                        l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64,
-                        DAP_CHAIN_CH_ERROR_SYNC_REQUEST_ALREADY_IN_PROCESS);
-                break;
-            }
-            log_it(L_INFO, "In:  UPDATE_GLOBAL_DB_REQ pkt: net 0x%016"DAP_UINT64_FORMAT_x" chain 0x%016"DAP_UINT64_FORMAT_x" cell 0x%016"DAP_UINT64_FORMAT_x,
-                            l_chain_pkt->hdr.net_id.uint64, l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64);
-            if (l_chain_pkt_data_size == (size_t)sizeof(dap_chain_ch_sync_request_old_t))
-                l_ch_chain->request = *(dap_chain_ch_sync_request_old_t*)l_chain_pkt->data;
-            struct sync_request *l_sync_request = dap_chain_ch_create_sync_request(l_chain_pkt, a_ch);
-            l_ch_chain->stats_request_gdb_processed = 0;
-            l_ch_chain->request_hdr = l_chain_pkt->hdr;
-            dap_proc_thread_callback_add(a_ch->stream_worker->worker->proc_queue_input, s_sync_update_gdb_proc_callback, l_sync_request);
-        } break;
-
-        // Response with metadata organized in TSD
-        case DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_TSD: {
-            if (s_debug_more)
-                log_it(L_DEBUG, "Global DB TSD packet detected");
-        } break;
-
-        // If requested - begin to recieve record's hashes
-        case DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_START:{
-            if (s_debug_more)
-                log_it(L_INFO, "In:  UPDATE_GLOBAL_DB_START pkt net 0x%016"DAP_UINT64_FORMAT_x" chain 0x%016"DAP_UINT64_FORMAT_x" cell 0x%016"DAP_UINT64_FORMAT_x,
-                                l_chain_pkt->hdr.net_id.uint64, l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64);
-            if (l_ch_chain->state != DAP_CHAIN_CH_STATE_IDLE){
-                log_it(L_WARNING, "Can't process UPDATE_GLOBAL_DB_START request because its already busy with syncronization");
-                dap_chain_ch_pkt_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id.uint64,
-                        l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64,
-                        DAP_CHAIN_CH_ERROR_SYNC_REQUEST_ALREADY_IN_PROCESS);
-                break;
-            }
-            l_ch_chain->request_hdr = l_chain_pkt->hdr;
-            l_ch_chain->state = DAP_CHAIN_CH_STATE_UPDATE_GLOBAL_DB_REMOTE;
-        } break;
-        // Response with gdb element hashes and sizes
-        case DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB:{
-            if(s_debug_more)
-                log_it(L_INFO, "In: UPDATE_GLOBAL_DB pkt data_size=%zu", l_chain_pkt_data_size);
-            if (l_ch_chain->state != DAP_CHAIN_CH_STATE_UPDATE_GLOBAL_DB_REMOTE ||
-                    memcmp(&l_ch_chain->request_hdr.net_id, &l_chain_pkt->hdr.net_id,
-                           sizeof(dap_chain_net_id_t) + sizeof(dap_chain_id_t) + sizeof(dap_chain_cell_id_t))) {
-                log_it(L_WARNING, "Can't process UPDATE_GLOBAL_DB request because its already busy with syncronization");
-                dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id.uint64,
-                        l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64,
-                        DAP_CHAIN_CH_ERROR_SYNC_REQUEST_ALREADY_IN_PROCESS);
-                break;
-            }
-            for ( dap_chain_ch_update_element_t * l_element =(dap_chain_ch_update_element_t *) l_chain_pkt->data;
-                   (size_t) (((byte_t*)l_element) - l_chain_pkt->data ) < l_chain_pkt_data_size;
-                  l_element++){
-                dap_chain_ch_hash_item_t * l_hash_item = NULL;
-                unsigned l_hash_item_hashv;
-                HASH_VALUE(&l_element->hash, sizeof(l_element->hash), l_hash_item_hashv);
-                HASH_FIND_BYHASHVALUE(hh, l_ch_chain->remote_gdbs, &l_element->hash, sizeof(l_element->hash),
-                                      l_hash_item_hashv, l_hash_item);
-                if (!l_hash_item) {
-                    l_hash_item = DAP_NEW_Z(dap_chain_ch_hash_item_t);
-                    if (!l_hash_item) {
-                        log_it(L_CRITICAL, "%s", g_error_memory_alloc);
-                        break;
-                    }
-                    l_hash_item->hash = l_element->hash;
-                    l_hash_item->size = l_element->size;
-                    HASH_ADD_BYHASHVALUE(hh, l_ch_chain->remote_gdbs, hash, sizeof(l_hash_item->hash),
-                                         l_hash_item_hashv, l_hash_item);
-                    /*if (s_debug_more){
-                        char l_hash_str[72]={ [0]='\0'};
-                        dap_chain_hash_fast_to_str(&l_hash_item->hash,l_hash_str,sizeof (l_hash_str));
-                        log_it(L_DEBUG,"In: Updated remote hash gdb list with %s ", l_hash_str);
-                    }*/
-                }
-            }
-        } break;
-        // End of response with starting of DB sync
-        case DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_END: {
-            if(l_chain_pkt_data_size == sizeof(dap_chain_ch_sync_request_old_t)) {
-                if (l_ch_chain->state != DAP_CHAIN_CH_STATE_UPDATE_GLOBAL_DB_REMOTE ||
-                        memcmp(&l_ch_chain->request_hdr.net_id, &l_chain_pkt->hdr.net_id,
-                               sizeof(dap_chain_net_id_t) + sizeof(dap_chain_id_t) + sizeof(dap_chain_cell_id_t))) {
-                    log_it(L_WARNING, "Can't process UPDATE_GLOBAL_DB_END request because its already busy with syncronization");
-                    dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id.uint64,
-                            l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64,
-                            DAP_CHAIN_CH_ERROR_SYNC_REQUEST_ALREADY_IN_PROCESS);
+    /// --- GDB update ---
+    // Request for gdbs list update
+    case DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_REQ: {
+        if (l_chain_pkt_data_size != sizeof(dap_chain_ch_sync_request_old_t)) {
+            log_it(L_WARNING, "Incorrect data size %zu in packet %s", l_chain_pkt_data_size,
+                                                    dap_chain_ch_pkt_type_to_str(l_ch_pkt->hdr.type));
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                    l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
+                    DAP_CHAIN_CH_ERROR_LEGACY_PKT_DATA_SIZE);
+            return false;
+        }
+        dap_cluster_t *l_net_cluster = dap_cluster_find(dap_guuid_compose(l_chain_pkt->hdr.net_id.uint64, 0));
+        if (!l_net_cluster || !l_net_cluster->mnemonim) {
+            log_it(L_WARNING, "Net id 0x%016" DAP_UINT64_FORMAT_x " not found", l_chain_pkt->hdr.net_id.uint64);
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                    l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
+                    DAP_CHAIN_CH_ERROR_NET_INVALID_ID);
+            break;
+        }
+        if (!dap_link_manager_get_net_condition(l_chain_pkt->hdr.net_id.uint64)) {
+            log_it(L_WARNING, "Net id 0x%016" DAP_UINT64_FORMAT_x " is offline", l_chain_pkt->hdr.net_id.uint64);
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                    l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
+                    DAP_CHAIN_CH_ERROR_NET_IS_OFFLINE);
+            break;
+        }
+        if (l_ch_chain->sync_context || l_ch_chain->legacy_sync_context) {
+            log_it(L_WARNING, "Can't process UPDATE_GLOBAL_DB request because its already busy with syncronization");
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                    l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
+                    DAP_CHAIN_CH_ERROR_SYNC_REQUEST_ALREADY_IN_PROCESS);
+            break;
+        }
+        dap_global_db_legacy_list_t *l_db_list = dap_global_db_legacy_list_start(l_net_cluster->mnemonim);
+        if (!l_db_list) {
+            log_it(L_ERROR, "Can't create legacy DB list");
+            dap_global_db_legacy_list_delete(l_db_list);
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                                            l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
+                                            DAP_CHAIN_CH_ERROR_OUT_OF_MEMORY);
+            break;
+        }
+        struct legacy_sync_context *l_context = s_legacy_sync_context_create(l_chain_pkt, a_ch);
+        if (!l_context) {
+            log_it(L_ERROR, "Can't create sychronization context");
+            dap_global_db_legacy_list_delete(l_db_list);
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                                            l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
+                                            DAP_CHAIN_CH_ERROR_OUT_OF_MEMORY);
+            break;
+        }
+        l_context->is_type_of_gdb = true;
+        l_context->db_list = l_db_list;
+        l_context->remote_addr = *(dap_stream_node_addr_t *)l_chain_pkt->data;
+        l_context->request_hdr = l_chain_pkt->hdr;
+        l_ch_chain->legacy_sync_context = l_context;
+        l_context->state = DAP_CHAIN_CH_STATE_UPDATE_GLOBAL_DB;
+        debug_if(s_debug_legacy, L_DEBUG, "Sync out gdb proc, requested %" DAP_UINT64_FORMAT_U " records from address " NODE_ADDR_FP_STR " (unverified)",
+                                                l_db_list->items_number, NODE_ADDR_FP_ARGS_S(l_context->remote_addr));
+        log_it(L_INFO, "In: UPDATE_GLOBAL_DB_REQ pkt: net 0x%016"DAP_UINT64_FORMAT_x" chain 0x%016"DAP_UINT64_FORMAT_x" cell 0x%016"DAP_UINT64_FORMAT_x,
+                        l_chain_pkt->hdr.net_id.uint64, l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64);
+        debug_if(s_debug_legacy, L_INFO, "Out: DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_START");
+        dap_chain_ch_pkt_write_unsafe(DAP_STREAM_CH(l_ch_chain), DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_START,
+                                        l_chain_pkt->hdr.net_id, l_chain_pkt->hdr.chain_id,
+                                        l_chain_pkt->hdr.cell_id, &g_node_addr, sizeof(dap_chain_node_addr_t),
+                                        DAP_CHAIN_CH_PKT_VERSION_LEGACY);
+        dap_proc_thread_callback_add(a_ch->stream_worker->worker->proc_queue_input, s_sync_out_gdb_proc_callback, l_context);
+    } break;
+
+    // If requested - begin to recieve record's hashes
+    case DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_START: {
+        struct legacy_sync_context *l_context = l_ch_chain->legacy_sync_context;
+        if (!l_context || l_context->state != DAP_CHAIN_CH_STATE_UPDATE_GLOBAL_DB_REMOTE) {
+            log_it(L_WARNING, "Can't process UPDATE_GLOBAL_DB_START packet cause synchronization sequence violation");
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                    l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
+                    DAP_CHAIN_CH_ERROR_INCORRECT_SYNC_SEQUENCE);
+            break;
+        }
+        debug_if(s_debug_legacy, L_INFO, "In: UPDATE_GLOBAL_DB_START pkt net 0x%016"DAP_UINT64_FORMAT_x" chain 0x%016"DAP_UINT64_FORMAT_x" cell 0x%016"DAP_UINT64_FORMAT_x,
+                            l_context->request_hdr.net_id.uint64, l_context->request_hdr.chain_id.uint64, l_context->request_hdr.cell_id.uint64);
+    } break;
+
+    // Response with gdb element hashes and sizes
+    case DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB: {
+        if (l_chain_pkt_data_size % sizeof(dap_chain_ch_update_element_t)) {
+            log_it(L_WARNING, "Incorrect data size %zu in packet %s", l_chain_pkt_data_size,
+                                                    dap_chain_ch_pkt_type_to_str(l_ch_pkt->hdr.type));
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                    l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
+                    DAP_CHAIN_CH_ERROR_LEGACY_PKT_DATA_SIZE);
+            return false;
+        }
+        debug_if(s_debug_legacy, L_INFO, "In: UPDATE_GLOBAL_DB pkt data_size=%zu", l_chain_pkt_data_size);
+        struct legacy_sync_context *l_context = l_ch_chain->legacy_sync_context;
+        if (!l_context || l_context->state != DAP_CHAIN_CH_STATE_UPDATE_GLOBAL_DB_REMOTE) {
+            log_it(L_WARNING, "Can't process UPDATE_GLOBAL_DB packet cause synchronization sequence violation");
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                    l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
+                    DAP_CHAIN_CH_ERROR_INCORRECT_SYNC_SEQUENCE);
+            break;
+        }
+        l_context->last_activity = dap_time_now();
+
+        for (dap_chain_ch_update_element_t *l_element = (dap_chain_ch_update_element_t *)l_chain_pkt->data;
+                (size_t)((byte_t *)(l_element + 1) - l_chain_pkt->data) <= l_chain_pkt_data_size;
+                l_element++) {
+            dap_chain_ch_hash_item_t * l_hash_item = NULL;
+            unsigned l_hash_item_hashv;
+            HASH_VALUE(&l_element->hash, sizeof(l_element->hash), l_hash_item_hashv);
+            HASH_FIND_BYHASHVALUE(hh, l_context->remote_gdbs, &l_element->hash, sizeof(l_element->hash),
+                                  l_hash_item_hashv, l_hash_item);
+            if (!l_hash_item) {
+                l_hash_item = DAP_NEW_Z(dap_chain_ch_hash_item_t);
+                if (!l_hash_item) {
+                    log_it(L_CRITICAL, "%s", g_error_memory_alloc);
+                    dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                            l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
+                            DAP_CHAIN_CH_ERROR_OUT_OF_MEMORY);
                     break;
                 }
-                debug_if(s_debug_more, L_INFO, "In: UPDATE_GLOBAL_DB_END pkt with total count %d hashes",
-                                        HASH_COUNT(l_ch_chain->remote_gdbs));
-                if (l_chain_pkt_data_size == sizeof(dap_chain_ch_sync_request_old_t))
-                    l_ch_chain->request = *(dap_chain_ch_sync_request_old_t*)l_chain_pkt->data;
-                struct sync_request *l_sync_request = dap_chain_ch_create_sync_request(l_chain_pkt, a_ch);
-                dap_proc_thread_callback_add(a_ch->stream_worker->worker->proc_queue_input, s_sync_out_gdb_proc_callback, l_sync_request);
-            } else {
-                log_it(L_WARNING, "DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_END: Wrong chain packet size %zd when expected %zd", l_chain_pkt_data_size, sizeof(l_ch_chain->request));
-                dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id.uint64,
-                        l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64,
-                        DAP_CHAIN_CH_ERROR_CHAIN_PKT_DATA_SIZE);
-            }
-        } break;
-        // first packet of data with source node address
-        case DAP_CHAIN_CH_PKT_TYPE_FIRST_GLOBAL_DB: {
-            if(l_chain_pkt_data_size == (size_t)sizeof(dap_chain_node_addr_t)){
-               l_ch_chain->request.node_addr = *(dap_chain_node_addr_t*)l_chain_pkt->data;
-               l_ch_chain->stats_request_gdb_processed = 0;
-               log_it(L_INFO, "In: FIRST_GLOBAL_DB data_size=%zu net 0x%016"DAP_UINT64_FORMAT_x" chain 0x%016"DAP_UINT64_FORMAT_x" cell 0x%016"DAP_UINT64_FORMAT_x
-                              " from address "NODE_ADDR_FP_STR, l_chain_pkt_data_size,   l_chain_pkt->hdr.net_id.uint64 ,
-                              l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64, NODE_ADDR_FP_ARGS_S(l_ch_chain->request.node_addr) );
-            }else {
-               log_it(L_WARNING,"Incorrect data size %zu in packet DAP_CHAIN_CH_PKT_TYPE_FIRST_GLOBAL_DB", l_chain_pkt_data_size);
-               dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id.uint64,
-                       l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64,
-                       DAP_CHAIN_CH_ERROR_CHAIN_PKT_DATA_SIZE);
-            }
-        } break;
-
-        case DAP_CHAIN_CH_PKT_TYPE_GLOBAL_DB: {
-            if(s_debug_more)
-                log_it(L_INFO, "In: GLOBAL_DB data_size=%zu", l_chain_pkt_data_size);
-            // get transaction and save it to global_db
-            if(l_chain_pkt_data_size > 0) {
-                struct sync_request *l_sync_request = dap_chain_ch_create_sync_request(l_chain_pkt, a_ch);
-                dap_chain_pkt_item_t *l_pkt_item = &l_sync_request->pkt;
-                l_pkt_item->pkt_data = DAP_DUP_SIZE(l_chain_pkt->data, l_chain_pkt_data_size);
-                l_pkt_item->pkt_data_size = l_chain_pkt_data_size;
-                dap_proc_thread_callback_add(a_ch->stream_worker->worker->proc_queue_input, s_gdb_in_pkt_proc_callback, l_sync_request);
-            } else {
-                log_it(L_WARNING, "Packet with GLOBAL_DB atom has zero body size");
-                dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id.uint64,
-                        l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64,
-                        DAP_CHAIN_CH_ERROR_CHAIN_PKT_DATA_SIZE);
-            }
-        }  break;
-
-        case DAP_CHAIN_CH_PKT_TYPE_SYNCED_GLOBAL_DB: {
-                log_it(L_INFO, "In:  SYNCED_GLOBAL_DB: net 0x%016"DAP_UINT64_FORMAT_x" chain 0x%016"DAP_UINT64_FORMAT_x" cell 0x%016"DAP_UINT64_FORMAT_x,
-                                l_chain_pkt->hdr.net_id.uint64, l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64);
-                // we haven't node client waitng, so reply to other side
-                dap_chain_ch_sync_request_old_t l_sync_gdb = {};
-                l_sync_gdb.node_addr.uint64 = g_node_addr.uint64;
-                dap_chain_ch_pkt_write_unsafe(a_ch, DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_REQ, l_chain_pkt->hdr.net_id.uint64,
-                                              l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64, &l_sync_gdb, sizeof(l_sync_gdb));
-        } break;
-
-        /// --- Chains update ---
-        // Request for atoms list update
-        case DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_REQ:{
-            if (l_ch_chain->state != DAP_CHAIN_CH_STATE_IDLE) {
-                log_it(L_WARNING, "Can't process UPDATE_CHAINS_REQ request because its already busy with syncronization");
-                dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id.uint64,
-                        l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64,
-                        DAP_CHAIN_CH_ERROR_SYNC_REQUEST_ALREADY_IN_PROCESS);
-                break;
-            }
-            if(s_debug_more)
-                log_it(L_INFO, "In: UPDATE_CHAINS_REQ pkt: net 0x%016"DAP_UINT64_FORMAT_x" chain 0x%016"DAP_UINT64_FORMAT_x" cell 0x%016"DAP_UINT64_FORMAT_x,
-                                l_chain_pkt->hdr.net_id.uint64, l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64);
-            dap_chain_t * l_chain = dap_chain_find_by_id(l_chain_pkt->hdr.net_id, l_chain_pkt->hdr.chain_id);
-            if (l_chain) {
-                l_ch_chain->state = DAP_CHAIN_CH_STATE_UPDATE_CHAINS;
-                if(s_debug_more)
-                    log_it(L_INFO, "Out: UPDATE_CHAINS_START pkt: net %s chain %s cell 0x%016"DAP_UINT64_FORMAT_X, l_chain->name,
-                                        l_chain->net_name, l_chain_pkt->hdr.cell_id.uint64);
-                l_ch_chain->request_atom_iter = l_chain->callback_atom_iter_create(l_chain, l_chain_pkt->hdr.cell_id, NULL, false);
-                l_chain->callback_atom_iter_get(l_ch_chain->request_atom_iter, DAP_CHAIN_ITER_OP_FIRST, NULL);
-                l_ch_chain->request_hdr = l_chain_pkt->hdr;
-                dap_chain_ch_pkt_write_unsafe(a_ch, DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_START,
-                                                     l_chain_pkt->hdr.net_id.uint64,l_chain_pkt->hdr.chain_id.uint64,
-                                                     l_chain_pkt->hdr.cell_id.uint64, NULL, 0);
-            }
-        } break;
-        // Response with metadata organized in TSD
-        case DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_TSD :{
-            if (s_debug_more)
-                log_it(L_DEBUG, "Chain TSD packet detected");
-        } break;
-
-        // If requested - begin to send atom hashes
-        case DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_START:{
-            if (l_ch_chain->state != DAP_CHAIN_CH_STATE_IDLE) {
-                log_it(L_WARNING, "Can't process UPDATE_CHAINS_START request because its already busy with syncronization");
-                dap_chain_ch_pkt_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id.uint64,
-                        l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64,
-                        DAP_CHAIN_CH_ERROR_SYNC_REQUEST_ALREADY_IN_PROCESS);
-                break;
-            }
-            dap_chain_t * l_chain = dap_chain_find_by_id(l_chain_pkt->hdr.net_id, l_chain_pkt->hdr.chain_id);
-            if (!l_chain) {
-                log_it(L_ERROR, "Invalid UPDATE_CHAINS_START request from %s with net id 0x%016"DAP_UINT64_FORMAT_x
-                                " chain id 0x%016"DAP_UINT64_FORMAT_x" cell_id 0x%016"DAP_UINT64_FORMAT_x" in packet",
-                                a_ch->stream->esocket->remote_addr_str, l_chain_pkt->hdr.net_id.uint64, l_chain_pkt->hdr.chain_id.uint64,
-                                l_chain_pkt->hdr.cell_id.uint64);
-                dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id.uint64,
-                                                    l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64,
-                                                    DAP_CHAIN_CH_ERROR_NET_INVALID_ID);
-                // Who are you? I don't know you! go away!
-                a_ch->stream->esocket->flags |= DAP_SOCK_SIGNAL_CLOSE;
-                break;
-            }
-            l_ch_chain->state = DAP_CHAIN_CH_STATE_UPDATE_CHAINS_REMOTE;
-            l_ch_chain->request_hdr = l_chain_pkt->hdr;
-            debug_if(s_debug_more, L_INFO, "In: UPDATE_CHAINS_START pkt");
-        } break;
-
-        // Response with atom hashes and sizes
-        case DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS: {
-            unsigned int l_count_added=0;
-            unsigned int l_count_total=0;
-
-            dap_chain_t * l_chain = dap_chain_find_by_id(l_chain_pkt->hdr.net_id, l_chain_pkt->hdr.chain_id);
-            if (! l_chain){
-                log_it(L_ERROR, "Invalid UPDATE_CHAINS packet from %s with net id 0x%016"DAP_UINT64_FORMAT_x
-                                " chain id 0x%016"DAP_UINT64_FORMAT_x" cell_id 0x%016"DAP_UINT64_FORMAT_x" in packet",
-                                a_ch->stream->esocket->remote_addr_str,
-                                l_chain_pkt->hdr.net_id.uint64, l_chain_pkt->hdr.chain_id.uint64,
-                                l_chain_pkt->hdr.cell_id.uint64);
-                dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id.uint64,
-                                                    l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64,
-                                                    DAP_CHAIN_CH_ERROR_NET_INVALID_ID);
-                // Who are you? I don't know you! go away!
-                a_ch->stream->esocket->flags |= DAP_SOCK_SIGNAL_CLOSE;
-                break;
-            }
-            for ( dap_chain_ch_update_element_t * l_element =(dap_chain_ch_update_element_t *) l_chain_pkt->data;
-                   (size_t) (((byte_t*)l_element) - l_chain_pkt->data ) < l_chain_pkt_data_size;
-                  l_element++){
-                dap_chain_ch_hash_item_t * l_hash_item = NULL;
-                unsigned l_hash_item_hashv;
-                HASH_VALUE(&l_element->hash, sizeof(dap_hash_fast_t), l_hash_item_hashv);
-                HASH_FIND_BYHASHVALUE(hh, l_ch_chain->remote_atoms, &l_element->hash, sizeof(dap_hash_fast_t),
-                                      l_hash_item_hashv, l_hash_item);
-                if( ! l_hash_item ){
-                    l_hash_item = DAP_NEW_Z(dap_chain_ch_hash_item_t);
-                    if (!l_hash_item) {
-                        log_it(L_CRITICAL, "%s", g_error_memory_alloc);
-                        break;
-                    }
-                    l_hash_item->hash = l_element->hash;
-                    l_hash_item->size = l_element->size;
-                    HASH_ADD_BYHASHVALUE(hh, l_ch_chain->remote_atoms, hash, sizeof(dap_hash_fast_t),
-                                         l_hash_item_hashv, l_hash_item);
-                    l_count_added++;
-                    /*
-                    if (s_debug_more){
-                        char l_hash_str[72]={ [0]='\0'};
-                        dap_chain_hash_fast_to_str(&l_hash_item->hash,l_hash_str,sizeof (l_hash_str));
-                        log_it(L_DEBUG,"In: Updated remote atom hash list with %s ", l_hash_str);
-                    }*/
-                }
-                l_count_total++;
+                l_hash_item->hash = l_element->hash;
+                l_hash_item->size = l_element->size;
+                HASH_ADD_BYHASHVALUE(hh, l_context->remote_gdbs, hash, sizeof(l_hash_item->hash),
+                                     l_hash_item_hashv, l_hash_item);
+                //debug_if(s_debug_legacy, L_DEBUG, "In: Updated remote hash GDB list with %s", dap_chain_hash_fast_to_str_static(&l_hash_item->hash));
             }
-            if (s_debug_more)
-                log_it(L_INFO,"In: Added %u from %u remote atom hash  in list",l_count_added,l_count_total);
-        } break;
-
-        case DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_END: {
-            if(l_chain_pkt_data_size == sizeof(dap_chain_ch_sync_request_old_t)) {
-                if (l_ch_chain->state != DAP_CHAIN_CH_STATE_UPDATE_CHAINS_REMOTE ||
-                        memcmp(&l_ch_chain->request_hdr.net_id, &l_chain_pkt->hdr.net_id,
-                               sizeof(dap_chain_net_id_t) + sizeof(dap_chain_id_t) + sizeof(dap_chain_cell_id_t))) {
-                    log_it(L_WARNING, "Can't process UPDATE_CHAINS_END request because its already busy with syncronization");
-                    dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id.uint64,
-                            l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64,
-                            DAP_CHAIN_CH_ERROR_SYNC_REQUEST_ALREADY_IN_PROCESS);
-                    break;
-                }
-                dap_chain_t * l_chain = dap_chain_find_by_id(l_chain_pkt->hdr.net_id, l_chain_pkt->hdr.chain_id);
-                if (!l_chain) {
-                    log_it(L_ERROR, "Invalid UPDATE_CHAINS packet from %s with net id 0x%016"DAP_UINT64_FORMAT_x
-                                    " chain id 0x%016"DAP_UINT64_FORMAT_x" cell_id 0x%016"DAP_UINT64_FORMAT_x" in packet",
-                                    a_ch->stream->esocket->remote_addr_str, l_chain_pkt->hdr.net_id.uint64, l_chain_pkt->hdr.chain_id.uint64,
-                                    l_chain_pkt->hdr.cell_id.uint64);
-                    dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id.uint64,
-                                                        l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64,
-                                                        DAP_CHAIN_CH_ERROR_NET_INVALID_ID);
+        }
+    } break;
+
+    // End of response with GlobalDB hashes
+    case DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_END: {
+        if (l_chain_pkt_data_size != sizeof(dap_chain_ch_sync_request_old_t)) {
+            log_it(L_WARNING, "Incorrect data size %zu in packet %s", l_chain_pkt_data_size,
+                                                    dap_chain_ch_pkt_type_to_str(l_ch_pkt->hdr.type));
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                    l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
+                    DAP_CHAIN_CH_ERROR_LEGACY_PKT_DATA_SIZE);
+            return false;
+        }
+        struct legacy_sync_context *l_context = l_ch_chain->legacy_sync_context;
+        if (!l_context || l_context->state != DAP_CHAIN_CH_STATE_UPDATE_GLOBAL_DB_REMOTE) {
+            log_it(L_WARNING, "Can't process UPDATE_GLOBAL_DB_END packet cause synchronization sequence violation");
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                    l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
+                    DAP_CHAIN_CH_ERROR_INCORRECT_SYNC_SEQUENCE);
+            break;
+        }
+        debug_if(s_debug_legacy, L_INFO, "In: UPDATE_GLOBAL_DB_END pkt with total count %d hashes", HASH_COUNT(l_context->remote_gdbs));
+        l_context->state = DAP_CHAIN_CH_STATE_SYNC_GLOBAL_DB;
+        debug_if(s_debug_legacy, L_INFO, "Out: DAP_CHAIN_CH_PKT_TYPE_FIRST_GLOBAL_DB");
+        dap_chain_ch_pkt_write_unsafe(DAP_STREAM_CH(l_ch_chain), DAP_CHAIN_CH_PKT_TYPE_FIRST_GLOBAL_DB,
+                l_context->request_hdr.net_id, l_context->request_hdr.chain_id,
+                l_context->request_hdr.cell_id, &g_node_addr, sizeof(dap_chain_node_addr_t),
+                DAP_CHAIN_CH_PKT_VERSION_LEGACY);
+        dap_proc_thread_callback_add(a_ch->stream_worker->worker->proc_queue_input, s_sync_out_gdb_proc_callback, l_context);
+    } break;
+
+    // first packet of data with source node address
+    case DAP_CHAIN_CH_PKT_TYPE_FIRST_GLOBAL_DB: {
+        if (l_chain_pkt_data_size != sizeof(dap_chain_node_addr_t)) {
+            log_it(L_WARNING, "Incorrect data size %zu in packet %s", l_chain_pkt_data_size,
+                                                    dap_chain_ch_pkt_type_to_str(l_ch_pkt->hdr.type));
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                    l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
+                    DAP_CHAIN_CH_ERROR_LEGACY_PKT_DATA_SIZE);
+            return false;
+        }
+        struct legacy_sync_context *l_context = l_ch_chain->legacy_sync_context;
+        if (!l_context || l_context->state != DAP_CHAIN_CH_STATE_SYNC_GLOBAL_DB_REMOTE) {
+            log_it(L_WARNING, "Can't process FIRST_GLOBAL_DB packet cause synchronization sequence violation");
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                    l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
+                    DAP_CHAIN_CH_ERROR_INCORRECT_SYNC_SEQUENCE);
+            break;
+        }
+        debug_if(s_debug_legacy, L_INFO, "In: FIRST_GLOBAL_DB data_size=%zu net 0x%016"DAP_UINT64_FORMAT_x" chain 0x%016"DAP_UINT64_FORMAT_x" cell 0x%016"DAP_UINT64_FORMAT_x
+                        " from address "NODE_ADDR_FP_STR "(unverified)", l_chain_pkt_data_size, l_context->request_hdr.net_id.uint64,
+                        l_context->request_hdr.chain_id.uint64, l_context->request_hdr.cell_id.uint64, NODE_ADDR_FP_ARGS_S(l_context->remote_addr));
+    } break;
+
+    // Dummy packet for freeze detection
+    case DAP_CHAIN_CH_PKT_TYPE_GLOBAL_DB_NO_FREEZE: {
+        struct legacy_sync_context *l_context = l_ch_chain->legacy_sync_context;
+        if (!l_context || l_context->state != DAP_CHAIN_CH_STATE_SYNC_GLOBAL_DB_REMOTE) {
+            log_it(L_WARNING, "Can't process GLOBAL_DB_NO_FREEZE packet cause synchronization sequence violation");
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                    l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
+                    DAP_CHAIN_CH_ERROR_INCORRECT_SYNC_SEQUENCE);
+            break;
+        }
+        debug_if(s_debug_legacy, L_DEBUG, "Global DB no freeze packet detected");
+        l_context->last_activity = dap_time_now();
+    } break;
+
+    case DAP_CHAIN_CH_PKT_TYPE_GLOBAL_DB: {
+        dap_global_db_pkt_old_t *l_pkt = (dap_global_db_pkt_old_t *)l_chain_pkt->data;
+        if (l_chain_pkt_data_size < sizeof(dap_global_db_pkt_old_t) ||
+                l_chain_pkt_data_size != sizeof(*l_pkt) + l_pkt->data_size) {
+            log_it(L_WARNING, "Incorrect data size %zu in packet %s", l_chain_pkt_data_size,
+                                                    dap_chain_ch_pkt_type_to_str(l_ch_pkt->hdr.type));
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                    l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
+                    DAP_CHAIN_CH_ERROR_LEGACY_PKT_DATA_SIZE);
+            return false;
+        }
+        struct legacy_sync_context *l_context = l_ch_chain->legacy_sync_context;
+        if (l_context && l_context->state != DAP_CHAIN_CH_STATE_SYNC_GLOBAL_DB_REMOTE) {
+            log_it(L_WARNING, "Can't process GLOBAL_DB packet cause synchronization sequence violation");
+            break;
+        }
+        if (l_context)
+            l_context->last_activity = dap_time_now();
+        debug_if(s_debug_legacy, L_INFO, "In: GLOBAL_DB_OLD data_size=%zu", l_chain_pkt_data_size);
+        // get records and save it to global_db
+        struct record_processing_args *l_args;
+        DAP_NEW_Z_RET_VAL(l_args, struct record_processing_args, true, NULL);
+        l_args->pkt = DAP_DUP_SIZE(l_pkt, l_chain_pkt_data_size);
+        if (!l_args->pkt) {
+            log_it(L_CRITICAL, "%s", g_error_memory_alloc);
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                    l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
+                    DAP_CHAIN_CH_ERROR_OUT_OF_MEMORY);
+            break;
+        }
+        l_args->worker = a_ch->stream_worker;
+        l_args->uuid = a_ch->uuid;
+        l_args->hdr = l_chain_pkt->hdr;
+        l_args->new = !l_context && l_pkt->obj_count == 1;
+        dap_proc_thread_callback_add(a_ch->stream_worker->worker->proc_queue_input, s_gdb_in_pkt_proc_callback, l_args);
+    } break;
+
+    case DAP_CHAIN_CH_PKT_TYPE_SYNCED_GLOBAL_DB: {
+        struct legacy_sync_context *l_context = l_ch_chain->legacy_sync_context;
+        if (!l_context || l_context->state != DAP_CHAIN_CH_STATE_SYNC_GLOBAL_DB_REMOTE) {
+            log_it(L_WARNING, "Can't process SYNCED_GLOBAL_DB packet cause synchronization sequence violation");
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                    l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
+                    DAP_CHAIN_CH_ERROR_INCORRECT_SYNC_SEQUENCE);
+            break;
+        }
+        debug_if(s_debug_legacy, L_INFO, "In:  SYNCED_GLOBAL_DB: net 0x%016"DAP_UINT64_FORMAT_x" chain 0x%016"DAP_UINT64_FORMAT_x" cell 0x%016"DAP_UINT64_FORMAT_x,
+                        l_context->request_hdr.net_id.uint64, l_context->request_hdr.chain_id.uint64, l_context->request_hdr.cell_id.uint64);
+        // we haven't node client waitng, so reply to other side
+        l_context->state = DAP_CHAIN_CH_STATE_UPDATE_GLOBAL_DB_REMOTE;
+        dap_chain_ch_sync_request_old_t l_request = { .node_addr = g_node_addr };
+        debug_if(s_debug_legacy, L_INFO, "Out: UPDATE_GLOBAL_DB_REQ pkt");
+        dap_chain_ch_pkt_write_unsafe(a_ch, DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_REQ, l_context->request_hdr.net_id,
+                                      l_context->request_hdr.chain_id, l_context->request_hdr.cell_id, &l_request, sizeof(l_request),
+                                      DAP_CHAIN_CH_PKT_VERSION_LEGACY);
+    } break;
+
+    /// --- Chains update ---
+    // Request for atoms list update
+    case DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_REQ: {
+        if (l_chain_pkt_data_size) { // Expected packet with no data
+            log_it(L_WARNING, "Incorrect data size %zu in packet %s", l_chain_pkt_data_size,
+                                                    dap_chain_ch_pkt_type_to_str(l_ch_pkt->hdr.type));
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                    l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
+                    DAP_CHAIN_CH_ERROR_LEGACY_PKT_DATA_SIZE);
+            return false;
+        }
+        if (!dap_link_manager_get_net_condition(l_chain_pkt->hdr.net_id.uint64)) {
+            log_it(L_WARNING, "Net id 0x%016" DAP_UINT64_FORMAT_x " is offline", l_chain_pkt->hdr.net_id.uint64);
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                    l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
+                    DAP_CHAIN_CH_ERROR_NET_IS_OFFLINE);
+            break;
+        }
+        if (l_ch_chain->sync_context || l_ch_chain->legacy_sync_context) {
+            log_it(L_WARNING, "Can't process UPDATE_CHAINS request because its already busy with syncronization");
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                    l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
+                    DAP_CHAIN_CH_ERROR_SYNC_REQUEST_ALREADY_IN_PROCESS);
+            break;
+        }
+        dap_chain_t * l_chain = dap_chain_find_by_id(l_chain_pkt->hdr.net_id, l_chain_pkt->hdr.chain_id);
+        if (!l_chain) {
+            log_it(L_WARNING, "Requested chain not found");
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id, l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
+                                                DAP_CHAIN_CH_ERROR_CHAIN_NOT_FOUND);
+            break;
+        }
+        dap_chain_atom_iter_t *l_atom_iter = l_chain->callback_atom_iter_create(l_chain, l_chain_pkt->hdr.cell_id, NULL);
+        if (!l_atom_iter) {
+            log_it(L_ERROR, "Can't create legacy atom iterator");
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                                            l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
+                                            DAP_CHAIN_CH_ERROR_OUT_OF_MEMORY);
+            break;
+        }
+        struct legacy_sync_context *l_context = s_legacy_sync_context_create(l_chain_pkt, a_ch);
+        if (!l_context) {
+            log_it(L_ERROR, "Can't create sychronization context");
+            l_chain->callback_atom_iter_delete(l_atom_iter);
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                                            l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
+                                            DAP_CHAIN_CH_ERROR_OUT_OF_MEMORY);
+            break;
+        }
+        l_chain->callback_atom_iter_get(l_atom_iter, DAP_CHAIN_ITER_OP_FIRST, NULL);
+        l_context->atom_iter = l_atom_iter;
+        l_context->remote_addr = *(dap_stream_node_addr_t *)l_chain_pkt->data;
+        l_context->request_hdr = l_chain_pkt->hdr;
+        l_ch_chain->legacy_sync_context = l_context;
+        l_context->state = DAP_CHAIN_CH_STATE_UPDATE_CHAINS;
+        debug_if(s_debug_legacy, L_DEBUG, "Sync out chains proc, requested chain %s for net %s from address " NODE_ADDR_FP_STR " (unverified)",
+                                                l_chain->name, l_chain->net_name, NODE_ADDR_FP_ARGS_S(l_context->remote_addr));
+        debug_if(s_debug_legacy, L_INFO, "In: UPDATE_CHAINS_REQ pkt: net 0x%016"DAP_UINT64_FORMAT_x" chain 0x%016"DAP_UINT64_FORMAT_x" cell 0x%016"DAP_UINT64_FORMAT_x,
+                            l_chain_pkt->hdr.net_id.uint64, l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64);
+        debug_if(s_debug_legacy, L_INFO, "Out: UPDATE_CHAINS_START pkt: net %s chain %s cell 0x%016"DAP_UINT64_FORMAT_X, l_chain->name,
+                                            l_chain->net_name, l_chain_pkt->hdr.cell_id.uint64);
+        dap_chain_ch_pkt_write_unsafe(a_ch, DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_START,
+                                            l_chain_pkt->hdr.net_id, l_chain_pkt->hdr.chain_id,
+                                            l_chain_pkt->hdr.cell_id, NULL, 0,
+                                            DAP_CHAIN_CH_PKT_VERSION_LEGACY);
+        dap_proc_thread_callback_add(a_ch->stream_worker->worker->proc_queue_input, s_sync_out_chains_proc_callback, l_context);
+    } break;
+
+    // If requested - begin to send atom hashes
+    case DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_START: {
+        struct legacy_sync_context *l_context = l_ch_chain->legacy_sync_context;
+        if (!l_context || l_context->state != DAP_CHAIN_CH_STATE_UPDATE_CHAINS_REMOTE) {
+            log_it(L_WARNING, "Can't process UPDATE_CHAINS_START packet cause synchronization sequence violation");
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                    l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
+                    DAP_CHAIN_CH_ERROR_INCORRECT_SYNC_SEQUENCE);
+            break;
+        }
+        debug_if(s_debug_legacy, L_INFO, "In: UPDATE_CHAINS_START pkt net 0x%016"DAP_UINT64_FORMAT_x" chain 0x%016"DAP_UINT64_FORMAT_x" cell 0x%016"DAP_UINT64_FORMAT_x,
+                            l_context->request_hdr.net_id.uint64, l_context->request_hdr.chain_id.uint64, l_context->request_hdr.cell_id.uint64);
+    } break;
+
+    // Response with atom hashes and sizes
+    case DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS: {
+        if (l_chain_pkt_data_size > sizeof(dap_chain_ch_update_element_t) * s_update_pack_size) {
+            log_it(L_WARNING, "Incorrect data size %zu in packet %s", l_chain_pkt_data_size,
+                                                    dap_chain_ch_pkt_type_to_str(l_ch_pkt->hdr.type));
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                    l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
+                    DAP_CHAIN_CH_ERROR_LEGACY_PKT_DATA_SIZE);
+            return false;
+        }
+        debug_if(s_debug_legacy, L_INFO, "In: UPDATE_CHAINS pkt data_size=%zu", l_chain_pkt_data_size);
+        struct legacy_sync_context *l_context = l_ch_chain->legacy_sync_context;
+        if (!l_context || l_context->state != DAP_CHAIN_CH_STATE_UPDATE_CHAINS_REMOTE) {
+            log_it(L_WARNING, "Can't process UPDATE_CHAINS packet cause synchronization sequence violation");
+            dap_stream_ch_write_error_unsafe(a_ch, l_context->request_hdr.net_id,
+                    l_context->request_hdr.chain_id, l_context->request_hdr.cell_id,
+                    DAP_CHAIN_CH_ERROR_INCORRECT_SYNC_SEQUENCE);
+            break;
+        }
+        l_context->last_activity = dap_time_now();
+
+        unsigned int l_count_added = 0;
+        unsigned int l_count_total = 0;
+        for (dap_chain_ch_update_element_t *l_element = (dap_chain_ch_update_element_t *)l_chain_pkt->data;
+                (size_t)((byte_t *)(l_element + 1) - l_chain_pkt->data) <= l_chain_pkt_data_size;
+                l_element++) {
+            dap_chain_ch_hash_item_t *l_hash_item = NULL;
+            unsigned l_hash_item_hashv;
+            HASH_VALUE(&l_element->hash, sizeof(l_element->hash), l_hash_item_hashv);
+            HASH_FIND_BYHASHVALUE(hh, l_context->remote_atoms, &l_element->hash, sizeof(l_element->hash),
+                                  l_hash_item_hashv, l_hash_item);
+            if (!l_hash_item) {
+                l_hash_item = DAP_NEW_Z(dap_chain_ch_hash_item_t);
+                if (!l_hash_item) {
+                    log_it(L_CRITICAL, "%s", g_error_memory_alloc);
+                    dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                            l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
+                            DAP_CHAIN_CH_ERROR_OUT_OF_MEMORY);
                     break;
                 }
-                debug_if(s_debug_more, L_INFO, "In: UPDATE_CHAINS_END pkt with total count %d hashes",
-                               HASH_COUNT(l_ch_chain->remote_atoms));
-                struct sync_request *l_sync_request = dap_chain_ch_create_sync_request(l_chain_pkt, a_ch);
-                l_ch_chain->stats_request_atoms_processed = 0;
-                l_ch_chain->request_hdr = l_chain_pkt->hdr;
-                dap_proc_thread_callback_add(a_ch->stream_worker->worker->proc_queue_input, s_sync_out_chains_proc_callback, l_sync_request);
-            } else {
-                log_it(L_WARNING, "DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_END: Wrong chain packet size %zd when expected %zd",
-                       l_chain_pkt_data_size, sizeof(l_ch_chain->request));
-                dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id.uint64,
-                        l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64,
-                        DAP_CHAIN_CH_ERROR_CHAIN_PKT_DATA_SIZE);
-            }
-        } break;
-        // first packet of data with source node address
-        case DAP_CHAIN_CH_PKT_TYPE_FIRST_CHAIN: {
-            if(l_chain_pkt_data_size == (size_t)sizeof(dap_chain_node_addr_t)){
-                l_ch_chain->request_hdr = l_chain_pkt->hdr;
-                l_ch_chain->request.node_addr = *(dap_chain_node_addr_t*)l_chain_pkt->data;
-                log_it(L_INFO, "From "NODE_ADDR_FP_STR": FIRST_CHAIN data_size=%zu net 0x%016"DAP_UINT64_FORMAT_x" chain 0x%016"DAP_UINT64_FORMAT_x" cell 0x%016"DAP_UINT64_FORMAT_x,
-                               NODE_ADDR_FP_ARGS_S(l_ch_chain->request.node_addr),
-                               l_chain_pkt_data_size, l_ch_chain->request_hdr.net_id.uint64 ,
-                               l_ch_chain->request_hdr.chain_id.uint64, l_ch_chain->request_hdr.cell_id.uint64);
-            }else{
-                log_it(L_WARNING,"Incorrect data size %zd in packet DAP_CHAIN_CH_PKT_TYPE_FIRST_CHAIN", l_chain_pkt_data_size);
-                dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id.uint64,
-                        l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64,
-                        DAP_CHAIN_CH_ERROR_CHAIN_PKT_DATA_SIZE);
+                l_hash_item->hash = l_element->hash;
+                l_hash_item->size = l_element->size;
+                HASH_ADD_BYHASHVALUE(hh, l_context->remote_atoms, hash, sizeof(l_hash_item->hash),
+                                     l_hash_item_hashv, l_hash_item);
+                l_count_added++;
+                //debug_if(s_debug_legacy, L_DEBUG, "In: Updated remote hash GDB list with %s", dap_chain_hash_fast_to_str_static(&l_hash_item->hash));
             }
-        } break;
+            l_count_total++;
+        }
+        debug_if(s_debug_legacy, L_INFO, "In: Added %u from %u remote atom hash in list", l_count_added, l_count_total);
+    } break;
 
-        case DAP_CHAIN_CH_PKT_TYPE_SYNCED_CHAINS: {
-            if (dap_log_level_get() <= L_INFO) {
-                dap_chain_hash_fast_t l_hash_from = l_ch_chain->request.hash_from;
-                char l_hash_from_str[DAP_CHAIN_HASH_FAST_STR_SIZE] = { '\0' }, l_hash_to_str[DAP_CHAIN_HASH_FAST_STR_SIZE] = { '\0' };
-                dap_chain_hash_fast_to_str(&l_hash_from, l_hash_from_str, DAP_CHAIN_HASH_FAST_STR_SIZE);
-                dap_chain_hash_fast_to_str(&c_dap_chain_addr_blank.data.hash_fast, l_hash_to_str, DAP_CHAIN_HASH_FAST_STR_SIZE);
-                log_it(L_INFO, "In:  SYNCED_CHAINS: between %s and %s",l_hash_from_str[0] ? l_hash_from_str : "(null)",
-                       l_hash_to_str[0] ? l_hash_to_str: "(null)");
+    // End of response with chain hashes
+    case DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_END: {
+        if (l_chain_pkt_data_size != sizeof(dap_chain_ch_sync_request_old_t)) {
+            log_it(L_WARNING, "Incorrect data size %zu in packet %s", l_chain_pkt_data_size,
+                                                    dap_chain_ch_pkt_type_to_str(l_ch_pkt->hdr.type));
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                    l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
+                    DAP_CHAIN_CH_ERROR_LEGACY_PKT_DATA_SIZE);
+            return false;
+        }
+        struct legacy_sync_context *l_context = l_ch_chain->legacy_sync_context;
+        if (!l_context || l_context->state != DAP_CHAIN_CH_STATE_UPDATE_CHAINS_REMOTE) {
+            log_it(L_WARNING, "Can't process UPDATE_CHAINS_END packet cause synchronization sequence violation");
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                    l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
+                    DAP_CHAIN_CH_ERROR_INCORRECT_SYNC_SEQUENCE);
+            break;
+        }
+        debug_if(s_debug_legacy, L_INFO, "In: UPDATE_CHAINS_END pkt with total count %d hashes", HASH_COUNT(l_context->remote_atoms));
+        l_context->state = DAP_CHAIN_CH_STATE_SYNC_CHAINS;
+        debug_if(s_debug_legacy, L_INFO, "Out: DAP_CHAIN_CH_PKT_TYPE_FIRST_CHAIN");
+        dap_chain_ch_pkt_write_unsafe(DAP_STREAM_CH(l_ch_chain), DAP_CHAIN_CH_PKT_TYPE_FIRST_CHAIN,
+                l_context->request_hdr.net_id, l_context->request_hdr.chain_id,
+                l_context->request_hdr.cell_id, &g_node_addr, sizeof(dap_chain_node_addr_t),
+                DAP_CHAIN_CH_PKT_VERSION_LEGACY);
+        dap_proc_thread_callback_add(a_ch->stream_worker->worker->proc_queue_input, s_sync_out_chains_proc_callback, l_context);
+    } break;
+
+    // first packet of data with source node address (legacy, unverified)
+    case DAP_CHAIN_CH_PKT_TYPE_FIRST_CHAIN: {
+        if (l_chain_pkt_data_size != sizeof(dap_chain_node_addr_t)) {
+            log_it(L_WARNING, "Incorrect data size %zu in packet %s", l_chain_pkt_data_size,
+                                                    dap_chain_ch_pkt_type_to_str(l_ch_pkt->hdr.type));
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                    l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
+                    DAP_CHAIN_CH_ERROR_LEGACY_PKT_DATA_SIZE);
+            return false;
+        }
+        struct legacy_sync_context *l_context = l_ch_chain->legacy_sync_context;
+        if (!l_context || l_context->state != DAP_CHAIN_CH_STATE_SYNC_CHAINS_REMOTE) {
+            log_it(L_WARNING, "Can't process FIRST_CHAIN packet cause synchronization sequence violation");
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                    l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
+                    DAP_CHAIN_CH_ERROR_INCORRECT_SYNC_SEQUENCE);
+            break;
+        }
+        debug_if(s_debug_legacy, L_INFO, "In: FIRST_CHAIN data_size=%zu net 0x%016"DAP_UINT64_FORMAT_x" chain 0x%016"DAP_UINT64_FORMAT_x" cell 0x%016"DAP_UINT64_FORMAT_x
+                        " from address "NODE_ADDR_FP_STR "(unverified)", l_chain_pkt_data_size, l_context->request_hdr.net_id.uint64,
+                        l_context->request_hdr.chain_id.uint64, l_context->request_hdr.cell_id.uint64, NODE_ADDR_FP_ARGS_S(l_context->remote_addr));
+    } break;
+
+    // Dummy packet for freeze detection
+    case DAP_CHAIN_CH_PKT_TYPE_CHAINS_NO_FREEZE: {
+        struct legacy_sync_context *l_context = l_ch_chain->legacy_sync_context;
+        if (!l_context || l_context->state != DAP_CHAIN_CH_STATE_SYNC_CHAINS_REMOTE) {
+            log_it(L_WARNING, "Can't process CHAINS_NO_FREEZE packet cause synchronization sequence violation");
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                    l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
+                    DAP_CHAIN_CH_ERROR_INCORRECT_SYNC_SEQUENCE);
+            break;
+        }
+        debug_if(s_debug_legacy, L_DEBUG, "Chains no freeze packet detected");
+        l_context->last_activity = dap_time_now();
+    } break;
+
+    case DAP_CHAIN_CH_PKT_TYPE_CHAIN_OLD: {
+        if (!l_chain_pkt_data_size) {
+            log_it(L_WARNING, "Incorrect data size %zu in packet %s", l_chain_pkt_data_size,
+                                                    dap_chain_ch_pkt_type_to_str(l_ch_pkt->hdr.type));
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                    l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
+                    DAP_CHAIN_CH_ERROR_LEGACY_PKT_DATA_SIZE);
+            return false;
+        }
+        struct legacy_sync_context *l_context = l_ch_chain->legacy_sync_context;
+        if (!l_context || l_context->state != DAP_CHAIN_CH_STATE_SYNC_CHAINS_REMOTE) {
+            log_it(L_WARNING, "Can't process FIRST_CHAIN packet cause synchronization sequence violation");
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                    l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
+                    DAP_CHAIN_CH_ERROR_INCORRECT_SYNC_SEQUENCE);
+            break;
+        }
+        debug_if(s_debug_legacy, L_INFO, "In: CHAIN_OLD data_size=%zu", l_chain_pkt_data_size);
+        struct atom_processing_args *l_args = DAP_NEW_Z_SIZE(struct atom_processing_args, l_ch_pkt->hdr.data_size + sizeof(struct atom_processing_args));
+        if (!l_args) {
+            log_it(L_CRITICAL, "%s", g_error_memory_alloc);
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                    l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
+                    DAP_CHAIN_CH_ERROR_OUT_OF_MEMORY);
+            break;
+        }
+        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_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_OLD pkt: atom hash %s (size %zd)", l_atom_hash_str, 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;
+
+    case DAP_CHAIN_CH_PKT_TYPE_SYNCED_CHAINS: {
+        struct legacy_sync_context *l_context = l_ch_chain->legacy_sync_context;
+        if (!l_context || l_context->state != DAP_CHAIN_CH_STATE_SYNC_CHAINS_REMOTE) {
+            log_it(L_WARNING, "Can't process SYNCED_CHAINS packet cause synchronization sequence violation");
+            dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id,
+                    l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id,
+                    DAP_CHAIN_CH_ERROR_INCORRECT_SYNC_SEQUENCE);
+            break;
+        }
+        debug_if(s_debug_legacy, L_INFO, "In:  SYNCED_CHAINS: net 0x%016"DAP_UINT64_FORMAT_x" chain 0x%016"DAP_UINT64_FORMAT_x" cell 0x%016"DAP_UINT64_FORMAT_x,
+                        l_context->request_hdr.net_id.uint64, l_context->request_hdr.chain_id.uint64, l_context->request_hdr.cell_id.uint64);
+        // we haven't node client waitng, so reply to other side
+        l_context->state = DAP_CHAIN_CH_STATE_UPDATE_CHAINS_REMOTE;
+        debug_if(s_debug_legacy, L_INFO, "Out: UPDATE_CHAINS_REQ pkt");
+        dap_chain_ch_sync_request_old_t l_request = { .node_addr = g_node_addr };
+        dap_chain_ch_pkt_write_unsafe(a_ch, DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_REQ, l_context->request_hdr.net_id,
+                                      l_context->request_hdr.chain_id, l_context->request_hdr.cell_id, &l_request, sizeof(l_request),
+                                      DAP_CHAIN_CH_PKT_VERSION_LEGACY);
+    } break;
 
-            }
-            s_ch_chain_get_idle(l_ch_chain);
-            if (l_ch_chain->activity_timer) {
-                dap_timerfd_delete_unsafe(l_ch_chain->activity_timer);
-                l_ch_chain->activity_timer = NULL;
-            }
-            // we haven't node client waitng, so reply to other side
-            dap_chain_t *l_chain = dap_chain_find_by_id(l_chain_pkt->hdr.net_id, l_chain_pkt->hdr.chain_id);
-            if (!l_chain) {
-                log_it(L_ERROR, "Invalid SYNCED_CHAINS packet from %s with net id 0x%016"DAP_UINT64_FORMAT_x
-                                " chain id 0x%016"DAP_UINT64_FORMAT_x" cell_id 0x%016"DAP_UINT64_FORMAT_x" in packet",
-                                a_ch->stream->esocket->remote_addr_str, l_chain_pkt->hdr.net_id.uint64,
-                                l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64);
-                dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id.uint64,
-                                                    l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64,
-                                                    DAP_CHAIN_CH_ERROR_NET_INVALID_ID);
-                break;
-            }
-            if (s_debug_more) {
-                log_it(L_INFO, "Out: UPDATE_CHAINS_REQ pkt");
-            }
-            dap_chain_ch_sync_request_old_t l_request= {};
-            dap_chain_ch_pkt_write_unsafe(a_ch, DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_REQ, l_chain_pkt->hdr.net_id.uint64,
-                                          l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64, &l_request, sizeof(l_request));
-        } break;
     }
+
     return true;
 }
 
 static bool s_sync_timer_callback(void *a_arg)
 {
-    dap_chain_ch_t *l_ch_chain = a_arg;
-    struct sync_context *l_context = l_ch_chain->sync_context;
-    if (l_context->last_activity + s_sync_timeout <= dap_time_now()) {
-        log_it(L_ERROR, "Sync timeout for node " NODE_ADDR_FP_STR " with net 0x%016" DAP_UINT64_FORMAT_x
-                            " chain 0x%016" DAP_UINT64_FORMAT_x " cell 0x%016" DAP_UINT64_FORMAT_x,
-                                        NODE_ADDR_FP_ARGS_S(l_context->addr), l_context->net_id.uint64,
-                                        l_context->chain_id.uint64, l_context->cell_id.uint64);
-        l_ch_chain->sync_timer = NULL;      // Preserve timer removing from s_ch_chain_go_idle()
-        dap_stream_ch_write_error_unsafe(DAP_STREAM_CH(l_ch_chain), l_context->net_id.uint64,
-                                         l_context->chain_id.uint64, l_context->cell_id.uint64,
-                                         DAP_CHAIN_CH_ERROR_SYNC_TIMEOUT);
+    dap_worker_t *l_worker = dap_worker_get_current();
+    dap_stream_ch_t *l_ch = dap_stream_ch_find_by_uuid_unsafe(DAP_STREAM_WORKER(l_worker), *(dap_stream_ch_uuid_t *)a_arg);
+    if (!l_ch) {
+        DAP_DELETE(a_arg);
+        return false;
+    }
+    dap_chain_ch_t *l_ch_chain = DAP_CHAIN_CH(l_ch);
+    if (!l_ch_chain) {
+        log_it(L_ERROR, "Channel without chain, dump it");
+        DAP_DELETE(a_arg);
+        return false;
+    }
+
+    bool l_timer_break = false;
+    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()) {
+            log_it(L_ERROR, "Sync timeout for node " NODE_ADDR_FP_STR " with net 0x%016" DAP_UINT64_FORMAT_x
+                                " chain 0x%016" DAP_UINT64_FORMAT_x " cell 0x%016" DAP_UINT64_FORMAT_x,
+                                            NODE_ADDR_FP_ARGS_S(l_context->addr), l_context->net_id.uint64,
+                                            l_context->chain_id.uint64, l_context->cell_id.uint64);
+            dap_chain_ch_pkt_write_unsafe(l_ch, DAP_CHAIN_CH_PKT_TYPE_ERROR, l_context->net_id,
+                                          l_context->chain_id, l_context->cell_id, l_err_str, strlen(l_err_str) + 1,
+                                          DAP_CHAIN_CH_PKT_VERSION_CURRENT);
+            l_timer_break = true;
+        }
+    } else if (l_ch_chain->legacy_sync_context) {
+        struct legacy_sync_context *l_context = l_ch_chain->legacy_sync_context;
+        if (l_context->last_activity + s_sync_timeout <= dap_time_now()) {
+            log_it(L_ERROR, "Sync timeout for node " NODE_ADDR_FP_STR " (unverified) with net 0x%016" DAP_UINT64_FORMAT_x
+                                " chain 0x%016" DAP_UINT64_FORMAT_x " cell 0x%016" DAP_UINT64_FORMAT_x,
+                                            NODE_ADDR_FP_ARGS_S(l_context->remote_addr), l_context->request_hdr.net_id.uint64,
+                                            l_context->request_hdr.chain_id.uint64, l_context->request_hdr.cell_id.uint64);
+            dap_chain_ch_pkt_write_unsafe(l_ch, DAP_CHAIN_CH_PKT_TYPE_ERROR, l_context->request_hdr.net_id,
+                                          l_context->request_hdr.chain_id, l_context->request_hdr.cell_id, l_err_str, strlen(l_err_str) + 1,
+                                          DAP_CHAIN_CH_PKT_VERSION_LEGACY);
+            l_timer_break = true;
+        }
+    } else
+        l_timer_break = true;
 
+    if (l_timer_break) {
+        l_ch_chain->sync_timer = NULL;      // Preserve timer removing from s_ch_chain_go_idle()
+        s_ch_chain_go_idle(l_ch_chain);
+        DAP_DELETE(a_arg);
         return false;
     }
     return true;
@@ -1476,8 +1605,8 @@ static bool s_chain_iter_callback(void *a_arg)
     while (l_atom && l_atom_size) {
         if (l_iter->cur_num > atomic_load_explicit(&l_context->allowed_num, memory_order_acquire))
             break;
-        dap_chain_ch_pkt_t *l_pkt = dap_chain_ch_pkt_new(l_context->net_id.uint64, l_context->chain_id.uint64, l_context->cell_id.uint64,
-                                                         l_atom, l_atom_size);
+        dap_chain_ch_pkt_t *l_pkt = dap_chain_ch_pkt_new(l_context->net_id, l_context->chain_id, l_context->cell_id,
+                                                         l_atom, l_atom_size, DAP_CHAIN_CH_PKT_VERSION_CURRENT);
         // For master format binary complience
         l_pkt->hdr.num_lo = l_iter->cur_num & 0xFFFF;
         l_pkt->hdr.num_hi = (l_iter->cur_num >> 16) & 0xFF;
@@ -1524,6 +1653,8 @@ static bool s_chain_iter_delete_callback(void *a_arg)
  */
 static void s_ch_chain_go_idle(dap_chain_ch_t *a_ch_chain)
 {
+    debug_if(s_debug_more, L_INFO, "Going to chain's stream channel STATE_IDLE");
+
     // New protocol
     if (a_ch_chain->sync_context) {
         atomic_store(&((struct sync_context *)a_ch_chain->sync_context)->state, SYNC_STATE_OVER);
@@ -1537,428 +1668,42 @@ static void s_ch_chain_go_idle(dap_chain_ch_t *a_ch_chain)
     }
 //}
     // Legacy
-    if (a_ch_chain->state == DAP_CHAIN_CH_STATE_IDLE) {
-        return;
-    }
-    a_ch_chain->state = DAP_CHAIN_CH_STATE_IDLE;
-
-    if(s_debug_more)
-        log_it(L_INFO, "Go in DAP_CHAIN_CH_STATE_IDLE");
-
-    // Cleanup after request
-    memset(&a_ch_chain->request, 0, sizeof(a_ch_chain->request));
-    memset(&a_ch_chain->request_hdr, 0, sizeof(a_ch_chain->request_hdr));
-    if (a_ch_chain->request_atom_iter && a_ch_chain->request_atom_iter->chain &&
-            a_ch_chain->request_atom_iter->chain->callback_atom_iter_delete) {
-        a_ch_chain->request_atom_iter->chain->callback_atom_iter_delete(a_ch_chain->request_atom_iter);
-        a_ch_chain->request_atom_iter = NULL;
+    if (a_ch_chain->legacy_sync_context) {
+        dap_chain_ch_state_t l_current_state = atomic_exchange(
+                    &((struct legacy_sync_context *)a_ch_chain->legacy_sync_context)->state, DAP_CHAIN_CH_STATE_IDLE);
+        if (l_current_state != DAP_CHAIN_CH_STATE_UPDATE_CHAINS &&
+                l_current_state != DAP_CHAIN_CH_STATE_SYNC_CHAINS &&
+                l_current_state != DAP_CHAIN_CH_STATE_UPDATE_GLOBAL_DB &&
+                l_current_state != DAP_CHAIN_CH_STATE_SYNC_GLOBAL_DB &&
+                l_current_state != DAP_CHAIN_CH_STATE_IDLE &&
+                l_current_state != DAP_CHAIN_CH_STATE_ERROR)
+            // Context will not be removed from proc thread
+            s_legacy_sync_context_delete(a_ch_chain->legacy_sync_context);
+        a_ch_chain->legacy_sync_context = NULL;
     }
-
-    dap_chain_ch_hash_item_t *l_hash_item = NULL, *l_tmp = NULL;
-
-    HASH_ITER(hh, a_ch_chain->remote_atoms, l_hash_item, l_tmp) {
-        // Clang bug at this, l_hash_item should change at every loop cycle
-        HASH_DEL(a_ch_chain->remote_atoms, l_hash_item);
-        DAP_DELETE(l_hash_item);
-    }
-    a_ch_chain->remote_atoms = NULL;
-    a_ch_chain->sent_breaks = 0;
 }
 
-struct chain_io_complete {
-    dap_stream_ch_uuid_t ch_uuid;
-    dap_chain_ch_state_t state;
-    uint8_t type;
-    uint64_t net_id;
-    uint64_t chain_id;
-    uint64_t cell_id;
-    size_t data_size;
-    byte_t data[];
-};
-
 static void s_stream_ch_io_complete(dap_events_socket_t *a_es, void *a_arg)
 {
-    dap_stream_t *l_stream = NULL;
-    if (!a_es->server) {
-        dap_client_t *l_client = DAP_ESOCKET_CLIENT(a_es);
-        assert(l_client);
-        dap_client_pvt_t *l_client_pvt = DAP_CLIENT_PVT(l_client);
-        l_stream = l_client_pvt->stream;
-    } else {
-        dap_http_client_t *l_http_client = DAP_HTTP_CLIENT(a_es);
-        if (l_http_client)
-            l_stream = DAP_STREAM(l_http_client);
-    }
-    if (!l_stream)
+    dap_return_if_fail(a_arg);
+    dap_stream_t *l_stream = dap_stream_get_from_es(a_es);
+    assert(l_stream);
+    dap_stream_ch_t *l_ch = dap_stream_ch_by_id_unsafe(l_stream, DAP_CHAIN_CH_ID);
+    assert(l_ch);
+    struct legacy_sync_context *l_context = DAP_CHAIN_CH(l_ch)->legacy_sync_context;
+    if (!l_context)
         return;
-    dap_stream_ch_t *l_ch = NULL;
-    for (size_t i = 0; i < l_stream->channel_count; i++)
-        if (l_stream->channel[i]->proc->id == DAP_CHAIN_CH_ID)
-            l_ch = l_stream->channel[i];
-    if (!l_ch || !DAP_CHAIN_CH(l_ch))
+    dap_chain_ch_state_t l_expected = DAP_CHAIN_CH_STATE_WAITING;
+    if (!atomic_compare_exchange_strong(&l_context->state, &l_expected, l_context->prev_state))
         return;
-    if (a_arg) {
-        struct chain_io_complete *l_arg = (struct chain_io_complete *)a_arg;
-        if (DAP_CHAIN_CH(l_ch)->state == DAP_CHAIN_CH_STATE_WAITING)
-            DAP_CHAIN_CH(l_ch)->state = l_arg->state;
-        dap_chain_ch_pkt_write_unsafe(l_ch, l_arg->type, l_arg->net_id, l_arg->chain_id,
-                                             l_arg->cell_id, l_arg->data, l_arg->data_size);
-        a_es->callbacks.arg = NULL;
-        DAP_DELETE(a_arg);
-        return;
-    }
-    s_stream_ch_packet_out(l_ch, NULL);
-}
-
-static void s_stream_ch_chain_pkt_write(dap_stream_ch_t *a_ch, uint8_t a_type, uint64_t a_net_id,
-                                        uint64_t a_chain_id, uint64_t a_cell_id,
-                                        const void * a_data, size_t a_data_size)
-{
-    size_t l_free_buf_size = dap_events_socket_get_free_buf_size(a_ch->stream->esocket) -
-                                sizeof(dap_chain_ch_pkt_t) - sizeof(dap_stream_ch_pkt_t) -
-                                sizeof(dap_stream_pkt_t) - DAP_STREAM_PKT_ENCRYPTION_OVERHEAD;
-    if (l_free_buf_size < a_data_size) {
-        struct chain_io_complete *l_arg = DAP_NEW_Z_SIZE(struct chain_io_complete, sizeof(struct chain_io_complete) + a_data_size);
-        l_arg->ch_uuid = a_ch->uuid;
-        l_arg->state = DAP_CHAIN_CH(a_ch)->state;
-        DAP_CHAIN_CH(a_ch)->state = DAP_CHAIN_CH_STATE_WAITING;
-        l_arg->type = a_type;
-        l_arg->net_id = a_net_id;
-        l_arg->chain_id = a_chain_id;
-        l_arg->cell_id = a_cell_id;
-        l_arg->data_size = a_data_size;
-        memcpy(l_arg->data, a_data, a_data_size);
-        a_ch->stream->esocket->callbacks.arg = l_arg;
-    }
-    else
-       dap_chain_ch_pkt_write_unsafe(a_ch, a_type, a_net_id, a_chain_id, a_cell_id, a_data, a_data_size);
-}
-
-/**
- * @brief s_stream_ch_packet_out
- * @param ch
- * @param arg
- */
-static bool s_stream_ch_packet_out(dap_stream_ch_t *a_ch, void *a_arg)
-{
-    dap_chain_ch_t *l_ch_chain = DAP_CHAIN_CH(a_ch);
-    if (!l_ch_chain) {
-        log_it(L_CRITICAL, "Channel without chain, dump it");
-        s_ch_chain_go_idle(l_ch_chain);
-        return false;
-    }
-    bool l_go_idle = false, l_was_sent_smth = false;
-    switch (l_ch_chain->state) {
-        // Update list of global DB records to remote
-    case DAP_CHAIN_CH_STATE_UPDATE_GLOBAL_DB: {
-#if 0
-        size_t i, q =
-                // s_update_pack_size;
-                0;
-        //dap_db_log_list_obj_t **l_objs = dap_db_log_list_get_multiple(l_ch_chain->request_db_log, DAP_STREAM_PKT_SIZE_MAX, &q);
-        dap_chain_ch_update_element_t *l_data = DAP_NEW_Z_SIZE(dap_chain_ch_update_element_t, q * sizeof(dap_chain_ch_update_element_t));
-        for (i = 0; i < q; ++i) {
-            l_data[i].hash = l_objs[i]->hash;
-            l_data[i].size = l_objs[i]->pkt->data_size;
-            DAP_DELETE(l_objs[i]->pkt);
-            DAP_DELETE(l_objs[i]);
-        }
-        if (i) {
-            l_was_sent_smth = true;
-            s_stream_ch_chain_pkt_write(a_ch, DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB,
-                                        l_ch_chain->request_hdr.net_id.uint64, l_ch_chain->request_hdr.chain_id.uint64,
-                                        l_ch_chain->request_hdr.cell_id.uint64,
-                                        l_data, i * sizeof(dap_chain_ch_update_element_t));
-            l_ch_chain->stats_request_gdb_processed += i;
-            DAP_DELETE(l_data);
-            DAP_DELETE(l_objs);
-            debug_if(s_debug_more, L_INFO, "Out: DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB, %zu records", i);
-        } else if (!l_objs) {
-            l_was_sent_smth = true;
-            l_ch_chain->request.node_addr.uint64 = dap_chain_net_get_cur_addr_int(dap_chain_net_by_id(
-                                                                                      l_ch_chain->request_hdr.net_id));
-            s_stream_ch_chain_pkt_write(a_ch, DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_END,
-                                                 l_ch_chain->request_hdr.net_id.uint64,
-                                                 l_ch_chain->request_hdr.chain_id.uint64,
-                                                 l_ch_chain->request_hdr.cell_id.uint64,
-                                                 &l_ch_chain->request, sizeof(dap_chain_ch_sync_request_old_t));
-            debug_if(s_debug_more, L_INFO, "Out: DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_END");
-            l_go_idle = true;
-        }
-            dap_chain_ch_update_element_t l_data[s_update_pack_size];
-            uint_fast16_t i;
-            dap_db_log_list_obj_t *l_obj = NULL;
-            for (i = 0; i < s_update_pack_size; i++) {
-                l_obj = dap_db_log_list_get(l_ch_chain->request_db_log);
-                if (!l_obj || DAP_POINTER_TO_SIZE(l_obj) == 1)
-                    break;
-                l_data[i].hash = l_obj->hash;
-                l_data[i].size = l_obj->pkt->data_size;
-                DAP_DELETE(l_obj->pkt);
-                DAP_DELETE(l_obj);
-            }
-            if (i) {
-                l_was_sent_smth = true;
-                s_stream_ch_chain_pkt_write(a_ch, DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB,
-                                            l_ch_chain->request_hdr.net_id.uint64, l_ch_chain->request_hdr.chain_id.uint64,
-                                            l_ch_chain->request_hdr.cell_id.uint64,
-                                            l_data, i * sizeof(dap_chain_ch_update_element_t));
-                l_ch_chain->stats_request_gdb_processed += i;
-                if (s_debug_more)
-                    log_it(L_INFO, "Out: DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB");
-            } else if (!l_obj) {
-                l_was_sent_smth = true;
-                l_ch_chain->request.node_addr.uint64 = dap_chain_net_get_cur_addr_int(dap_chain_net_by_id(
-                                                                                          l_ch_chain->request_hdr.net_id));
-                s_stream_ch_chain_pkt_write(a_ch, DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_END,
-                                                     l_ch_chain->request_hdr.net_id.uint64,
-                                                     l_ch_chain->request_hdr.chain_id.uint64,
-                                                     l_ch_chain->request_hdr.cell_id.uint64,
-                                                     &l_ch_chain->request, sizeof(dap_chain_ch_sync_request_old_t));
-                if (s_debug_more )
-                    log_it(L_INFO, "Out: DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_END");
-                l_go_idle = true;
-            }
-#endif
-        } break;
-
-        // Synchronize GDB
-    case DAP_CHAIN_CH_STATE_SYNC_GLOBAL_DB: {
-#if 0
-        dap_global_db_pkt_t *l_pkt = NULL;
-        size_t l_pkt_size = 0, i, q = 0;
-        dap_db_log_list_obj_t **l_objs = dap_db_log_list_get_multiple(l_ch_chain->request_db_log, DAP_STREAM_PKT_SIZE_MAX, &q);
-        for (i = 0; i < q; ++i) {
-            dap_chain_ch_hash_item_t *l_hash_item = NULL;
-            unsigned l_hash_item_hashv = 0;
-            HASH_VALUE(&l_objs[i]->hash, sizeof(dap_chain_hash_fast_t), l_hash_item_hashv);
-            HASH_FIND_BYHASHVALUE(hh, l_ch_chain->remote_gdbs, &l_objs[i]->hash,
-                                  sizeof(dap_hash_fast_t), l_hash_item_hashv, l_hash_item);
-            if (!l_hash_item) {
-                l_hash_item = DAP_NEW_Z(dap_chain_ch_hash_item_t);
-                *l_hash_item = (dap_chain_ch_hash_item_t) {
-                        .hash   = l_objs[i]->hash, .size   = l_objs[i]->pkt->data_size
-                };
-                HASH_ADD_BYHASHVALUE(hh, l_ch_chain->remote_gdbs, hash, sizeof(dap_chain_hash_fast_t),
-                                     l_hash_item_hashv, l_hash_item);
-                l_pkt = dap_global_db_pkt_pack(l_pkt, l_objs[i]->pkt);
-                l_ch_chain->stats_request_gdb_processed++;
-                l_pkt_size = sizeof(dap_global_db_pkt_t) + l_pkt->data_size;
-            }
-
-            DAP_DELETE(l_objs[i]->pkt);
-            DAP_DELETE(l_objs[i]);
-        }
-
-        if (l_pkt_size) {
-            l_was_sent_smth = true;
-            // If request was from defined node_addr we update its state
-            s_stream_ch_chain_pkt_write(a_ch, DAP_CHAIN_CH_PKT_TYPE_GLOBAL_DB,
-                                        l_ch_chain->request_hdr.net_id.uint64, l_ch_chain->request_hdr.chain_id.uint64,
-                                        l_ch_chain->request_hdr.cell_id.uint64, l_pkt, l_pkt_size);
-            debug_if(s_debug_more, L_INFO, "Send one global_db packet, size %zu, rest %zu/%zu items", l_pkt_size,
-                     l_ch_chain->request_db_log->items_rest,
-                     l_ch_chain->request_db_log->items_number);
-            DAP_DELETE(l_pkt);
-            DAP_DELETE(l_objs);
-        } else if (!l_objs) {
-            l_was_sent_smth = true;
-            // last message
-            dap_chain_ch_sync_request_old_t l_request = { };
-            s_stream_ch_chain_pkt_write(a_ch, DAP_CHAIN_CH_PKT_TYPE_SYNCED_GLOBAL_DB,
-                                        l_ch_chain->request_hdr.net_id.uint64, l_ch_chain->request_hdr.chain_id.uint64,
-                                        l_ch_chain->request_hdr.cell_id.uint64, &l_request, sizeof(l_request));
-            l_go_idle = true;
-            if (l_ch_chain->callback_notify_packet_out)
-                l_ch_chain->callback_notify_packet_out(l_ch_chain, DAP_CHAIN_CH_PKT_TYPE_SYNCED_GLOBAL_DB,
-                                                       NULL, 0, l_ch_chain->callback_notify_arg);
-            log_it(L_INFO,"Syncronized database: items syncronyzed %"DAP_UINT64_FORMAT_U" of %zu",
-                    l_ch_chain->stats_request_gdb_processed, l_ch_chain->request_db_log->items_number);
-        }
-            // Get global DB record
-            dap_global_db_pkt_t *l_pkt = NULL;
-            dap_db_log_list_obj_t *l_obj = NULL;
-            size_t l_pkt_size = 0;
-            for (uint_fast16_t l_skip_count = 0; l_skip_count < s_skip_in_reactor_count; ) {
-                l_obj = dap_db_log_list_get(l_ch_chain->request_db_log);
-                if (!l_obj || DAP_POINTER_TO_SIZE(l_obj) == 1) {
-                    l_skip_count = s_skip_in_reactor_count;
-                    break;
-                }
-                dap_chain_ch_hash_item_t *l_hash_item = NULL;
-                unsigned l_hash_item_hashv = 0;
-                HASH_VALUE(&l_obj->hash, sizeof(dap_chain_hash_fast_t), l_hash_item_hashv);
-                HASH_FIND_BYHASHVALUE(hh, l_ch_chain->remote_gdbs, &l_obj->hash, sizeof(dap_hash_fast_t),
-                                      l_hash_item_hashv, l_hash_item);
-                if (l_hash_item) { // If found - skip it
-                    /*if (s_debug_more) {
-                        char l_request_atom_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE];
-                        dap_chain_hash_fast_to_str(&l_obj->hash, l_request_atom_hash_str, DAP_CHAIN_HASH_FAST_STR_SIZE);
-                        log_it(L_DEBUG, "Out CHAIN: skip GDB hash %s because its already present in remote GDB hash table",
-                                        l_request_atom_hash_str);
-                    }*/
-                    l_skip_count++;
-                } else {
-                    l_hash_item = DAP_NEW_Z(dap_chain_ch_hash_item_t);
-                    if (!l_hash_item) {
-                        log_it(L_CRITICAL, "%s", g_error_memory_alloc);
-                        return;
-                    }
-                    l_hash_item->hash = l_obj->hash;
-                    l_hash_item->size = l_obj->pkt->data_size;
-                    HASH_ADD_BYHASHVALUE(hh, l_ch_chain->remote_gdbs, hash, sizeof(dap_chain_hash_fast_t),
-                                         l_hash_item_hashv, l_hash_item);
-                    l_pkt = dap_global_db_pkt_pack(l_pkt, l_obj->pkt);
-                    l_ch_chain->stats_request_gdb_processed++;
-                    l_pkt_size = sizeof(dap_global_db_pkt_t) + l_pkt->data_size;
-                }
-                DAP_DELETE(l_obj->pkt);
-                DAP_DELETE(l_obj);
-                if (l_pkt_size >= DAP_CHAIN_PKT_EXPECT_SIZE)
-                    break;
-            }
-            if (l_pkt_size) {
-                l_was_sent_smth = true;
-                // If request was from defined node_addr we update its state
-                if (s_debug_more)
-                    log_it(L_INFO, "Send one global_db packet len=%zu (rest=%zu/%zu items)", l_pkt_size,
-                                    dap_db_log_list_get_count_rest(l_ch_chain->request_db_log),
-                                    dap_db_log_list_get_count(l_ch_chain->request_db_log));
-                s_stream_ch_chain_pkt_write(a_ch, DAP_CHAIN_CH_PKT_TYPE_GLOBAL_DB,
-                                                     l_ch_chain->request_hdr.net_id.uint64, l_ch_chain->request_hdr.chain_id.uint64,
-                                                     l_ch_chain->request_hdr.cell_id.uint64, l_pkt, l_pkt_size);
-                DAP_DELETE(l_pkt);
-            } else if (!l_obj) {
-                l_was_sent_smth = true;
-                log_it( L_INFO,"Syncronized database: items syncronyzed %"DAP_UINT64_FORMAT_U" from %zu",
-                        l_ch_chain->stats_request_gdb_processed, dap_db_log_list_get_count(l_ch_chain->request_db_log));
-                // last message
-                dap_chain_ch_sync_request_old_t l_request = {};
-                s_stream_ch_chain_pkt_write(a_ch, DAP_CHAIN_CH_PKT_TYPE_SYNCED_GLOBAL_DB,
-                                                     l_ch_chain->request_hdr.net_id.uint64, l_ch_chain->request_hdr.chain_id.uint64,
-                                                     l_ch_chain->request_hdr.cell_id.uint64, &l_request, sizeof(l_request));
-                l_go_idle = true;
-                if (l_ch_chain->callback_notify_packet_out)
-                    l_ch_chain->callback_notify_packet_out(l_ch_chain, DAP_CHAIN_CH_PKT_TYPE_SYNCED_GLOBAL_DB,
-                                                           NULL, 0, l_ch_chain->callback_notify_arg);
-            }
-#endif
-    } break;
-
-        // Update list of atoms to remote
-        case DAP_CHAIN_CH_STATE_UPDATE_CHAINS:{
-            dap_chain_ch_update_element_t *l_data = DAP_NEW_Z_SIZE(dap_chain_ch_update_element_t,
-                                                                          sizeof(dap_chain_ch_update_element_t) * s_update_pack_size);
-            size_t l_data_size=0;
-            for(uint_fast16_t n=0; n<s_update_pack_size && (l_ch_chain->request_atom_iter && l_ch_chain->request_atom_iter->cur);n++){
-                l_data[n].hash = *l_ch_chain->request_atom_iter->cur_hash;
-                // Shift offset counter
-                l_data_size += sizeof(dap_chain_ch_update_element_t);
-                // Then get next atom
-                l_ch_chain->request_atom_iter->chain->callback_atom_iter_get(l_ch_chain->request_atom_iter, DAP_CHAIN_ITER_OP_NEXT, NULL);
-            }
-            if (l_data_size){
-                l_was_sent_smth = true;
-                if(s_debug_more)
-                    log_it(L_DEBUG,"Out: UPDATE_CHAINS with %zu hashes sent", l_data_size / sizeof(dap_chain_ch_update_element_t));
-                s_stream_ch_chain_pkt_write(a_ch, DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS,
-                                                     l_ch_chain->request_hdr.net_id.uint64,
-                                                     l_ch_chain->request_hdr.chain_id.uint64,
-                                                     l_ch_chain->request_hdr.cell_id.uint64,
-                                                     l_data,l_data_size);
-            }
-            if(!l_data_size  ||  !l_ch_chain->request_atom_iter){ // We over with all the hashes here
-                l_was_sent_smth = true;
-                if(s_debug_more)
-                    log_it(L_INFO,"Out: UPDATE_CHAINS_END sent ");
-                dap_chain_ch_sync_request_old_t l_request = {};
-                s_stream_ch_chain_pkt_write(a_ch, DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_END,
-                                                     l_ch_chain->request_hdr.net_id.uint64,
-                                                     l_ch_chain->request_hdr.chain_id.uint64,
-                                                     l_ch_chain->request_hdr.cell_id.uint64,
-                                                     &l_request, sizeof(dap_chain_ch_sync_request_old_t));
-                l_go_idle = true;
-                dap_stream_ch_set_ready_to_write_unsafe(a_ch, false);
-            }
-            DAP_DELETE(l_data);
-        }break;
-
-        // Synchronize chains
-        case DAP_CHAIN_CH_STATE_SYNC_CHAINS: {
-            // Process one chain from l_ch_chain->request_atom_iter
-            // Pack loop to skip quicker
-            for(uint_fast16_t k=0; k<s_skip_in_reactor_count     &&
-                                   l_ch_chain->request_atom_iter &&
-                                   l_ch_chain->request_atom_iter->cur; k++){
-                // Check if present and skip if present
-                dap_chain_ch_hash_item_t *l_hash_item = NULL;
-                unsigned l_hash_item_hashv = 0;
-                HASH_VALUE(l_ch_chain->request_atom_iter->cur_hash, sizeof(dap_chain_hash_fast_t), l_hash_item_hashv);
-                HASH_FIND_BYHASHVALUE(hh, l_ch_chain->remote_atoms, l_ch_chain->request_atom_iter->cur_hash,
-                                      sizeof(dap_chain_hash_fast_t), l_hash_item_hashv, l_hash_item);
-                if( l_hash_item ){ // If found - skip it
-                    /*if(s_debug_more){
-                        char l_request_atom_hash_str[81]={[0]='\0'};
-                        dap_chain_hash_fast_to_str(l_ch_chain->request_atom_iter->cur_hash,l_request_atom_hash_str,sizeof (l_request_atom_hash_str));
-                        log_it(L_DEBUG, "Out CHAIN: skip atom hash %s because its already present in remote atom hash table",
-                                        l_request_atom_hash_str);
-                    }*/
-                }else{
-                    l_hash_item = DAP_NEW_Z(dap_chain_ch_hash_item_t);
-                    if (!l_hash_item) {
-                        log_it(L_CRITICAL, "%s", g_error_memory_alloc);
-                        return false;
-                    }
-                    l_hash_item->hash = *l_ch_chain->request_atom_iter->cur_hash;
-                    if(s_debug_more){
-                        char l_atom_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE];
-                        dap_chain_hash_fast_to_str(&l_hash_item->hash, l_atom_hash_str, sizeof(l_atom_hash_str));
-                        log_it(L_INFO, "Out CHAIN pkt: atom hash %s (size %zd) ", l_atom_hash_str, l_ch_chain->request_atom_iter->cur_size);
-                    }
-                    s_stream_ch_chain_pkt_write(a_ch, DAP_CHAIN_CH_PKT_TYPE_CHAIN, l_ch_chain->request_hdr.net_id.uint64,
-                                                         l_ch_chain->request_hdr.chain_id.uint64, l_ch_chain->request_hdr.cell_id.uint64,
-                                                         l_ch_chain->request_atom_iter->cur, l_ch_chain->request_atom_iter->cur_size);
-                    l_was_sent_smth = true;
-                    l_ch_chain->stats_request_atoms_processed++;
-
-                    l_hash_item->size = l_ch_chain->request_atom_iter->cur_size;
-                    // Because we sent this atom to remote - we record it to not to send it twice
-                    HASH_ADD_BYHASHVALUE(hh, l_ch_chain->remote_atoms, hash, sizeof(dap_hash_fast_t), l_hash_item_hashv,
-                                         l_hash_item);
-                }
-                // Then get next atom and populate new last
-                l_ch_chain->request_atom_iter->chain->callback_atom_iter_get(l_ch_chain->request_atom_iter, DAP_CHAIN_ITER_OP_NEXT, NULL);
-                if (l_was_sent_smth)
-                    break;
-            }
-            if(!l_ch_chain->request_atom_iter || !l_ch_chain->request_atom_iter->cur)  { // All chains synced
-                dap_chain_ch_sync_request_old_t l_request = {};
-                // last message
-                l_was_sent_smth = true;
-                s_stream_ch_chain_pkt_write(a_ch, DAP_CHAIN_CH_PKT_TYPE_SYNCED_CHAINS,
-                                                     l_ch_chain->request_hdr.net_id.uint64, l_ch_chain->request_hdr.chain_id.uint64,
-                                                     l_ch_chain->request_hdr.cell_id.uint64, &l_request, sizeof(l_request));
-                log_it( L_INFO,"Synced: %"DAP_UINT64_FORMAT_U" atoms processed", l_ch_chain->stats_request_atoms_processed);
-                l_go_idle = true;
-            }
-        } break;
-
-        default:
-            return false;
-    }
-    if (l_was_sent_smth) {
-        s_chain_timer_reset(l_ch_chain);
-        l_ch_chain->sent_breaks = 0;
+    if (l_context->prev_state == DAP_CHAIN_CH_STATE_UPDATE_CHAINS ||
+            l_context->prev_state == DAP_CHAIN_CH_STATE_SYNC_CHAINS) {
+        l_context->enqueued_data_size = 0;
+        dap_proc_thread_callback_add(l_ch->stream_worker->worker->proc_queue_input, s_sync_out_chains_proc_callback, l_context);
+    } else if (l_context->prev_state == DAP_CHAIN_CH_STATE_UPDATE_GLOBAL_DB ||
+                l_context->prev_state == DAP_CHAIN_CH_STATE_SYNC_GLOBAL_DB) {
+        l_context->enqueued_data_size = 0;
+        dap_proc_thread_callback_add(l_ch->stream_worker->worker->proc_queue_input, s_sync_out_gdb_proc_callback, l_context);
     } else
-        l_ch_chain->sent_breaks++;
-    if (l_go_idle) {
-        s_ch_chain_go_idle(l_ch_chain);
-        if (l_ch_chain->activity_timer) {
-            if (!a_arg)
-                dap_timerfd_delete_unsafe(l_ch_chain->activity_timer);
-            l_ch_chain->activity_timer = NULL;
-        }
-        return false;
-    }
-    return true;
+        log_it(L_ERROR, "Unexpected legacy sync context state %d", l_context->state);
 }
diff --git a/modules/chain/dap_chain_ch_pkt.c b/modules/chain/dap_chain_ch_pkt.c
index 9149522a97a2856db22b24a4e0c3369518c4b6ed..e774210cf23eebb1bc0ac8e4e42c7603396dbb55 100644
--- a/modules/chain/dap_chain_ch_pkt.c
+++ b/modules/chain/dap_chain_ch_pkt.c
@@ -23,6 +23,23 @@
 
 #define LOG_TAG "dap_chain_ch_pkt"
 
+static void s_chain_pkt_fill(dap_chain_ch_pkt_t *a_pkt, dap_chain_net_id_t a_net_id,
+                             dap_chain_id_t a_chain_id, dap_chain_cell_id_t a_cell_id,
+                             const void *a_data, size_t a_data_size, uint8_t a_version)
+{
+    *a_pkt = (dap_chain_ch_pkt_t) {
+            .hdr = { .version = a_version,
+                     .data_size = a_version == DAP_CHAIN_CH_PKT_VERSION_LEGACY
+                                        ? 0
+                                        : a_data_size,
+                     .net_id = a_net_id,
+                     .cell_id = a_cell_id,
+                     .chain_id = a_chain_id }
+    };
+    if (a_data_size && a_data)
+        memcpy(a_pkt->data, a_data, a_data_size);
+}
+
 /**
  * @brief dap_stream_ch_net_pkt_write
  * @param sid
@@ -30,33 +47,36 @@
  * @param data_size
  * @return
  */
-size_t dap_chain_ch_pkt_write_unsafe(dap_stream_ch_t *a_ch, uint8_t a_type, uint64_t a_net_id,
-                                            uint64_t a_chain_id, uint64_t a_cell_id,
-                                            const void * a_data, size_t a_data_size)
+size_t dap_chain_ch_pkt_write_unsafe(dap_stream_ch_t *a_ch, uint8_t a_type,
+                                     dap_chain_net_id_t a_net_id, dap_chain_id_t a_chain_id, dap_chain_cell_id_t a_cell_id,
+                                     const void *a_data, size_t a_data_size, uint8_t a_version)
 {
-    dap_chain_ch_pkt_t *l_chain_pkt = dap_chain_ch_pkt_new(a_net_id, a_chain_id, a_cell_id, a_data, a_data_size);
-    size_t l_ret = dap_stream_ch_pkt_write_unsafe(a_ch, a_type, l_chain_pkt, dap_chain_ch_pkt_get_size(l_chain_pkt));
-    DAP_DELETE(l_chain_pkt);
+    size_t l_chain_pkt_size = sizeof(dap_chain_ch_pkt_hdr_t) + a_data_size;
+    dap_chain_ch_pkt_t *l_chain_pkt = l_chain_pkt_size > 0x3FFF
+            ? DAP_NEW_Z_SIZE(dap_chain_ch_pkt_t, l_chain_pkt_size)
+            : DAP_NEW_STACK_SIZE(dap_chain_ch_pkt_t, l_chain_pkt_size);
+
+    if (!l_chain_pkt) {
+        log_it(L_CRITICAL, "%s", g_error_memory_alloc);
+        return 0;
+    }
+    s_chain_pkt_fill(l_chain_pkt, a_net_id, a_chain_id, a_cell_id, a_data, a_data_size, a_version);
+
+    size_t l_ret = dap_stream_ch_pkt_write_unsafe(a_ch, a_type, l_chain_pkt, l_chain_pkt_size);
+    if (l_chain_pkt_size > 0x3FFF)
+        DAP_DELETE(l_chain_pkt);
     return l_ret;
 }
 
-dap_chain_ch_pkt_t *dap_chain_ch_pkt_new(uint64_t a_net_id, uint64_t a_chain_id, uint64_t a_cell_id,
-                                         const void *a_data, size_t a_data_size)
+dap_chain_ch_pkt_t *dap_chain_ch_pkt_new(dap_chain_net_id_t a_net_id, dap_chain_id_t a_chain_id, dap_chain_cell_id_t a_cell_id,
+                                         const void *a_data, size_t a_data_size, uint8_t a_version)
 {
     size_t l_chain_pkt_size = sizeof(dap_chain_ch_pkt_hdr_t) + a_data_size;
     dap_chain_ch_pkt_t *l_chain_pkt = DAP_NEW_Z_SIZE(dap_chain_ch_pkt_t, l_chain_pkt_size);
-    if (l_chain_pkt) {
-        *l_chain_pkt = (dap_chain_ch_pkt_t) {
-                .hdr = { .version = DAP_CHAIN_CH_PKT_VERSION,
-                         .data_size = a_data_size,
-                         .net_id.uint64 = a_net_id,
-                         .cell_id.uint64 = a_cell_id,
-                         .chain_id.uint64 = a_chain_id }
-        };
-        if (a_data_size && a_data)
-            memcpy(l_chain_pkt->data, a_data, a_data_size);
-    } else
-        log_it(L_CRITICAL, g_error_memory_alloc);
+    if (l_chain_pkt)
+        s_chain_pkt_fill(l_chain_pkt, a_net_id, a_chain_id, a_cell_id, a_data, a_data_size, a_version);
+    else
+        log_it(L_CRITICAL, "%s", g_error_memory_alloc);
     return l_chain_pkt;
 }
 /**
@@ -71,20 +91,20 @@ dap_chain_ch_pkt_t *dap_chain_ch_pkt_new(uint64_t a_net_id, uint64_t a_chain_id,
  * @param a_data_size
  * @return
  */
-size_t dap_chain_ch_pkt_write_mt(dap_stream_worker_t *a_worker, dap_stream_ch_uuid_t a_ch_uuid, uint8_t a_type,uint64_t a_net_id,
-                                        uint64_t a_chain_id, uint64_t a_cell_id,
-                                        const void * a_data, size_t a_data_size)
+size_t dap_chain_ch_pkt_write_mt(dap_stream_worker_t *a_worker, dap_stream_ch_uuid_t a_ch_uuid, uint8_t a_type,
+                                 dap_chain_net_id_t a_net_id, dap_chain_id_t a_chain_id, dap_chain_cell_id_t a_cell_id,
+                                 const void *a_data, size_t a_data_size, uint8_t a_version)
 {
     size_t l_chain_pkt_size = sizeof(dap_chain_ch_pkt_hdr_t) + a_data_size;
     dap_chain_ch_pkt_t *l_chain_pkt = l_chain_pkt_size > 0x3FFF
             ? DAP_NEW_Z_SIZE(dap_chain_ch_pkt_t, l_chain_pkt_size)
             : DAP_NEW_STACK_SIZE(dap_chain_ch_pkt_t, l_chain_pkt_size);
-    *l_chain_pkt = (dap_chain_ch_pkt_t){
-            .hdr = { .version = DAP_CHAIN_CH_PKT_VERSION, .net_id.uint64 = a_net_id, .cell_id.uint64 = a_cell_id, .chain_id.uint64 = a_chain_id }
-    };
 
-    if (a_data_size && a_data)
-        memcpy(l_chain_pkt->data, a_data, a_data_size);
+    if (!l_chain_pkt) {
+        log_it(L_CRITICAL, "%s", g_error_memory_alloc);
+        return 0;
+    }
+    s_chain_pkt_fill(l_chain_pkt, a_net_id, a_chain_id, a_cell_id, a_data, a_data_size, a_version);
 
     size_t l_ret = dap_stream_ch_pkt_write_mt(a_worker, a_ch_uuid, a_type, l_chain_pkt, l_chain_pkt_size);
     if (l_chain_pkt_size > 0x3FFF)
@@ -92,35 +112,6 @@ size_t dap_chain_ch_pkt_write_mt(dap_stream_worker_t *a_worker, dap_stream_ch_uu
     return l_ret;
 }
 
-size_t dap_chain_ch_pkt_write_multi_mt(dap_stream_ch_cachet_t *a_links, size_t a_count, uint8_t a_type,uint64_t a_net_id,
-                                        uint64_t a_chain_id, uint64_t a_cell_id,
-                                        const void * a_data, size_t a_data_size)
-{
-    size_t l_chain_pkt_size = sizeof(dap_chain_ch_pkt_hdr_t) + a_data_size;
-    dap_chain_ch_pkt_t *l_chain_pkt = l_chain_pkt_size > 0x3FFF
-            ? DAP_NEW_Z_SIZE(dap_chain_ch_pkt_t, l_chain_pkt_size)
-            : DAP_NEW_STACK_SIZE(dap_chain_ch_pkt_t, l_chain_pkt_size);
-    *l_chain_pkt = (dap_chain_ch_pkt_t){
-            .hdr = { .version = DAP_CHAIN_CH_PKT_VERSION, .net_id.uint64 = a_net_id, .cell_id.uint64 = a_cell_id, .chain_id.uint64 = a_chain_id }
-    };
-
-    if (a_data_size && a_data)
-        memcpy(l_chain_pkt->data, a_data, a_data_size);
-    size_t l_ret = 0, l_tmp = 0, i;
-    for (i = 0; i < a_count; ++i) {
-        l_tmp = dap_stream_ch_pkt_write_mt(a_links[i].stream_worker, a_links[i].uuid, a_type, l_chain_pkt, l_chain_pkt_size);
-        if (!l_tmp) {
-            l_ret = 0;
-            break;
-        } else {
-            l_ret += l_tmp;
-        }
-    }
-    if (l_chain_pkt_size > 0x3FFF)
-        DAP_DELETE(l_chain_pkt);
-    return l_ret;
-}
-
 /**
  * @brief Write ch chain packet into the queue input
  * @param a_es_input,
@@ -134,21 +125,13 @@ size_t dap_chain_ch_pkt_write_multi_mt(dap_stream_ch_cachet_t *a_links, size_t a
  * @param a_data_size
  * @return
  */
-size_t dap_chain_ch_pkt_write_inter(dap_events_socket_t * a_es_input, dap_stream_ch_uuid_t a_ch_uuid,
-                                           uint8_t a_type,uint64_t a_net_id,
-                                        uint64_t a_chain_id, uint64_t a_cell_id,
-                                        const void * a_data, size_t a_data_size)
+size_t dap_chain_ch_pkt_write_inter(dap_events_socket_t *a_es_input, dap_stream_ch_uuid_t a_ch_uuid, uint8_t a_type,
+                                    dap_chain_net_id_t a_net_id, dap_chain_id_t a_chain_id, dap_chain_cell_id_t a_cell_id,
+                                    const void * a_data, size_t a_data_size, uint8_t a_version)
 {
-    size_t l_chain_pkt_size = sizeof(dap_chain_ch_pkt_hdr_t) + a_data_size;
-    dap_chain_ch_pkt_t *l_chain_pkt = DAP_NEW_Z_SIZE(dap_chain_ch_pkt_t, l_chain_pkt_size );
-    *l_chain_pkt = (dap_chain_ch_pkt_t){
-            .hdr = { .version = DAP_CHAIN_CH_PKT_VERSION, .net_id.uint64 = a_net_id, .cell_id.uint64 = a_cell_id, .chain_id.uint64 = a_chain_id }
-    };
-
-    if (a_data_size && a_data)
-        memcpy(l_chain_pkt->data, a_data, a_data_size);
+    dap_chain_ch_pkt_t *l_chain_pkt = dap_chain_ch_pkt_new(a_net_id, a_chain_id, a_cell_id, a_data, a_data_size, a_version);
 
-    size_t l_ret = dap_stream_ch_pkt_write_inter(a_es_input, a_ch_uuid, a_type, l_chain_pkt, l_chain_pkt_size);
+    size_t l_ret = dap_stream_ch_pkt_write_inter(a_es_input, a_ch_uuid, a_type, l_chain_pkt, dap_chain_ch_pkt_get_size(l_chain_pkt));
     DAP_DELETE(l_chain_pkt);
     return l_ret;
 }
diff --git a/modules/chain/include/dap_chain.h b/modules/chain/include/dap_chain.h
index b7f72d944c67ecca8cc83e6095ee94915a51a29c..7f8a9f636bde85def19933419fdcd7e468293d63 100644
--- a/modules/chain/include/dap_chain.h
+++ b/modules/chain/include/dap_chain.h
@@ -29,9 +29,6 @@
 #include "dap_config.h"
 #include "dap_chain_common.h"
 #include "dap_chain_datum.h"
-#include "dap_chain_datum_tx.h"
-#include "dap_cert.h"
-#include "dap_global_db_cluster.h"
 
 typedef struct dap_chain dap_chain_t;
 
@@ -90,7 +87,7 @@ typedef enum dap_chain_iter_op {
 typedef dap_chain_t* (*dap_chain_callback_new_t)(void);
 
 typedef void (*dap_chain_callback_t)(dap_chain_t *);
-typedef int (*dap_chain_callback_new_cfg_t)(dap_chain_t*, dap_config_t *);
+typedef int (*dap_chain_callback_new_cfg_t)(dap_chain_t *, dap_config_t *);
 typedef void (*dap_chain_callback_ptr_t)(dap_chain_t *, void * );
 
 typedef dap_chain_atom_verify_res_t (*dap_chain_callback_atom_t)(dap_chain_t *, dap_chain_atom_ptr_t, size_t, dap_hash_fast_t*);
@@ -124,23 +121,18 @@ typedef void (*dap_chain_callback_notify_t)(void *a_arg, dap_chain_t *a_chain, d
 typedef uint64_t (*dap_chain_callback_get_count)(dap_chain_t *a_chain);
 typedef dap_list_t *(*dap_chain_callback_get_list)(dap_chain_t *a_chain, size_t a_count, size_t a_page, bool a_reverse);
 typedef dap_list_t *(*dap_chain_callback_get_poa_certs)(dap_chain_t *a_chain, size_t *a_auth_certs_count, uint16_t *count_verify);
-typedef void (*dap_chain_callback_set_min_validators_count)(dap_chain_t *a_chain,  uint16_t a_new_value);
-typedef uint256_t (*dap_chain_callback_get_minimum_fee)(dap_chain_t *a_chain);
-typedef uint256_t (*dap_chain_callback_get_collectiong_level)(dap_chain_t *a_chain);
-typedef dap_enc_key_t* (*dap_chain_callback_get_signing_certificate)(dap_chain_t *a_chain);
 typedef void (*dap_chain_callback_load_from_gdb)(dap_chain_t *a_chain);
 typedef uint256_t (*dap_chain_callback_calc_reward)(dap_chain_t *a_chain, dap_hash_fast_t *a_block_hash, dap_pkey_t *a_block_sign_pkey);
 
 typedef enum dap_chain_type {
-    CHAIN_TYPE_FIRST,
-    CHAIN_TYPE_TOKEN,
-    CHAIN_TYPE_EMISSION,
-    CHAIN_TYPE_TX,
-    CHAIN_TYPE_CA,
-    CHAIN_TYPE_SIGNER,
-    CHAIN_TYPE_LAST,
-    CHAIN_TYPE_DECREE,
-    CHAIN_TYPE_ANCHOR
+    CHAIN_TYPE_INVALID = -1,
+    CHAIN_TYPE_TOKEN = 1,
+    CHAIN_TYPE_EMISSION = 2,
+    CHAIN_TYPE_TX = 3,
+    CHAIN_TYPE_CA = 4,
+    CHAIN_TYPE_SIGNER = 5,
+    CHAIN_TYPE_DECREE = 7,
+    CHAIN_TYPE_ANCHOR = 8
 } dap_chain_type_t;
 
 typedef struct dap_chain {
@@ -204,10 +196,6 @@ typedef struct dap_chain {
 
     // Consensus specific callbacks
     dap_chain_callback_get_poa_certs callback_get_poa_certs;
-    dap_chain_callback_set_min_validators_count callback_set_min_validators_count;
-    dap_chain_callback_get_minimum_fee callback_get_minimum_fee;
-    dap_chain_callback_get_collectiong_level callback_get_collectiong_level;
-    dap_chain_callback_get_signing_certificate callback_get_signing_certificate;
     dap_chain_callback_calc_reward callback_calc_reward;
     dap_chain_callback_load_from_gdb callback_load_from_gdb;
 
@@ -275,5 +263,7 @@ DAP_STATIC_INLINE bool dap_chain_get_atom_last_hash(dap_chain_t *a_chain, dap_ch
 }
 ssize_t dap_chain_atom_save(dap_chain_cell_t *a_chain_cell, const uint8_t *a_atom, size_t a_atom_size, dap_hash_fast_t *a_new_atom_hash);
 int dap_cert_chain_file_save(dap_chain_datum_t *datum, char *net_name);
-const char* dap_chain_get_path(dap_chain_t *a_chain);
 
+const char *dap_chain_type_to_str(dap_chain_type_t a_chain_type);
+const char *dap_chain_get_path(dap_chain_t *a_chain);
+const char *dap_chain_get_cs_type(dap_chain_t *l_chain);
diff --git a/modules/chain/include/dap_chain_ch.h b/modules/chain/include/dap_chain_ch.h
index 9d51f6319edd336118b3ef1e375a0cf6171dbc1c..384e5ec3d9154c784f783acb6caa0b6b06122237 100644
--- a/modules/chain/include/dap_chain_ch.h
+++ b/modules/chain/include/dap_chain_ch.h
@@ -33,17 +33,19 @@
 #include "uthash.h"
 #include "dap_global_db_cluster.h"
 
-#define DAP_SYNC_TICKS_PER_SECOND           10
+#define DAP_CHAIN_CH_ID 'C'
 
 typedef enum dap_chain_ch_state {
     DAP_CHAIN_CH_STATE_IDLE = 0,
     DAP_CHAIN_CH_STATE_WAITING,
-    DAP_CHAIN_CH_STATE_UPDATE_GLOBAL_DB_REMOTE, // Downloadn GDB hashtable from remote
-    DAP_CHAIN_CH_STATE_UPDATE_GLOBAL_DB, // Update GDB hashtable to remote
-    DAP_CHAIN_CH_STATE_SYNC_GLOBAL_DB,
-    DAP_CHAIN_CH_STATE_UPDATE_CHAINS_REMOTE, // Update chains hashtable from remote
-    DAP_CHAIN_CH_STATE_UPDATE_CHAINS, // Update chains hashtable to remote
-    DAP_CHAIN_CH_STATE_SYNC_CHAINS,
+    DAP_CHAIN_CH_STATE_UPDATE_GLOBAL_DB_REMOTE, // Download GDB hashtable from remote
+    DAP_CHAIN_CH_STATE_UPDATE_GLOBAL_DB,        // Upload GDB hashtable to remote
+    DAP_CHAIN_CH_STATE_SYNC_GLOBAL_DB_REMOTE,   // Download GDB records from remote
+    DAP_CHAIN_CH_STATE_SYNC_GLOBAL_DB,          // Upload GDB records to remote
+    DAP_CHAIN_CH_STATE_UPDATE_CHAINS_REMOTE,    // Download chains hashtable from remote
+    DAP_CHAIN_CH_STATE_UPDATE_CHAINS,           // Upload chains hashtable to remote
+    DAP_CHAIN_CH_STATE_SYNC_CHAINS_REMOTE,      // Download chains atoms from remote
+    DAP_CHAIN_CH_STATE_SYNC_CHAINS,             // Upload chains atoms from remote
     DAP_CHAIN_CH_STATE_ERROR
 } dap_chain_ch_state_t;
 
@@ -56,62 +58,15 @@ typedef enum dap_chain_ch_error_type {
     DAP_CHAIN_CH_ERROR_CHAIN_NOT_FOUND,
     DAP_CHAIN_CH_ERROR_ATOM_NOT_FOUND,
     DAP_CHAIN_CH_ERROR_UNKNOWN_CHAIN_PKT_TYPE,
-    DAP_CHAIN_CH_ERROR_GLOBAL_DB_INTERNAL_NOT_SAVED,
     DAP_CHAIN_CH_ERROR_NET_IS_OFFLINE,
     DAP_CHAIN_CH_ERROR_OUT_OF_MEMORY,
-    DAP_CHAIN_CH_ERROR_INTERNAL
+    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_type_t;
 
-typedef struct dap_chain_ch dap_chain_ch_t;
-typedef void (*dap_chain_ch_callback_packet_t)(dap_chain_ch_t*, uint8_t a_pkt_type,
-                                                      dap_chain_ch_pkt_t *a_pkt, size_t a_pkt_data_size,
-                                                      void * a_arg);
-typedef struct dap_chain_pkt_item {
-    uint64_t pkt_data_size;
-    byte_t *pkt_data;
-} dap_chain_pkt_item_t;
-
-typedef struct dap_chain_ch_hash_item {
-    dap_hash_fast_t hash;
-    uint32_t size;
-    UT_hash_handle hh;
-} dap_chain_ch_hash_item_t;
-
-
-typedef struct dap_chain_ch {
-    void *_inheritor;
-    dap_timerfd_t *sync_timer;
-    void *sync_context;
-
-    // Legacy section //
-    int state;
-
-    uint64_t stats_request_atoms_processed;
-    uint64_t stats_request_gdb_processed;
-
-    dap_chain_ch_hash_item_t * remote_atoms; // Remote atoms
-    dap_chain_ch_hash_item_t * remote_gdbs; // Remote gdbs
-
-    // request section
-    dap_chain_atom_iter_t *request_atom_iter;
-    //dap_db_log_list_t *request_db_log; // list of global db records
-    dap_chain_ch_sync_request_old_t request;
-    dap_chain_ch_pkt_hdr_t request_hdr;
-    dap_list_t *request_db_iter;
-
-    uint32_t timer_shots;
-    dap_timerfd_t *activity_timer;
-    int sent_breaks;
-} dap_chain_ch_t;
-
-#define DAP_CHAIN_CH(a) ((dap_chain_ch_t *) ((a)->internal) )
-#define DAP_STREAM_CH(a) ((dap_stream_ch_t *)((a)->_inheritor))
-#define DAP_CHAIN_PKT_EXPECT_SIZE 7168
-#define DAP_CHAIN_CH_ID 'C'
-
 int dap_chain_ch_init(void);
 void dap_chain_ch_deinit(void);
 
-void dap_chain_ch_timer_start(dap_chain_ch_t *a_ch_chain);
-
-void dap_stream_ch_write_error_unsafe(dap_stream_ch_t *a_ch, uint64_t a_net_id, uint64_t a_chain_id, uint64_t a_cell_id, dap_chain_ch_error_type_t a_error);
+void dap_stream_ch_write_error_unsafe(dap_stream_ch_t *a_ch, dap_chain_net_id_t a_net_id, dap_chain_id_t a_chain_id, dap_chain_cell_id_t a_cell_id, dap_chain_ch_error_type_t a_error);
diff --git a/modules/chain/include/dap_chain_ch_pkt.h b/modules/chain/include/dap_chain_ch_pkt.h
index 0c721f1408379a5972fdf7138514607b9574cacc..67b0465d74251d973c672143f6d2cba1d607a093 100644
--- a/modules/chain/include/dap_chain_ch_pkt.h
+++ b/modules/chain/include/dap_chain_ch_pkt.h
@@ -36,16 +36,10 @@
 
 #include "dap_stream_ch.h"
 
-#define DAP_CHAIN_CH_PKT_VERSION                        0x02
+#define DAP_CHAIN_CH_PKT_VERSION_LEGACY                 0x01
+#define DAP_CHAIN_CH_PKT_VERSION_CURRENT                0x02
 
 //Legacy
-#define DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_REQ         0x05
-#define DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_START       0x25
-#define DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS             0x35
-#define DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_END         0x45
-#define DAP_CHAIN_CH_PKT_TYPE_FIRST_CHAIN               0x20
-#define DAP_CHAIN_CH_PKT_TYPE_SYNCED_CHAINS             0x03
-
 #define DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_REQ      0x06
 #define DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_START    0x26
 #define DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB          0x36
@@ -54,31 +48,30 @@
 #define DAP_CHAIN_CH_PKT_TYPE_GLOBAL_DB                 0x11
 #define DAP_CHAIN_CH_PKT_TYPE_SYNCED_GLOBAL_DB          0x13
 
-#define DAP_CHAIN_CH_PKT_TYPE_DELETE                    0xda
-#define DAP_CHAIN_CH_PKT_TYPE_TIMEOUT                   0xfe
-#define DAP_CHAIN_CH_PKT_TYPE_ERROR                     0xff
+#define DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_REQ         0x05
+#define DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_START       0x25
+#define DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS             0x35
+#define DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_END         0x45
+#define DAP_CHAIN_CH_PKT_TYPE_FIRST_CHAIN               0x20
+#define DAP_CHAIN_CH_PKT_TYPE_CHAIN_OLD                 0x01
+#define DAP_CHAIN_CH_PKT_TYPE_SYNCED_CHAINS             0x03
+
+// Freeze detectors
+#define DAP_CHAIN_CH_PKT_TYPE_CHAINS_NO_FREEZE          0x15
+#define DAP_CHAIN_CH_PKT_TYPE_GLOBAL_DB_NO_FREEZE       0x16
 
 // Stable
 #define DAP_CHAIN_CH_PKT_TYPE_CHAIN_REQ                 0x80
 #define DAP_CHAIN_CH_PKT_TYPE_CHAIN_MISS                0x69
-#define DAP_CHAIN_CH_PKT_TYPE_CHAIN                     0x01
+#define DAP_CHAIN_CH_PKT_TYPE_CHAIN                     0x84
 #define DAP_CHAIN_CH_PKT_TYPE_CHAIN_SUMMARY             0x81
 #define DAP_CHAIN_CH_PKT_TYPE_CHAIN_ACK                 0x82
 #define DAP_CHAIN_CH_PKT_TYPE_SYNCED_CHAIN              0x88
-
-// TSD sections
-#define DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_TSD         0x15
-#define DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_TSD      0x16
-
-#define DAP_CHAIN_CH_PKT_TYPE_UPDATE_TSD_PROTO        0x0001   // Protocol version
-#define DAP_CHAIN_CH_PKT_TYPE_UPDATE_TSD_COUNT        0x0002   // Items count
-#define DAP_CHAIN_CH_PKT_TYPE_UPDATE_TSD_HASH_LAST    0x0003   // Hash of last(s) item
-#define DAP_CHAIN_CH_PKT_TYPE_UPDATE_TSD_HASH_FIRST   0x0004   // Hash of first(s) item
-#define DAP_CHAIN_CH_PKT_TYPE_UPDATE_TSD_LAST_ID      0x0100   // Last ID of GDB synced group
+#define DAP_CHAIN_CH_PKT_TYPE_ERROR                     0xff
 
 // *** Legacy *** //
 
-typedef struct dap_chain_ch_update_element{
+typedef struct dap_chain_ch_update_element {
     dap_hash_fast_t hash;
     uint32_t size;
 } DAP_ALIGN_PACKED dap_chain_ch_update_element_t;
@@ -86,17 +79,39 @@ typedef struct dap_chain_ch_update_element{
 typedef struct dap_chain_ch_sync_request_old {
     dap_chain_node_addr_t node_addr; // Requesting node's address
     dap_chain_hash_fast_t hash_from;
-    byte_t unused[96];
+    byte_t unused[48];
 } DAP_ALIGN_PACKED dap_chain_ch_sync_request_old_t;
 
-static const char* c_dap_chain_ch_pkt_type_str[]={
-    [DAP_CHAIN_CH_PKT_TYPE_CHAIN] = "DAP_CHAIN_CH_PKT_TYPE_CHAIN",
-    [DAP_CHAIN_CH_PKT_TYPE_GLOBAL_DB] = "DAP_CHAIN_CH_PKT_TYPE_GLOBAL_DB",
-    [DAP_CHAIN_CH_PKT_TYPE_SYNCED_CHAINS] = "DAP_CHAIN_CH_PKT_TYPE_SYNCED_CHAINS",
-    [DAP_CHAIN_CH_PKT_TYPE_SYNCED_GLOBAL_DB] = "DAP_CHAIN_CH_PKT_TYPE_SYNCED_GLOBAL_DB",
-    [DAP_CHAIN_CH_PKT_TYPE_ERROR] = "DAP_CHAIN_CH_PKT_TYPE_ERROR"
-
-};
+DAP_STATIC_INLINE const char *dap_chain_ch_pkt_type_to_str(uint8_t a_pkt_type)
+{
+    switch (a_pkt_type) {
+    case DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_REQ: return "DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_REQ";
+    case DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_START: return "DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_START";
+    case DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB: return "DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB";
+    case DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_END: return "DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_END";
+    case DAP_CHAIN_CH_PKT_TYPE_FIRST_GLOBAL_DB: return "DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_END";
+    case DAP_CHAIN_CH_PKT_TYPE_GLOBAL_DB: return "DAP_CHAIN_CH_PKT_TYPE_GLOBAL_DB";
+    case DAP_CHAIN_CH_PKT_TYPE_SYNCED_GLOBAL_DB: return "DAP_CHAIN_CH_PKT_TYPE_SYNCED_GLOBAL_DB";
+
+    case DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_REQ: return "DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_REQ";
+    case DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_START: return "DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_START";
+    case DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS: return "DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS";
+    case DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_END: return "DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_END";
+    case DAP_CHAIN_CH_PKT_TYPE_FIRST_CHAIN: return "DAP_CHAIN_CH_PKT_TYPE_FIRST_CHAIN";
+    case DAP_CHAIN_CH_PKT_TYPE_CHAIN_OLD: return "DAP_CHAIN_CH_PKT_TYPE_CHAIN_OLD";
+    case DAP_CHAIN_CH_PKT_TYPE_SYNCED_CHAINS: return "DAP_CHAIN_CH_PKT_TYPE_SYNCED_CHAINS";
+
+    case DAP_CHAIN_CH_PKT_TYPE_CHAIN_REQ: return "DAP_CHAIN_CH_PKT_TYPE_CHAIN_REQ";
+    case DAP_CHAIN_CH_PKT_TYPE_CHAIN_MISS: return "DAP_CHAIN_CH_PKT_TYPE_CHAIN_MISS";
+    case DAP_CHAIN_CH_PKT_TYPE_CHAIN: return "DAP_CHAIN_CH_PKT_TYPE_CHAIN";
+    case DAP_CHAIN_CH_PKT_TYPE_CHAIN_SUMMARY: return "DAP_CHAIN_CH_PKT_TYPE_CHAIN_SUMMARY";
+    case DAP_CHAIN_CH_PKT_TYPE_CHAIN_ACK: return "DAP_CHAIN_CH_PKT_TYPE_CHAIN_ACK";
+    case DAP_CHAIN_CH_PKT_TYPE_SYNCED_CHAIN: return "DAP_CHAIN_CH_PKT_TYPE_SYNCED_CHAIN";
+
+    case DAP_CHAIN_CH_PKT_TYPE_ERROR: return "DAP_CHAIN_CH_PKT_TYPE_ERROR";
+    default: return "DAP_CHAIN_CH_PKT_TYPE_UNKNOWN";
+    }
+}
 
 // *** Active *** //
 
@@ -134,80 +149,17 @@ typedef struct dap_chain_ch_pkt {
 
 DAP_STATIC_INLINE size_t dap_chain_ch_pkt_get_size(dap_chain_ch_pkt_t *a_pkt) { return sizeof(dap_chain_ch_pkt_hdr_t) + a_pkt->hdr.data_size; }
 
-dap_chain_ch_pkt_t *dap_chain_ch_pkt_new(uint64_t a_net_id, uint64_t a_chain_id, uint64_t a_cell_id,
-                                         const void *a_data, size_t a_data_size);
-
-size_t dap_chain_ch_pkt_write_unsafe(dap_stream_ch_t *a_ch, uint8_t a_type, uint64_t a_net_id,
-                                            uint64_t a_chain_id, uint64_t a_cell_id,
-                                            const void * a_data, size_t a_data_size);
-
-size_t dap_chain_ch_pkt_write_mt(dap_stream_worker_t *a_worker, dap_stream_ch_uuid_t a_ch_uuid, uint8_t a_type, uint64_t a_net_id,
-                                        uint64_t a_chain_id, uint64_t a_cell_id,
-                                        const void * a_data, size_t a_data_size);
-
-size_t dap_chain_ch_pkt_write_multi_mt(dap_stream_ch_cachet_t *a_links, size_t a_count, uint8_t a_type, uint64_t a_net_id,
-                                        uint64_t a_chain_id, uint64_t a_cell_id,
-                                        const void * a_data, size_t a_data_size);
-
-size_t dap_chain_ch_pkt_write_inter(dap_events_socket_t * a_es_input, dap_stream_ch_uuid_t a_ch_uuid, uint8_t a_type,uint64_t a_net_id,
-                                        uint64_t a_chain_id, uint64_t a_cell_id,
-                                        const void * a_data, size_t a_data_size);
-
-/**
- * @brief dap_chain_ch_pkt_write_error_unsafe
- * @param a_ch
- * @param a_net_id
- * @param a_chain_id
- * @param a_cell_id
- * @param a_err_string_format
- * @return
- */
-inline static DAP_PRINTF_ATTR(5, 6) size_t dap_chain_ch_pkt_write_error_unsafe(dap_stream_ch_t *a_ch, uint64_t a_net_id,
-                                                  uint64_t a_chain_id, uint64_t a_cell_id, const char *a_err_string_format, ...)
-{
-    va_list l_va;
-    char *l_str;
-    va_start(l_va, a_err_string_format);
-    int l_size = vsnprintf(NULL,0,a_err_string_format,l_va);
-    va_end(l_va);
-    if (l_size > 0) {
-        l_size++;
-        l_str = DAP_NEW_STACK_SIZE(char, l_size);
-        va_start(l_va, a_err_string_format);
-        vsnprintf(l_str, l_size,a_err_string_format, l_va);
-        va_end(l_va);
-        return dap_chain_ch_pkt_write_unsafe(a_ch, DAP_CHAIN_CH_PKT_TYPE_ERROR,
-                                                    a_net_id, a_chain_id, a_cell_id, l_str, l_size);
-    }
-    return 0;
-}
+dap_chain_ch_pkt_t *dap_chain_ch_pkt_new(dap_chain_net_id_t a_net_id, dap_chain_id_t a_chain_id, dap_chain_cell_id_t a_cell_id,
+                                         const void *a_data, size_t a_data_size, uint8_t a_version);
 
-/**
- * @brief dap_chain_ch_pkt_write_error_inter
- * @param a_es_input
- * @param a_ch
- * @param a_net_id
- * @param a_chain_id
- * @param a_cell_id
- * @param a_err_string_format
- * @return
- */
-static inline size_t dap_chain_ch_pkt_write_error_inter(dap_events_socket_t *a_es_input,  dap_stream_ch_uuid_t a_ch_uuid,
-                                                               uint64_t a_net_id, uint64_t a_chain_id, uint64_t a_cell_id, const char *a_err_string_format, ...)
-{
-    va_list l_va;
-    char *l_str;
-    va_start(l_va, a_err_string_format);
-    int l_size = vsnprintf(NULL, 0, a_err_string_format, l_va);
-    va_end(l_va);
-    if (l_size > 0) {
-        l_size++;
-        l_str = DAP_NEW_STACK_SIZE(char, l_size);
-        va_start(l_va, a_err_string_format);
-        vsnprintf(l_str, l_size, a_err_string_format, l_va);
-        va_end(l_va);
-        return dap_chain_ch_pkt_write_inter(a_es_input, a_ch_uuid, DAP_CHAIN_CH_PKT_TYPE_ERROR,
-                                                    a_net_id, a_chain_id, a_cell_id, l_str, l_size);
-    }
-    return 0;
-}
+size_t dap_chain_ch_pkt_write_unsafe(dap_stream_ch_t *a_ch, uint8_t a_type,
+                                     dap_chain_net_id_t a_net_id, dap_chain_id_t a_chain_id, dap_chain_cell_id_t a_cell_id,
+                                     const void *a_data, size_t a_data_size, uint8_t a_version);
+
+size_t dap_chain_ch_pkt_write_mt(dap_stream_worker_t *a_worker, dap_stream_ch_uuid_t a_ch_uuid, uint8_t a_type,
+                                 dap_chain_net_id_t a_net_id, dap_chain_id_t a_chain_id, dap_chain_cell_id_t a_cell_id,
+                                 const void *a_data, size_t a_data_size, uint8_t a_version);
+
+size_t dap_chain_ch_pkt_write_inter(dap_events_socket_t *a_es_input, dap_stream_ch_uuid_t a_ch_uuid, uint8_t a_type,
+                                    dap_chain_net_id_t a_net_id, dap_chain_id_t a_chain_id, dap_chain_cell_id_t a_cell_id,
+                                    const void *a_data, size_t a_data_size, uint8_t a_version);
diff --git a/modules/chain/tests/dap_chain_ledger_tests.c b/modules/chain/tests/dap_chain_ledger_tests.c
index 455fe7a1ab1366be6c027d76434727bf9543d0cc..61250d2c2ee38a7f09bfe055866b61b7ec7e8b5c 100644
--- a/modules/chain/tests/dap_chain_ledger_tests.c
+++ b/modules/chain/tests/dap_chain_ledger_tests.c
@@ -24,7 +24,7 @@ dap_chain_datum_token_t  *dap_ledger_test_create_datum_decl(dap_cert_t *a_cert,
     l_token->version = 2;
     l_token->type = DAP_CHAIN_DATUM_TOKEN_TYPE_DECL;
     l_token->subtype = DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE;
-    dap_snprintf(l_token->ticker, sizeof(l_token->ticker), "%s", a_token_ticker);
+    snprintf(l_token->ticker, sizeof(l_token->ticker), "%s", a_token_ticker);
     l_token->signs_valid = 1;
     l_token->total_supply = a_total_supply;
     l_token->header_native_decl.decimals = 18;
@@ -798,7 +798,7 @@ void dap_ledger_test_run(void){
     dap_chain_net_srv_stake_pos_delegate_init();
     dap_assert_PIF(!dap_chain_net_srv_init(), "Srv initializstion");
     dap_chain_net_id_t l_iddn = {0};
-    dap_sscanf("0xFA0", "0x%16"DAP_UINT64_FORMAT_x, &l_iddn.uint64);
+    sscanf("0xFA0", "0x%16"DAP_UINT64_FORMAT_x, &l_iddn.uint64);
     dap_print_module_name("dap_ledger");
     uint16_t l_flags = 0;
     l_flags |= DAP_LEDGER_CHECK_TOKEN_EMISSION;
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 b23a4e5e1cb25d00cb37b8971b40917d4167d043..39441608440095821083be8f57969a1f4667e75f 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
@@ -826,7 +826,7 @@ void s_set_usage_data_to_gdb(const dap_chain_net_srv_usage_t *a_usage)
     client_statistic_value_t l_bin_value_new = {0};
     size_t l_value_size = 0;
     // forming key
-    dap_sprintf(l_bin_key.key, "0x%016"DAP_UINT64_FORMAT_X"", a_usage->service->uid.uint64);
+    sprintf(l_bin_key.key, "0x%016"DAP_UINT64_FORMAT_X"", a_usage->service->uid.uint64);
     dap_chain_hash_fast_to_str_do(&a_usage->client_pkey_hash, l_bin_key.key + 18);
     // check writed value
     client_statistic_value_t *l_bin_value = (client_statistic_value_t *)dap_global_db_get_sync(SRV_STATISTIC_GDB_GROUP, l_bin_key.key, &l_value_size, NULL, NULL);
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 23d3aaac5a2808a68dec9aac455be73aba851857..448a1e0a8dec601490c9089bd47243de23228037 100644
--- a/modules/channel/chain-net/dap_stream_ch_chain_net.c
+++ b/modules/channel/chain-net/dap_stream_ch_chain_net.c
@@ -43,10 +43,8 @@
 
 #include "dap_common.h"
 #include "dap_strfuncs.h"
-#include "dap_cert.h"
-#include "uthash.h"
-#include "dap_http_client.h"
-#include "dap_global_db.h"
+#include "dap_chain_cs_esbocs.h"
+#include "dap_chain_net_srv_order.h"
 #include "dap_stream.h"
 #include "dap_stream_ch_pkt.h"
 #include "dap_stream_ch_proc.h"
@@ -207,12 +205,12 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t *a_ch, void* a_arg)
                 log_it(L_ERROR, "Invalid net id in packet");
             } else {
                 dap_list_t * l_orders = NULL;
-                dap_enc_key_t * enc_key_pvt = NULL;
+                dap_enc_key_t *l_enc_key_pvt = NULL;
                 dap_chain_t *l_chain = NULL;
                 DL_FOREACH(l_net->pub.chains, l_chain)
-                    if(l_chain->callback_get_signing_certificate != NULL){
-                        enc_key_pvt = l_chain->callback_get_signing_certificate(l_chain);
-                        if(enc_key_pvt)
+                    if (!dap_strcmp(dap_chain_get_cs_type(l_chain), "esbocs")) {
+                        l_enc_key_pvt = dap_chain_esbocs_get_sign_key(l_chain);
+                        if (l_enc_key_pvt)
                             break;
                     }
                 dap_sign_t *l_sign = NULL;
@@ -228,10 +226,9 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t *a_ch, void* a_arg)
                     .uint64 = dap_chain_net_get_cur_addr_int(l_net)
                 };
 
-                if(enc_key_pvt)
-                {
+                if (l_enc_key_pvt) {
                     flags = flags | F_CERT;//faund sert
-                    l_sign = dap_sign_create(enc_key_pvt, (uint8_t*)l_ch_chain_net_pkt->data,
+                    l_sign = dap_sign_create(l_enc_key_pvt, (uint8_t*)l_ch_chain_net_pkt->data,
                                            l_ch_chain_net_pkt->hdr.data_size, 0);
                     if(l_sign)
                     {
diff --git a/modules/common/dap_chain_common.c b/modules/common/dap_chain_common.c
index 1968c12792f1fbdc230738092bcc502dc7448c52..d3351160e6efa6f17901f12e2932c1f401617029 100644
--- a/modules/common/dap_chain_common.c
+++ b/modules/common/dap_chain_common.c
@@ -52,14 +52,15 @@ size_t dap_chain_hash_slow_to_str( dap_chain_hash_slow_t *a_hash, char *a_str, s
 {
     const size_t c_hash_str_size = sizeof(*a_hash) * 2 + 1 /*trailing zero*/+ 2 /* heading 0x */;
 
-    if(a_str_max < c_hash_str_size) {
+    if (a_str_max < c_hash_str_size) {
         log_it(L_ERROR, "String for hash too small, need %zu but have only %zu", c_hash_str_size, a_str_max);
+        return 0;
     }
     size_t i;
-    snprintf(a_str, 3, "0x");
+    sprintf(a_str, "0x");
 
-    for(i = 0; i < sizeof(a_hash->raw); ++i)
-        snprintf( a_str + i * 2 + 2, 3, "%02x", a_hash->raw[i] );
+    for (i = 0; i < sizeof(a_hash->raw); ++i)
+        sprintf( a_str + i * 2 + 2, "%02x", a_hash->raw[i] );
 
     a_str[c_hash_str_size] = '\0';
 
@@ -71,10 +72,11 @@ size_t dap_chain_hash_slow_to_str( dap_chain_hash_slow_t *a_hash, char *a_str, s
  * @param a_addr
  * @return
  */
-char *dap_chain_addr_to_str(const dap_chain_addr_t *a_addr)
+const char *dap_chain_addr_to_str(const dap_chain_addr_t *a_addr)
 {
     dap_return_val_if_pass(!a_addr, NULL);
-    dap_return_val_if_pass(dap_chain_addr_is_blank(a_addr), "null");
+    if (dap_chain_addr_is_blank(a_addr))
+        return "null";
     static _Thread_local char s_buf[DAP_ENC_BASE58_ENCODE_SIZE(sizeof(dap_chain_addr_t))] = { '\0' };
     return dap_enc_base58_encode(a_addr, sizeof(dap_chain_addr_t), s_buf) ? s_buf : NULL;
 }
diff --git a/modules/common/dap_chain_datum.c b/modules/common/dap_chain_datum.c
index b1f7aec824abdaf6728ddc5366cafa4c64ce961d..54d06bfa0397b406e8e4218dc983abe0def4087f 100644
--- a/modules/common/dap_chain_datum.c
+++ b/modules/common/dap_chain_datum.c
@@ -34,6 +34,7 @@
 #include "dap_chain_datum_tx_voting.h"
 #include "dap_chain_datum_hashtree_roots.h"
 #include "dap_enc_base58.h"
+#include "dap_sign.h"
 
 #define LOG_TAG "dap_chain_datum"
 
@@ -161,7 +162,7 @@ void dap_chain_datum_token_dump_tsd(dap_string_t *a_str_out, dap_chain_datum_tok
             continue;
             case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DELEGATE_EMISSION_FROM_STAKE_LOCK: {
                 dap_chain_datum_token_tsd_delegate_from_stake_lock_t *l_tsd_section = _dap_tsd_get_object(l_tsd, dap_chain_datum_token_tsd_delegate_from_stake_lock_t);
-                char *l_balance, *l_tmp = dap_uint256_to_char(l_tsd_section->emission_rate, &l_balance);
+                const char *l_balance, *l_tmp = dap_uint256_to_char(l_tsd_section->emission_rate, &l_balance);
                 dap_string_append_printf(a_str_out, "ticker_token_from: %s\nemission_rate: %s\n",
                                          l_tsd_section->ticker_token_from, l_balance);
             }continue;
@@ -369,7 +370,7 @@ void dap_datum_token_dump_tsd_to_json(json_object * json_obj_out, dap_chain_datu
             continue;
         default: {
                 char l_tsd_type_char[50] = {};
-                dap_snprintf(l_tsd_type_char, 50, "<0x%04hX>", l_tsd->type);
+                snprintf(l_tsd_type_char, 50, "<0x%04hX>", l_tsd->type);
                 json_object_object_add(json_obj_out, "tsd_type", json_object_new_string(l_tsd_type_char));
                 json_object_object_add(json_obj_out, "tsd_size", json_object_new_int(l_tsd->size));
             }
@@ -429,7 +430,7 @@ bool dap_chain_datum_dump_tx(dap_chain_datum_tx_t *a_datum,
                                         ((dap_chain_tx_in_t*)item)->header.tx_out_prev_idx);
             break;
         case TX_ITEM_TYPE_OUT_OLD: {
-            char *l_value_str = dap_uint256_to_char(
+            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"
@@ -439,7 +440,7 @@ bool dap_chain_datum_dump_tx(dap_chain_datum_tx_t *a_datum,
                                         dap_chain_addr_to_str(&((dap_chain_tx_out_old_t*)item)->addr));
         } break;
         case TX_ITEM_TYPE_OUT: { // 256
-            char    *l_coins_str,
+            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(&((dap_chain_tx_out_t*)item)->addr);
             dap_string_append_printf(a_str_out, "\t OUT:\n"
@@ -502,7 +503,7 @@ bool dap_chain_datum_dump_tx(dap_chain_datum_tx_t *a_datum,
             dap_string_append_printf(a_str_out, "\tSender addr: %s\n", dap_chain_addr_to_str(&l_sender_addr));
         } break;
         case TX_ITEM_TYPE_RECEIPT: {
-            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);
+            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"
@@ -575,7 +576,7 @@ bool dap_chain_datum_dump_tx(dap_chain_datum_tx_t *a_datum,
                                      ((dap_chain_tx_in_cond_t*)item)->header.tx_out_prev_idx);
             break;
         case TX_ITEM_TYPE_OUT_COND: {
-            char *l_coins_str, *l_value_str = dap_uint256_to_char(((dap_chain_tx_out_cond_t*)item)->header.value, &l_coins_str);
+            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"
@@ -589,7 +590,7 @@ bool dap_chain_datum_dump_tx(dap_chain_datum_tx_t *a_datum,
                                      ((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: {
-                    char *l_coins_str, *l_value_str =
+                    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")
@@ -618,7 +619,7 @@ bool dap_chain_datum_dump_tx(dap_chain_datum_tx_t *a_datum,
                                                         NODE_ADDR_FP_ARGS(l_signer_node_addr));
                 } break;
                 case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE: {
-                    char *l_rate_str, *l_tmp_str =
+                    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"
@@ -636,7 +637,7 @@ bool dap_chain_datum_dump_tx(dap_chain_datum_tx_t *a_datum,
             }
         } break;
         case TX_ITEM_TYPE_OUT_EXT: {
-            char *l_coins_str, *l_value_str = dap_uint256_to_char( ((dap_chain_tx_out_ext_t*)item)->header.value, &l_coins_str );
+            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"
@@ -698,6 +699,320 @@ bool dap_chain_datum_dump_tx(dap_chain_datum_tx_t *a_datum,
     return true;
 }
 
+/**
+ * @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_json(dap_chain_datum_tx_t *a_datum,
+                             const char *a_ticker,
+                             json_object* json_obj_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, 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);
+    json_object* json_arr_items = json_object_new_array();
+    dap_time_to_str_rfc822(l_tmp_buf, DAP_TIME_STR_SIZE, a_datum->header.ts_created);
+    l_is_first ? 
+    json_object_object_add(json_obj_out, "first transaction", json_object_new_string("emit")):
+    json_object_object_add(json_obj_out, "first transaction", json_object_new_string(""));
+    json_object_object_add(json_obj_out, "hash", json_object_new_string(l_hash_str));
+    json_object_object_add(json_obj_out, "TS Created", json_object_new_string(l_tmp_buf));
+    json_object_object_add(json_obj_out, "Token ticker", a_ticker ? json_object_new_string(a_ticker) : json_object_new_string(""));
+    //json_object_array_add(json_arr_items, json_obj_tx);
+    
+    uint32_t l_tx_items_count = 0;
+    uint32_t l_tx_items_size = a_datum->header.tx_items_size;
+    dap_hash_fast_t *l_hash_tmp = NULL;
+    while (l_tx_items_count < l_tx_items_size) {
+        json_object* json_obj_item = json_object_new_object();
+        uint8_t *item = a_datum->tx_items + l_tx_items_count;
+        size_t l_item_tx_size = dap_chain_datum_item_tx_get_size(item);
+        switch(dap_chain_datum_tx_item_get_type(item)){
+        case TX_ITEM_TYPE_IN:
+            l_hash_tmp = &((dap_chain_tx_in_t*)item)->header.tx_prev_hash;
+            if (dap_hash_fast_is_blank(l_hash_tmp)) {
+                l_hash_str = "BLANK";
+            } else {
+                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,"item type", json_object_new_string("IN"));
+            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_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 );
+            json_object_object_add(json_obj_item,"item type", json_object_new_string("OUT OLD"));
+            json_object_object_add(json_obj_item,"Value", json_object_new_uint64(((dap_chain_tx_out_old_t*)item)->header.value));
+            json_object_object_add(json_obj_item,"Address", json_object_new_string(dap_chain_addr_to_str(&((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(&((dap_chain_tx_out_t*)item)->addr);
+            json_object_object_add(json_obj_item,"item type", json_object_new_string("OUT"));
+            json_object_object_add(json_obj_item,"Coins", json_object_new_string(l_coins_str));
+            json_object_object_add(json_obj_item,"Value", json_object_new_string(l_value_str));
+            json_object_object_add(json_obj_item,"Address", json_object_new_string(l_addr_str));            
+        } break;
+        case TX_ITEM_TYPE_IN_EMS: {
+            char l_tmp_buff[70]={0};
+            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);
+            json_object_object_add(json_obj_item,"item type", json_object_new_string("IN_EMS"));
+            json_object_object_add(json_obj_item,"ticker", json_object_new_string(((dap_chain_tx_in_ems_t*)item)->header.ticker));
+            json_object_object_add(json_obj_item,"token_emission_hash", json_object_new_string(l_hash_str));
+            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;
+            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,"item type", json_object_new_string("IN_REWARD"));
+            json_object_object_add(json_obj_item,"block_hash", json_object_new_string(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);
+            json_object_object_add(json_obj_item,"item type", json_object_new_string("SIG"));
+            dap_sign_get_information_json(l_sign, json_obj_item, 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);
+            json_object_object_add(json_obj_item,"Sender addr", json_object_new_string(dap_chain_addr_to_str(&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);
+            json_object_object_add(json_obj_item,"item type", json_object_new_string("RECEIPT"));
+            json_object_object_add(json_obj_item,"size", json_object_new_uint64(((dap_chain_datum_tx_receipt_t*)item)->size));
+            json_object_object_add(json_obj_item,"ext size", json_object_new_uint64(((dap_chain_datum_tx_receipt_t*)item)->exts_size));
+            json_object_object_add(json_obj_item,"INFO", json_object_new_string(""));
+            json_object_object_add(json_obj_item,"units", json_object_new_uint64(((dap_chain_datum_tx_receipt_t*)item)->receipt_info.units));
+            json_object_object_add(json_obj_item,"uid", json_object_new_uint64(((dap_chain_datum_tx_receipt_t*)item)->receipt_info.srv_uid.uint64));
+            json_object_object_add(json_obj_item,"units type", json_object_new_string(dap_chain_srv_unit_enum_to_str(((dap_chain_datum_tx_receipt_t*)item)->receipt_info.units_type.enm)));
+            json_object_object_add(json_obj_item,"coins", json_object_new_string(l_coins_str));
+            json_object_object_add(json_obj_item,"value", json_object_new_string(l_value_str));
+
+            json_object_object_add(json_obj_item,"Exts",json_object_new_string(""));                         
+            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) );
+                json_object_object_add(json_obj_item,"Client", json_object_new_string(""));
+                dap_sign_get_information_json(l_client, json_obj_item, 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 );
+                json_object_object_add(json_obj_item,"Provider", json_object_new_string(""));
+                dap_sign_get_information_json(l_provider,json_obj_item, 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);
+            json_object_object_add(json_obj_item,"item type", json_object_new_string("PKey"));
+            json_object_object_add(json_obj_item,"PKey", json_object_new_string(""));
+            json_object_object_add(json_obj_item,"SIG type", json_object_new_string(dap_sign_type_to_str(((dap_chain_tx_pkey_t*)item)->header.sig_type)));
+            json_object_object_add(json_obj_item,"SIG size", json_object_new_uint64(((dap_chain_tx_pkey_t*)item)->header.sig_size));
+            json_object_object_add(json_obj_item,"Sequence number", json_object_new_uint64(((dap_chain_tx_pkey_t*)item)->seq_no));
+            json_object_object_add(json_obj_item,"Key", json_object_new_string(""));
+            json_object_object_add(json_obj_item,"Type", json_object_new_string(dap_pkey_type_to_str(l_pkey->header.type)));
+            json_object_object_add(json_obj_item,"Size", json_object_new_uint64(l_pkey->header.size));
+            json_object_object_add(json_obj_item,"Hash", json_object_new_string(l_hash_str));
+
+        } break;
+        case TX_ITEM_TYPE_TSD: {
+            json_object_object_add(json_obj_item,"item type", json_object_new_string("TSD data"));
+            json_object_object_add(json_obj_item,"type", json_object_new_uint64(((dap_chain_tx_tsd_t*)item)->header.type));
+            json_object_object_add(json_obj_item,"size", json_object_new_uint64(((dap_chain_tx_tsd_t*)item)->header.size));            
+        } break;
+        case TX_ITEM_TYPE_IN_COND:
+            json_object_object_add(json_obj_item,"item type", json_object_new_string("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);
+            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,"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;
+        case TX_ITEM_TYPE_OUT_COND: {
+            char l_tmp_buff[70]={0};
+            json_object_object_add(json_obj_item,"item type", json_object_new_string("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);
+            json_object_object_add(json_obj_item,"Header", json_object_new_string(""));
+            json_object_object_add(json_obj_item,"ts_expires", l_ts_exp ? json_object_new_string(l_tmp_buf) : json_object_new_string("never"));
+            json_object_object_add(json_obj_item,"coins", json_object_new_string(l_coins_str));
+            json_object_object_add(json_obj_item,"value", json_object_new_string(l_value_str));
+            json_object_object_add(json_obj_item,"subtype", json_object_new_string(dap_chain_tx_out_cond_subtype_to_str(((dap_chain_tx_out_cond_t*)item)->header.subtype)));
+            sprintf(l_tmp_buff,"0x%016"DAP_UINT64_FORMAT_x"",((dap_chain_tx_out_cond_t*)item)->header.srv_uid.uint64);
+            json_object_object_add(json_obj_item,"uid", json_object_new_string(l_tmp_buff));
+            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);
+                    sprintf(l_tmp_buff,"0x%08x",((dap_chain_tx_out_cond_t*)item)->subtype.srv_pay.unit.uint32);
+                    json_object_object_add(json_obj_item,"unit", json_object_new_string(l_tmp_buff));
+                    json_object_object_add(json_obj_item,"pkey", json_object_new_string(l_hash_str));
+                    json_object_object_add(json_obj_item,"max price(coins)", json_object_new_string(l_coins_str));
+                    json_object_object_add(json_obj_item,"max price(value)", json_object_new_string(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);
+                    json_object_object_add(json_obj_item,"signing_addr", json_object_new_string(dap_chain_addr_to_str(l_signing_addr)));
+                    json_object_object_add(json_obj_item,"with pkey hash", json_object_new_string(l_hash_str));                    
+                    sprintf(l_tmp_buff,""NODE_ADDR_FP_STR"",NODE_ADDR_FP_ARGS(l_signer_node_addr));
+                    json_object_object_add(json_obj_item,"signer_node_addr", json_object_new_string(l_tmp_buff));
+                    
+                } 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 );
+                    sprintf(l_tmp_buff,"0x%016"DAP_UINT64_FORMAT_x"",((dap_chain_tx_out_cond_t*)item)->subtype.srv_xchange.buy_net_id.uint64);
+                    json_object_object_add(json_obj_item,"net id", json_object_new_string(l_tmp_buff));
+                    json_object_object_add(json_obj_item,"buy_token", json_object_new_string(((dap_chain_tx_out_cond_t*)item)->subtype.srv_xchange.buy_token));
+                    json_object_object_add(json_obj_item,"rate", json_object_new_string(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);
+                    json_object_object_add(json_obj_item,"time_unlock", json_object_new_string(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 );
+            json_object_object_add(json_obj_item,"item type", json_object_new_string("OUT EXT"));
+            json_object_object_add(json_obj_item,"Addr", json_object_new_string(dap_chain_addr_to_str(&((dap_chain_tx_out_ext_t*)item)->addr)));
+            json_object_object_add(json_obj_item,"Token", json_object_new_string(((dap_chain_tx_out_ext_t*)item)->token));
+            json_object_object_add(json_obj_item,"Coins", json_object_new_string(l_coins_str));
+            json_object_object_add(json_obj_item,"Value", json_object_new_string(l_value_str));
+            
+        } break;
+        case TX_ITEM_TYPE_VOTING:{
+            char l_tmp_buff[10]={0};
+            int l_tsd_size = 0;
+            dap_chain_tx_tsd_t *l_item = (dap_chain_tx_tsd_t *)dap_chain_datum_tx_item_get(a_datum, 0, 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);
+            json_object_object_add(json_obj_item,"item type", json_object_new_string("VOTING"));
+            json_object_object_add(json_obj_item,"Voting question", json_object_new_string(l_voting_params->voting_question));
+            json_object_object_add(json_obj_item,"Answer options", json_object_new_string(""));
+            
+            dap_list_t *l_temp = l_voting_params->answers_list;
+            uint8_t l_index = 0;
+            while (l_temp) {
+                sprintf(l_tmp_buff, "%i", l_index);
+                json_object_object_add(json_obj_item, l_tmp_buff, json_object_new_string((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);
+                json_object_object_add(json_obj_item,"Voting expire", json_object_new_string(l_tmp_buf));                
+            }
+            if (l_voting_params->votes_max_count) {
+                sprintf(l_tmp_buff, "%"DAP_UINT64_FORMAT_U, l_voting_params->votes_max_count);
+                json_object_object_add(json_obj_item, "Votes max count", json_object_new_string(l_tmp_buff));
+            }
+            json_object_object_add(json_obj_item,"Changing vote is", l_voting_params->vote_changing_allowed ? json_object_new_string("available") : 
+                                    json_object_new_string("not available"));
+            l_voting_params->delegate_key_required ? 
+                json_object_object_add(json_obj_item,"Votes max count", json_object_new_string("A delegated key is required to participate in voting.")):
+                json_object_object_add(json_obj_item,"Votes max count", json_object_new_string("A delegated key is not required to participate in voting."));                 
+
+            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:{
+            char l_tmp_buff[10]={0};
+            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);
+            json_object_object_add(json_obj_item,"item type", json_object_new_string("VOTE"));
+            json_object_object_add(json_obj_item,"Voting hash", json_object_new_string(l_hash_str));
+            sprintf(l_tmp_buff,"%"DAP_UINT64_FORMAT_U"",l_vote_item->answer_idx);
+            json_object_object_add(json_obj_item,"Vote answer idx", json_object_new_string(l_tmp_buff));
+
+        } break;
+        default:
+            json_object_object_add(json_obj_item,"item type", json_object_new_string("This transaction have unknown item type"));
+            break;
+        }
+        json_object_array_add(json_arr_items, json_obj_item);
+        l_tx_items_count += l_item_tx_size;
+        // Freeze protection
+        if(!l_item_tx_size)
+        {
+            break;
+        }
+
+    }
+    json_object_object_add(json_obj_out, "ITEMS", json_arr_items);
+    return true;
+}
+
 /**
  * @brief dap_chain_net_dump_datum
  * process datum verification process. Can be:
@@ -819,7 +1134,7 @@ void dap_chain_datum_dump(dap_string_t *a_str_out, dap_chain_datum_t *a_datum, c
         case DAP_CHAIN_DATUM_TOKEN_EMISSION: {
             size_t l_emission_size = a_datum->header.data_size;
             dap_chain_datum_token_emission_t *l_emission = dap_chain_datum_emission_read(a_datum->data, &l_emission_size);
-            char *l_coins_str, *l_value_str = dap_uint256_to_char(l_emission->hdr.value, &l_coins_str);
+            const char *l_coins_str, *l_value_str = dap_uint256_to_char(l_emission->hdr.value, &l_coins_str);
             dap_string_append_printf(a_str_out, "emission: hash %s\n\t%s(%s) %s, type: %s, version: %d\n",
                                     l_hash_str,
                                     l_coins_str,
@@ -889,3 +1204,212 @@ void dap_chain_datum_dump(dap_string_t *a_str_out, dap_chain_datum_t *a_datum, c
         } break;
     }    
 }
+
+
+
+/**
+ * @brief dap_chain_net_dump_datum
+ * process datum verification process. Can be:
+ * if DAP_CHAIN_DATUM_TX, called dap_ledger_tx_add_check
+ * if DAP_CHAIN_DATUM_TOKEN_DECL, called dap_ledger_token_decl_add_check
+ * if DAP_CHAIN_DATUM_TOKEN_EMISSION, called dap_ledger_token_emission_add_check
+ * @param a_obj_out
+ * @param a_datum
+ */
+void dap_chain_datum_dump_json(json_object  *a_obj_out, dap_chain_datum_t *a_datum, const char *a_hash_out_type, dap_chain_net_id_t a_net_id)
+{
+    if( a_datum == NULL){
+        dap_json_rpc_error_add(-1,"==Datum is NULL");
+        return;
+    }
+    json_object * json_obj_datum = json_object_new_object();
+    dap_hash_fast_t l_datum_hash;
+    dap_hash_fast(a_datum->data, a_datum->header.data_size, &l_datum_hash);
+    const char *l_hash_str = dap_strcmp(a_hash_out_type, "hex")
+            ? dap_enc_base58_encode_hash_to_str_static(&l_datum_hash)
+            : dap_chain_hash_fast_to_str_static(&l_datum_hash);
+    switch (a_datum->header.type_id) {
+        case DAP_CHAIN_DATUM_TOKEN_DECL: {
+            size_t l_token_size = a_datum->header.data_size;
+            dap_chain_datum_token_t * l_token = dap_chain_datum_token_read(a_datum->data, &l_token_size);
+            if(l_token_size < sizeof(dap_chain_datum_token_t)){
+                dap_json_rpc_error_add(-2,"==Datum has incorrect size. Only %zu, while at least %zu is expected\n",
+                                         l_token_size, sizeof(dap_chain_datum_token_t));
+                DAP_DEL_Z(l_token);
+                return;
+            }
+            json_object_object_add(json_obj_datum,"=== Datum Token Declaration ===",json_object_new_string("empty"));
+            json_object_object_add(json_obj_datum,"hash",json_object_new_string(l_hash_str));
+            json_object_object_add(json_obj_datum,"ticker",json_object_new_string(l_token->ticker));
+            json_object_object_add(json_obj_datum,"size",json_object_new_uint64(l_token_size));
+            json_object_object_add(json_obj_datum,"version",json_object_new_int(l_token->version));
+            
+            switch (l_token->type) {
+                case DAP_CHAIN_DATUM_TOKEN_TYPE_DECL: {
+                    json_object_object_add(json_obj_datum,"type",json_object_new_string("DECL"));
+                    switch (l_token->subtype) {
+                        case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE:{
+                            json_object_object_add(json_obj_datum,"subtype",json_object_new_string("PRIVATE"));
+                            json_object_object_add(json_obj_datum,"decimals",json_object_new_uint64(l_token->header_private_decl.decimals));
+                            json_object_object_add(json_obj_datum,"auth signs valid",json_object_new_uint64(l_token->signs_valid));
+                            json_object_object_add(json_obj_datum,"auth signs total",json_object_new_uint64(l_token->signs_total));
+                            json_object_object_add(json_obj_datum,"total_supply",json_object_new_string(dap_uint256_to_char(l_token->total_supply, NULL)));
+                            json_object_object_add(json_obj_datum,"Flags",json_object_new_string(""));
+
+                            dap_chain_datum_token_flags_dump_to_json(json_obj_datum,l_token->header_private_update.flags);
+                            dap_datum_token_dump_tsd_to_json(json_obj_datum,l_token, l_token_size, a_hash_out_type);               
+                            size_t l_certs_field_size = l_token_size - sizeof(*l_token) - l_token->header_private_update.tsd_total_size;
+                            dap_chain_datum_token_certs_dump_to_json(json_obj_datum,l_token->data_n_tsd + l_token->header_private_update.tsd_total_size,
+                                                             l_certs_field_size, a_hash_out_type);                            
+                        } break;
+                        case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE: {
+                            json_object_object_add(json_obj_datum,"subtype",json_object_new_string("CF20"));
+                            json_object_object_add(json_obj_datum,"decimals",json_object_new_uint64(l_token->header_native_decl.decimals));
+                            json_object_object_add(json_obj_datum,"auth signs valid",json_object_new_uint64(l_token->signs_valid));
+                            json_object_object_add(json_obj_datum,"auth signs total",json_object_new_uint64(l_token->signs_total));
+                            json_object_object_add(json_obj_datum,"total_supply",json_object_new_string(dap_uint256_to_char(l_token->total_supply, NULL)));
+                            json_object_object_add(json_obj_datum,"Flags",json_object_new_string(""));
+
+                            dap_chain_datum_token_flags_dump_to_json(json_obj_datum, l_token->header_native_decl.flags);
+                            dap_datum_token_dump_tsd_to_json(json_obj_datum, l_token, l_token_size, a_hash_out_type);
+                            size_t l_certs_field_size = l_token_size - sizeof(*l_token) - l_token->header_native_decl.tsd_total_size;
+                            dap_chain_datum_token_certs_dump_to_json(json_obj_datum, l_token->data_n_tsd + l_token->header_native_decl.tsd_total_size,
+                                                             l_certs_field_size, a_hash_out_type);
+                        } break;
+                        case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PUBLIC: {
+                            dap_chain_addr_t l_premine_addr = l_token->header_public.premine_address;
+                            json_object_object_add(json_obj_datum,"subtype",json_object_new_string("PUBLIC"));
+                            json_object_object_add(json_obj_datum,"premine_supply", json_object_new_string(dap_uint256_to_char(l_token->header_public.premine_supply, NULL)));
+                            json_object_object_add(json_obj_datum,"premine_address", json_object_new_string(dap_chain_addr_to_str(&l_premine_addr)));
+
+                            json_object_object_add(json_obj_datum,"Flags",json_object_new_string(""));
+                            dap_chain_datum_token_flags_dump_to_json(json_obj_datum, l_token->header_public.flags);
+                        } break;
+                    }
+                } break;
+                case DAP_CHAIN_DATUM_TOKEN_TYPE_UPDATE: {
+                    json_object_object_add(json_obj_datum,"type",json_object_new_string("UPDATE"));
+                    switch (l_token->subtype) {
+                        case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE: {
+                            json_object_object_add(json_obj_datum,"subtype",json_object_new_string("PRIVATE"));
+                            json_object_object_add(json_obj_datum,"decimals",json_object_new_uint64(l_token->header_private_decl.decimals));
+                            json_object_object_add(json_obj_datum,"auth signs valid",json_object_new_uint64(l_token->signs_valid));
+                            json_object_object_add(json_obj_datum,"auth signs total",json_object_new_uint64(l_token->signs_total));
+                            json_object_object_add(json_obj_datum,"total_supply",json_object_new_string(dap_uint256_to_char(l_token->total_supply, NULL)));
+                            
+                            json_object_object_add(json_obj_datum,"Flags",json_object_new_string(""));
+                            dap_chain_datum_token_flags_dump_to_json(json_obj_datum, l_token->header_private_update.flags);
+                            dap_datum_token_dump_tsd_to_json(json_obj_datum, l_token, l_token_size, a_hash_out_type);
+                            size_t l_certs_field_size = l_token_size - sizeof(*l_token) - l_token->header_private_update.tsd_total_size;
+                            dap_chain_datum_token_certs_dump_to_json(json_obj_datum, l_token->data_n_tsd + l_token->header_private_update.tsd_total_size,
+                                                             l_certs_field_size, a_hash_out_type);
+                        } break;
+                        case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE: {
+                            json_object_object_add(json_obj_datum,"subtype", json_object_new_string("CF20"));
+                            json_object_object_add(json_obj_datum,"decimals", json_object_new_uint64(l_token->header_native_update.decimals));
+                            json_object_object_add(json_obj_datum,"auth signs valid",json_object_new_uint64(l_token->signs_valid));
+                            json_object_object_add(json_obj_datum,"auth signs total",json_object_new_uint64(l_token->signs_total));
+                            json_object_object_add(json_obj_datum,"total_supply",json_object_new_string(dap_uint256_to_char(l_token->total_supply, NULL)));
+                            
+                            json_object_object_add(json_obj_datum,"Flags",json_object_new_string(""));
+                            dap_chain_datum_token_flags_dump_to_json(json_obj_datum, l_token->header_native_update.flags);
+                            dap_datum_token_dump_tsd_to_json(json_obj_datum, l_token, l_token_size, a_hash_out_type);
+                            size_t l_certs_field_size = l_token_size - sizeof(*l_token) - l_token->header_native_update.tsd_total_size;
+                            dap_chain_datum_token_certs_dump_to_json(json_obj_datum, l_token->data_n_tsd + l_token->header_native_update.tsd_total_size,
+                                                             l_certs_field_size, a_hash_out_type);
+                        } break;
+                    }
+                } break;
+                default:
+                    json_object_object_add(json_obj_datum,"type", json_object_new_string("UNKNOWN"));
+                    break;
+            }
+            if (l_token->subtype == DAP_CHAIN_DATUM_TOKEN_SUBTYPE_SIMPLE ) {
+                json_object_object_add(json_obj_datum,"subtype", json_object_new_string("SIMPLE"));
+                json_object_object_add(json_obj_datum,"decimals", json_object_new_uint64(l_token->header_simple.decimals));
+                json_object_object_add(json_obj_datum,"sign_total", json_object_new_uint64(l_token->signs_total));
+                json_object_object_add(json_obj_datum,"sign_valid", json_object_new_uint64(l_token->signs_valid));
+                json_object_object_add(json_obj_datum,"total_supply",json_object_new_string(dap_uint256_to_char(l_token->total_supply, NULL)));
+                
+                size_t l_certs_field_size = l_token_size - sizeof(*l_token);
+                dap_chain_datum_token_certs_dump_to_json(json_obj_datum, l_token->data_n_tsd,
+                                                 l_certs_field_size, a_hash_out_type);
+            }
+            DAP_DELETE(l_token);
+        } break;
+        case DAP_CHAIN_DATUM_TOKEN_EMISSION: {
+            size_t l_emission_size = a_datum->header.data_size;
+            dap_chain_datum_token_emission_t *l_emission = dap_chain_datum_emission_read(a_datum->data, &l_emission_size);
+            const char *l_coins_str, *l_value_str = dap_uint256_to_char(l_emission->hdr.value, &l_coins_str);
+            json_object_object_add(json_obj_datum,"emission hash", json_object_new_string(l_hash_str));
+            json_object_object_add(json_obj_datum,"coins", json_object_new_string(l_coins_str));
+            json_object_object_add(json_obj_datum,"value", json_object_new_string(l_value_str));
+            json_object_object_add(json_obj_datum,"ticker", json_object_new_string(l_emission->hdr.ticker));
+            json_object_object_add(json_obj_datum,"type", json_object_new_string(c_dap_chain_datum_token_emission_type_str[l_emission->hdr.type]));
+            json_object_object_add(json_obj_datum,"version", json_object_new_uint64(l_emission->hdr.version));
+            json_object_object_add(json_obj_datum,"to addr", json_object_new_string(dap_chain_addr_to_str(&(l_emission->hdr.address))));
+
+            switch (l_emission->hdr.type) {
+            case DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_AUTH:
+                json_object_object_add(json_obj_datum,"signs_count", json_object_new_uint64(l_emission->data.type_auth.signs_count));
+                json_object_object_add(json_obj_datum,"tsd_total_size", json_object_new_uint64(l_emission->data.type_auth.tsd_total_size));
+
+                if (  ( (void *) l_emission->tsd_n_signs + l_emission->data.type_auth.tsd_total_size) >
+                      ((void *) l_emission + l_emission_size) )
+                {
+                    log_it(L_ERROR, "Illformed DATUM type %d, TSD section is out-of-buffer (%" DAP_UINT64_FORMAT_U " vs %zu)",
+                        l_emission->hdr.type, l_emission->data.type_auth.tsd_total_size, l_emission_size);
+                    dap_json_rpc_error_add(-3,"Skip incorrect or illformed DATUM");
+                    break;
+                }
+                dap_chain_datum_token_certs_dump_to_json(json_obj_datum, l_emission->tsd_n_signs + l_emission->data.type_auth.tsd_total_size,
+                                                l_emission->data.type_auth.size - l_emission->data.type_auth.tsd_total_size, a_hash_out_type);
+                break;
+            case DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_ALGO:
+                json_object_object_add(json_obj_datum,"codename",json_object_new_string(l_emission->data.type_algo.codename));
+                break;
+            case DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_SMART_CONTRACT: {
+                char l_time_str[32];
+                char l_flags[50] = {};
+                // get time of create datum
+                if(dap_time_to_str_rfc822(l_time_str, sizeof(l_time_str), l_emission->data.type_presale.lock_time) < 1)
+                        l_time_str[0] = '\0';                        
+                snprintf(l_flags, 50, "0x%x", l_emission->data.type_presale.flags);
+                json_object_object_add(json_obj_datum,"flags", json_object_new_string(l_flags));
+                json_object_object_add(json_obj_datum,"lock_time", json_object_new_string(l_time_str));
+                json_object_object_add(json_obj_datum,"addr", json_object_new_string(dap_chain_addr_to_str(&l_emission->data.type_presale.addr)));                
+            }
+            case DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_ATOM_OWNER:
+            case DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_UNDEFINED:
+            default:
+                break;
+            }
+            DAP_DELETE(l_emission);
+        } break;
+        case DAP_CHAIN_DATUM_TX: {
+            dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t*)a_datum->data;
+            dap_chain_datum_dump_tx_json(l_tx, NULL, json_obj_datum, a_hash_out_type, &l_datum_hash, a_net_id);
+        } break;
+        case DAP_CHAIN_DATUM_DECREE:{
+            dap_chain_datum_decree_t *l_decree = (dap_chain_datum_decree_t *)a_datum->data;
+            size_t l_decree_size = dap_chain_datum_decree_get_size(l_decree);
+            json_object_object_add(json_obj_datum,"=== Datum decree ===",json_object_new_string("empty"));
+            json_object_object_add(json_obj_datum,"hash",json_object_new_string(l_hash_str));
+            json_object_object_add(json_obj_datum,"size",json_object_new_uint64(l_decree_size));
+            dap_chain_datum_decree_dump_json(json_obj_datum, l_decree, l_decree_size, a_hash_out_type);
+        } break;
+        case DAP_CHAIN_DATUM_ANCHOR:{
+            dap_chain_datum_anchor_t *l_anchor = (dap_chain_datum_anchor_t *)a_datum->data;
+            size_t l_anchor_size = sizeof(dap_chain_datum_anchor_t) + l_anchor->header.data_size + l_anchor->header.signs_size;
+            json_object_object_add(json_obj_datum,"=== Datum anchor ===",json_object_new_string("empty"));
+            json_object_object_add(json_obj_datum,"hash",json_object_new_string(l_hash_str));
+            json_object_object_add(json_obj_datum,"size",json_object_new_uint64(l_anchor_size));
+            dap_hash_fast_t l_decree_hash = { };
+            dap_chain_datum_anchor_get_hash_from_data(l_anchor, &l_decree_hash);
+            l_hash_str = dap_chain_hash_fast_to_str_static(&l_decree_hash);
+            json_object_object_add(json_obj_datum,"decree hash",json_object_new_string(l_hash_str));
+            dap_chain_datum_anchor_certs_dump_json(json_obj_datum,l_anchor->data_n_sign + l_anchor->header.data_size, l_anchor->header.signs_size, a_hash_out_type);
+        } break;
+    }  
+    json_object_object_add(a_obj_out,"Datum",json_obj_datum);  
+}
diff --git a/modules/common/dap_chain_datum_anchor.c b/modules/common/dap_chain_datum_anchor.c
index 58cdc378b7257a7476c41a29d617a1df3a635b9d..a87618bb02b8308c80bf19bab1b72da2027df42a 100644
--- a/modules/common/dap_chain_datum_anchor.c
+++ b/modules/common/dap_chain_datum_anchor.c
@@ -90,3 +90,41 @@ void dap_chain_datum_anchor_certs_dump(dap_string_t * a_str_out, byte_t * a_sign
                                  dap_sign_type_to_str(l_sign->header.type), l_sign->header.sign_size);
     }
 }
+
+void dap_chain_datum_anchor_certs_dump_json(json_object * a_json_out, byte_t * a_signs, size_t a_certs_size, const char *a_hash_out_type)
+{
+    json_object_object_add(a_json_out, "signatures", json_object_new_string(""));
+    if (!a_certs_size) {
+        json_object_object_add(a_json_out, "Cert status", json_object_new_string("NONE"));
+        return;
+    }
+    json_object* json_arr_certs_out = json_object_new_array();    
+    size_t l_offset = 0;
+    for (int i = 1; l_offset < (a_certs_size); i++) {
+        json_object* json_obj_sign = json_object_new_object();
+        dap_sign_t *l_sign = (dap_sign_t*)(a_signs + l_offset);
+        l_offset += dap_sign_get_size(l_sign);
+        if (l_sign->header.sign_size == 0) {
+            json_object_object_add(json_obj_sign, "sign status", json_object_new_string("CORRUPTED - 0 size signature"));
+            json_object_array_add(json_arr_certs_out, json_obj_sign);
+            continue;
+        }
+
+        dap_chain_hash_fast_t l_pkey_hash = {0};
+        if (dap_sign_get_pkey_hash(l_sign, &l_pkey_hash) == false) {
+            json_object_object_add(json_obj_sign, "sign status", json_object_new_string("CORRUPTED - can't calc hash"));
+            json_object_array_add(json_arr_certs_out, json_obj_sign);
+            continue;
+        }
+        const char *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);
+        json_object_object_add(json_obj_sign, "sign #", json_object_new_uint64(i));
+        json_object_object_add(json_obj_sign, "hash", json_object_new_string(l_hash_str));
+        json_object_object_add(json_obj_sign, "type", json_object_new_string(dap_sign_type_to_str(l_sign->header.type)));
+        json_object_object_add(json_obj_sign, "sign size", json_object_new_uint64(l_sign->header.sign_size));
+        json_object_array_add(json_arr_certs_out, json_obj_sign); 
+    }
+    json_object_object_add(a_json_out,"SIGNS",json_arr_certs_out);
+}
+
diff --git a/modules/common/dap_chain_datum_decree.c b/modules/common/dap_chain_datum_decree.c
index 6920023a493e992d1188653a5ccb0a2d7affe229..951b8d04741fe1cb44eae563481c6f251738c2b1 100644
--- a/modules/common/dap_chain_datum_decree.c
+++ b/modules/common/dap_chain_datum_decree.c
@@ -41,11 +41,7 @@
 
 dap_sign_t *dap_chain_datum_decree_get_signs(dap_chain_datum_decree_t *a_decree, size_t* a_signs_size)
 {
-    if (!a_decree || !a_signs_size) {
-        log_it(L_CRITICAL, "Invalid arguments");
-        return NULL;
-    }
-
+    dap_return_val_if_fail(a_decree && a_signs_size, NULL);
     dap_sign_t *l_signs_section = (dap_sign_t*)(a_decree->data_n_signs + a_decree->header.data_size);
     *a_signs_size = a_decree->header.signs_size;
     return l_signs_section;
@@ -53,29 +49,23 @@ dap_sign_t *dap_chain_datum_decree_get_signs(dap_chain_datum_decree_t *a_decree,
 
 int dap_chain_datum_decree_get_fee(dap_chain_datum_decree_t *a_decree, uint256_t *a_fee_value)
 {
-    if(!a_decree || !a_fee_value) {
-        log_it(L_CRITICAL, "Invalid arguments");
-        return -1;
-    }
-    dap_tsd_t* l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_FEE);
-    return l_tsd ? ({ _dap_tsd_get_scalar(l_tsd, a_fee_value); 0; }) : 1;
+    dap_return_val_if_fail(a_decree && a_fee_value, -1);
+    dap_tsd_t *l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_FEE);
+    return l_tsd && l_tsd->size == sizeof(uint256_t) ? ({ _dap_tsd_get_scalar(l_tsd, a_fee_value); 0; }) : 1;
 }
 
 int dap_chain_datum_decree_get_value(dap_chain_datum_decree_t *a_decree, uint256_t *a_value)
 {
     dap_return_val_if_fail(a_decree && a_value, -1);
     dap_tsd_t *l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_VALUE);
-    return l_tsd ? ({ _dap_tsd_get_scalar(l_tsd, a_value); 0; }) : 1;
+    return l_tsd && l_tsd->size == sizeof(uint256_t) ? ({ _dap_tsd_get_scalar(l_tsd, a_value); 0; }) : 1;
 }
 
 int dap_chain_datum_decree_get_fee_addr(dap_chain_datum_decree_t *a_decree, dap_chain_addr_t *a_fee_wallet)
 {
-    if(!a_decree || !a_fee_wallet) {
-        log_it(L_CRITICAL, "Invalid arguments");
-        return -1;
-    }
-    dap_tsd_t* l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_FEE_WALLET);
-    return l_tsd ? ({ _dap_tsd_get_scalar(l_tsd, a_fee_wallet); 0; }) : 1;
+    dap_return_val_if_fail(a_decree && a_fee_wallet, -1);
+    dap_tsd_t *l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_FEE_WALLET);
+    return l_tsd && l_tsd->size == sizeof(dap_chain_addr_t) ? ({ _dap_tsd_get_scalar(l_tsd, a_fee_wallet); 0; }) : 1;
 }
 
 static void *s_cb_copy_pkeys(const void *a_pkey, UNUSED_ARG void *a_data) {
@@ -84,10 +74,7 @@ static void *s_cb_copy_pkeys(const void *a_pkey, UNUSED_ARG void *a_data) {
 
 dap_list_t *dap_chain_datum_decree_get_owners(dap_chain_datum_decree_t *a_decree, uint16_t *a_owners_num)
 {
-    if(!a_decree || !a_owners_num){
-        log_it(L_CRITICAL, "Invalid arguments");
-        return NULL;
-    }
+    dap_return_val_if_fail(a_decree && a_owners_num, NULL);
     dap_list_t *l_tsd_list = dap_tsd_find_all(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_OWNER);
     *a_owners_num = (uint16_t)dap_list_length(l_tsd_list);
     dap_list_t *l_ret = dap_list_copy_deep(l_tsd_list, s_cb_copy_pkeys, NULL);
@@ -95,77 +82,80 @@ dap_list_t *dap_chain_datum_decree_get_owners(dap_chain_datum_decree_t *a_decree
     return l_ret;
 }
 
-int dap_chain_datum_decree_get_min_owners(dap_chain_datum_decree_t *a_decree, uint16_t *a_min_owners_num)
+int dap_chain_datum_decree_get_min_owners(dap_chain_datum_decree_t *a_decree, uint256_t *a_min_owners_num)
 {
-    if(!a_decree || !a_min_owners_num){
-        log_it(L_CRITICAL, "Invalid arguments");
-        return -1;
-    }
-    dap_tsd_t* l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_MIN_OWNER);
-    return l_tsd ? ({ _dap_tsd_get_scalar(l_tsd, a_min_owners_num); 0; }) : 1;
+    dap_return_val_if_fail(a_decree && a_min_owners_num, -1);
+    dap_tsd_t *l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_MIN_OWNER);
+    return l_tsd && l_tsd->size == sizeof(uint256_t) ? ({ _dap_tsd_get_scalar(l_tsd, a_min_owners_num); 0; }) : 1;
 }
 
-int dap_chain_datum_decree_get_stake_tx_hash(dap_chain_datum_decree_t *a_decree, dap_hash_fast_t *a_tx_hash)
+int dap_chain_datum_decree_get_hash(dap_chain_datum_decree_t *a_decree, dap_hash_fast_t *a_tx_hash)
 {
-    if(!a_decree || !a_tx_hash){
-        log_it(L_CRITICAL, "Invalid arguments");
-        return -1;
-    }
-    dap_tsd_t* l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_TX_HASH);
-    return l_tsd ? ({ _dap_tsd_get_scalar(l_tsd, a_tx_hash); 0; }) : 1;
+    dap_return_val_if_fail(a_decree && a_tx_hash, -1);
+    dap_tsd_t *l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_HASH);
+    return l_tsd && l_tsd->size == sizeof(dap_hash_fast_t) ? ({ _dap_tsd_get_scalar(l_tsd, a_tx_hash); 0; }) : 1;
 }
 
 int dap_chain_datum_decree_get_stake_value(dap_chain_datum_decree_t *a_decree, uint256_t *a_stake_value)
 {
-    if(!a_decree || !a_stake_value){
-        log_it(L_CRITICAL, "Invalid arguments");
-        return -1;
-    }
-    dap_tsd_t* l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_VALUE);
-    return l_tsd ? ({ _dap_tsd_get_scalar(l_tsd, a_stake_value); 0; }) : 1;
+    dap_return_val_if_fail(a_decree && a_stake_value, -1);
+    dap_tsd_t *l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_VALUE);
+    return l_tsd && l_tsd->size == sizeof(uint256_t) ? ({ _dap_tsd_get_scalar(l_tsd, a_stake_value); 0; }) : 1;
 }
 
 int dap_chain_datum_decree_get_stake_signing_addr(dap_chain_datum_decree_t *a_decree, dap_chain_addr_t *a_signing_addr)
 {
-    if(!a_decree || !a_signing_addr){
-        log_it(L_CRITICAL, "Invalid arguments");
-        return -1;
-    }
-    dap_tsd_t* l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_SIGNING_ADDR);
-    return l_tsd ? ({ _dap_tsd_get_scalar(l_tsd, a_signing_addr); 0; }) : 1;
+    dap_return_val_if_fail(a_decree && a_signing_addr, -1);
+    dap_tsd_t *l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_SIGNING_ADDR);
+    return l_tsd && l_tsd->size == sizeof(dap_chain_addr_t) ? ({ _dap_tsd_get_scalar(l_tsd, a_signing_addr); 0; }) : 1;
 }
 
 int dap_chain_datum_decree_get_stake_signer_node_addr(dap_chain_datum_decree_t *a_decree, dap_chain_node_addr_t *a_node_addr)
 {
-    if(!a_decree || !a_node_addr){
-        log_it(L_CRITICAL, "Invalid arguments");
-        return -1;
-    }
-    dap_tsd_t* l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_SIGNER_NODE_ADDR);
-    return l_tsd ? ({ _dap_tsd_get_scalar(l_tsd, a_node_addr); 0; }) : 1;
+    dap_return_val_if_fail(a_decree && a_node_addr, -1);
+    dap_tsd_t *l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_NODE_ADDR);
+    return l_tsd && l_tsd->size == sizeof(dap_chain_node_addr_t) ? ({ _dap_tsd_get_scalar(l_tsd, a_node_addr); 0; }) : 1;
 }
 
 int dap_chain_datum_decree_get_stake_min_value(dap_chain_datum_decree_t *a_decree, uint256_t *a_min_value)
 {
-    if(!a_decree || !a_min_value){
-        log_it(L_CRITICAL, "Invalid arguments");
-        return -1;
-    }
-    dap_tsd_t* l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_MIN_VALUE);
-    return l_tsd ? ({ _dap_tsd_get_scalar(l_tsd, a_min_value); 0; }) : 1;
+    dap_return_val_if_fail(a_decree && a_min_value, -1);
+    dap_tsd_t *l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_MIN_VALUE);
+    return l_tsd && l_tsd->size == sizeof(uint256_t) ? ({ _dap_tsd_get_scalar(l_tsd, a_min_value); 0; }) : 1;
 }
 
 int dap_chain_datum_decree_get_stake_min_signers_count(dap_chain_datum_decree_t *a_decree, uint256_t *a_min_signers_count)
 {
-    if(!a_decree || !a_min_signers_count){
-        log_it(L_CRITICAL, "Invalid arguments");
-        return -1;
-    }
-    dap_tsd_t* l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_MIN_SIGNERS_COUNT);
-    return l_tsd ? ({ _dap_tsd_get_scalar(l_tsd, a_min_signers_count); 0; }) : 1;
+    dap_return_val_if_fail(a_decree && a_min_signers_count, -1);
+    dap_tsd_t *l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_MIN_SIGNERS_COUNT);
+    return l_tsd && l_tsd->size == sizeof(uint256_t) ? ({ _dap_tsd_get_scalar(l_tsd, a_min_signers_count); 0; }) : 1;
 }
 
-void dap_chain_datum_decree_dump(dap_string_t *a_str_out, dap_chain_datum_decree_t *a_decree, size_t a_decree_size, const char *a_hash_out_type) {
+int dap_chain_datum_decree_get_action(dap_chain_datum_decree_t *a_decree, uint8_t *a_action)
+{
+    dap_return_val_if_fail(a_decree && a_action, -1);
+    dap_tsd_t *l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_ACTION);
+    return l_tsd && l_tsd->size == sizeof(uint8_t) ? ({ _dap_tsd_get_scalar(l_tsd, a_action); 0; }) : 1;
+}
+
+int dap_chain_datum_decree_get_signature_type(dap_chain_datum_decree_t *a_decree, uint32_t *a_signature_type)
+{
+    dap_return_val_if_fail(a_decree && a_signature_type, -1);
+    dap_tsd_t *l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_SIGNATURE_TYPE);
+    return l_tsd && l_tsd->size == sizeof(uint32_t) ? ({ _dap_tsd_get_scalar(l_tsd, a_signature_type); 0; }) : 1;
+}
+
+int dap_chain_datum_decree_get_ban_addr(dap_chain_datum_decree_t *a_decree, const char **a_addr)
+{
+    dap_return_val_if_fail(a_decree && a_addr, -1);
+    dap_tsd_t *l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_HOST);
+    if (!l_tsd)
+        l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STRING);
+    return l_tsd ? ({ *a_addr = dap_tsd_get_string_const(l_tsd); !dap_strcmp(*a_addr, DAP_TSD_CORRUPTED_STRING); }) : 1;
+}
+
+void dap_chain_datum_decree_dump(dap_string_t *a_str_out, dap_chain_datum_decree_t *a_decree, size_t a_decree_size, const char *a_hash_out_type)
+{
     char *l_type_str = "";
     switch(a_decree->header.type)
     {
@@ -193,7 +183,7 @@ void dap_chain_datum_decree_dump(dap_string_t *a_str_out, dap_chain_datum_decree
                 }
                 uint256_t l_value = uint256_0;
                 _dap_tsd_get_scalar(l_tsd, &l_value);
-                char *l_value_str = dap_uint256_to_char(l_value, NULL);
+                const char *l_value_str = dap_uint256_to_char(l_value, NULL);
                 dap_string_append_printf(a_str_out, "\tValue: %s\n", l_value_str);
                 break;
             case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_SIGN:
@@ -205,7 +195,7 @@ void dap_chain_datum_decree_dump(dap_string_t *a_str_out, dap_chain_datum_decree
                 }
                 uint256_t l_fee_value = uint256_0;
                 _dap_tsd_get_scalar(l_tsd, &l_fee_value);
-                char *l_fee_value_str = dap_uint256_to_char(l_fee_value, NULL);
+                const char *l_fee_value_str = dap_uint256_to_char(l_fee_value, NULL);
                 dap_string_append_printf(a_str_out, "\tFee: %s\n", l_fee_value_str);
                 break;
             case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_OWNER:
@@ -220,13 +210,13 @@ void dap_chain_datum_decree_dump(dap_string_t *a_str_out, dap_chain_datum_decree
                 dap_string_append_printf(a_str_out, "\tOwner fingerprint: %s\n", l_owner_pkey_str);
                 break;
             case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_MIN_OWNER:
-                if (l_tsd->size > sizeof(uint256_t)){
+                if (l_tsd->size != sizeof(uint32_t)){
                     dap_string_append_printf(a_str_out, "\tOwner min: <WRONG SIZE>\n");
                     break;
                 }
                 uint256_t l_owner_min = uint256_0;
                 _dap_tsd_get_scalar(l_tsd, &l_owner_min);
-                char *l_owner_min_str = dap_uint256_to_char(l_owner_min, NULL);
+                const char *l_owner_min_str = dap_uint256_to_char(l_owner_min, NULL);
                 dap_string_append_printf(a_str_out, "\tOwner min: %s\n", l_owner_min_str);
                 break;
             case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_FEE_WALLET:
@@ -238,9 +228,9 @@ void dap_chain_datum_decree_dump(dap_string_t *a_str_out, dap_chain_datum_decree
                 _dap_tsd_get_scalar(l_tsd, &l_addr_fee_wallet);*/ _dap_tsd_get_object(l_tsd, dap_chain_addr_t);
                 dap_string_append_printf(a_str_out, "\tWallet for fee: %s\n", dap_chain_addr_to_str(l_addr_fee_wallet));
                 break;
-            case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_TX_HASH:
+            case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_HASH:
                 if (l_tsd->size > sizeof(dap_hash_fast_t)) {
-                    dap_string_append_printf(a_str_out, "\tStake tx: <WRONG SIZE>\n");
+                    dap_string_append_printf(a_str_out, "\tHash: <WRONG SIZE>\n");
                     break;
                 }
                 dap_hash_fast_t *l_stake_tx = /*{ };
@@ -248,7 +238,7 @@ void dap_chain_datum_decree_dump(dap_string_t *a_str_out, dap_chain_datum_decree
                 const char *l_stake_tx_hash = dap_strcmp(a_hash_out_type, "hex")
                         ? dap_enc_base58_encode_hash_to_str_static(l_stake_tx)
                         : dap_chain_hash_fast_to_str_static(l_stake_tx);
-                dap_string_append_printf(a_str_out, "\tStake tx: %s\n", l_stake_tx_hash);
+                dap_string_append_printf(a_str_out, "\tHash: %s\n", l_stake_tx_hash);
                 break;
             case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_VALUE:
                 if (l_tsd->size > sizeof(uint256_t)){
@@ -257,7 +247,7 @@ void dap_chain_datum_decree_dump(dap_string_t *a_str_out, dap_chain_datum_decree
                 }
                 uint256_t l_stake_value = uint256_0;
                 _dap_tsd_get_scalar(l_tsd, &l_stake_value);
-                char *l_stake_value_str = dap_uint256_to_char(l_stake_value, NULL);
+                const char *l_stake_value_str = dap_uint256_to_char(l_stake_value, NULL);
                 dap_string_append_printf(a_str_out, "\tStake value: %s\n", l_stake_value_str);
                 break;
             case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_SIGNING_ADDR:
@@ -274,7 +264,7 @@ void dap_chain_datum_decree_dump(dap_string_t *a_str_out, dap_chain_datum_decree
                         : dap_chain_hash_fast_to_str_static(&l_pkey_signing);
                 dap_string_append_printf(a_str_out, "\tSigning pkey fingerprint: %s\n", l_pkey_signing_str);
                 break;
-            case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_SIGNER_NODE_ADDR:
+            case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_NODE_ADDR:
                 if(l_tsd->size > sizeof(dap_chain_node_addr_t)){
                     dap_string_append_printf(a_str_out, "\tNode addr: <WRONG SIZE>\n");
                     break;
@@ -290,7 +280,7 @@ void dap_chain_datum_decree_dump(dap_string_t *a_str_out, dap_chain_datum_decree
                 }
                 uint256_t l_min_value = uint256_0;
                 _dap_tsd_get_scalar(l_tsd, &l_min_value);
-                char *l_min_value_str = dap_uint256_to_char(l_min_value, NULL);
+                const char *l_min_value_str = dap_uint256_to_char(l_min_value, NULL);
                 dap_string_append_printf(a_str_out, "\tMin value: %s\n", l_min_value_str);
                 break;
             case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_MIN_SIGNERS_COUNT:
@@ -300,13 +290,32 @@ void dap_chain_datum_decree_dump(dap_string_t *a_str_out, dap_chain_datum_decree
                 }
                 uint256_t l_min_signers_count = uint256_0;
                 _dap_tsd_get_scalar(l_tsd, &l_min_signers_count);
-                char *l_min_signers_count_str = dap_uint256_to_char(l_min_signers_count, NULL);
+                const char *l_min_signers_count_str = dap_uint256_to_char(l_min_signers_count, NULL);
                 dap_string_append_printf(a_str_out, "\tMin signers count: %s\n", l_min_signers_count_str);
                 break;
             case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_HOST:
-            case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_NODE_ADDR: {
-                dap_string_append_printf(a_str_out, "\tNode address: %s\n", dap_tsd_get_string(l_tsd));
-            } break;
+            case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STRING:
+                dap_string_append_printf(a_str_out, "\tHost address: %s\n", dap_tsd_get_string(l_tsd));
+                break;
+            case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_ACTION:
+                if (l_tsd->size != sizeof(uint8_t)){
+                    dap_string_append_printf(a_str_out, "\tAction: <WRONG SIZE>\n");
+                    break;
+                }
+                uint8_t l_action = 0;
+                _dap_tsd_get_scalar(l_tsd, &l_action);
+                dap_string_append_printf(a_str_out, "\tAction: %s\n", l_action ? "add (enable)" : "delete (disable)");
+                break;
+            case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_SIGNATURE_TYPE:
+                if (l_tsd->size != sizeof(uint32_t)){
+                    dap_string_append_printf(a_str_out, "\tSignature type: <WRONG SIZE>\n");
+                    break;
+                }
+                uint32_t l_type = 0;
+                _dap_tsd_get_scalar(l_tsd, &l_type);
+                dap_sign_type_t l_sign_type = { .type = l_type };
+                dap_string_append_printf(a_str_out, "\tSignature type: %s\n", dap_sign_type_to_str(l_sign_type));
+                break;
             default:
                 dap_string_append_printf(a_str_out, "\t<UNKNOWN_TYPE_TSD_SECTION>\n");
                 break;
@@ -349,30 +358,263 @@ void dap_chain_datum_decree_certs_dump(dap_string_t * a_str_out, byte_t * a_sign
     }
 }
 
-dap_chain_datum_decree_t* dap_chain_datum_decree_sign_in_cycle(dap_cert_t ** a_certs, dap_chain_datum_decree_t *a_datum_decree,
+void dap_chain_datum_decree_dump_json(json_object *a_json_out, dap_chain_datum_decree_t *a_decree, size_t a_decree_size, const char *a_hash_out_type)
+{
+    char *l_type_str = "";
+    char l_tmp_buff[70]={0};
+    switch(a_decree->header.type)
+    {
+        case DAP_CHAIN_DATUM_DECREE_TYPE_COMMON:
+            l_type_str = "DECREE_TYPE_COMMON";
+            break;
+        case DAP_CHAIN_DATUM_DECREE_TYPE_SERVICE:
+            l_type_str = "DECREE_TYPE_SERVICE";
+            break;
+        default:
+            l_type_str = "DECREE_TYPE_UNKNOWN";
+    }
+    json_object_object_add(a_json_out, "type", json_object_new_string(l_type_str));
+    const char *l_subtype_str = dap_chain_datum_decree_subtype_to_str(a_decree->header.sub_type);
+    json_object_object_add(a_json_out, "subtype", json_object_new_string(l_subtype_str));
+    json_object_object_add(a_json_out, "TSD", json_object_new_string(""));
+    for (size_t l_offset = 0; l_offset < a_decree->header.data_size;) {
+        dap_tsd_t *l_tsd = (dap_tsd_t *)((byte_t*)a_decree->data_n_signs + l_offset);
+        l_offset += dap_tsd_size(l_tsd);
+        switch(l_tsd->type) {
+            case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_VALUE:
+                if (l_tsd->size > sizeof(uint256_t)){
+                    json_object_object_add(a_json_out, "Value", json_object_new_string("WRONG SIZE"));
+                    break;
+                }
+                uint256_t l_value = uint256_0;
+                _dap_tsd_get_scalar(l_tsd, &l_value);
+                const char *l_value_str = dap_uint256_to_char(l_value, NULL);
+                json_object_object_add(a_json_out, "Value", json_object_new_string(l_value_str));
+                break;
+            case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_SIGN:
+            break;
+            case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_FEE:
+                if (l_tsd->size > sizeof(uint256_t)){
+                    json_object_object_add(a_json_out, "Fee", json_object_new_string("WRONG SIZE"));
+                    break;
+                }
+                uint256_t l_fee_value = uint256_0;
+                _dap_tsd_get_scalar(l_tsd, &l_fee_value);
+                const char *l_fee_value_str = dap_uint256_to_char(l_fee_value, NULL);
+                json_object_object_add(a_json_out, "Fee", json_object_new_string(l_fee_value_str));
+                break;
+            case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_OWNER:
+                if (l_tsd->size < sizeof(dap_pkey_t)) {
+                    json_object_object_add(a_json_out, "Owner fingerprint", json_object_new_string("WRONG SIZE"));
+                    break;
+                }
+                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));
+                break;
+            case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_MIN_OWNER:
+                if (l_tsd->size > sizeof(uint256_t)){
+                    json_object_object_add(a_json_out, "Owner min", json_object_new_string("WRONG SIZE"));
+                    break;
+                }
+                uint256_t l_owner_min = uint256_0;
+                _dap_tsd_get_scalar(l_tsd, &l_owner_min);
+                const char *l_owner_min_str = dap_uint256_to_char(l_owner_min, NULL);
+                json_object_object_add(a_json_out, "Owner min", json_object_new_string(l_owner_min_str));
+                break;
+            case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_FEE_WALLET:
+                if (l_tsd->size > sizeof(dap_chain_addr_t)) {
+                    json_object_object_add(a_json_out, "Wallet for fee", json_object_new_string("WRONG SIZE"));
+                    break;
+                }
+                dap_chain_addr_t *l_addr_fee_wallet = /*{ };
+                _dap_tsd_get_scalar(l_tsd, &l_addr_fee_wallet);*/ _dap_tsd_get_object(l_tsd, dap_chain_addr_t);
+                json_object_object_add(a_json_out, "Wallet for fee", json_object_new_string(dap_chain_addr_to_str(l_addr_fee_wallet)));
+                break;
+            case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_HASH:
+                if (l_tsd->size > sizeof(dap_hash_fast_t)) {
+                    json_object_object_add(a_json_out, "Stake tx", json_object_new_string("WRONG SIZE"));
+                    break;
+                }
+                dap_hash_fast_t *l_stake_tx = /*{ };
+                _dap_tsd_get_scalar(l_tsd, &l_stake_tx);*/ _dap_tsd_get_object(l_tsd, dap_hash_fast_t);
+                const char *l_stake_tx_hash = dap_strcmp(a_hash_out_type, "hex")
+                        ? dap_enc_base58_encode_hash_to_str_static(l_stake_tx)
+                        : dap_chain_hash_fast_to_str_static(l_stake_tx);
+                json_object_object_add(a_json_out, "Stake tx", json_object_new_string(l_stake_tx_hash));
+                break;
+            case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_VALUE:
+                if (l_tsd->size > sizeof(uint256_t)){
+                    json_object_object_add(a_json_out, "Stake value", json_object_new_string("WRONG SIZE"));
+                    break;
+                }
+                uint256_t l_stake_value = uint256_0;
+                _dap_tsd_get_scalar(l_tsd, &l_stake_value);
+                const char *l_stake_value_str = dap_uint256_to_char(l_stake_value, NULL);
+                json_object_object_add(a_json_out, "Stake value", json_object_new_string(l_stake_value_str));
+                break;
+            case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_SIGNING_ADDR:
+                if (l_tsd->size > sizeof(dap_chain_addr_t)) {
+                    json_object_object_add(a_json_out, "Signing addr", json_object_new_string("WRONG SIZE"));
+                    break;
+                }
+                dap_chain_addr_t *l_stake_addr_signing = /*{ };
+                _dap_tsd_get_scalar(l_tsd, &l_stake_addr_signing);*/ _dap_tsd_get_object(l_tsd, dap_chain_addr_t);
+                json_object_object_add(a_json_out, "Signing addr", json_object_new_string(dap_chain_addr_to_str(l_stake_addr_signing)));
+                dap_chain_hash_fast_t l_pkey_signing = l_stake_addr_signing->data.hash_fast;
+                const char *l_pkey_signing_str = dap_strcmp(a_hash_out_type, "hex")
+                        ? dap_enc_base58_encode_hash_to_str_static(&l_pkey_signing)
+                        : dap_chain_hash_fast_to_str_static(&l_pkey_signing);
+                json_object_object_add(a_json_out, "Signing pkey fingerprint", json_object_new_string(l_pkey_signing_str));
+                break;
+            case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_NODE_ADDR:
+                if(l_tsd->size > sizeof(dap_chain_node_addr_t)){
+                    json_object_object_add(a_json_out, "Node addr", json_object_new_string("WRONG SIZE"));
+                    break;
+                }
+                dap_chain_node_addr_t *l_node_addr = _dap_tsd_get_object(l_tsd, dap_chain_node_addr_t);
+                sprintf(l_tmp_buff, NODE_ADDR_FP_STR, NODE_ADDR_FP_ARGS(l_node_addr));
+                json_object_object_add(a_json_out, "Node addr", json_object_new_string(l_tmp_buff));
+                break;
+            case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_MIN_VALUE:
+                if (l_tsd->size > sizeof(uint256_t)) {
+                    json_object_object_add(a_json_out, "Min value", json_object_new_string("WRONG SIZE"));
+                    break;
+                }
+                uint256_t l_min_value = uint256_0;
+                _dap_tsd_get_scalar(l_tsd, &l_min_value);
+                const char *l_min_value_str = dap_uint256_to_char(l_min_value, NULL);
+                json_object_object_add(a_json_out, "Min value", json_object_new_string(l_min_value_str));
+                break;
+            case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_MIN_SIGNERS_COUNT:
+                if (l_tsd->size > sizeof(uint256_t)) {
+                    json_object_object_add(a_json_out, "Min signers count", json_object_new_string("WRONG SIZE"));
+                    break;
+                }
+                uint256_t l_min_signers_count = uint256_0;
+                _dap_tsd_get_scalar(l_tsd, &l_min_signers_count);
+                const char *l_min_signers_count_str = dap_uint256_to_char(l_min_signers_count, NULL);
+                json_object_object_add(a_json_out, "Min signers count", json_object_new_string(l_min_signers_count_str));
+                break;
+            case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_HOST:
+            case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STRING:
+                json_object_object_add(a_json_out, "Host address", json_object_new_string(dap_tsd_get_string(l_tsd)));
+                break;
+            case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_ACTION:
+                if (l_tsd->size != sizeof(uint8_t)) {
+                    json_object_object_add(a_json_out, "Action", json_object_new_string("WRONG SIZE"));
+                    break;
+                }
+                uint8_t l_action = 0;
+                _dap_tsd_get_scalar(l_tsd, &l_action);
+                json_object_object_add(a_json_out, "tAction", l_action ?
+                                           json_object_new_string("add (enable)") : json_object_new_string("delete (disable)"));
+                break;
+            case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_SIGNATURE_TYPE:
+                if (l_tsd->size != sizeof(uint32_t)) {
+                    json_object_object_add(a_json_out, "Signature type", json_object_new_string("WRONG SIZE"));
+                    break;
+                }
+                uint32_t l_type = 0;
+                _dap_tsd_get_scalar(l_tsd, &l_type);
+                dap_sign_type_t l_sign_type = { .type = l_type };
+                json_object_object_add(a_json_out, "Signature type", json_object_new_string(dap_sign_type_to_str(l_sign_type)));
+                break;
+            default:
+                json_object_object_add(a_json_out, "UNKNOWN_TYPE_TSD_SECTION", json_object_new_string(""));
+                break;
+        }
+    }
+    dap_chain_datum_decree_certs_dump_json(a_json_out, a_decree->data_n_signs + a_decree->header.data_size,
+                                      a_decree->header.signs_size, a_hash_out_type);
+}
+
+void dap_chain_datum_decree_certs_dump_json(json_object * a_json_out, byte_t * a_signs, size_t a_certs_size, const char *a_hash_out_type)
+{
+    json_object_object_add(a_json_out, "signatures", json_object_new_string(""));
+    if (!a_certs_size) {
+        json_object_object_add(a_json_out, "Cert status", json_object_new_string("NONE"));
+        return;
+    }
+    json_object* json_arr_certs_out = json_object_new_array();
+    size_t l_offset = 0;
+    for (int i = 1; l_offset < (a_certs_size); i++) {
+        json_object* json_obj_sign = json_object_new_object();
+        dap_sign_t *l_sign = (dap_sign_t *) (a_signs + l_offset);
+        l_offset += dap_sign_get_size(l_sign);
+        if (l_sign->header.sign_size == 0) {
+            json_object_object_add(json_obj_sign, "sign status", json_object_new_string("CORRUPTED - 0 size signature"));
+            json_object_array_add(json_arr_certs_out, json_obj_sign);
+            continue;
+        }
+
+        dap_chain_hash_fast_t l_pkey_hash = {0};
+        if (dap_sign_get_pkey_hash(l_sign, &l_pkey_hash) == false) {
+            json_object_object_add(json_obj_sign, "sign status", json_object_new_string("CORRUPTED - can't calc hash"));
+            json_object_array_add(json_arr_certs_out, json_obj_sign);
+            continue;
+        }
+
+        const char *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);
+        json_object_object_add(json_obj_sign, "sign #", json_object_new_uint64(i));
+        json_object_object_add(json_obj_sign, "hash", json_object_new_string(l_hash_str));
+        json_object_object_add(json_obj_sign, "type", json_object_new_string(dap_sign_type_to_str(l_sign->header.type)));
+        json_object_object_add(json_obj_sign, "sign size", json_object_new_uint64(l_sign->header.sign_size));
+        json_object_array_add(json_arr_certs_out, json_obj_sign);        
+    }
+    json_object_object_add(a_json_out,"SIGNS", json_arr_certs_out);
+}
+
+dap_chain_datum_decree_t *dap_chain_datum_decree_new(dap_chain_net_id_t a_net_id, dap_chain_id_t a_chain_id,
+                                                     dap_chain_cell_id_t a_cell_id, size_t a_total_tsd_size)
+{
+    dap_chain_datum_decree_t *l_decree = NULL;
+    DAP_NEW_Z_SIZE_RET_VAL(l_decree, dap_chain_datum_decree_t, sizeof(dap_chain_datum_decree_t) + a_total_tsd_size, NULL, NULL);
+
+    l_decree->decree_version = DAP_CHAIN_DATUM_DECREE_VERSION;
+    l_decree->header.ts_created = dap_time_now();
+    l_decree->header.type = DAP_CHAIN_DATUM_DECREE_TYPE_COMMON;
+    l_decree->header.common_decree_params.net_id = a_net_id;
+    l_decree->header.common_decree_params.chain_id = a_chain_id;
+    l_decree->header.common_decree_params.cell_id = a_cell_id;
+    l_decree->header.data_size = a_total_tsd_size;
+    return l_decree;
+}
+
+dap_chain_datum_decree_t *dap_chain_datum_decree_sign_in_cycle(dap_cert_t **a_certs, dap_chain_datum_decree_t *a_datum_decree,
                                                   size_t a_certs_count, size_t *a_total_sign_count)
 {
     size_t l_cur_sign_offset = a_datum_decree->header.data_size + a_datum_decree->header.signs_size;
     size_t l_total_signs_size = a_datum_decree->header.signs_size, l_total_sign_count = 0;
 
-    for(size_t i = 0; i < a_certs_count; i++)
-    {
-        dap_sign_t * l_sign = dap_cert_sign(a_certs[i],  a_datum_decree,
+    for(size_t i = 0; i < a_certs_count; i++) {
+        dap_sign_t * l_sign = dap_cert_sign(a_certs[i], a_datum_decree,
                                             sizeof(dap_chain_datum_decree_t) + a_datum_decree->header.data_size, 0);
-
-        if (l_sign) {
-            size_t l_sign_size = dap_sign_get_size(l_sign);
-            a_datum_decree = DAP_REALLOC(a_datum_decree, sizeof(dap_chain_datum_decree_t) + l_cur_sign_offset + l_sign_size);
-            memcpy((byte_t*)a_datum_decree->data_n_signs + l_cur_sign_offset, l_sign, l_sign_size);
-            l_total_signs_size += l_sign_size;
-            l_cur_sign_offset += l_sign_size;
-            a_datum_decree->header.signs_size = l_total_signs_size;
+        if (!l_sign) {
+            log_it(L_ERROR, "Decree signing failed");
+            DAP_DELETE(a_datum_decree);
+            return NULL;
+        }
+        size_t l_sign_size = dap_sign_get_size(l_sign);
+        a_datum_decree = DAP_REALLOC(a_datum_decree, sizeof(dap_chain_datum_decree_t) + l_cur_sign_offset + l_sign_size);
+        if (!a_datum_decree) {
+            log_it(L_CRITICAL, "%s", g_error_memory_alloc);
             DAP_DELETE(l_sign);
-            log_it(L_DEBUG,"<-- Signed with '%s'", a_certs[i]->name);
-            l_total_sign_count++;
+            return NULL;
         }
+        memcpy(a_datum_decree->data_n_signs + l_cur_sign_offset, l_sign, l_sign_size);
+        DAP_DELETE(l_sign);
+        l_total_signs_size += l_sign_size;
+        l_cur_sign_offset += l_sign_size;
+        a_datum_decree->header.signs_size = l_total_signs_size;
+        log_it(L_DEBUG,"<-- Signed with '%s'", a_certs[i]->name);
+        l_total_sign_count++;
     }
-
-    *a_total_sign_count = l_total_sign_count;
+    if (a_total_sign_count)
+        *a_total_sign_count = l_total_sign_count;
     return a_datum_decree;
 }
diff --git a/modules/common/dap_chain_datum_tx_items.c b/modules/common/dap_chain_datum_tx_items.c
index 83b2c2cb79586aaa8664531515fa99cd92742aa9..6f5b32842a2ad59997ee77c6532bf514e14674ae 100644
--- a/modules/common/dap_chain_datum_tx_items.c
+++ b/modules/common/dap_chain_datum_tx_items.c
@@ -34,6 +34,7 @@
 #include "dap_chain_datum_tx_items.h"
 #include "dap_chain_datum_tx_voting.h"
 
+#define LOG_TAG "dap_chain_datum_tx_items"
 
 static size_t dap_chain_tx_in_get_size(const dap_chain_tx_in_t *a_item)
 {
@@ -696,3 +697,152 @@ uint8_t *dap_chain_datum_tx_out_get_by_out_idx(dap_chain_datum_tx_t *a_tx, int a
     return l_ret;
 
 }
+
+void dap_chain_datum_tx_group_items_free( dap_chain_datum_tx_item_groups_t *a_items_groups)
+{   
+    if (a_items_groups->items_in) dap_list_free(a_items_groups->items_in);
+    if (a_items_groups->items_in_cond) dap_list_free(a_items_groups->items_in_cond);
+    if (a_items_groups->items_in_reward) dap_list_free(a_items_groups->items_in_reward);
+    if (a_items_groups->items_sig) dap_list_free(a_items_groups->items_sig);
+    if (a_items_groups->items_out) dap_list_free(a_items_groups->items_out);
+    if (a_items_groups->items_out_ext) dap_list_free(a_items_groups->items_out_ext);
+    if (a_items_groups->items_out_cond) dap_list_free(a_items_groups->items_out_cond);
+    if (a_items_groups->items_out_cond_srv_fee) dap_list_free(a_items_groups->items_out_cond_srv_fee);
+    if (a_items_groups->items_out_cond_srv_pay) dap_list_free(a_items_groups->items_out_cond_srv_pay);
+    if (a_items_groups->items_out_cond_srv_xchange) dap_list_free(a_items_groups->items_out_cond_srv_xchange);
+    if (a_items_groups->items_out_cond_srv_stake_pos_delegate) dap_list_free(a_items_groups->items_out_cond_srv_stake_pos_delegate);
+    if (a_items_groups->items_out_cond_srv_stake_lock) dap_list_free(a_items_groups->items_out_cond_srv_stake_lock);
+    if (a_items_groups->items_in_ems) dap_list_free(a_items_groups->items_in_ems);
+    if (a_items_groups->items_vote) dap_list_free(a_items_groups->items_vote);
+    if (a_items_groups->items_voting) dap_list_free(a_items_groups->items_voting);
+    if (a_items_groups->items_tsd) dap_list_free(a_items_groups->items_tsd);
+    if (a_items_groups->items_pkey) dap_list_free(a_items_groups->items_pkey);
+    if (a_items_groups->items_receipt) dap_list_free(a_items_groups->items_receipt);
+    if (a_items_groups->items_unknown) dap_list_free(a_items_groups->items_unknown);
+    if (a_items_groups->items_out_old) dap_list_free(a_items_groups->items_out_old);
+    if (a_items_groups->items_out_cond_unknonwn) dap_list_free(a_items_groups->items_out_cond_unknonwn);
+    if (a_items_groups->items_out_cond_undefined) dap_list_free(a_items_groups->items_out_cond_undefined);
+    if (a_items_groups->items_out_all) dap_list_free(a_items_groups->items_out_all);
+    if (a_items_groups->items_in_all) dap_list_free(a_items_groups->items_in_all);
+}
+
+#define DAP_LIST_SAPPEND(X, Y) X = dap_list_append(X,Y)
+bool dap_chain_datum_tx_group_items(dap_chain_datum_tx_t *a_tx, dap_chain_datum_tx_item_groups_t *a_res_group)
+{   
+    
+    if(!a_tx || !a_res_group)
+        return NULL;
+    
+    uint32_t l_tx_items_pos = 0, l_tx_items_size = a_tx->header.tx_items_size;
+
+    int l_item_idx = 0;
+
+    while (l_tx_items_pos < l_tx_items_size) {
+
+        uint8_t *l_item = a_tx->tx_items + l_tx_items_pos;
+        int l_item_size = dap_chain_datum_item_tx_get_size(l_item);
+        
+        if(!l_item_size)
+            return false;
+        
+        dap_chain_tx_item_type_t l_type = dap_chain_datum_tx_item_get_type(l_item);
+        
+        switch (l_type)
+        {
+            case TX_ITEM_TYPE_IN:
+                DAP_LIST_SAPPEND(a_res_group->items_in, l_item);
+                DAP_LIST_SAPPEND(a_res_group->items_in_all, l_item);
+                break;
+
+            case TX_ITEM_TYPE_IN_COND:
+                DAP_LIST_SAPPEND(a_res_group->items_in_cond, l_item);
+                DAP_LIST_SAPPEND(a_res_group->items_in_all, l_item);
+                break;
+
+            case TX_ITEM_TYPE_IN_REWARD:
+                DAP_LIST_SAPPEND(a_res_group->items_in_reward, l_item);
+                DAP_LIST_SAPPEND(a_res_group->items_in_all, l_item);
+                break;
+
+            case TX_ITEM_TYPE_IN_EMS:
+                DAP_LIST_SAPPEND(a_res_group->items_in_ems, l_item);
+                DAP_LIST_SAPPEND(a_res_group->items_in_all, l_item);
+                break;
+
+            case TX_ITEM_TYPE_OUT_OLD:
+                DAP_LIST_SAPPEND(a_res_group->items_out_old, l_item);
+                DAP_LIST_SAPPEND(a_res_group->items_out_all, l_item);
+                break;
+
+            case TX_ITEM_TYPE_OUT_EXT:
+                DAP_LIST_SAPPEND(a_res_group->items_out_ext, l_item);
+                DAP_LIST_SAPPEND(a_res_group->items_out_all, l_item);
+                break;
+
+            case TX_ITEM_TYPE_OUT:
+                DAP_LIST_SAPPEND(a_res_group->items_out, l_item);
+                DAP_LIST_SAPPEND(a_res_group->items_out_all, l_item);
+                break;
+
+            case TX_ITEM_TYPE_OUT_COND: {
+                switch ( ((dap_chain_tx_out_cond_t *)l_item)->header.subtype )
+                {
+                    case DAP_CHAIN_TX_OUT_COND_SUBTYPE_UNDEFINED:
+                        DAP_LIST_SAPPEND(a_res_group->items_out_cond_undefined, l_item);
+                        break;
+                    case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY:
+                        DAP_LIST_SAPPEND(a_res_group->items_out_cond_srv_pay, l_item);
+                        break;
+                    case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE:
+                        DAP_LIST_SAPPEND(a_res_group->items_out_cond_srv_xchange, l_item);
+                        break;
+                    case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE:
+                        DAP_LIST_SAPPEND(a_res_group->items_out_cond_srv_stake_pos_delegate, l_item);
+                        break;
+                    case DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE:
+                        DAP_LIST_SAPPEND(a_res_group->items_out_cond_srv_fee, l_item);
+                        break;
+                    case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK:
+                        DAP_LIST_SAPPEND(a_res_group->items_out_cond_srv_stake_lock, l_item);
+                        break;
+                    default:
+                        DAP_LIST_SAPPEND(a_res_group->items_out_cond_unknonwn, l_item);
+                        break;
+                }
+
+                DAP_LIST_SAPPEND(a_res_group->items_out_cond, l_item);
+                DAP_LIST_SAPPEND(a_res_group->items_out_all, l_item);
+                }
+                break;
+
+            case TX_ITEM_TYPE_PKEY:
+                DAP_LIST_SAPPEND(a_res_group->items_pkey, l_item);
+                break;
+            case TX_ITEM_TYPE_SIG:
+                DAP_LIST_SAPPEND(a_res_group->items_sig, l_item);
+                break;
+            case TX_ITEM_TYPE_RECEIPT:
+                DAP_LIST_SAPPEND(a_res_group->items_receipt, l_item);
+                break;
+            case TX_ITEM_TYPE_TSD:
+                DAP_LIST_SAPPEND(a_res_group->items_tsd, l_item);
+                break;
+
+            case TX_ITEM_TYPE_VOTING:
+                DAP_LIST_SAPPEND(a_res_group->items_voting, l_item);
+                break;
+
+            case TX_ITEM_TYPE_VOTE:
+                DAP_LIST_SAPPEND(a_res_group->items_vote, l_item);
+                break;
+            default:
+                DAP_LIST_SAPPEND(a_res_group->items_unknown, l_item);
+        }
+        
+        l_tx_items_pos += l_item_size;
+        l_item_idx++;
+    }
+    
+    return true;
+
+}
diff --git a/modules/common/include/dap_chain_common.h b/modules/common/include/dap_chain_common.h
index fe9cebf3cc00646789cb6f1b5ecf23ba3e1d967c..a6e9143468133b9c46045e0af2ee24082f0f2550 100644
--- a/modules/common/include/dap_chain_common.h
+++ b/modules/common/include/dap_chain_common.h
@@ -30,10 +30,8 @@
 #include "dap_math_ops.h"
 #include "dap_math_convert.h"
 #include "dap_enc_key.h"
-#include "dap_pkey.h"
 #include "dap_sign.h"
 #include "dap_hash.h"
-#include "json.h"
 #include "dap_strfuncs.h"
 
 #define DAP_CHAIN_ADDR_VERSION_CURRENT 1
@@ -200,7 +198,7 @@ extern "C" {
 
 size_t dap_chain_hash_slow_to_str(dap_chain_hash_slow_t * a_hash, char * a_str, size_t a_str_max);
 
-char* dap_chain_addr_to_str(const dap_chain_addr_t *a_addr);
+const char *dap_chain_addr_to_str(const dap_chain_addr_t *a_addr);
 dap_chain_addr_t* dap_chain_addr_from_str(const char *str);
 bool dap_chain_addr_is_blank(const dap_chain_addr_t *a_addr);
 
diff --git a/modules/common/include/dap_chain_datum.h b/modules/common/include/dap_chain_datum.h
index c3be81a88aeea7a52b0a01a1d98a3ccd6aabb8da..d9df56a67ef7a469df6992b15ecc4eff0aec3bc7 100644
--- a/modules/common/include/dap_chain_datum.h
+++ b/modules/common/include/dap_chain_datum.h
@@ -25,11 +25,9 @@
 #pragma once
 #include <stdint.h>
 #include "dap_common.h"
-#include "dap_math_ops.h"
 #include "dap_chain_common.h"
 #include "dap_chain_datum_tx.h"
 #include "dap_chain_datum_token.h"
-#include "json.h"
 
 #define DAP_CHAIN_DATUM_VERSION 0x00
 
@@ -162,4 +160,11 @@ bool dap_chain_datum_dump_tx(dap_chain_datum_tx_t *a_datum,
                              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(dap_chain_datum_tx_t *a_datum,
+                             const char *a_ticker,
+                             json_object* json_obj_out,
+                             const char *a_hash_out_type,
+                             dap_hash_fast_t *a_tx_hash,
+                             dap_chain_net_id_t a_net_id);
 json_object * dap_chain_datum_to_json(dap_chain_datum_t* a_datum);
+void dap_chain_datum_dump_json(json_object  *a_obj_out, dap_chain_datum_t *a_datum, const char *a_hash_out_type, dap_chain_net_id_t a_net_id);
diff --git a/modules/common/include/dap_chain_datum_anchor.h b/modules/common/include/dap_chain_datum_anchor.h
index 044b8165f68ac20636796a08fb6da920556c9d23..16c1ab915990752fbdae51a3851f621c2981dda8 100644
--- a/modules/common/include/dap_chain_datum_anchor.h
+++ b/modules/common/include/dap_chain_datum_anchor.h
@@ -51,3 +51,5 @@ DAP_STATIC_INLINE size_t dap_chain_datum_anchor_get_size(dap_chain_datum_anchor_
 int dap_chain_datum_anchor_get_hash_from_data(dap_chain_datum_anchor_t* a_anchor, dap_hash_fast_t * l_out_hash);
 void dap_chain_datum_anchor_certs_dump(dap_string_t * a_str_out, byte_t * a_signs,
                                        size_t a_certs_size, const char *a_hash_out_type);
+
+void dap_chain_datum_anchor_certs_dump_json(json_object * a_json_out, byte_t * a_signs, size_t a_certs_size, const char *a_hash_out_type);
diff --git a/modules/common/include/dap_chain_datum_decree.h b/modules/common/include/dap_chain_datum_decree.h
index 42964d99c508c3717876134c261584b57ca79b77..f8f40ea74fbd7f417d455d0f3b3f7729d280890a 100644
--- a/modules/common/include/dap_chain_datum_decree.h
+++ b/modules/common/include/dap_chain_datum_decree.h
@@ -26,7 +26,6 @@
 #include "dap_math_ops.h"
 #include "dap_time.h"
 #include "dap_list.h"
-#include "dap_tsd.h"
 #include "dap_cert.h"
 #include <stdint.h>
 
@@ -73,6 +72,9 @@ DAP_STATIC_INLINE size_t dap_chain_datum_decree_get_size(dap_chain_datum_decree_
 #define DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_BAN                           0x0009
 #define DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_UNBAN                         0x000A
 #define DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_REWARD                        0x000B
+#define DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_MAX_WEIGHT                    0x000C
+#define DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_EMERGENCY_VALIDATORS          0x000D
+#define DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_CHECK_SIGNS_STRUCTURE         0x000E
 
 // DECREE TSD types
 #define DAP_CHAIN_DATUM_DECREE_TSD_TYPE_VALUE                               0x0100
@@ -81,14 +83,16 @@ DAP_STATIC_INLINE size_t dap_chain_datum_decree_get_size(dap_chain_datum_decree_
 #define DAP_CHAIN_DATUM_DECREE_TSD_TYPE_OWNER                               0x0103
 #define DAP_CHAIN_DATUM_DECREE_TSD_TYPE_MIN_OWNER                           0x0104
 #define DAP_CHAIN_DATUM_DECREE_TSD_TYPE_FEE_WALLET                          0x0106
-#define DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_TX_HASH                       0x0107
+#define DAP_CHAIN_DATUM_DECREE_TSD_TYPE_HASH                                0x0107
 #define DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_VALUE                         0x0108
 #define DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_SIGNING_ADDR                  0x0109
-#define DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_SIGNER_NODE_ADDR              0x0110
+#define DAP_CHAIN_DATUM_DECREE_TSD_TYPE_NODE_ADDR                           0x0110
 #define DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_MIN_VALUE                     0x0111
 #define DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_MIN_SIGNERS_COUNT             0x0112
 #define DAP_CHAIN_DATUM_DECREE_TSD_TYPE_HOST                                0x0113
-#define DAP_CHAIN_DATUM_DECREE_TSD_TYPE_NODE_ADDR                           0x0115
+#define DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STRING                              0x0115
+#define DAP_CHAIN_DATUM_DECREE_TSD_TYPE_ACTION                              0x010A
+#define DAP_CHAIN_DATUM_DECREE_TSD_TYPE_SIGNATURE_TYPE                      0x010B
 
 DAP_STATIC_INLINE const char *dap_chain_datum_decree_subtype_to_str(uint16_t a_decree_subtype)
 {
@@ -113,6 +117,12 @@ DAP_STATIC_INLINE const char *dap_chain_datum_decree_subtype_to_str(uint16_t a_d
         return "DECREE_COMMON_SUBTYPE_UNBAN";
     case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_REWARD:
         return "DECREE_COMMON_SUBTYPE_REWARD";
+    case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_MAX_WEIGHT:
+        return "DECREE_COMMON_SUBTYPE_VALIDATOR_MAX_WEIGHT";
+    case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_EMERGENCY_VALIDATORS:
+        return "DECREE_COMMON_SUBTYPE_EMERGENCY_VALIDATORS";
+    case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_CHECK_SIGNS_STRUCTURE:
+        return "DECREE_COMMON_SUBTYPE_CHECK_SIGNS_STRUCTURE";
     default:
         return "DECREE_SUBTYPE_UNKNOWN";
     }
@@ -120,39 +130,45 @@ DAP_STATIC_INLINE const char *dap_chain_datum_decree_subtype_to_str(uint16_t a_d
 
 DAP_STATIC_INLINE const char *dap_chain_datum_decree_tsd_type_to_str(uint16_t a_decree_tsd_type) {
     switch (a_decree_tsd_type) {
-        case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_VALUE:
-            return "DAP_CHAIN_DATUM_DECREE_TSD_TYPE_VALUE";
-        case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_SIGN:
-            return "DAP_CHAIN_DATUM_DECREE_TSD_TYPE_SIGN";
-        case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_FEE:
-            return "DAP_CHAIN_DATUM_DECREE_TSD_TYPE_FEE";
-        case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_OWNER:
-            return "DAP_CHAIN_DATUM_DECREE_TSD_TYPE_OWNER";
-        case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_MIN_OWNER:
-            return "DAP_CHAIN_DATUM_DECREE_TSD_TYPE_MIN_OWNER";
-        case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_FEE_WALLET:
-            return "DAP_CHAIN_DATUM_DECREE_TSD_TYPE_FEE_WALLET";
-        case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_TX_HASH:
-            return "DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_TX_HASH";
-        case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_VALUE:
-            return "DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_VALUE";
-        case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_SIGNING_ADDR:
-            return "DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_SIGNING_ADDR";
-        case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_SIGNER_NODE_ADDR:
-            return "DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_SIGNER_NODE_ADDR";
-        case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_MIN_VALUE:
-            return "DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_MIN_VALUE";
-        case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_MIN_SIGNERS_COUNT:
-            return "DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_MIN_SIGNERS_COUNT";
-        case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_HOST:
-            return "DAP_CHAIN_DATUM_DECREE_TSD_TYPE_HOST";
-        case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_NODE_ADDR:
-            return "DAP_CHAIN_DATUM_DECREE_TSD_TYPE_NODE_ADDR";
-        default:
-            return "DECREE_TSD_TYPE_UNKNOWN";
+    case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_VALUE:
+        return "DAP_CHAIN_DATUM_DECREE_TSD_TYPE_VALUE";
+    case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_SIGN:
+        return "DAP_CHAIN_DATUM_DECREE_TSD_TYPE_SIGN";
+    case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_FEE:
+        return "DAP_CHAIN_DATUM_DECREE_TSD_TYPE_FEE";
+    case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_OWNER:
+        return "DAP_CHAIN_DATUM_DECREE_TSD_TYPE_OWNER";
+    case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_MIN_OWNER:
+        return "DAP_CHAIN_DATUM_DECREE_TSD_TYPE_MIN_OWNER";
+    case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_FEE_WALLET:
+        return "DAP_CHAIN_DATUM_DECREE_TSD_TYPE_FEE_WALLET";
+    case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_HASH:
+        return "DAP_CHAIN_DATUM_DECREE_TSD_TYPE_HASH";
+    case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_VALUE:
+        return "DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_VALUE";
+    case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_SIGNING_ADDR:
+        return "DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_SIGNING_ADDR";
+    case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_NODE_ADDR:
+        return "DAP_CHAIN_DATUM_DECREE_TSD_TYPE_NODE_ADDR";
+    case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_MIN_VALUE:
+        return "DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_MIN_VALUE";
+    case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_MIN_SIGNERS_COUNT:
+        return "DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_MIN_SIGNERS_COUNT";
+    case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_HOST:
+        return "DAP_CHAIN_DATUM_DECREE_TSD_TYPE_HOST";
+    case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STRING:
+        return "DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STRING";
+    case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_ACTION:
+         return "DAP_CHAIN_DATUM_DECREE_TSD_TYPE_ACTION";
+    case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_SIGNATURE_TYPE:
+         return "DAP_CHAIN_DATUM_DECREE_TSD_TYPE_SIGNATURE_TYPE";
+    default:
+        return "DECREE_TSD_TYPE_UNKNOWN";
     }
 }
 
+dap_chain_datum_decree_t *dap_chain_datum_decree_new(dap_chain_net_id_t a_net_id, dap_chain_id_t a_chain_id,
+                                                     dap_chain_cell_id_t a_cell_id, size_t a_total_tsd_size);
 /**
  * @brief dap_chain_datum_decree_get_signs
  * @param decree pointer to decree
@@ -192,7 +208,7 @@ dap_list_t *dap_chain_datum_decree_get_owners(dap_chain_datum_decree_t *a_decree
  * @param a_owners_num pointer to minimum number of owners buffer
  * @return result code. 0 - success
  */
-int dap_chain_datum_decree_get_min_owners(dap_chain_datum_decree_t *a_decree, uint16_t *a_min_owners_num);
+int dap_chain_datum_decree_get_min_owners(dap_chain_datum_decree_t *a_decree, uint256_t *a_min_owners_num);
 
 /**
  * @brief dap_chain_datum_decree_get_tx_hash get stake tx hash
@@ -200,7 +216,7 @@ int dap_chain_datum_decree_get_min_owners(dap_chain_datum_decree_t *a_decree, ui
  * @param a_tx_hash pointer to tx hash buffer
  * @return result code. 0 - success
  */
-int dap_chain_datum_decree_get_stake_tx_hash(dap_chain_datum_decree_t *a_decree, dap_hash_fast_t *a_tx_hash);
+int dap_chain_datum_decree_get_hash(dap_chain_datum_decree_t *a_decree, dap_hash_fast_t *a_tx_hash);
 
 /**
  * @brief dap_chain_datum_decree_get_stake_value get stake value
@@ -250,6 +266,9 @@ int dap_chain_datum_decree_get_stake_min_value(dap_chain_datum_decree_t *a_decre
  * @return result code. 0 - success
  */
 int dap_chain_datum_decree_get_stake_min_signers_count(dap_chain_datum_decree_t *a_decree, uint256_t *a_min_signers_count);
+int dap_chain_datum_decree_get_action(dap_chain_datum_decree_t *a_decree, uint8_t *a_action);
+int dap_chain_datum_decree_get_signature_type(dap_chain_datum_decree_t *a_decree, uint32_t *a_signature_type);
+int dap_chain_datum_decree_get_ban_addr(dap_chain_datum_decree_t *a_decree, const char **a_addr);
 
 /**
  * @breif dap_chain_datum_decree_dump Dump information about decree
@@ -260,6 +279,15 @@ int dap_chain_datum_decree_get_stake_min_signers_count(dap_chain_datum_decree_t
  */
 void dap_chain_datum_decree_dump(dap_string_t *a_str_out, dap_chain_datum_decree_t *a_decree, size_t a_decree_size, const char *a_hash_out_type);
 
+/**
+ * @breif dap_chain_datum_decree_dump Dump information about decree
+ * @param a_obj_out pointer to output json object
+ * @param a_decree pointer to decree
+ * @param a_decree_size size data
+ * @param a_hash_out_type
+ */
+void dap_chain_datum_decree_dump_json(json_object  *a_obj_out, dap_chain_datum_decree_t *a_decree, size_t a_decree_size, const char *a_hash_out_type);
+
 /**
  * @brief dap_chain_datum_decree_certs_dump compose decree signatures output string
  * @param a_str_out pointer to output text buffer
@@ -268,6 +296,8 @@ void dap_chain_datum_decree_dump(dap_string_t *a_str_out, dap_chain_datum_decree
  */
 void dap_chain_datum_decree_certs_dump(dap_string_t * a_str_out, byte_t * a_signs, size_t a_certs_size, const char *a_hash_out_type);
 
+void dap_chain_datum_decree_certs_dump_json(json_object * a_json_out, byte_t * a_signs, size_t a_certs_size, const char *a_hash_out_type);
+
 /**
  * @brief dap_chain_datum_decree_sign_in_cycle
  * sign data (datum_decree) by certificates (1 or more)
diff --git a/modules/common/include/dap_chain_datum_token.h b/modules/common/include/dap_chain_datum_token.h
index 4fb52984e1bc6c68a1e32c84da0434cdd57fa4d9..e993e219a04ba91d4d17bc605cb60def9943938c 100644
--- a/modules/common/include/dap_chain_datum_token.h
+++ b/modules/common/include/dap_chain_datum_token.h
@@ -500,6 +500,22 @@ typedef struct dap_chain_datum_token_emission {
 #define DAP_CHAIN_DATUM_EMISSION_TSD_TYPE_UNIQUE_ID         0x000F
 #define DAP_CHAIN_DATUM_EMISSION_TSD_TYPE_BASE_TX_HASH      0x0010
 
+#define DAP_CHAIN_DATUM_TOKEN_EMISSION_SOURCE_STAKING "STAKING"
+#define DAP_CHAIN_DATUM_TOKEN_EMISSION_SOURCE_SUBTYPE_STAKING_STAKE_CROSSCHAIN "CONTRACT"
+#define DAP_CHAIN_DATUM_TOKEN_EMISSION_SOURCE_SUBTYPE_STAKING_STAKE_CROSSCHAINV2 "CONTRACT_NFT"
+#define DAP_CHAIN_DATUM_TOKEN_EMISSION_SOURCE_SUBTYPE_STAKING_HARVEST "HARVEST"
+#define DAP_CHAIN_DATUM_TOKEN_EMISSION_SOURCE_SUBTYPE_STAKING_ADDLIQ "ADDLIQ"
+#define DAP_CHAIN_DATUM_TOKEN_EMISSION_SOURCE_SUBTYPE_STAKING_EMSFIX "EMSFIX"
+#define DAP_CHAIN_DATUM_TOKEN_EMISSION_SOURCE_SUBTYPE_STAKING_BONUS "BONUS"
+#define DAP_CHAIN_DATUM_TOKEN_EMISSION_SOURCE_SUBTYPE_STAKING_UNSTAKE_FINALIZATION "UNSTAKE"
+
+#define DAP_CHAIN_DATUM_TOKEN_EMISSION_SOURCE_BRIDGE "BRIDGE"
+#define DAP_CHAIN_DATUM_TOKEN_EMISSION_SOURCE_SUBTYPE_BRIDGE_TRANSFER "TO_WALLET"
+#define DAP_CHAIN_DATUM_TOKEN_EMISSION_SOURCE_SUBTYPE_BRIDGE_COMMISSION_OLD "COMISSION"
+#define DAP_CHAIN_DATUM_TOKEN_EMISSION_SOURCE_SUBTYPE_BRIDGE_COMMISSION "COMMISSION"
+#define DAP_CHAIN_DATUM_TOKEN_EMISSION_SOURCE_SUBTYPE_BRIDGE_CROSSCHAIN "CROSSCHAIN"
+
+
 extern const char *c_dap_chain_datum_token_emission_type_str[];
 
 /// TDS op funcs
diff --git a/modules/common/include/dap_chain_datum_tx.h b/modules/common/include/dap_chain_datum_tx.h
index 87776da8f6d5d02eda7f1b7206ea8799a39848c6..3473e3ffe8585db8c1bd5bb1c600ba26e14c473d 100644
--- a/modules/common/include/dap_chain_datum_tx.h
+++ b/modules/common/include/dap_chain_datum_tx.h
@@ -27,7 +27,7 @@
 #include "dap_enc_key.h"
 #include "dap_chain_common.h"
 #include "dap_time.h"
-#include "json.h"
+#include "dap_pkey.h"
 
 /**
   * @struct dap_chain_datum_tx
@@ -153,6 +153,5 @@ dap_sign_t *dap_chain_datum_tx_get_sign(dap_chain_datum_tx_t *a_tx, int a_sign_n
  */
 int dap_chain_datum_tx_verify_sign(dap_chain_datum_tx_t *a_tx);
 
-//json_object *dap_chain_datum_tx_to_json(dap_chain_datum_tx_t *a_tx);
 
 int dap_chain_datum_tx_get_fee_value (dap_chain_datum_tx_t *a_tx, uint256_t *a_value);
diff --git a/modules/common/include/dap_chain_datum_tx_items.h b/modules/common/include/dap_chain_datum_tx_items.h
index 8c312f097c12534c14ae0ef9c88fbaed7848fa6a..b81995e3ff6865e041c58484cac38062c6330249 100644
--- a/modules/common/include/dap_chain_datum_tx_items.h
+++ b/modules/common/include/dap_chain_datum_tx_items.h
@@ -85,6 +85,42 @@ DAP_STATIC_INLINE const char * dap_chain_datum_tx_item_type_to_str(dap_chain_tx_
     }
 }
 
+typedef struct dap_chain_datum_tx_item_groups {
+
+    dap_list_t *items_in_all;
+    dap_list_t *items_in;
+    dap_list_t *items_in_cond;
+    dap_list_t *items_in_reward;
+    dap_list_t *items_sig;
+
+    
+    dap_list_t *items_out;
+    dap_list_t *items_out_all;
+    dap_list_t *items_out_old;
+    dap_list_t *items_out_ext;
+    dap_list_t *items_out_cond;
+    dap_list_t *items_out_cond_srv_fee;
+    dap_list_t *items_out_cond_srv_pay;
+    dap_list_t *items_out_cond_srv_xchange;
+    dap_list_t *items_out_cond_srv_stake_pos_delegate;
+    dap_list_t *items_out_cond_srv_stake_lock;
+    dap_list_t *items_out_cond_unknonwn;
+    dap_list_t *items_out_cond_undefined;
+    
+    dap_list_t *items_in_ems;
+    dap_list_t *items_vote;
+    dap_list_t *items_voting;
+    dap_list_t *items_tsd;
+    dap_list_t *items_pkey;
+    dap_list_t *items_receipt;
+
+    dap_list_t *items_unknown;
+
+} dap_chain_datum_tx_item_groups_t;
+
+bool dap_chain_datum_tx_group_items(dap_chain_datum_tx_t *a_tx,  dap_chain_datum_tx_item_groups_t *a_res_group);
+void dap_chain_datum_tx_group_items_free( dap_chain_datum_tx_item_groups_t *a_group);
+
 /**
  * Get item type by item name
  *
diff --git a/modules/common/include/dap_chain_datum_tx_out_cond.h b/modules/common/include/dap_chain_datum_tx_out_cond.h
index 85414a2fabea9b3328bdd20e69617c86b0d6ca45..f8dd739dd37c84b8e468d0ddb64b269bbda41cb2 100644
--- a/modules/common/include/dap_chain_datum_tx_out_cond.h
+++ b/modules/common/include/dap_chain_datum_tx_out_cond.h
@@ -28,7 +28,6 @@
 #include "dap_common.h"
 #include "dap_time.h"
 #include "dap_chain_common.h"
-#include "dap_chain_datum_tx.h"
 
 enum dap_chain_tx_out_cond_subtype {
     DAP_CHAIN_TX_OUT_COND_SUBTYPE_UNDEFINED = 0x0,
diff --git a/modules/consensus/block-poa/dap_chain_cs_block_poa.c b/modules/consensus/block-poa/dap_chain_cs_block_poa.c
index 6498631906238d2b6540062ecd5d9e2e8519b1ae..d36958cfc24183c9e148b7a530608ba212a452ea 100644
--- a/modules/consensus/block-poa/dap_chain_cs_block_poa.c
+++ b/modules/consensus/block-poa/dap_chain_cs_block_poa.c
@@ -112,11 +112,12 @@ static int s_cli_block_poa(int argc, char ** argv, void **a_str_reply)
         return -1;
     }
 
-    if (dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index,argc,argv,a_str_reply,&l_chain,&l_chain_net)){
+    if (dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index,argc,argv,a_str_reply,&l_chain,&l_chain_net,
+                                                      CHAIN_TYPE_INVALID)){
         return -3;
     }
 
-    const char *l_chain_type = dap_chain_net_get_type(l_chain);
+    const char *l_chain_type = dap_chain_get_cs_type(l_chain);
     if (strcmp(l_chain_type, "block_poa")){
             dap_cli_server_cmd_set_reply_text(a_str_reply,
                         "Type of chain %s is not block_poa. This chain with type %s is not supported by this command",
@@ -211,9 +212,9 @@ static int s_callback_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg)
             }
             char l_cert_name[512];
             for (size_t i = 0; i < l_poa_pvt->auth_certs_count ; i++ ){
-                snprintf(l_cert_name,sizeof(l_cert_name),"%s.%zu",l_poa_pvt->auth_certs_prefix, i);
+                snprintf(l_cert_name, sizeof(l_cert_name), "%s.%zu",l_poa_pvt->auth_certs_prefix, i);
                 if ((l_poa_pvt->auth_certs[i] = dap_cert_find_by_name( l_cert_name)) == NULL) {
-                    snprintf(l_cert_name,sizeof(l_cert_name),"%s.%zu.pub",l_poa_pvt->auth_certs_prefix, i);
+                    snprintf(l_cert_name, sizeof(l_cert_name), "%s.%zu.pub",l_poa_pvt->auth_certs_prefix, i);
                     if ((l_poa_pvt->auth_certs[i] = dap_cert_find_by_name( l_cert_name)) == NULL) {
                         log_it(L_ERROR, "Can't find cert \"%s\"", l_cert_name);
                         return -1;
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 40f10dc4c5b9a9f498eaf2eb2cad2ce5c7524c99..2aaac68b091d488e62da30ecdb513f22b6efe50a 100644
--- a/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c
+++ b/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c
@@ -190,11 +190,12 @@ static int s_cli_dag_poa(int argc, char ** argv, void **a_str_reply)
         return -1;
     }
 
-    if (dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index,argc,argv,a_str_reply,&l_chain,&l_chain_net)) {
+    if (dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index,argc,argv,a_str_reply,&l_chain,&l_chain_net,
+                                                      CHAIN_TYPE_INVALID)) {
         return -3;
     }
 
-    const char *l_chain_type = dap_chain_net_get_type(l_chain);
+    const char *l_chain_type = dap_chain_get_cs_type(l_chain);
 
     if (strcmp(l_chain_type, "dag_poa")){
             dap_cli_server_cmd_set_reply_text(a_str_reply,
@@ -378,9 +379,9 @@ static int s_callback_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg)
             }
             char l_cert_name[512];
             for (size_t i = 0; i < l_poa_pvt->auth_certs_count ; i++ ){
-                snprintf(l_cert_name,sizeof(l_cert_name),"%s.%zu",l_poa_pvt->auth_certs_prefix, i);
+                snprintf(l_cert_name, sizeof(l_cert_name), "%s.%zu",l_poa_pvt->auth_certs_prefix, i);
                 if ((l_poa_pvt->auth_certs[i] = dap_cert_find_by_name( l_cert_name)) == NULL) {
-                    snprintf(l_cert_name,sizeof(l_cert_name),"%s.%zu.pub",l_poa_pvt->auth_certs_prefix, i);
+                    snprintf(l_cert_name, sizeof(l_cert_name), "%s.%zu.pub",l_poa_pvt->auth_certs_prefix, i);
                     if ((l_poa_pvt->auth_certs[i] = dap_cert_find_by_name( l_cert_name)) == NULL) {
                         log_it(L_ERROR, "Can't find cert \"%s\"", l_cert_name);
                         return -1;
@@ -740,7 +741,7 @@ static int s_callback_created(dap_chain_t * a_chain, dap_config_t *a_chain_net_c
     dap_global_db_cluster_t *l_dag_cluster = dap_global_db_cluster_add(dap_global_db_instance_get_default(), NULL,
                                                                        dap_guuid_compose(l_net->pub.id.uint64, DAP_CHAIN_CLUSTER_ID_DAG),
                                                                        l_dag->gdb_group_events_round_new, 900, true,
-                                                                       DAP_GDB_MEMBER_ROLE_NOBODY, DAP_CLUSTER_ROLE_AUTONOMIC);
+                                                                       DAP_GDB_MEMBER_ROLE_NOBODY, DAP_CLUSTER_TYPE_AUTONOMIC);
     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);
diff --git a/modules/consensus/esbocs/dap_chain_cs_esbocs.c b/modules/consensus/esbocs/dap_chain_cs_esbocs.c
index 325a9058eeb04c57cee1f8e85ea7447142edfc3b..c2c0effb2f8cbb327f67bc7f54779f5219e4a402 100644
--- a/modules/consensus/esbocs/dap_chain_cs_esbocs.c
+++ b/modules/consensus/esbocs/dap_chain_cs_esbocs.c
@@ -22,11 +22,13 @@ You should have received a copy of the GNU General Public License
 along with any CellFrame SDK based project.  If not, see <http://www.gnu.org/licenses/>.
 */
 #include "dap_common.h"
+#include "dap_context.h"
 #include "utlist.h"
 #include "dap_timerfd.h"
 #include "rand/dap_rand.h"
 #include "dap_stream_ch_proc.h"
 #include "dap_chain_net.h"
+#include "dap_chain_net_srv_order.h"
 #include "dap_chain_common.h"
 #include "dap_chain_mempool.h"
 #include "dap_chain_cell.h"
@@ -35,7 +37,6 @@ along with any CellFrame SDK based project.  If not, see <http://www.gnu.org/lic
 #include "dap_chain_cs_esbocs.h"
 #include "dap_chain_net_srv_stake_pos_delegate.h"
 #include "dap_chain_ledger.h"
-#include "dap_chain_node_cli.h"
 #include "dap_chain_node_cli_cmd.h"
 
 #define LOG_TAG "dap_chain_cs_esbocs"
@@ -50,11 +51,12 @@ enum s_esbocs_session_state {
 };
 
 static dap_list_t *s_validator_check(dap_chain_addr_t *a_addr, dap_list_t *a_validators);
+static void s_session_proc_state(void *a_arg);
 static void s_session_state_change(dap_chain_esbocs_session_t *a_session, enum s_esbocs_session_state a_new_state, dap_time_t a_time);
 static bool s_stream_ch_packet_in(dap_stream_ch_t *a_ch, void *a_arg);
 static void s_session_packet_in(dap_chain_esbocs_session_t *a_session, dap_chain_node_addr_t *a_sender_node_addr, uint8_t *a_data, size_t a_data_size);
 static void s_session_round_clear(dap_chain_esbocs_session_t *a_session);
-static void s_session_round_new(dap_chain_esbocs_session_t *a_session);
+static bool s_session_round_new(void *a_session);
 static bool s_session_candidate_to_chain(
             dap_chain_esbocs_session_t *a_session, dap_chain_hash_fast_t *a_candidate_hash,
                             dap_chain_block_t *a_candidate, size_t a_candidate_size);
@@ -64,7 +66,6 @@ static void s_session_candidate_verify(dap_chain_esbocs_session_t *a_session, da
 static void s_session_candidate_precommit(dap_chain_esbocs_session_t *a_session, dap_chain_esbocs_message_t *a_message);
 static void s_session_round_finish(dap_chain_esbocs_session_t *a_session, dap_chain_esbocs_store_t *l_store);
 
-static bool s_session_timer(void *a_arg);
 static void s_message_send(dap_chain_esbocs_session_t *a_session, uint8_t a_message_type, dap_hash_fast_t *a_block_hash,
                                     const void *a_data, size_t a_data_size, dap_list_t *a_validators);
 static void s_message_chain_add(dap_chain_esbocs_session_t * a_session,
@@ -78,12 +79,8 @@ static void s_callback_delete(dap_chain_cs_blocks_t *a_blocks);
 static int s_callback_created(dap_chain_t *a_chain, dap_config_t *a_chain_net_cfg);
 static size_t s_callback_block_sign(dap_chain_cs_blocks_t *a_blocks, dap_chain_block_t **a_block_ptr, size_t a_block_size);
 static int s_callback_block_verify(dap_chain_cs_blocks_t *a_blocks, dap_chain_block_t *a_block, size_t a_block_size);
-static uint256_t s_callback_get_minimum_fee(dap_chain_t *a_chain);
-static uint256_t s_callback_get_collectiong_level(dap_chain_t *a_chain);
-static dap_enc_key_t *s_callback_get_sign_key(dap_chain_t *a_chain);
-static void s_callback_set_min_validators_count(dap_chain_t *a_chain, uint16_t a_new_value);
 static void s_db_change_notifier(dap_store_obj_t *a_obj, void * a_arg);
-
+static dap_list_t *s_check_emergency_rights(dap_chain_esbocs_t *a_esbocs, dap_chain_addr_t *a_signing_addr);
 static int s_cli_esbocs(int a_argc, char **a_argv, void **a_str_reply);
 
 DAP_STATIC_INLINE const char *s_voting_msg_type_to_str(uint8_t a_type)
@@ -127,18 +124,26 @@ DAP_STATIC_INLINE size_t s_get_esbocs_message_size(dap_chain_esbocs_message_t *a
 
 static dap_chain_esbocs_session_t *s_session_items;
 
+struct precached_key {
+    uint64_t frequency;
+    dap_hash_fast_t pkey_hash;
+    size_t pkey_size;
+    struct precached_key *prev, *next;
+    byte_t sign_pkey[];
+};
+
 typedef struct dap_chain_esbocs_pvt {
     // Base params
     dap_enc_key_t *blocks_sign_key;
     dap_hash_fast_t candidate_hash;
     // Validators section
     bool poa_mode;
-    uint16_t min_validators_count;
     uint16_t start_validators_min;
     // Debug flag
     bool debug;
     // Emergancy mode with signing by current online validators only
     bool emergency_mode;
+    dap_list_t *emergency_validator_addrs;
     // Round params
     uint16_t new_round_delay;
     uint16_t round_start_sync_timeout;
@@ -151,6 +156,11 @@ typedef struct dap_chain_esbocs_pvt {
     uint256_t minimum_fee;
     uint256_t collecting_level;
     dap_pkey_t *block_sign_pkey;
+    // Decree controoled params
+    uint16_t min_validators_count;
+    bool check_signs_structure;
+    // Internal cache
+    struct precached_key *precached_keys;
 } dap_chain_esbocs_pvt_t;
 
 #define PVT(a) ((dap_chain_esbocs_pvt_t *)a->_pvt)
@@ -174,10 +184,18 @@ int dap_chain_cs_esbocs_init()
                            s_stream_ch_packet_in,
                            NULL);
     dap_cli_server_cmd_add ("esbocs", s_cli_esbocs, "ESBOCS commands",
-        "esbocs min_validators_count set -net <net_name> -chain <chain_name> -cert <poa_cert_name> -val_count <value>"
+        "esbocs min_validators_count set -net <net_name> -chain <chain_name> -cert <poa_cert_name> -val_count <value>\n"
             "\tSets minimum validators count for ESBOCS consensus\n"
-        "esbocs min_validators_count print -net <net_name> -chain <chain_name>"
-            "\tShow minimum validators count for ESBOCS consensus\n\n");
+        "esbocs min_validators_count show -net <net_name> -chain <chain_name>\n"
+            "\tShow minimum validators count for ESBOCS consensus\n"
+        "esbocs check_signs_structure {enable|disable} -net <net_name> -chain <chain_name> -cert <poa_cert_name>\n"
+            "\tEnables or disables checks for blocks signs structure validity\n"
+        "esbocs check_signs_structure show -net <net_name> -chain <chain_name>\n"
+            "\tShow status of checks for blocks signs structure validity\n"
+        "esbocs emergency_validator {add|remove} -net <net_name> -chain <chain_name> -cert <poa_cert_name> -pkey_hash <validator_pkey_hash>\n"
+            "\tAdd or remove validator by its signature public key hash to list of validators allowed to work in emergency mode\n"
+        "esbocs emergency_validator show -net <net_name> -chain <chain_name>\n"
+            "\tShow list of validators public key hashes allowed to work in emergency mode\n");
     return 0;
 }
 
@@ -201,11 +219,6 @@ static int s_callback_new(dap_chain_t *a_chain, dap_config_t *a_chain_cfg)
     l_blocks->callback_block_sign = s_callback_block_sign;
 
     l_esbocs->chain = a_chain;
-    a_chain->callback_set_min_validators_count = s_callback_set_min_validators_count;
-    a_chain->callback_get_minimum_fee = s_callback_get_minimum_fee;
-    a_chain->callback_get_collectiong_level = s_callback_get_collectiong_level;
-    a_chain->callback_get_signing_certificate = s_callback_get_sign_key;
-
     l_esbocs->_pvt = DAP_NEW_Z(dap_chain_esbocs_pvt_t);
     dap_chain_esbocs_pvt_t *l_esbocs_pvt = PVT(l_esbocs);
     if (!l_esbocs_pvt) {
@@ -214,7 +227,6 @@ static int s_callback_new(dap_chain_t *a_chain, dap_config_t *a_chain_cfg)
         goto lb_err;
     }
     l_esbocs_pvt->debug = dap_config_get_item_bool_default(a_chain_cfg, "esbocs", "consensus_debug", false);
-    l_esbocs_pvt->emergency_mode = dap_config_get_item_bool_default(a_chain_cfg, "esbocs", "emergency_mode", false);
     l_esbocs_pvt->poa_mode = dap_config_get_item_bool_default(a_chain_cfg, "esbocs", "poa_mode", false);
     l_esbocs_pvt->round_start_sync_timeout = dap_config_get_item_uint16_default(a_chain_cfg, "esbocs", "round_start_sync_timeout", 15);
     l_esbocs_pvt->new_round_delay = dap_config_get_item_uint16_default(a_chain_cfg, "esbocs", "new_round_delay", 10);
@@ -231,15 +243,16 @@ static int s_callback_new(dap_chain_t *a_chain, dap_config_t *a_chain_cfg)
     const char *l_auth_certs_prefix = dap_config_get_item_str(a_chain_cfg, "esbocs", "auth_certs_prefix");
     uint16_t l_node_addrs_count;
     char **l_addrs = dap_config_get_array_str(a_chain_cfg, "esbocs", "validators_addrs", &l_node_addrs_count);
-    uint16_t l_auth_certs_count = l_node_addrs_count;
-    if (l_auth_certs_count < l_esbocs_pvt->min_validators_count) {
+    if (l_node_addrs_count < l_esbocs_pvt->min_validators_count) {
         l_ret = -2;
         goto lb_err;
     }
-    char l_cert_name[512];
-    dap_cert_t *l_cert_cur;
+    dap_chain_net_srv_stake_net_add(a_chain->net_id);
+    uint16_t l_auth_certs_count = dap_config_get_item_uint16_default(a_chain_cfg, "esbocs", "auth_certs_count", l_node_addrs_count);
     dap_chain_net_t *l_net = dap_chain_net_by_id(a_chain->net_id);
     for (size_t i = 0; i < l_auth_certs_count; i++) {
+        char l_cert_name[512];
+        dap_cert_t *l_cert_cur;
         snprintf(l_cert_name, sizeof(l_cert_name), "%s.%zu", l_auth_certs_prefix, i);
         if ((l_cert_cur = dap_cert_find_by_name(l_cert_name)) == NULL) {
             snprintf(l_cert_name, sizeof(l_cert_name), "%s.%zu.pub", l_auth_certs_prefix, i);
@@ -252,13 +265,18 @@ 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);
         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,
+                                                                  DAP_DUP(&l_signing_addr));
+        if (i >= l_node_addrs_count)
+            continue;
+
         dap_chain_node_addr_t l_signer_node_addr;
         if (dap_chain_node_addr_from_str(&l_signer_node_addr, l_addrs[i])) {
             log_it(L_ERROR, "Wrong address format, should be like 0123::4567::89AB::CDEF");
             l_ret = -4;
             goto lb_err;
         }
-
         dap_chain_esbocs_validator_t *l_validator = DAP_NEW_Z(dap_chain_esbocs_validator_t);
         if (!l_validator) {
         log_it(L_CRITICAL, "%s", g_error_memory_alloc);
@@ -274,7 +292,7 @@ static int s_callback_new(dap_chain_t *a_chain, dap_config_t *a_chain_cfg)
 
         if (!l_esbocs_pvt->poa_mode) { // auth certs in PoA mode will be first PoS validators keys
             dap_hash_fast_t l_stake_tx_hash = {};
-            uint256_t l_weight = dap_chain_net_srv_stake_get_allowed_min_value();
+            uint256_t l_weight = dap_chain_net_srv_stake_get_allowed_min_value(a_chain->net_id);
             dap_chain_net_srv_stake_key_delegate(l_net, &l_signing_addr, &l_stake_tx_hash,
                                                  l_weight, &l_signer_node_addr);
         }
@@ -351,39 +369,40 @@ static void s_check_db_collect_callback(dap_global_db_instance_t UNUSED_ARG *a_d
     dap_global_db_objs_delete(l_objs, l_objs_count);
 }
 
-void dap_chain_esbocs_add_block_collect(dap_chain_block_t *a_block_ptr, size_t a_block_size,
-                                        dap_chain_esbocs_block_collect_t *a_block_collect_params,int a_type)
+void dap_chain_esbocs_add_block_collect(dap_chain_block_cache_t *a_block_cache,
+                                        dap_chain_esbocs_block_collect_t *a_block_collect_params,
+                                        dap_chain_block_autocollect_type_t a_type)
 {
-    dap_hash_fast_t l_last_block_hash;
-    dap_chain_get_atom_last_hash(a_block_collect_params->chain, a_block_collect_params->cell_id, &l_last_block_hash);
+    dap_return_if_fail(a_block_cache && a_block_collect_params);
     dap_chain_t *l_chain = a_block_collect_params->chain;
-    dap_sign_t *l_sign = dap_chain_block_sign_get(a_block_ptr, a_block_size, 0);
-    if (dap_pkey_match_sign(a_block_collect_params->block_sign_pkey, l_sign)&&(!a_type||a_type==1)) {
-        dap_chain_esbocs_block_collect_t *l_block_collect_params = DAP_NEW_Z(dap_chain_esbocs_block_collect_t);
-        l_block_collect_params->collecting_level = a_block_collect_params->collecting_level;
-        l_block_collect_params->minimum_fee = a_block_collect_params->minimum_fee;
-        l_block_collect_params->chain = a_block_collect_params->chain;
-        l_block_collect_params->blocks_sign_key = a_block_collect_params->blocks_sign_key;
-        l_block_collect_params->block_sign_pkey = a_block_collect_params->block_sign_pkey;
-        l_block_collect_params->collecting_addr = a_block_collect_params->collecting_addr;
-
-        dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(l_chain);
-        dap_chain_block_cache_t *l_block_cache = dap_chain_block_cache_get_by_hash(l_blocks, &l_last_block_hash);
-        assert(l_block_cache);
-        dap_chain_net_t *l_net = dap_chain_net_by_id(l_chain->net_id);
-        assert(l_net);
-        uint256_t l_value_fee = uint256_0;
-        dap_list_t *l_list_used_out = dap_chain_block_get_list_tx_cond_outs_with_val(
-                                        l_net->pub.ledger, l_block_cache, &l_value_fee);
-        if (!IS_ZERO_256(l_value_fee)) {
-            char *l_fee_group = dap_chain_cs_blocks_get_fee_group(l_chain->net_name);
-            dap_global_db_set(l_fee_group, l_block_cache->block_hash_str, &l_value_fee, sizeof(l_value_fee),
-                                false, s_check_db_collect_callback, l_block_collect_params);
-            DAP_DELETE(l_fee_group);
-        }
-        dap_list_free_full(l_list_used_out, NULL);
-    }
-    if (dap_chain_block_sign_match_pkey(a_block_ptr, a_block_size, a_block_collect_params->block_sign_pkey)&&(!a_type||a_type==2)) {
+    if (a_type == DAP_CHAIN_BLOCK_COLLECT_BOTH || a_type == DAP_CHAIN_BLOCK_COLLECT_FEES) {
+        dap_sign_t *l_sign = dap_chain_block_sign_get(a_block_cache->block, a_block_cache->block_size, 0);
+        if (dap_pkey_match_sign(a_block_collect_params->block_sign_pkey, l_sign)) {
+            dap_chain_esbocs_block_collect_t *l_block_collect_params = DAP_NEW_Z(dap_chain_esbocs_block_collect_t);
+            l_block_collect_params->collecting_level = a_block_collect_params->collecting_level;
+            l_block_collect_params->minimum_fee = a_block_collect_params->minimum_fee;
+            l_block_collect_params->chain = a_block_collect_params->chain;
+            l_block_collect_params->blocks_sign_key = a_block_collect_params->blocks_sign_key;
+            l_block_collect_params->block_sign_pkey = a_block_collect_params->block_sign_pkey;
+            l_block_collect_params->collecting_addr = a_block_collect_params->collecting_addr;
+            dap_chain_net_t *l_net = dap_chain_net_by_id(l_chain->net_id);
+            assert(l_net);
+            uint256_t l_value_fee = uint256_0;
+            dap_list_t *l_list_used_out = dap_chain_block_get_list_tx_cond_outs_with_val(
+                                            l_net->pub.ledger, a_block_cache, &l_value_fee);
+            if (!IS_ZERO_256(l_value_fee)) {
+                char *l_fee_group = dap_chain_cs_blocks_get_fee_group(l_chain->net_name);
+                dap_global_db_set(l_fee_group, a_block_cache->block_hash_str, &l_value_fee, sizeof(l_value_fee),
+                                    false, s_check_db_collect_callback, l_block_collect_params);
+                DAP_DELETE(l_fee_group);
+            }
+            dap_list_free_full(l_list_used_out, NULL);
+        }
+    }
+    if (a_type != DAP_CHAIN_BLOCK_COLLECT_BOTH && a_type != DAP_CHAIN_BLOCK_COLLECT_REWARDS)
+        return;
+    if (dap_chain_block_sign_match_pkey(a_block_cache->block, a_block_cache->block_size,
+                                        a_block_collect_params->block_sign_pkey)) {
         dap_chain_esbocs_block_collect_t *l_block_collect_params = DAP_NEW_Z(dap_chain_esbocs_block_collect_t);
         l_block_collect_params->collecting_level = a_block_collect_params->collecting_level;
         l_block_collect_params->minimum_fee = a_block_collect_params->minimum_fee;
@@ -391,19 +410,15 @@ void dap_chain_esbocs_add_block_collect(dap_chain_block_t *a_block_ptr, size_t a
         l_block_collect_params->blocks_sign_key = a_block_collect_params->blocks_sign_key;
         l_block_collect_params->block_sign_pkey = a_block_collect_params->block_sign_pkey;
         l_block_collect_params->collecting_addr = a_block_collect_params->collecting_addr;
-
-        dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(l_chain);
-        dap_chain_block_cache_t *l_block_cache = dap_chain_block_cache_get_by_hash(l_blocks, &l_last_block_hash);
-        assert(l_block_cache);
         dap_chain_net_t *l_net = dap_chain_net_by_id(l_chain->net_id);
         assert(l_net);
-        if (!dap_ledger_is_used_reward(l_net->pub.ledger, &l_block_cache->block_hash,
+        if (!dap_ledger_is_used_reward(l_net->pub.ledger, &a_block_cache->block_hash,
                                         &l_block_collect_params->collecting_addr->data.hash_fast)) {
-            uint256_t l_value_reward = l_chain->callback_calc_reward(l_chain, &l_block_cache->block_hash,
+            uint256_t l_value_reward = l_chain->callback_calc_reward(l_chain, &a_block_cache->block_hash,
                                                                      l_block_collect_params->block_sign_pkey);
             if (!IS_ZERO_256(l_value_reward)) {
                 char *l_reward_group = dap_chain_cs_blocks_get_reward_group(l_chain->net_name);
-                dap_global_db_set(l_reward_group, l_block_cache->block_hash_str, &l_value_reward, sizeof(l_value_reward),
+                dap_global_db_set(l_reward_group, a_block_cache->block_hash_str, &l_value_reward, sizeof(l_value_reward),
                                     false, s_check_db_collect_callback, l_block_collect_params);
                 DAP_DELETE(l_reward_group);
             }
@@ -433,7 +448,8 @@ static void s_new_atom_notifier(void *a_arg, dap_chain_t *a_chain, dap_chain_cel
             .collecting_addr = PVT(l_session->esbocs)->collecting_addr,
             .cell_id = a_id
     };
-    dap_chain_esbocs_add_block_collect(a_atom, a_atom_size, &l_block_collect_params,0);
+    dap_chain_block_cache_t *l_block_cache = dap_chain_block_cache_get_by_hash(DAP_CHAIN_CS_BLOCKS(a_chain), &l_last_block_hash);
+    dap_chain_esbocs_add_block_collect(l_block_cache, &l_block_collect_params, DAP_CHAIN_BLOCK_COLLECT_BOTH);
 }
 
 bool dap_chain_esbocs_get_autocollect_status(dap_chain_net_id_t a_net_id)
@@ -460,7 +476,7 @@ static int s_callback_created(dap_chain_t *a_chain, dap_config_t *a_chain_net_cf
     l_esbocs_pvt->collecting_addr = dap_chain_addr_from_str(dap_config_get_item_str(a_chain_net_cfg, "esbocs", "fee_addr"));
     l_esbocs_pvt->collecting_level = dap_chain_coins_to_balance(dap_config_get_item_str_default(a_chain_net_cfg, "esbocs", "set_collect_fee", "10.0"));
 
-    dap_list_t *l_validators = dap_chain_net_srv_stake_get_validators(a_chain->net_id, false);
+    dap_list_t *l_validators = dap_chain_net_srv_stake_get_validators(a_chain->net_id, false, NULL);
     for (dap_list_t *it = l_validators; it; it = it->next) {
         dap_stream_node_addr_t *l_addr = &((dap_chain_net_srv_stake_item_t *)it->data)->node_addr;
         dap_chain_net_add_validator_to_clusters(a_chain, l_addr);
@@ -518,21 +534,24 @@ static int s_callback_created(dap_chain_t *a_chain, dap_config_t *a_chain_net_cf
 
     l_session->my_addr.uint64 = dap_chain_net_get_cur_addr_int(l_net);
     l_session->my_signing_addr = l_my_signing_addr;
-// TODO make correct link management w/o global DB cluster
-#ifdef DAP_CHAIN_CS_ESBOCS_DIRECTIVE_SUPPORT
+
     char *l_sync_group = s_get_penalty_group(l_net->pub.id);
     l_session->db_cluster = dap_global_db_cluster_add(dap_global_db_instance_get_default(), NULL,
                                                       dap_guuid_compose(l_net->pub.id.uint64, DAP_CHAIN_CLUSTER_ID_ESBOCS),
                                                       l_sync_group, 72 * 3600, true,
-                                                      DAP_GDB_MEMBER_ROLE_NOBODY, DAP_CLUSTER_ROLE_AUTONOMIC);
+                                                      DAP_GDB_MEMBER_ROLE_NOBODY, DAP_CLUSTER_TYPE_AUTONOMIC);
     DAP_DELETE(l_sync_group);
     dap_global_db_cluster_add_notify_callback(l_session->db_cluster, s_db_change_notifier, l_session);
-#endif
     dap_link_manager_add_net_associate(l_net->pub.id.uint64, l_session->db_cluster->links_cluster);
 
+#ifdef DAP_CHAIN_CS_ESBOCS_DIRECTIVE_SUPPORT
+    dap_global_db_role_t l_directives_cluster_role_default = DAP_GDB_MEMBER_ROLE_ROOT;
+#else
+    dap_global_db_role_t l_directives_cluster_role_default = DAP_GDB_MEMBER_ROLE_GUEST;
+#endif
     for (dap_list_t *it = l_validators; it; it = it->next) {
         dap_stream_node_addr_t *l_addr = &((dap_chain_net_srv_stake_item_t *)it->data)->node_addr;
-        dap_global_db_cluster_member_add(l_session->db_cluster, l_addr, DAP_GDB_MEMBER_ROLE_ROOT);
+        dap_global_db_cluster_member_add(l_session->db_cluster, l_addr, l_directives_cluster_role_default);
     }
     dap_list_free_full(l_validators, NULL);
 
@@ -567,16 +586,17 @@ static int s_callback_created(dap_chain_t *a_chain, dap_config_t *a_chain_net_cf
         log_it(L_ERROR, "No valid order found was signed by this validator deledgated key. Switch off validator mode.");
         return -4;
     }
-    pthread_mutexattr_t l_mutex_attr;
-    pthread_mutexattr_init(&l_mutex_attr);
-    pthread_mutexattr_settype(&l_mutex_attr, PTHREAD_MUTEX_RECURSIVE);
-    pthread_mutex_init(&l_session->mutex, &l_mutex_attr);
-    pthread_mutexattr_destroy(&l_mutex_attr);
+    l_esbocs_pvt->emergency_mode = dap_config_get_item_bool_default(a_chain_net_cfg, "esbocs", "emergency_mode", false);
+    if (l_esbocs_pvt->emergency_mode && !s_check_emergency_rights(l_esbocs, &l_my_signing_addr)) {
+        log_it(L_ERROR, "This validator is not allowed to work in emergency mode. Use special decree to supply it");
+        return -5;
+    }
+    pthread_mutex_init(&l_session->mutex, NULL);
     dap_chain_add_callback_notify(a_chain, s_new_atom_notifier, l_session);
     s_session_round_new(l_session);
 
-    l_session->cs_timer = dap_timerfd_start(1000, s_session_timer, l_session);
-    debug_if(l_esbocs_pvt->debug, L_MSG, "Consensus main timer is started");
+    l_session->cs_timer = !dap_proc_thread_timer_add(NULL, s_session_proc_state, l_session, 1000);
+    debug_if(l_esbocs_pvt->debug && l_session->cs_timer, L_MSG, "Consensus main timer is started");
 
     DAP_CHAIN_PVT(a_chain)->cs_started = true;
     return 0;
@@ -618,10 +638,9 @@ void dap_chain_esbocs_stop_timer(dap_chain_net_id_t a_net_id)
     dap_chain_esbocs_session_t *l_session;
     DL_FOREACH(s_session_items, l_session) {
         if (l_session->chain->net_id.uint64 == a_net_id.uint64 &&
-            l_session->cs_timer){
+            l_session->cs_timer) {
             log_it(L_INFO, "Stop consensus timer for net: %s, chain: %s", dap_chain_net_by_id(a_net_id)->pub.name, l_session->chain->name);
-            dap_timerfd_delete_mt(l_session->cs_timer->worker, l_session->cs_timer->esocket_uuid);
-            l_session->cs_timer = NULL;
+            l_session->cs_timer = false;
         }
     }
 }
@@ -630,9 +649,9 @@ void dap_chain_esbocs_start_timer(dap_chain_net_id_t a_net_id)
 {
     dap_chain_esbocs_session_t *l_session;
     DL_FOREACH(s_session_items, l_session) {
-        if (l_session->chain->net_id.uint64 == a_net_id.uint64){
+        if (l_session->chain->net_id.uint64 == a_net_id.uint64) {
             log_it(L_INFO, "Start consensus timer for net: %s, chain: %s", dap_chain_net_by_id(a_net_id)->pub.name, l_session->chain->name);
-            l_session->cs_timer = dap_timerfd_start(1000, s_session_timer, l_session);
+            l_session->cs_timer = true;
         }
     }
 }
@@ -667,31 +686,86 @@ bool dap_chain_esbocs_remove_validator_from_clusters(dap_chain_net_id_t a_net_id
     return NULL;
 }
 
-static uint256_t s_callback_get_minimum_fee(dap_chain_t *a_chain)
+uint256_t dap_chain_esbocs_get_collecting_level(dap_chain_t *a_chain)
 {
+    dap_return_val_if_fail(a_chain && !strcmp(dap_chain_get_cs_type(a_chain), "esbocs"), uint256_0);
     dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(a_chain);
     dap_chain_esbocs_t *l_esbocs = DAP_CHAIN_ESBOCS(l_blocks);
     dap_chain_esbocs_pvt_t *l_esbocs_pvt = PVT(l_esbocs);
 
-    return l_esbocs_pvt->minimum_fee;
+    return l_esbocs_pvt->collecting_level;
 }
 
-static uint256_t s_callback_get_collectiong_level(dap_chain_t *a_chain)
+dap_enc_key_t *dap_chain_esbocs_get_sign_key(dap_chain_t *a_chain)
 {
+    dap_return_val_if_fail(a_chain && !strcmp(dap_chain_get_cs_type(a_chain), "esbocs"), NULL);
     dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(a_chain);
     dap_chain_esbocs_t *l_esbocs = DAP_CHAIN_ESBOCS(l_blocks);
     dap_chain_esbocs_pvt_t *l_esbocs_pvt = PVT(l_esbocs);
 
-    return l_esbocs_pvt->collecting_level;
+    return l_esbocs_pvt->blocks_sign_key;
 }
 
-static dap_enc_key_t *s_callback_get_sign_key(dap_chain_t *a_chain)
+int dap_chain_esbocs_set_min_validators_count(dap_chain_t *a_chain, uint16_t a_new_value)
 {
+    dap_return_val_if_fail(a_chain && !strcmp(dap_chain_get_cs_type(a_chain), "esbocs"), -1);
     dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(a_chain);
     dap_chain_esbocs_t *l_esbocs = DAP_CHAIN_ESBOCS(l_blocks);
     dap_chain_esbocs_pvt_t *l_esbocs_pvt = PVT(l_esbocs);
+    if (a_new_value)
+        l_esbocs_pvt->min_validators_count = a_new_value;
+    else {
+        dap_hash_fast_t l_stake_tx_hash = {};
+        dap_chain_net_t *l_net = dap_chain_net_by_id(a_chain->net_id);
+        uint256_t l_weight = dap_chain_net_srv_stake_get_allowed_min_value(a_chain->net_id);
+        for (dap_list_t *it = l_esbocs_pvt->poa_validators; it; it = it->next) {
+            dap_chain_esbocs_validator_t *l_validator = it->data;
+            dap_chain_net_srv_stake_key_delegate(l_net, &l_validator->signing_addr, &l_stake_tx_hash,
+                                                 l_weight, &l_validator->node_addr);
+        }
+        l_esbocs_pvt->min_validators_count = l_esbocs_pvt->start_validators_min;
+    }
+    return 0;
+}
 
-    return l_esbocs_pvt->blocks_sign_key;
+int dap_chain_esbocs_set_signs_struct_check(dap_chain_t *a_chain, bool a_enable)
+{
+    dap_return_val_if_fail(a_chain && !strcmp(dap_chain_get_cs_type(a_chain), "esbocs"), -1);
+    dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(a_chain);
+    dap_chain_esbocs_t *l_esbocs = DAP_CHAIN_ESBOCS(l_blocks);
+    dap_chain_esbocs_pvt_t *l_esbocs_pvt = PVT(l_esbocs);
+    l_esbocs_pvt->check_signs_structure = a_enable;
+    return 0;
+}
+
+int dap_chain_esbocs_set_emergency_validator(dap_chain_t *a_chain, bool a_add, uint32_t a_sign_type, dap_hash_fast_t *a_validator_hash)
+{
+    dap_return_val_if_fail(a_chain && !strcmp(dap_chain_get_cs_type(a_chain), "esbocs"), -1);
+    dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(a_chain);
+    dap_chain_esbocs_t *l_esbocs = DAP_CHAIN_ESBOCS(l_blocks);
+    dap_chain_esbocs_pvt_t *l_esbocs_pvt = PVT(l_esbocs);
+    dap_chain_addr_t l_signing_addr;
+    dap_sign_type_t l_type = { .type = a_sign_type };
+    dap_chain_addr_fill(&l_signing_addr, l_type , a_validator_hash, a_chain->net_id);
+    if (a_add) {
+        if (s_check_emergency_rights(l_esbocs, &l_signing_addr))
+            return -2;
+        dap_chain_addr_t *l_addr_new = DAP_DUP(&l_signing_addr);
+        if (!l_addr_new) {
+            log_it(L_CRITICAL, "%s", g_error_memory_alloc);
+            return -4;
+        }
+        l_esbocs_pvt->emergency_validator_addrs = dap_list_append(
+                                    l_esbocs_pvt->emergency_validator_addrs, l_addr_new);
+    } else {
+        dap_list_t *l_to_remove = s_check_emergency_rights(l_esbocs, &l_signing_addr);
+        if (!l_to_remove)
+            return -3;
+        DAP_DELETE(l_to_remove->data);
+        l_esbocs_pvt->emergency_validator_addrs = dap_list_delete_link(
+                                    l_esbocs_pvt->emergency_validator_addrs, l_to_remove);
+    }
+    return 0;
 }
 
 static void s_callback_delete(dap_chain_cs_blocks_t *a_blocks)
@@ -706,7 +780,6 @@ static void s_callback_delete(dap_chain_cs_blocks_t *a_blocks)
     }
     pthread_mutex_lock(&l_session->mutex);
     DL_DELETE(s_session_items, l_session);
-    dap_timerfd_delete_mt(l_session->cs_timer->worker, l_session->cs_timer->esocket_uuid);
     s_session_round_clear(l_session);
     dap_chain_esbocs_sync_item_t *l_sync_item, *l_sync_tmp;
     HASH_ITER(hh, l_session->sync_items, l_sync_item, l_sync_tmp) {
@@ -743,33 +816,30 @@ static void *s_callback_list_form(const void *a_srv_validator, UNUSED_ARG void *
     return l_validator;
 }
 
-static void s_callback_set_min_validators_count(dap_chain_t *a_chain, uint16_t a_new_value)
-{
-    dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(a_chain);
-    dap_chain_esbocs_t *l_esbocs = DAP_CHAIN_ESBOCS(l_blocks);
-    dap_chain_esbocs_pvt_t *l_esbocs_pvt = PVT(l_esbocs);
-    if (a_new_value)
-        l_esbocs_pvt->min_validators_count = a_new_value;
-    else {
-        dap_hash_fast_t l_stake_tx_hash = {};
-        dap_chain_net_t *l_net = dap_chain_net_by_id(a_chain->net_id);
-        uint256_t l_weight = dap_chain_net_srv_stake_get_allowed_min_value();
-        for (dap_list_t *it = l_esbocs_pvt->poa_validators; it; it = it->next) {
-            dap_chain_esbocs_validator_t *l_validator = it->data;
-            dap_chain_net_srv_stake_key_delegate(l_net, &l_validator->signing_addr, &l_stake_tx_hash,
-                                                 l_weight, &l_validator->node_addr);
-        }
-        l_esbocs_pvt->min_validators_count = l_esbocs_pvt->start_validators_min;
-    }
-}
-
-static dap_list_t *s_get_validators_list(dap_chain_esbocs_session_t *a_session, uint64_t a_skip_count)
+static dap_list_t *s_get_validators_list(dap_chain_esbocs_t *a_esbocs, dap_hash_fast_t *a_last_hash, uint64_t a_skip_count,
+                                         uint16_t *a_excluded_list, uint16_t a_excluded_list_size)
 {
-    dap_chain_esbocs_pvt_t *l_esbocs_pvt = PVT(a_session->esbocs);
+    dap_chain_esbocs_pvt_t *l_esbocs_pvt = PVT(a_esbocs);
     dap_list_t *l_ret = NULL;
-
+    dap_list_t *l_validators = NULL;
     if (!l_esbocs_pvt->poa_mode) {
-        dap_list_t *l_validators = dap_chain_net_srv_stake_get_validators(a_session->chain->net_id, true);
+        if (a_excluded_list_size) {
+            l_validators =  dap_chain_net_srv_stake_get_validators(a_esbocs->chain->net_id, false, NULL);
+            uint16_t l_excluded_num = *a_excluded_list;
+            uint16_t l_excluded_list_idx = 0, l_validator_idx = 0;
+            dap_list_t *it, *tmp;
+            DL_FOREACH_SAFE(l_validators, it, tmp) {
+                if (l_validator_idx++ == l_excluded_num) {
+                    DAP_DELETE(it->data);
+                    l_validators = dap_list_delete_link(l_validators, it);
+                    if (l_excluded_list_idx == a_excluded_list_size - 1)
+                        break;
+                    l_excluded_num = a_excluded_list[++l_excluded_list_idx];
+                }
+            }
+        } else
+            l_validators = dap_chain_net_srv_stake_get_validators(a_esbocs->chain->net_id, true,
+                                                                  &a_esbocs->session->cur_round.excluded_list);
         uint16_t l_total_validators_count = dap_list_length(l_validators);
         if (l_total_validators_count < l_esbocs_pvt->min_validators_count) {
             log_it(L_MSG, "Can't start new round. Totally active validators count %hu is below minimum count %hu",
@@ -792,7 +862,7 @@ static dap_list_t *s_get_validators_list(dap_chain_esbocs_session_t *a_session,
         size_t l_consensus_optimum = (size_t)l_esbocs_pvt->min_validators_count * 2 - 1;
         size_t l_need_vld_cnt = dap_min(l_total_validators_count, l_consensus_optimum);
 
-        dap_pseudo_random_seed(*(uint256_t *)&a_session->cur_round.last_block_hash);
+        dap_pseudo_random_seed(*(uint256_t *)a_last_hash);
         for (uint64_t i = 0; i < a_skip_count * l_need_vld_cnt; i++)
             dap_pseudo_random_get(uint256_0, NULL);
         for (size_t l_current_vld_cnt = 0; l_current_vld_cnt < l_need_vld_cnt; l_current_vld_cnt++) {
@@ -800,16 +870,17 @@ static dap_list_t *s_get_validators_list(dap_chain_esbocs_session_t *a_session,
             uint256_t l_chosen_weight = dap_pseudo_random_get(l_total_weight, &l_raw_result);
             if (false) { //PVT(a_session->esbocs)->debug) {
                 unsigned l_strlen = 1024, l_off = 0;
-                char *l_chosen_weight_str, *l_total_weight_str, *l_raw_result_str, l_str[l_strlen];
+                const char *l_chosen_weight_str, *l_total_weight_str, *l_raw_result_str;
+                char l_str[l_strlen];
                 dap_uint256_to_char(l_chosen_weight, &l_chosen_weight_str);
-                l_off = dap_snprintf(l_str, l_strlen,
+                l_off = snprintf(l_str, l_strlen,
                                      "Round seed %s, sync attempt %"DAP_UINT64_FORMAT_U", chosen weight %s ",
-                                     dap_hash_fast_to_str_static(&a_session->cur_round.last_block_hash),
+                                     dap_hash_fast_to_str_static(a_last_hash),
                                      a_skip_count + 1, l_chosen_weight_str);
                 dap_uint256_to_char(l_total_weight, &l_total_weight_str);
-                l_off += dap_snprintf(l_str + l_off, l_strlen - l_off, "from %s, ", l_total_weight_str);
+                l_off += snprintf(l_str + l_off, l_strlen - l_off, "from %s, ", l_total_weight_str);
                 dap_uint256_to_char(l_raw_result, &l_raw_result_str);
-                l_off += dap_snprintf(l_str + l_off, l_strlen - l_off, "by number %s", l_raw_result_str);
+                l_off += snprintf(l_str + l_off, l_strlen - l_off, "by number %s", l_raw_result_str);
                 log_it(L_MSG, "%s", l_str);
             }
             dap_list_t *l_chosen = NULL;
@@ -846,7 +917,7 @@ static int s_callback_addr_compare(dap_list_t *a_list_elem, dap_list_t *a_addr_e
         log_it(L_CRITICAL, "Invalid argument");
         return -1;
     }
-    return memcmp(&l_validator->signing_addr, l_addr, sizeof(dap_chain_addr_t));
+    return memcmp(&l_validator->signing_addr.data.hash_fast, &l_addr->data.hash_fast, sizeof(dap_hash_fast_t));
 }
 
 static dap_list_t *s_validator_check(dap_chain_addr_t *a_addr, dap_list_t *a_validators)
@@ -862,7 +933,9 @@ static int s_callback_addr_compare_synced(dap_list_t *a_list_elem, dap_list_t *a
         log_it(L_CRITICAL, "Invalid argument");
         return -1;
     }
-    return memcmp(&l_validator->signing_addr, l_addr, sizeof(dap_chain_addr_t)) || !l_validator->is_synced;
+    return memcmp(&l_validator->signing_addr.data.hash_fast,
+                  &l_addr->data.hash_fast, sizeof(dap_hash_fast_t)) ||
+            !l_validator->is_synced;
 }
 
 static dap_list_t *s_validator_check_synced(dap_chain_addr_t *a_addr, dap_list_t *a_validators)
@@ -944,6 +1017,7 @@ static void s_session_round_clear(dap_chain_esbocs_session_t *a_session)
     dap_chain_esbocs_store_t *l_store_item, *l_store_tmp;
     HASH_ITER(hh, a_session->cur_round.store_items, l_store_item, l_store_tmp) {
         HASH_DEL(a_session->cur_round.store_items, l_store_item);
+        DAP_DEL_Z(l_store_item->candidate);
         dap_list_free_full(l_store_item->candidate_signs, NULL);
         DAP_DELETE(l_store_item);
     }
@@ -960,8 +1034,9 @@ static void s_session_round_clear(dap_chain_esbocs_session_t *a_session)
     };
 }
 
-static void s_session_round_new(dap_chain_esbocs_session_t *a_session)
+static bool s_session_round_new(void *a_arg)
 {
+    dap_chain_esbocs_session_t *a_session = (dap_chain_esbocs_session_t*)a_arg;
     if (!a_session->round_fast_forward)
         s_session_update_penalty(a_session);
     s_session_round_clear(a_session);
@@ -986,15 +1061,18 @@ static void s_session_round_new(dap_chain_esbocs_session_t *a_session)
             a_session->cur_round.sync_attempt = 1;
     }
     if (!PVT(a_session->esbocs)->emergency_mode) {
-        a_session->cur_round.validators_list = s_get_validators_list(a_session, a_session->cur_round.sync_attempt - 1);
+        a_session->cur_round.validators_list = s_get_validators_list(a_session->esbocs,
+                                                                     &a_session->cur_round.last_block_hash,
+                                                                     a_session->cur_round.sync_attempt - 1,
+                                                                     NULL, 0);
         if (!a_session->cur_round.validators_list) {
             log_it(L_WARNING, "Minimum active validators not found");
             a_session->ts_round_sync_start = dap_time_now();
             a_session->sync_failed = true;
-            return;
+            return false;
         }
     }
-    dap_list_t *l_validators = dap_chain_net_srv_stake_get_validators(a_session->chain->net_id, false);
+    dap_list_t *l_validators = dap_chain_net_srv_stake_get_validators(a_session->chain->net_id, false, NULL);
     a_session->cur_round.all_validators = dap_list_copy_deep(l_validators, s_callback_list_form, NULL);
     dap_list_free_full(l_validators, NULL);
     bool l_round_already_started = a_session->round_fast_forward;
@@ -1035,6 +1113,7 @@ static void s_session_round_new(dap_chain_esbocs_session_t *a_session)
     a_session->round_fast_forward = false;
     a_session->sync_failed = false;
     a_session->listen_ensure = 0;
+    return false;
 }
 
 static void s_session_attempt_new(dap_chain_esbocs_session_t *a_session)
@@ -1314,7 +1393,8 @@ static void s_session_state_change(dap_chain_esbocs_session_t *a_session, enum s
             s_session_state_change(a_session, a_session->old_state, a_time);
         else {
             log_it(L_ERROR, "No previous state registered, can't roll back");
-            s_session_round_new(a_session);
+            dap_proc_thread_t *l_thread = DAP_PROC_THREAD(dap_context_current());
+            dap_proc_thread_callback_add(l_thread, s_session_round_new, a_session);
         }
     }
     default:
@@ -1322,117 +1402,115 @@ static void s_session_state_change(dap_chain_esbocs_session_t *a_session, enum s
     }
 }
 
-static void s_session_proc_state(dap_chain_esbocs_session_t *a_session)
+static void s_session_proc_state(void *a_arg)
 {
-    if (pthread_mutex_trylock(&a_session->mutex) != 0)
+    dap_chain_esbocs_session_t *l_session = a_arg;
+    if (!l_session->cs_timer)
+        return; // Timer is inactive
+    if (pthread_mutex_trylock(&l_session->mutex) != 0)
         return; // Session is busy
-    bool l_cs_debug = PVT(a_session->esbocs)->debug;
+    bool l_cs_debug = PVT(l_session->esbocs)->debug;
     dap_time_t l_time = dap_time_now();
-    switch (a_session->state) {
+    switch (l_session->state) {
     case DAP_CHAIN_ESBOCS_SESSION_STATE_WAIT_START: {
-        a_session->listen_ensure = 1;
-        bool l_round_skip = PVT(a_session->esbocs)->emergency_mode ?
-                    false : !s_validator_check(&a_session->my_signing_addr, a_session->cur_round.validators_list);
-        if (a_session->ts_round_sync_start && l_time - a_session->ts_round_sync_start >=
-                (dap_time_t)PVT(a_session->esbocs)->round_start_sync_timeout +
-                    (a_session->sync_failed ? s_get_round_skip_timeout(a_session) : 0)) {
-            if (a_session->cur_round.attempt_num > PVT(a_session->esbocs)->round_attempts_max ) {
-                debug_if(PVT(a_session->esbocs)->debug, L_MSG, "net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U"."
+        l_session->listen_ensure = 1;
+        bool l_round_skip = PVT(l_session->esbocs)->emergency_mode ?
+                    false : !s_validator_check(&l_session->my_signing_addr, l_session->cur_round.validators_list);
+        if (l_session->ts_round_sync_start && l_time - l_session->ts_round_sync_start >=
+                (dap_time_t)PVT(l_session->esbocs)->round_start_sync_timeout +
+                    (l_session->sync_failed ? s_get_round_skip_timeout(l_session) : 0)) {
+            if (l_session->cur_round.attempt_num > PVT(l_session->esbocs)->round_attempts_max ) {
+                debug_if(PVT(l_session->esbocs)->debug, L_MSG, "net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U"."
                                                                 " Round finished by reason: attempts is out",
-                                                                    a_session->chain->net_name, a_session->chain->name,
-                                                                        a_session->cur_round.id);
-                s_session_round_new(a_session);
+                                                                    l_session->chain->net_name, l_session->chain->name,
+                                                                        l_session->cur_round.id);
+                dap_proc_thread_t *l_thread = DAP_PROC_THREAD(dap_context_current());
+                dap_proc_thread_callback_add(l_thread, s_session_round_new, l_session);
                 break;
             }
-            uint16_t l_min_validators_synced = PVT(a_session->esbocs)->emergency_mode ?
-                        a_session->cur_round.total_validators_synced : a_session->cur_round.validators_synced_count;
-            if (l_min_validators_synced >= PVT(a_session->esbocs)->min_validators_count && !l_round_skip) {
-                a_session->cur_round.id = s_session_calc_current_round_id(a_session);
+            uint16_t l_min_validators_synced = PVT(l_session->esbocs)->emergency_mode ?
+                        l_session->cur_round.total_validators_synced : l_session->cur_round.validators_synced_count;
+            if (l_min_validators_synced >= PVT(l_session->esbocs)->min_validators_count && !l_round_skip) {
+                l_session->cur_round.id = s_session_calc_current_round_id(l_session);
                 debug_if(l_cs_debug, L_MSG, "net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hhu."
                                             " Minimum count of validators are synchronized, wait to submit candidate",
-                                                a_session->chain->net_name, a_session->chain->name,
-                                                    a_session->cur_round.id, a_session->cur_round.attempt_num);
-                s_session_state_change(a_session, DAP_CHAIN_ESBOCS_SESSION_STATE_WAIT_PROC, l_time);
+                                                l_session->chain->net_name, l_session->chain->name,
+                                                    l_session->cur_round.id, l_session->cur_round.attempt_num);
+                s_session_state_change(l_session, DAP_CHAIN_ESBOCS_SESSION_STATE_WAIT_PROC, l_time);
             } else { // timeout start sync
                 debug_if(l_cs_debug, L_MSG, "net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hhu."
                                             " Round finished by reason: %s",
-                                                a_session->chain->net_name, a_session->chain->name,
-                                                    a_session->cur_round.id, a_session->cur_round.attempt_num,
+                                                l_session->chain->net_name, l_session->chain->name,
+                                                    l_session->cur_round.id, l_session->cur_round.attempt_num,
                                                         l_round_skip ? "skipped" : "can't synchronize minimum number of validators");
-                a_session->sync_failed = true;
-                s_session_round_new(a_session);
+                l_session->sync_failed = true;
+                dap_proc_thread_t *l_thread = DAP_PROC_THREAD(dap_context_current());
+                dap_proc_thread_callback_add(l_thread, s_session_round_new, l_session);
             }
         }
     } break;
     case DAP_CHAIN_ESBOCS_SESSION_STATE_WAIT_PROC:
-        if (l_time - a_session->ts_stage_entry >= PVT(a_session->esbocs)->round_attempt_timeout * a_session->listen_ensure) {
-            a_session->listen_ensure += 2;
+        if (l_time - l_session->ts_stage_entry >= PVT(l_session->esbocs)->round_attempt_timeout * l_session->listen_ensure) {
+            l_session->listen_ensure += 2;
             debug_if(l_cs_debug, L_MSG, "net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hhu."
                                         " Attempt finished by reason: haven't cantidate submitted",
-                                            a_session->chain->net_name, a_session->chain->name,
-                                                a_session->cur_round.id, a_session->cur_round.attempt_num);
-            s_session_attempt_new(a_session);
+                                            l_session->chain->net_name, l_session->chain->name,
+                                                l_session->cur_round.id, l_session->cur_round.attempt_num);
+            s_session_attempt_new(l_session);
         }
         break;
     case DAP_CHAIN_ESBOCS_SESSION_STATE_WAIT_SIGNS:
-        if (l_time - a_session->ts_stage_entry >= PVT(a_session->esbocs)->round_attempt_timeout) {
+        if (l_time - l_session->ts_stage_entry >= PVT(l_session->esbocs)->round_attempt_timeout) {
             dap_chain_esbocs_store_t *l_store;
-            HASH_FIND(hh, a_session->cur_round.store_items, &a_session->cur_round.attempt_candidate_hash, sizeof(dap_hash_fast_t), l_store);
+            HASH_FIND(hh, l_session->cur_round.store_items, &l_session->cur_round.attempt_candidate_hash, sizeof(dap_hash_fast_t), l_store);
             if (!l_store) {
                 log_it(L_ERROR, "No round candidate found!");
-                s_session_attempt_new(a_session);
+                s_session_attempt_new(l_session);
                 break;
             }
-            if (dap_list_length(l_store->candidate_signs) >= PVT(a_session->esbocs)->min_validators_count) {
+            if (dap_list_length(l_store->candidate_signs) >= PVT(l_session->esbocs)->min_validators_count) {
                 if(l_cs_debug) {
-                    const char *l_candidate_hash_str = dap_chain_hash_fast_to_str_static(&a_session->cur_round.attempt_candidate_hash);
+                    const char *l_candidate_hash_str = dap_chain_hash_fast_to_str_static(&l_session->cur_round.attempt_candidate_hash);
                     log_it(L_MSG, "net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hhu"
                                             " Candidate %s collected sings of minimum number of validators, so to sent PRE_COMMIT",
-                                                a_session->chain->net_name, a_session->chain->name, a_session->cur_round.id,
-                                                    a_session->cur_round.attempt_num, l_candidate_hash_str);
+                                                l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id,
+                                                    l_session->cur_round.attempt_num, l_candidate_hash_str);
                 }
-                s_session_state_change(a_session, DAP_CHAIN_ESBOCS_SESSION_STATE_WAIT_FINISH, l_time);
+                s_session_state_change(l_session, DAP_CHAIN_ESBOCS_SESSION_STATE_WAIT_FINISH, l_time);
                 break;
             }
             debug_if(l_cs_debug, L_MSG, "net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hhu."
                                         " Attempt finished by reason: cant't collect minimum number of validator's signs",
-                                            a_session->chain->net_name, a_session->chain->name,
-                                                a_session->cur_round.id, a_session->cur_round.attempt_num);
-            s_session_attempt_new(a_session);
+                                            l_session->chain->net_name, l_session->chain->name,
+                                                l_session->cur_round.id, l_session->cur_round.attempt_num);
+            s_session_attempt_new(l_session);
         }
         break;
     case DAP_CHAIN_ESBOCS_SESSION_STATE_WAIT_FINISH:
-        if (l_time - a_session->ts_stage_entry >= PVT(a_session->esbocs)->round_attempt_timeout * 2) {
+        if (l_time - l_session->ts_stage_entry >= PVT(l_session->esbocs)->round_attempt_timeout * 2) {
             debug_if(l_cs_debug, L_MSG, "net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hhu."
                                         " Attempt finished by reason: cant't collect minimum number of validator's precommits with same final hash",
-                                            a_session->chain->net_name, a_session->chain->name,
-                                                a_session->cur_round.id, a_session->cur_round.attempt_num);
-            s_session_attempt_new(a_session);
+                                            l_session->chain->net_name, l_session->chain->name,
+                                                l_session->cur_round.id, l_session->cur_round.attempt_num);
+            s_session_attempt_new(l_session);
         }
         break;
     case DAP_CHAIN_ESBOCS_SESSION_STATE_WAIT_VOTING:
-        if (l_time - a_session->ts_stage_entry >= PVT(a_session->esbocs)->round_attempt_timeout * 2) {
-            const char *l_hash_str = dap_chain_hash_fast_to_str_static(&a_session->cur_round.directive_hash);
+        if (l_time - l_session->ts_stage_entry >= PVT(l_session->esbocs)->round_attempt_timeout * 2) {
+            const char *l_hash_str = dap_chain_hash_fast_to_str_static(&l_session->cur_round.directive_hash);
             debug_if(l_cs_debug, L_MSG, "net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hhu."
                                         " Voting finished by reason: cant't collect minimum number of validator's votes for directive %s",
-                                            a_session->chain->net_name, a_session->chain->name,
-                                                a_session->cur_round.id, a_session->cur_round.attempt_num,
+                                            l_session->chain->net_name, l_session->chain->name,
+                                                l_session->cur_round.id, l_session->cur_round.attempt_num,
                                                     l_hash_str);
-            s_session_state_change(a_session, DAP_CHAIN_ESBOCS_SESSION_STATE_PREVIOUS, l_time);
+            s_session_state_change(l_session, DAP_CHAIN_ESBOCS_SESSION_STATE_PREVIOUS, l_time);
         }
         break;
     default:
         break;
     }
 
-    pthread_mutex_unlock(&a_session->mutex);
-}
-
-static bool s_session_timer(void *a_arg)
-{
-    dap_chain_esbocs_session_t *l_session = a_arg;
-    s_session_proc_state(l_session);
-    return true;
+    pthread_mutex_unlock(&l_session->mutex);
 }
 
 static void s_message_chain_add(dap_chain_esbocs_session_t *a_session,
@@ -1463,20 +1541,34 @@ static void s_session_candidate_submit(dap_chain_esbocs_session_t *a_session)
 {
     dap_chain_t *l_chain = a_session->chain;
     dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(l_chain);
-    dap_chain_block_t *l_candidate;
     size_t l_candidate_size = 0;
     dap_hash_fast_t l_candidate_hash = {0};
     dap_chain_node_mempool_process_all(a_session->chain, false);
-    l_candidate = l_blocks->callback_new_block_move(l_blocks, &l_candidate_size);
-    if (l_candidate_size) {
-        dap_hash_fast(l_candidate, l_candidate_size, &l_candidate_hash);
-        if (PVT(a_session->esbocs)->debug) {
-            const char *l_candidate_hash_str = dap_chain_hash_fast_to_str_static(&l_candidate_hash);
-            log_it(L_MSG, "net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hhu. Submit my candidate %s",
-                    a_session->chain->net_name, a_session->chain->name,
-                        a_session->cur_round.id, a_session->cur_round.attempt_num, l_candidate_hash_str);
+    dap_chain_block_t *l_candidate = l_blocks->callback_new_block_move(l_blocks, &l_candidate_size);
+    if (l_candidate && l_candidate_size) {
+        if (PVT(a_session->esbocs)->emergency_mode)
+            l_candidate_size = dap_chain_block_meta_add(&l_candidate, l_candidate_size, DAP_CHAIN_BLOCK_META_EMERGENCY, NULL, 0);
+        if (PVT(a_session->esbocs)->check_signs_structure && l_candidate_size) {
+            l_candidate_size = dap_chain_block_meta_add(&l_candidate, l_candidate_size, DAP_CHAIN_BLOCK_META_SYNC_ATTEMPT,
+                                                        &a_session->cur_round.sync_attempt, sizeof(uint64_t));
+            if (l_candidate_size)
+                l_candidate_size = dap_chain_block_meta_add(&l_candidate, l_candidate_size, DAP_CHAIN_BLOCK_META_ROUND_ATTEMPT,
+                                                            &a_session->cur_round.attempt_num, sizeof(uint8_t));
+            if (l_candidate_size)
+                 l_candidate_size = dap_chain_block_meta_add(&l_candidate, l_candidate_size, DAP_CHAIN_BLOCK_META_EXCLUDED_KEYS,
+                                                            a_session->cur_round.excluded_list, *a_session->cur_round.excluded_list * sizeof(uint16_t));
+        }
+        if (l_candidate_size) {
+            dap_hash_fast(l_candidate, l_candidate_size, &l_candidate_hash);
+            if (PVT(a_session->esbocs)->debug) {
+                const char *l_candidate_hash_str = dap_chain_hash_fast_to_str_static(&l_candidate_hash);
+                log_it(L_MSG, "net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hhu. Submit my candidate %s",
+                        a_session->chain->net_name, a_session->chain->name,
+                            a_session->cur_round.id, a_session->cur_round.attempt_num, l_candidate_hash_str);
+            }
         }
-    } else { // there is no my candidate, send null hash
+    }
+    if (!l_candidate || !l_candidate_size) { // there is no my candidate, send null hash
         if (PVT(a_session->esbocs)->debug)
             log_it(L_MSG, "net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hhu."
                           " I don't have a candidate. I submit a null candidate.",
@@ -1688,7 +1780,7 @@ void s_session_sync_queue_add(dap_chain_esbocs_session_t *a_session, dap_chain_e
 
     void *l_message_copy = DAP_DUP_SIZE(a_message, a_message_size);
     if (!l_message_copy) {
-        log_it(L_CRITICAL, g_error_memory_alloc);
+        log_it(L_CRITICAL, "%s", g_error_memory_alloc);
         return;
     }
     dap_chain_esbocs_sync_item_t *l_sync_item;
@@ -1910,6 +2002,70 @@ static int s_session_directive_apply(dap_chain_esbocs_directive_t *a_directive,
     return 0;
 }
 
+DAP_STATIC_INLINE bool s_block_is_emergency(dap_chain_block_t *a_block, size_t a_block_size)
+{
+    return dap_chain_block_meta_get(a_block, a_block_size, DAP_CHAIN_BLOCK_META_EMERGENCY);
+}
+
+static dap_list_t *s_check_emergency_rights(dap_chain_esbocs_t *a_esbocs, dap_chain_addr_t *a_signing_addr)
+{
+    for (dap_list_t *it = PVT(a_esbocs)->emergency_validator_addrs; it; it = it->next) {
+        dap_chain_addr_t *l_authorized_pkey = it->data;
+        if (dap_hash_fast_compare(&l_authorized_pkey->data.hash_fast, &a_signing_addr->data.hash_fast))
+            return it;
+    }
+    return NULL;
+}
+
+static bool s_check_signing_rights(dap_chain_esbocs_t *a_esbocs, dap_chain_block_t *a_block, size_t a_block_size,
+                                   dap_chain_addr_t *a_signing_addr, bool a_first_sign)
+{
+    uint8_t *l_sync_attempt_ptr = dap_chain_block_meta_get(a_block, a_block_size, DAP_CHAIN_BLOCK_META_SYNC_ATTEMPT);
+    if (!l_sync_attempt_ptr) {
+        log_it(L_ERROR, "Can't get block metadata for SYNC_ATTEMPT");
+        return false;
+    }
+    uint64_t l_sync_attempt = *(uint64_t *)l_sync_attempt_ptr;
+    uint8_t l_round_attempt = 0;
+    if (a_first_sign) {
+        uint8_t *l_round_attempt_ptr = dap_chain_block_meta_get(a_block, a_block_size, DAP_CHAIN_BLOCK_META_ROUND_ATTEMPT);
+        if (!l_round_attempt_ptr) {
+            log_it(L_ERROR, "Can't get block metadata for ROUND_ATTEMPT");
+            return false;
+        }
+        l_round_attempt = *l_round_attempt_ptr;
+    }
+    dap_hash_fast_t *l_prev_hash_ptr = (dap_hash_fast_t *)dap_chain_block_meta_get(a_block, a_block_size, DAP_CHAIN_BLOCK_META_PREV);
+    if (!l_prev_hash_ptr) {
+        log_it(L_ERROR, "Can't get block metadata for PREV_HASH");
+        return false;
+    }
+    uint16_t *l_excluded_list = (uint16_t *)dap_chain_block_meta_get(a_block, a_block_size, DAP_CHAIN_BLOCK_META_EXCLUDED_KEYS);
+    if (!l_excluded_list) {
+        log_it(L_ERROR, "Can't get block metadata for EXCLUDED_KEYS");
+        return false;
+    }
+    dap_list_t *l_allowed_validators_list = s_get_validators_list(a_esbocs, l_prev_hash_ptr, l_sync_attempt - 1,
+                                                                  l_excluded_list + 1, *l_excluded_list);
+    if (!l_allowed_validators_list) {
+        log_it(L_ERROR, "Can't get block allowed validators list");
+        return false;
+    }
+    if (a_first_sign) {
+        size_t l_list_len = dap_list_length(l_allowed_validators_list);
+        if (l_list_len < l_round_attempt) {
+            log_it(L_ERROR, "Round attempt %hhu is greater than length of allowed validators list %zu",
+                                                l_round_attempt, l_list_len);
+            return false;
+        }
+        dap_chain_esbocs_validator_t *l_chosen_validator = dap_list_nth(l_allowed_validators_list, l_round_attempt)->data;
+        if (dap_hash_fast_compare(&l_chosen_validator->signing_addr.data.hash_fast, &a_signing_addr->data.hash_fast))
+            return true;
+        return false;
+    }
+    return s_validator_check(a_signing_addr, l_allowed_validators_list);
+}
+
 struct esbocs_msg_args {
     dap_stream_node_addr_t addr_from;
     dap_chain_esbocs_session_t *session;
@@ -1975,7 +2131,7 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t *a_ch, void *a_arg)
                                         NODE_ADDR_FP_ARGS_S(a_ch->stream->node), NODE_ADDR_FP_ARGS_S(l_session->my_addr));
     struct esbocs_msg_args *l_args = DAP_NEW_SIZE(struct esbocs_msg_args, sizeof(struct esbocs_msg_args) + l_message_size);
     if (!l_args) {
-        log_it(L_CRITICAL, g_error_memory_alloc);
+        log_it(L_CRITICAL, "%s", g_error_memory_alloc);
         return false;
     }
     l_args->addr_from = a_ch->stream->node;
@@ -2115,7 +2271,7 @@ static void s_session_packet_in(dap_chain_esbocs_session_t *a_session, dap_chain
     }
     if (l_not_in_list) {
         debug_if(l_cs_debug, L_MSG, "net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hhu."
-                                    " Message rejected: validator addr:%s not in the current validators list or not synced yet",
+                                    " Message rejected: validator key:%s not in the current validators list or not synced yet",
                                         l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id,
                                             l_message->hdr.attempt_num, l_validator_addr_str);
         goto session_unlock;
@@ -2132,8 +2288,9 @@ static void s_session_packet_in(dap_chain_esbocs_session_t *a_session, dap_chain
                                     " Receive START_SYNC: from validator:%s, sync attempt %"DAP_UINT64_FORMAT_U,
                                         l_session->chain->net_name, l_session->chain->name, l_message->hdr.round_id,
                                             l_validator_addr_str, l_sync_attempt);
+        dap_global_db_driver_hash_t l_msg_hash = ((struct sync_params *)l_message_data)->db_hash, l_session_hash = l_session->db_hash;
         if (!PVT(l_session->esbocs)->emergency_mode &&
-                dap_global_db_driver_hash_compare(((struct sync_params *)l_message_data)->db_hash, l_session->db_hash)) {
+                dap_global_db_driver_hash_compare(&l_msg_hash, &l_session_hash)) {
             debug_if(l_cs_debug, L_MSG, "net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", sync_attempt %"DAP_UINT64_FORMAT_U
                                         " SYNC message is rejected cause DB hash mismatch",
                                            l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id,
@@ -2173,7 +2330,8 @@ static void s_session_packet_in(dap_chain_esbocs_session_t *a_session, dap_chain
                     l_session->round_fast_forward = true;
                     l_session->cur_round.id = l_message->hdr.round_id - 1;
                     l_session->cur_round.sync_attempt = l_sync_attempt - 1;
-                    s_session_round_new(l_session);
+                    dap_proc_thread_t *l_thread = DAP_PROC_THREAD(dap_context_current());
+                    dap_proc_thread_callback_add(l_thread, s_session_round_new, l_session);
                 }
             }
         } else // Send it immediatly, if was not sent yet
@@ -2200,13 +2358,25 @@ static void s_session_packet_in(dap_chain_esbocs_session_t *a_session, dap_chain
     case DAP_CHAIN_ESBOCS_MSG_TYPE_SUBMIT: {
         uint8_t *l_candidate = l_message_data;
         size_t l_candidate_size = l_message_data_size;
+        // check submission rights
+        if (s_block_is_emergency((dap_chain_block_t *)l_candidate, l_candidate_size)) {
+            if (!s_check_emergency_rights(l_session->esbocs, &l_signing_addr)) {
+                debug_if(l_cs_debug, L_MSG, "net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hhu."
+                                            " Decline emergency SUBMIT candidate from not authorized validator %s",
+                                                l_session->chain->net_name, l_session->chain->name,
+                                                    l_session->cur_round.id, l_message->hdr.attempt_num,
+                                                        l_validator_addr_str);
+                break;
+            }
+            l_session->cur_round.attempt_submit_validator = l_signing_addr;
+        }
+        // check for NULL candidate
         if (!l_candidate_size || dap_hash_fast_is_blank(&l_message->hdr.candidate_hash)) {
             debug_if(l_cs_debug, L_MSG, "net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hhu."
                                         " Receive SUBMIT candidate NULL",
                                             l_session->chain->net_name, l_session->chain->name,
                                                 l_session->cur_round.id, l_message->hdr.attempt_num);
-            if (dap_chain_addr_compare(&l_session->cur_round.attempt_submit_validator, &l_signing_addr))
-                s_session_attempt_new(l_session);
+            s_session_attempt_new(l_session);
             break;
         }
         // check candidate hash
@@ -2214,12 +2384,11 @@ static void s_session_packet_in(dap_chain_esbocs_session_t *a_session, dap_chain
         dap_hash_fast(l_candidate, l_candidate_size, &l_check_hash);
         if (!dap_hash_fast_compare(&l_check_hash, l_candidate_hash)) {
             debug_if(l_cs_debug, L_MSG, "net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hhu."
-                                        " Receive SUBMIT candidate hash broken",
+                                        " Decline SUBMIT candidate with broken hash",
                                             l_session->chain->net_name, l_session->chain->name,
                                                 l_session->cur_round.id, l_message->hdr.attempt_num);
             break;
         }
-
         if (l_cs_debug) {
             const char *l_candidate_hash_str = dap_chain_hash_fast_to_str_static(l_candidate_hash);
             log_it(L_MSG, "net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hhu."
@@ -2331,13 +2500,21 @@ static void s_session_packet_in(dap_chain_esbocs_session_t *a_session, dap_chain
         if (!l_store) {
             l_candidate_hash_str = dap_chain_hash_fast_to_str_static(l_candidate_hash);
             log_it(L_WARNING, "net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hhu."
-                                " Receive COMMIT_SIGN message for unknown candidate %s",
+                                " Decline COMMIT_SIGN message for unknown candidate %s",
                                     l_session->chain->net_name, l_session->chain->name,
                                         l_session->cur_round.id, l_message->hdr.attempt_num,
                                             l_candidate_hash_str);
             break;
         }
-
+        dap_list_t *l_list = s_validator_check(&l_signing_addr, l_session->cur_round.validators_list);
+        if (!l_list) {
+            log_it(L_WARNING, "net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hhu."
+                                " Decline COMMIT_SIGN message for validator %s not present in current validator's list",
+                                    l_session->chain->net_name, l_session->chain->name,
+                                        l_session->cur_round.id, l_message->hdr.attempt_num,
+                                            l_validator_addr_str);
+            break;
+        }
         if (l_cs_debug) {
             l_candidate_hash_str = dap_chain_hash_fast_to_str_static(l_candidate_hash);
             log_it(L_MSG, "net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hhu."
@@ -2345,26 +2522,25 @@ static void s_session_packet_in(dap_chain_esbocs_session_t *a_session, dap_chain
                                 l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id,
                                     l_message->hdr.attempt_num, l_candidate_hash_str);
         }
-
+        // check candidate's sign
         size_t l_offset = dap_chain_block_get_sign_offset(l_store->candidate, l_store->candidate_size);
         int l_sign_verified = dap_sign_verify(l_candidate_sign, l_store->candidate,
                                                 l_offset + sizeof(l_store->candidate->hdr));
-        // check candidate's sign
-        if (!l_sign_verified) {
-            l_store->candidate_signs = dap_list_append(l_store->candidate_signs,
-                                                       DAP_DUP_SIZE(l_candidate_sign, l_candidate_sign_size));
-            if (dap_list_length(l_store->candidate_signs) == l_round->validators_synced_count) {
-                if (PVT(l_session->esbocs)->debug)
-                    log_it(L_MSG, "net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hhu."
-                                  " Candidate %s collected signs of all synced validators",
-                                        l_session->chain->net_name, l_session->chain->name, l_round->id,
-                                            l_message->hdr.attempt_num, l_candidate_hash_str);
-                s_session_state_change(l_session, DAP_CHAIN_ESBOCS_SESSION_STATE_WAIT_FINISH, dap_time_now());
-            }
-        } else {
+        if (l_sign_verified != 0) {
             if (!l_candidate_hash_str)
                 l_candidate_hash_str = dap_chain_hash_fast_to_str_static(l_candidate_hash);
             log_it(L_WARNING, "Candidate: %s sign is incorrect: code %d", l_candidate_hash_str, l_sign_verified);
+            break;
+        }
+        l_store->candidate_signs = dap_list_append(l_store->candidate_signs,
+                                                   DAP_DUP_SIZE(l_candidate_sign, l_candidate_sign_size));
+        if (dap_list_length(l_store->candidate_signs) == l_round->validators_synced_count) {
+            if (PVT(l_session->esbocs)->debug)
+                log_it(L_MSG, "net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hhu."
+                              " Candidate %s collected signs of all synced validators",
+                                    l_session->chain->net_name, l_session->chain->name, l_round->id,
+                                        l_message->hdr.attempt_num, l_candidate_hash_str);
+            s_session_state_change(l_session, DAP_CHAIN_ESBOCS_SESSION_STATE_WAIT_FINISH, dap_time_now());
         }
     } break;
 
@@ -2510,7 +2686,7 @@ static void s_message_send(dap_chain_esbocs_session_t *a_session, uint8_t a_mess
             struct esbocs_msg_args *l_args = DAP_NEW_SIZE(struct esbocs_msg_args,
                                                           sizeof(struct esbocs_msg_args) + l_message_size + l_sign_size);
             if (!l_args) {
-                log_it(L_CRITICAL, g_error_memory_alloc);
+                log_it(L_CRITICAL, "%s", g_error_memory_alloc);
                 return;
             }
             l_args->addr_from = a_session->my_addr;
@@ -2540,6 +2716,49 @@ static size_t s_callback_block_sign(dap_chain_cs_blocks_t *a_blocks, dap_chain_b
     return dap_chain_block_sign_add(a_block_ptr, a_block_size, l_esbocs_pvt->blocks_sign_key);
 }
 
+static uint64_t s_get_precached_key_hash(struct precached_key **a_precached_keys_list, dap_sign_t *a_source_sign, dap_hash_fast_t *a_result)
+{
+    bool l_found = false;
+    struct precached_key *l_key = NULL;
+    DL_FOREACH(*a_precached_keys_list, l_key) {
+        if (l_key->pkey_size == a_source_sign->header.sign_pkey_size &&
+                !memcmp(l_key->sign_pkey, dap_sign_get_pkey(a_source_sign, NULL), l_key->pkey_size)) {
+            l_found = true;
+            l_key->frequency++;
+            break;
+        }
+    }
+    if (l_found) {
+        struct precached_key *l_key_swap = NULL;
+        DL_FOREACH(*a_precached_keys_list, l_key_swap) {
+            if (l_key_swap == l_key)
+                break;
+            if (l_key_swap->frequency < l_key->frequency) {
+                struct precached_key *l_swapper = l_key->next;
+                l_key->next = l_key_swap->next;
+                l_key_swap->next = l_swapper;
+                l_swapper = l_key->prev;
+                l_key->prev = l_key_swap->prev;
+                l_key_swap->prev = l_swapper;
+                break;
+            }
+        }
+        if (a_result)
+            *a_result = l_key->pkey_hash;
+        return l_key->frequency;
+    }
+    struct precached_key *l_key_new = DAP_NEW_SIZE(struct precached_key,
+                                                   sizeof(struct precached_key) + a_source_sign->header.sign_pkey_size);
+    l_key_new->pkey_size = a_source_sign->header.sign_pkey_size;
+    l_key_new->frequency = 0;
+    memcpy(l_key_new->sign_pkey, dap_sign_get_pkey(a_source_sign, NULL), l_key_new->pkey_size);
+    dap_sign_get_pkey_hash(a_source_sign, &l_key_new->pkey_hash);
+    DL_APPEND(*a_precached_keys_list, l_key_new);
+    if (a_result)
+        *a_result = l_key_new->pkey_hash;
+    return 0;
+}
+
 static int s_callback_block_verify(dap_chain_cs_blocks_t *a_blocks, dap_chain_block_t *a_block, size_t a_block_size)
 {
     dap_chain_esbocs_t *l_esbocs = DAP_CHAIN_ESBOCS(a_blocks);
@@ -2550,10 +2769,11 @@ static int s_callback_block_verify(dap_chain_cs_blocks_t *a_blocks, dap_chain_bl
         return  -7;
     }
 
-    /*if (a_block->hdr.meta_n_datum_n_signs_size != a_block_size - sizeof(a_block->hdr)) {
+    if (a_block->hdr.meta_n_datum_n_signs_size &&
+            a_block->hdr.meta_n_datum_n_signs_size != a_block_size - sizeof(a_block->hdr)) {
         log_it(L_WARNING, "Incorrect size with block %p on chain %s", a_block, a_blocks->chain->name);
         return -8;
-    }*/ // TODO Retun it after hard-fork with correct block sizes
+    }
 
     if (l_esbocs->session && l_esbocs->session->processing_candidate == a_block)
         // It's a block candidate, don't check signs
@@ -2583,19 +2803,19 @@ static int s_callback_block_verify(dap_chain_cs_blocks_t *a_blocks, dap_chain_bl
     int l_ret = 0;
     uint16_t l_signs_verified_count = 0;
     size_t l_block_excl_sign_size = dap_chain_block_get_sign_offset(a_block, a_block_size) + sizeof(a_block->hdr);
+    bool l_block_is_emergency = s_block_is_emergency(a_block, a_block_size);
     // Get the header on signing operation time
     size_t l_block_original = a_block->hdr.meta_n_datum_n_signs_size;
     a_block->hdr.meta_n_datum_n_signs_size = l_block_excl_sign_size - sizeof(a_block->hdr);
-    for (size_t i=0; i< l_signs_count; i++) {
-        dap_sign_t *l_sign = (dap_sign_t *)l_signs[i];
+    for (size_t i = 0; i < l_signs_count; i++) {
+        dap_sign_t *l_sign = l_signs[i];
         if (!dap_sign_verify_size(l_sign, a_block_size - l_block_excl_sign_size + sizeof(a_block->hdr))) {
             log_it(L_ERROR, "Corrupted block: sign size is bigger than block size");
             l_ret = -3;
             break;
         }
-
-        dap_chain_addr_t l_signing_addr;
-        dap_chain_addr_fill_from_sign(&l_signing_addr, l_sign, a_blocks->chain->net_id);
+        dap_chain_addr_t l_signing_addr = { .net_id = a_blocks->chain->net_id };
+        s_get_precached_key_hash(&l_esbocs_pvt->precached_keys, l_sign, &l_signing_addr.data.hash_fast);
         if (!l_esbocs_pvt->poa_mode) {
              // Compare signature with delegated keys
             if (!dap_chain_net_srv_stake_key_delegated(&l_signing_addr)) {
@@ -2611,6 +2831,35 @@ static int s_callback_block_verify(dap_chain_cs_blocks_t *a_blocks, dap_chain_bl
                 continue;
             }
         }
+        if (i == 0) {
+            if (l_block_is_emergency && !s_check_emergency_rights(l_esbocs, &l_signing_addr)) {
+                log_it(L_ATT, "Restricted emergency block submitter %s",
+                                dap_chain_hash_fast_to_str_static(&l_signing_addr.data.hash_fast));
+                l_ret = -5;
+                break;
+            } else if (l_esbocs_pvt->check_signs_structure &&
+                       !s_check_signing_rights(l_esbocs, a_block, a_block_size, &l_signing_addr, true)) {
+                log_it(L_ATT, "Restricted block submitter %s",
+                                dap_chain_hash_fast_to_str_static(&l_signing_addr.data.hash_fast));
+                l_ret = -5;
+                break;
+            }
+        } else {
+            if (l_block_is_emergency && !s_check_emergency_rights(l_esbocs, &l_signing_addr) &&
+                    l_esbocs_pvt->check_signs_structure &&
+                    !s_check_signing_rights(l_esbocs, a_block, a_block_size, &l_signing_addr, false)) {
+                log_it(L_ATT, "Restricted emergency block signer %s",
+                                dap_chain_hash_fast_to_str_static(&l_signing_addr.data.hash_fast));
+                l_ret = -5;
+                break;
+            } else if (l_esbocs_pvt->check_signs_structure &&
+                    !s_check_signing_rights(l_esbocs, a_block, a_block_size, &l_signing_addr, false)) {
+                log_it(L_ATT, "Restricted block signer %s",
+                                dap_chain_hash_fast_to_str_static(&l_signing_addr.data.hash_fast));
+                l_ret = -5;
+                break;
+            }
+        }
         if (!dap_sign_verify(l_sign, a_block, l_block_excl_sign_size))
             l_signs_verified_count++;
     }
@@ -2649,73 +2898,56 @@ static dap_chain_datum_decree_t *s_esbocs_decree_set_min_validators_count(dap_ch
                                                                           uint256_t a_value, dap_cert_t *a_cert)
 {
     size_t l_total_tsd_size = sizeof(dap_tsd_t) + sizeof(uint256_t);
-    dap_chain_datum_decree_t *l_decree = NULL;
-    dap_list_t *l_tsd_list = NULL;
-    dap_tsd_t *l_tsd = NULL;
-// memory alloc
-    DAP_NEW_Z_SIZE_RET_VAL(l_tsd, dap_tsd_t, l_total_tsd_size, NULL, NULL);
-    DAP_NEW_Z_SIZE_RET_VAL(l_decree, dap_chain_datum_decree_t, sizeof(dap_chain_datum_decree_t) + l_total_tsd_size, NULL, l_tsd);
-
-    l_tsd->type = DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_MIN_SIGNERS_COUNT;
-    l_tsd->size = sizeof(uint256_t);
-    *(uint256_t*)(l_tsd->data) = a_value;
-    l_tsd_list = dap_list_append(l_tsd_list, l_tsd);
-
-    l_decree->decree_version = DAP_CHAIN_DATUM_DECREE_VERSION;
-    l_decree->header.ts_created = dap_time_now();
-    l_decree->header.type = DAP_CHAIN_DATUM_DECREE_TYPE_COMMON;
-    l_decree->header.common_decree_params.net_id = a_net->pub.id;
-    dap_chain_t *l_chain = a_chain;
-    if (!a_chain)
-        l_chain = dap_chain_net_get_default_chain_by_chain_type(a_net, CHAIN_TYPE_ANCHOR);
-    if(!l_chain){
-        log_it(L_ERROR, "Can't find chain with anchor support.");
-        dap_list_free_full(l_tsd_list, NULL);
-        DAP_DELETE(l_decree);
+    dap_chain_datum_decree_t *l_decree = dap_chain_datum_decree_new(a_net->pub.id, a_chain->id,
+                                                                    *dap_chain_net_get_cur_cell(a_net), l_total_tsd_size);
+    if (!l_decree)
         return NULL;
-    }
-    l_decree->header.common_decree_params.chain_id = l_chain->id;
-    l_decree->header.common_decree_params.cell_id = *dap_chain_net_get_cur_cell(a_net);
     l_decree->header.sub_type = DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_MIN_VALIDATORS_COUNT;
-    l_decree->header.data_size = l_total_tsd_size;
-    l_decree->header.signs_size = 0;
-
-    size_t l_data_tsd_offset = 0;
-    for ( dap_list_t* l_iter=dap_list_first(l_tsd_list); l_iter; l_iter=l_iter->next){
-        dap_tsd_t * l_b_tsd = (dap_tsd_t *) l_iter->data;
-        size_t l_tsd_size = dap_tsd_size(l_b_tsd);
-        memcpy((byte_t*)l_decree->data_n_signs + l_data_tsd_offset, l_b_tsd, l_tsd_size);
-        l_data_tsd_offset += l_tsd_size;
-    }
-    dap_list_free_full(l_tsd_list, NULL);
-
-    size_t l_cur_sign_offset = l_decree->header.data_size + l_decree->header.signs_size;
-    size_t l_total_signs_size = l_decree->header.signs_size;
+    dap_tsd_write(l_decree->data_n_signs, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_MIN_SIGNERS_COUNT, &a_value, sizeof(uint256_t));
+    return dap_chain_datum_decree_sign_in_cycle(&a_cert, l_decree, 1, NULL);
+}
 
-    dap_sign_t * l_sign = dap_cert_sign(a_cert,  l_decree,
-       sizeof(dap_chain_datum_decree_t) + l_decree->header.data_size, 0);
+static dap_chain_datum_decree_t *s_esbocs_decree_set_signs_check(dap_chain_net_t *a_net, dap_chain_t *a_chain,
+                                                                 bool a_enable, dap_cert_t *a_cert)
+{
+    size_t l_total_tsd_size = sizeof(dap_tsd_t) + sizeof(uint8_t);
+    dap_chain_datum_decree_t *l_decree = dap_chain_datum_decree_new(a_net->pub.id, a_chain->id,
+                                                                    *dap_chain_net_get_cur_cell(a_net), l_total_tsd_size);
+    if (!l_decree)
+        return NULL;
+    l_decree->header.sub_type = DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_CHECK_SIGNS_STRUCTURE;
+    uint8_t l_data = a_enable ? 1 : 0;
+    dap_tsd_write(l_decree->data_n_signs, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_ACTION, &l_data, sizeof(uint8_t));
+    return dap_chain_datum_decree_sign_in_cycle(&a_cert, l_decree, 1, NULL);
+}
 
-    if (l_sign) {
-        size_t l_sign_size = dap_sign_get_size(l_sign);
-        l_decree = DAP_REALLOC(l_decree, sizeof(dap_chain_datum_decree_t) + l_cur_sign_offset + l_sign_size);
-        if (!l_decree) {
-            log_it(L_CRITICAL, "%s", g_error_memory_alloc);
-            DAP_DELETE(l_sign);
-            return NULL;
-        }
-        memcpy((byte_t*)l_decree->data_n_signs + l_cur_sign_offset, l_sign, l_sign_size);
-        l_total_signs_size += l_sign_size;
-        l_cur_sign_offset += l_sign_size;
-        l_decree->header.signs_size = l_total_signs_size;
-        DAP_DELETE(l_sign);
-        log_it(L_DEBUG,"<-- Signed with '%s'", a_cert->name);
-    }else{
-        log_it(L_ERROR, "Decree signing failed");
-        DAP_DELETE(l_decree);
+static dap_chain_datum_decree_t *s_esbocs_decree_set_emergency_validator(dap_chain_net_t *a_net, dap_chain_t *a_chain,
+                                                                         dap_hash_fast_t *a_pkey_hash, dap_sign_type_t a_sign_type,
+                                                                         bool a_add, dap_cert_t *a_cert)
+{
+    size_t l_total_tsd_size = sizeof(dap_tsd_t) * 3 + sizeof(uint8_t) + sizeof(uint32_t) + sizeof(dap_hash_fast_t);
+    dap_chain_datum_decree_t *l_decree = dap_chain_datum_decree_new(a_net->pub.id, a_chain->id,
+                                                                    *dap_chain_net_get_cur_cell(a_net), l_total_tsd_size);
+    if (!l_decree)
         return NULL;
-    }
+    l_decree->header.sub_type = DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_EMERGENCY_VALIDATORS;
+    uint8_t l_data = a_add ? 1 : 0;
+    byte_t *l_ptr = dap_tsd_write(l_decree->data_n_signs, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_ACTION, &l_data, sizeof(uint8_t));
+    uint32_t l_type_numeric = a_sign_type.type;
+    l_ptr = dap_tsd_write(l_ptr, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_SIGNATURE_TYPE, &l_type_numeric, sizeof(uint32_t));
+    dap_tsd_write(l_ptr, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_HASH, a_pkey_hash, sizeof(dap_hash_fast_t));
+    return dap_chain_datum_decree_sign_in_cycle(&a_cert, l_decree, 1, NULL);
+}
 
-    return l_decree;
+static void s_print_emergency_validators(char **a_str_reply, dap_list_t *a_validator_addrs)
+{
+    dap_string_t *l_str_out = dap_string_new("Current emergency validators list:\n");
+    for (dap_list_t *it = a_validator_addrs; it; it = it->next) {
+        dap_chain_addr_t *l_addr = it->data;
+        dap_string_append_printf(l_str_out, "%s\n", dap_chain_hash_fast_to_str_static(&l_addr->data.hash_fast));
+    }
+    *a_str_reply = l_str_out->str;
+    dap_string_free(l_str_out, false);
 }
 
 /**
@@ -2729,65 +2961,166 @@ static dap_chain_datum_decree_t *s_esbocs_decree_set_min_validators_count(dap_ch
  */
 static int s_cli_esbocs(int a_argc, char **a_argv, void **a_str_reply)
 {
-    int ret = -666;
-    int l_arg_index = 2;
-    dap_chain_net_t * l_chain_net = NULL;
-    dap_chain_t * l_chain = NULL;
-    const char *l_cert_str = NULL,
-               *l_value_str = NULL;
+    int l_arg_index = 1;
+    dap_chain_net_t *l_chain_net = NULL;
+    dap_chain_t *l_chain = NULL;
 
-    if (dap_chain_node_cli_cmd_values_parse_net_chain(&l_arg_index, a_argc, a_argv, a_str_reply, &l_chain, &l_chain_net))
+    if (dap_chain_node_cli_cmd_values_parse_net_chain(&l_arg_index, a_argc, a_argv, a_str_reply, &l_chain, &l_chain_net,
+                                                      CHAIN_TYPE_ANCHOR))
         return -3;
-    const char *l_chain_type = dap_chain_net_get_type(l_chain);
+    const char *l_chain_type = dap_chain_get_cs_type(l_chain);
     if (strcmp(l_chain_type, "esbocs")) {
             dap_cli_server_cmd_set_reply_text(a_str_reply,
                         "Type of chain \"%s\" is not block. Chain with current consensus \"%s\" is not supported by this command",
                         l_chain->name, l_chain_type);
-            return ret;
+            return -2;
     }
+    dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(l_chain);
+    dap_chain_esbocs_t *l_esbocs = DAP_CHAIN_ESBOCS(l_blocks);
+    dap_chain_esbocs_pvt_t *l_esbocs_pvt = PVT(l_esbocs);
 
-    if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, l_arg_index + 1, "set", NULL)) {
-        dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-cert", &l_cert_str);
-        if (!l_cert_str) {
-            dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'min_validators_count' requires parameter -cert");
-            return -3;
-        }
-        dap_cert_t *l_poa_cert = dap_cert_find_by_name(l_cert_str);
-        if (!l_poa_cert) {
-            dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified certificate not found");
-            return -25;
-        }
+    enum {
+        SUBCMD_UNDEFINED = 0,
+        SUBCMD_MIN_VALIDATORS_COUNT,
+        SUBCMD_CHECK_SIGNS_STRUCTURE,
+        SUBCMD_EMERGENCY_VALIDATOR
+    } l_subcmd = SUBCMD_UNDEFINED;
+    const char *l_subcmd_strs[] = {
+        [SUBCMD_UNDEFINED] = NULL,
+        [SUBCMD_MIN_VALIDATORS_COUNT] = "min_validators_count",
+        [SUBCMD_CHECK_SIGNS_STRUCTURE] = "check_signs_structure",
+        [SUBCMD_EMERGENCY_VALIDATOR] = "emergency_validator",
+    };
 
-        dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-val_count", &l_value_str);
-        if (!l_value_str) {
-            dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'min_validators_count' requires parameter -val_count");
-            return -9;
-        }
-        uint256_t l_value = dap_chain_balance_scan(l_value_str);
-        if (IS_ZERO_256(l_value)) {
-            dap_cli_server_cmd_set_reply_text(a_str_reply, "Unrecognized number in '-val_count' param");
-            return -10;
+    const size_t l_subcmd_str_count = sizeof(l_subcmd_strs) / sizeof(char *);
+    const char *l_subcmd_str_arg = NULL;
+    // Parse commands
+    for (size_t i = 1; i < l_subcmd_str_count; i++) {
+        if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, l_arg_index + 1, l_subcmd_strs[i], &l_subcmd_str_arg)) {
+            l_subcmd = i;
+            break;
         }
+    }
+    dap_cert_t *l_poa_cert = NULL;
+    l_arg_index++;
+    bool l_subcommand_show = false, l_subcommand_add = false;
+    if (l_subcmd) {
+        if ((dap_cli_server_cmd_check_option(a_argv, l_arg_index, l_arg_index + 1, "set") > 0 && l_subcmd == SUBCMD_MIN_VALIDATORS_COUNT) ||
+                (dap_cli_server_cmd_check_option(a_argv, l_arg_index, l_arg_index + 1, "enable") > 0 && l_subcmd == SUBCMD_CHECK_SIGNS_STRUCTURE) ||
+                (dap_cli_server_cmd_check_option(a_argv, l_arg_index, l_arg_index + 1, "disable") > 0 && l_subcmd == SUBCMD_CHECK_SIGNS_STRUCTURE) ||
+                (dap_cli_server_cmd_check_option(a_argv, l_arg_index, l_arg_index + 1, "add") > 0 && l_subcmd == SUBCMD_EMERGENCY_VALIDATOR) ||
+                (dap_cli_server_cmd_check_option(a_argv, l_arg_index, l_arg_index + 1, "remove") > 0 && l_subcmd == SUBCMD_EMERGENCY_VALIDATOR))
+        {
+            if (dap_cli_server_cmd_check_option(a_argv, l_arg_index, l_arg_index + 1, "enable") ||
+                    dap_cli_server_cmd_check_option(a_argv, l_arg_index, l_arg_index + 1, "add"))
+                l_subcommand_add = true;
+            const char *l_cert_str = NULL;
+            dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-cert", &l_cert_str);
+            if (!l_cert_str) {
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'min_validators_count' requires parameter -cert");
+                return -3;
+            }
+            l_poa_cert = dap_cert_find_by_name(l_cert_str);
+            if (!l_poa_cert) {
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified certificate not found");
+                return -25;
+            }
+            if (!l_poa_cert->enc_key || !l_poa_cert->enc_key->priv_key_data) {
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified certificate doesn't contain a private key");
+                return -26;
+            }
+        } else if (dap_cli_server_cmd_check_option(a_argv, l_arg_index, l_arg_index + 1, "show") > 0)
+            l_subcommand_show = true;
+        else
+            dap_cli_server_cmd_set_reply_text(a_str_reply, "Unrecognized subcommand '%s'", a_argv[l_arg_index]);
+    }
 
-        dap_chain_datum_decree_t *l_decree = s_esbocs_decree_set_min_validators_count(
-                                                l_chain_net, l_chain, l_value, l_poa_cert);
-        char *l_decree_hash_str = NULL;
-        if (l_decree && (l_decree_hash_str = s_esbocs_decree_put(l_decree, l_chain_net))) {
-            dap_cli_server_cmd_set_reply_text(a_str_reply, "Minimum validators count has been set."
-                                                           " Decree hash %s", l_decree_hash_str);
-            DAP_DEL_MULTY(l_decree, l_decree_hash_str);
-        } else {
-            dap_cli_server_cmd_set_reply_text(a_str_reply, "Minimum validators count setting failed");
-            DAP_DEL_Z(l_decree);
-            return -21;
-        }
-    } else if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, l_arg_index + 1, "print", NULL)) {
-        dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(l_chain);
-        dap_chain_esbocs_t *l_esbocs = DAP_CHAIN_ESBOCS(l_blocks);
-        dap_chain_esbocs_pvt_t *l_esbocs_pvt = PVT(l_esbocs);
-        dap_cli_server_cmd_set_reply_text(a_str_reply, "Minimum validators count is %d",
-                                          l_esbocs_pvt->min_validators_count);
-    } else
+    int ret = 0;
+    // Do subcommand action
+    switch (l_subcmd) {
+
+    case SUBCMD_MIN_VALIDATORS_COUNT: {
+        if (!l_subcommand_show) {
+            const char *l_value_str = NULL;
+            dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-val_count", &l_value_str);
+            if (!l_value_str) {
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "Command '%s' requires parameter -val_count", l_subcmd_strs[l_subcmd]);
+                return -9;
+            }
+            uint256_t l_value = dap_chain_balance_scan(l_value_str);
+            if (IS_ZERO_256(l_value)) {
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "Unrecognized number in '-val_count' param");
+                return -10;
+            }
+            dap_chain_datum_decree_t *l_decree = s_esbocs_decree_set_min_validators_count(
+                                                    l_chain_net, l_chain, l_value, l_poa_cert);
+            char *l_decree_hash_str = NULL;
+            if (l_decree && (l_decree_hash_str = s_esbocs_decree_put(l_decree, l_chain_net))) {
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "Minimum validators count has been set."
+                                                               " Decree hash %s", l_decree_hash_str);
+                DAP_DEL_MULTY(l_decree, l_decree_hash_str);
+            } else {
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "Minimum validators count setting failed");
+                DAP_DEL_Z(l_decree);
+                return -21;
+            }
+        } else
+            dap_cli_server_cmd_set_reply_text(a_str_reply, "Minimum validators count is %d", l_esbocs_pvt->min_validators_count);
+    } break;
+
+    case SUBCMD_CHECK_SIGNS_STRUCTURE: {
+        if (!l_subcommand_show) {
+            dap_chain_datum_decree_t *l_decree = s_esbocs_decree_set_signs_check(l_chain_net, l_chain, l_subcommand_add, l_poa_cert);
+            char *l_decree_hash_str = NULL;
+            if (l_decree && (l_decree_hash_str = s_esbocs_decree_put(l_decree, l_chain_net))) {
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "Checking signs structure has been %s. Decree hash %s",
+                                                                l_subcommand_add ? "enabled" : "disabled", l_decree_hash_str);
+                DAP_DEL_MULTY(l_decree, l_decree_hash_str);
+            } else {
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "Checking signs structure setting failed");
+                DAP_DEL_Z(l_decree);
+                return -21;
+            }
+        } else
+            dap_cli_server_cmd_set_reply_text(a_str_reply, "Checking signs structure is %s", l_esbocs_pvt->check_signs_structure ?
+                                                                                "enabled" : "disabled");
+    } break;
+
+    case SUBCMD_EMERGENCY_VALIDATOR: {
+        if (!l_subcommand_show) {
+            const char *l_hash_str = NULL, *l_type_str = NULL;
+            dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-pkey_hash", &l_hash_str);
+            if (!l_hash_str) {
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "Command '%s' requires parameter -pkey_hash", l_subcmd_strs[l_subcmd]);
+                return -9;
+            }
+            dap_hash_fast_t l_pkey_hash;
+            if (dap_chain_hash_fast_from_str(l_hash_str, &l_pkey_hash)) {
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "Invalid hash format in 'pkey_hash' param");
+                return -10;
+            }
+            dap_sign_type_t l_sig_type = { .type = SIG_TYPE_DILITHIUM };
+            dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-sig_type", &l_type_str);
+            if (l_type_str)
+                l_sig_type = dap_sign_type_from_str(l_type_str);
+            dap_chain_datum_decree_t *l_decree = s_esbocs_decree_set_emergency_validator(l_chain_net, l_chain, &l_pkey_hash, l_sig_type, l_subcommand_add, l_poa_cert);
+            char *l_decree_hash_str = NULL;
+            if (l_decree && (l_decree_hash_str = s_esbocs_decree_put(l_decree, l_chain_net))) {
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "Emergency validator %s has been %s. Decree hash %s",
+                                                        dap_chain_hash_fast_to_str_static(&l_pkey_hash),
+                                                        l_subcommand_add ? "added" : "deleted", l_decree_hash_str);
+                DAP_DEL_MULTY(l_decree, l_decree_hash_str);
+            } else {
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "Emergency validator %s failed", l_subcommand_add ? "adding" : "deleting");
+                DAP_DEL_Z(l_decree);
+                return -21;
+            }
+        } else
+            s_print_emergency_validators((char **)a_str_reply, l_esbocs_pvt->emergency_validator_addrs);
+    } break;
+
+    default:
         dap_cli_server_cmd_set_reply_text(a_str_reply, "Unrecognized subcommand '%s'", a_argv[l_arg_index]);
+    }
     return ret;
 }
diff --git a/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h b/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h
index 6b2df2be82ec8da3a67bde9187717b4f06d3b2c8..fc2c218bdf45bfa4d4f1a6f5db2af2338716d711 100644
--- a/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h
+++ b/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h
@@ -27,7 +27,6 @@ along with any CellFrame SDK based project.  If not, see <http://www.gnu.org/lic
 #include "dap_chain.h"
 #include "dap_chain_block.h"
 #include "dap_chain_cs_blocks.h"
-#include "dap_cert.h"
 #include "dap_global_db_driver.h"
 
 #define DAP_STREAM_CH_ESBOCS_ID                     'E'
@@ -156,6 +155,7 @@ typedef struct dap_chain_esbocs_round {
     // Validators section
     dap_list_t *validators_list;
     uint16_t validators_synced_count;
+    uint16_t *excluded_list;
     // Synchronization params
     uint64_t sync_attempt;
     bool sync_sent;
@@ -182,7 +182,7 @@ typedef struct dap_chain_esbocs_penalty_item {
 
 typedef struct dap_chain_esbocs_session {
     pthread_mutex_t mutex;
-    dap_timerfd_t *cs_timer;
+    bool cs_timer;
     dap_chain_block_t *processing_candidate;
 
     dap_chain_t *chain;
@@ -223,16 +223,30 @@ typedef struct dap_chain_esbocs_block_collect{
 
 #define DAP_CHAIN_ESBOCS(a) ((dap_chain_esbocs_t *)(a)->_inheritor)
 
+typedef enum dap_chain_block_autocollect_type {
+    DAP_CHAIN_BLOCK_COLLECT_BOTH,
+    DAP_CHAIN_BLOCK_COLLECT_FEES,
+    DAP_CHAIN_BLOCK_COLLECT_REWARDS
+} dap_chain_block_autocollect_type_t;
+
 int dap_chain_cs_esbocs_init();
 void dap_chain_cs_esbocs_deinit(void);
-bool dap_chain_esbocs_started();
 
+bool dap_chain_esbocs_started(dap_chain_net_id_t a_net_id);
 void dap_chain_esbocs_stop_timer(dap_chain_net_id_t a_net_id);
 void dap_chain_esbocs_start_timer(dap_chain_net_id_t a_net_id);
+
 dap_pkey_t *dap_chain_esbocs_get_sign_pkey(dap_chain_net_id_t a_net_id);
 uint256_t dap_chain_esbocs_get_fee(dap_chain_net_id_t a_net_id);
 bool dap_chain_esbocs_get_autocollect_status(dap_chain_net_id_t a_net_id);
-void dap_chain_esbocs_add_block_collect(dap_chain_block_t *a_block_ptr, size_t a_block_size,
-                                        dap_chain_esbocs_block_collect_t *a_block_collect_params,int a_type);
+void dap_chain_esbocs_add_block_collect(dap_chain_block_cache_t *a_block_cache,
+                                        dap_chain_esbocs_block_collect_t *a_block_collect_params,
+                                        dap_chain_block_autocollect_type_t a_type);
 bool dap_chain_esbocs_add_validator_to_clusters(dap_chain_net_id_t a_net_id, dap_stream_node_addr_t *a_validator_addr);
 bool dap_chain_esbocs_remove_validator_from_clusters(dap_chain_net_id_t a_net_id, dap_stream_node_addr_t *a_validator_addr);
+
+uint256_t dap_chain_esbocs_get_collecting_level(dap_chain_t *a_chain);
+dap_enc_key_t *dap_chain_esbocs_get_sign_key(dap_chain_t *a_chain);
+int dap_chain_esbocs_set_min_validators_count(dap_chain_t *a_chain, uint16_t a_new_value);
+int dap_chain_esbocs_set_emergency_validator(dap_chain_t *a_chain, bool a_add, uint32_t a_sign_type, dap_hash_fast_t *a_validator_hash);
+int dap_chain_esbocs_set_signs_struct_check(dap_chain_t *a_chain, bool a_enable);
diff --git a/modules/json_rpc/CMakeLists.txt b/modules/json_rpc/CMakeLists.txt
deleted file mode 100644
index 526bc29d7597ec77286a5fbfc59ee15b9c307131..0000000000000000000000000000000000000000
--- a/modules/json_rpc/CMakeLists.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-
-add_subdirectory(mempool)
-add_subdirectory(common)
diff --git a/modules/json_rpc/common/CMakeLists.txt b/modules/json_rpc/common/CMakeLists.txt
deleted file mode 100644
index 4cd22f12205316ba754833b58898fb4fb6c748e0..0000000000000000000000000000000000000000
--- a/modules/json_rpc/common/CMakeLists.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-cmake_minimum_required(VERSION 3.10)
-project(dap_json_rpc_chain_common)
-
-file(GLOB DAP_JSON_RPC_CHAIN_COMMON_HEADERS include/*.h)
-file(GLOB DAP_JSON_RPC_CHAIN_COMMON_SRCS *.c)
-
-add_library(${PROJECT_NAME}  STATIC ${DAP_JSON_RPC_CHAIN_COMMON_SRCS} ${DAP_JSON_RPC_CHAIN_COMMON_HEADERS})
-
-target_link_libraries(dap_json_rpc_chain_common dap_core dap_crypto dap_chain_common dap_json-c dap_json_rpc_core dap_json_rpc_crypto)
-target_include_directories(dap_json_rpc_chain_common PUBLIC include/)
diff --git a/modules/json_rpc/common/dap_json_rpc_chain_common.c b/modules/json_rpc/common/dap_json_rpc_chain_common.c
deleted file mode 100644
index c26cbe73306f547ec442cb84a3a77d0b2f520b5c..0000000000000000000000000000000000000000
--- a/modules/json_rpc/common/dap_json_rpc_chain_common.c
+++ /dev/null
@@ -1,13 +0,0 @@
-#include "dap_json_rpc_chain_common.h"
-#include "json.h"
-
-#define LOG_TAG "dap_json_rpc_chain_common"
-
-/**
- * @brief dap_chain_addr_to_json
- * @param a_addr
- * @return
- */
-json_object *dap_chain_addr_to_json(const dap_chain_addr_t *a_addr) {
-    return json_object_new_string(dap_chain_addr_to_str(a_addr));
-}
diff --git a/modules/json_rpc/common/dap_json_rpc_chain_datum.c b/modules/json_rpc/common/dap_json_rpc_chain_datum.c
deleted file mode 100644
index 5b61d66f4075d7ea40e272167d8a72dc07c1ec65..0000000000000000000000000000000000000000
--- a/modules/json_rpc/common/dap_json_rpc_chain_datum.c
+++ /dev/null
@@ -1,728 +0,0 @@
-
-#include "dap_common.h"
-#include "dap_time.h"
-#include "dap_chain_datum.h"
-#include "dap_chain_datum_tx.h"
-#include "dap_chain_datum_token.h"
-#include "dap_chain_datum_tx_items.h"
-#include "dap_chain_datum_decree.h"
-#include "dap_chain_datum_anchor.h"
-#include "dap_chain_datum_hashtree_roots.h"
-#include "dap_enc_base58.h"
-
-#include "dap_json_rpc_chain_datum.h"
-#include "dap_json_rpc_chain_datum_tx.h"
-#include "dap_json_rpc_chain_datum_token.h"
-#include "dap_json_rpc_chain_datum_anchor.h"
-#include "dap_json_rpc_chain_datum_decree.h"
-#include "json.h"
-
-#define LOG_TAG "dap_json_rpc_chain_datum"
-
-json_object *s_dap_chain_datum_token_tsd_to_json(dap_chain_datum_token_t *a_token, size_t a_token_size) {
-    dap_tsd_t *l_tsd = dap_chain_datum_token_tsd_get(a_token, a_token_size);
-    if (l_tsd == NULL) {
-        json_object *l_tsd_wgn = json_object_new_object();
-        if (!l_tsd_wgn){
-            dap_json_rpc_allocation_error;
-            return NULL;
-        }
-        json_object *l_tsd_wgn_warning = json_object_new_string("<CORRUPTED TSD SECTION>");
-        if (!l_tsd_wgn_warning) {
-            json_object_put(l_tsd_wgn);
-            dap_json_rpc_allocation_error;
-            return NULL;
-        }
-        json_object_object_add(l_tsd_wgn, "warning", l_tsd_wgn_warning);
-        return l_tsd_wgn;
-    }
-    json_object *l_tsd_array = json_object_new_array();
-    if (!l_tsd_array) {
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    size_t l_tsd_total_size = 0;
-    switch (a_token->type) {
-        case DAP_CHAIN_DATUM_TOKEN_TYPE_DECL:
-            switch (a_token->subtype) {
-                case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE:
-                    l_tsd_total_size = a_token->header_private_decl.tsd_total_size; break;
-                case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE:
-                    l_tsd_total_size = a_token->header_native_decl.tsd_total_size; break;
-                default: break;
-            } break;
-        case DAP_CHAIN_DATUM_TOKEN_TYPE_UPDATE:
-            switch (a_token->subtype) {
-                case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE:
-                    l_tsd_total_size = a_token->header_private_update.tsd_total_size; break;
-                case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE:
-                    l_tsd_total_size = a_token->header_native_update.tsd_total_size; break;
-                default: break;
-            } break;
-        default: break;
-    }
-    size_t l_tsd_size = 0;
-    for (size_t l_offset = 0; l_offset < l_tsd_total_size; l_offset += l_tsd_size) {
-        json_object *l_jobj_tsd = json_object_new_object();
-        l_tsd = (dap_tsd_t *) (((byte_t*)l_tsd) + l_tsd_size);
-        l_tsd_size = l_tsd ? dap_tsd_size(l_tsd) : 0;
-        if (l_tsd_size == 0) {
-            json_object *l_wgn_text = json_object_new_string("Wrong zero TSD size, exiting s_datum_token_dump_tsd()");
-            if (!l_wgn_text) {
-                json_object_put(l_tsd_array);
-                dap_json_rpc_allocation_error;
-                return NULL;
-            }
-            json_object *l_wgn = json_object_new_object();
-            if (!l_wgn) {
-                json_object_put(l_wgn_text);
-                json_object_put(l_tsd_array);
-                dap_json_rpc_allocation_error;
-                return NULL;
-            }
-            json_object_object_add(l_wgn, "error", l_wgn_text);
-            json_object_array_add(l_tsd_array, l_wgn);
-            break;
-        } else if (l_tsd_size+l_offset > l_tsd_total_size) {
-            char *l_wgn_str = dap_strdup_printf("<CORRUPTED TSD> too big size %u when left maximum %zu",
-                                           l_tsd->size, l_tsd_total_size - l_offset);
-            if (!l_wgn_str) {
-                json_object_put(l_tsd_array);
-                dap_json_rpc_allocation_error;
-                return NULL;
-            }
-            json_object *l_wgn_text = json_object_new_string(l_wgn_str);
-            DAP_DELETE(l_wgn_str);
-            if (!l_wgn_text) {
-                json_object_put(l_tsd_array);
-                dap_json_rpc_allocation_error;
-                return NULL;
-            }
-            json_object *l_wgn = json_object_new_object();
-            if (!l_wgn) {
-                json_object_put(l_wgn_text);
-                json_object_put(l_tsd_array);
-                dap_json_rpc_allocation_error;
-                return NULL;
-            }
-            json_object_object_add(l_wgn, "error", l_wgn_text);
-            json_object_array_add(l_tsd_array, l_wgn);
-            break;
-        }
-        switch( l_tsd->type){
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_SET_FLAGS: {
-                json_object *l_jobj_tsd = json_object_new_object();
-                if (!l_jobj_tsd) {
-                    json_object_put(l_tsd_array);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object *l_jobj_tsd_type = json_object_new_string("DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_SET_FLAGS");
-                if (!l_jobj_tsd_type) {
-                    json_object_put(l_jobj_tsd);
-                    json_object_put(l_tsd_array);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                uint16_t l_flags = 0;
-                _dap_tsd_get_scalar(l_tsd, &l_flags);
-                json_object *l_jobj_tsd_flag = dap_chain_datum_token_flags_to_json(l_flags);
-                if (!l_jobj_tsd_flag) {
-                    json_object_put(l_jobj_tsd_type);
-                    json_object_put(l_jobj_tsd);
-                    json_object_put(l_tsd_array);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object_object_add(l_jobj_tsd, "type", l_jobj_tsd_type);
-                json_object_object_add(l_jobj_tsd, "flags", l_jobj_tsd_flag);
-                json_object_array_add(l_tsd_array, l_jobj_tsd);
-            } continue;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_UNSET_FLAGS: {
-                json_object *l_jobj_tsd = json_object_new_object();
-                if (!l_jobj_tsd) {
-                    json_object_put(l_tsd_array);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object *l_jobj_tsd_type = json_object_new_string("DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_UNSET_FLAGS");
-                if (!l_jobj_tsd_type) {
-                    json_object_put(l_jobj_tsd);
-                    json_object_put(l_tsd_array);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                uint16_t l_flags = 0;
-                _dap_tsd_get_scalar(l_tsd, &l_flags);
-                json_object *l_jobj_tsd_flag = dap_chain_datum_token_flags_to_json(l_flags);
-                if (!l_jobj_tsd_flag) {
-                    json_object_put(l_jobj_tsd_type);
-                    json_object_put(l_jobj_tsd);
-                    json_object_put(l_tsd_array);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object_object_add(l_jobj_tsd, "type", l_jobj_tsd_type);
-                json_object_object_add(l_jobj_tsd, "flags", l_jobj_tsd_flag);
-                json_object_array_add(l_tsd_array, l_jobj_tsd);
-            } continue;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SUPPLY: { // 256
-                json_object *l_jobj_tsd = json_object_new_object();
-                if (!l_jobj_tsd) {
-                    json_object_put(l_tsd_array);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object *l_jobj_tsd_type = json_object_new_string("DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SUPPLY");
-                if (!l_jobj_tsd_type) {
-                    json_object_put(l_jobj_tsd);
-                    json_object_put(l_tsd_array);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                uint256_t l_balance_native = uint256_0;
-                _dap_tsd_get_scalar(l_tsd, &l_balance_native);
-                json_object *l_jobj_tsd_value = json_object_new_string(dap_uint256_to_char(l_balance_native, NULL));
-                if (!l_jobj_tsd_value) {
-                    json_object_put(l_jobj_tsd);
-                    json_object_put(l_jobj_tsd_type);
-                    json_object_put(l_tsd_array);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object_object_add(l_jobj_tsd, "type", l_jobj_tsd_type);
-                json_object_object_add(l_jobj_tsd, "value", l_jobj_tsd_value);
-                json_object_array_add(l_tsd_array, l_jobj_tsd);
-            } continue;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SUPPLY_OLD: {// 128
-                json_object *l_jobj_tsd = json_object_new_object();
-                if (!l_jobj_tsd) {
-                    json_object_put(l_tsd_array);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object *l_jobj_tsd_type = json_object_new_string("DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SUPPLY_OLD");
-                if (!l_jobj_tsd_type) {
-                    json_object_put(l_jobj_tsd);
-                    json_object_put(l_tsd_array);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                uint128_t l_balance_native_old = uint128_0;
-                _dap_tsd_get_scalar(l_tsd, &l_balance_native_old);
-                json_object *l_jobj_tsd_value =
-                    json_object_new_string(dap_uint256_to_char(GET_256_FROM_128(l_balance_native_old), NULL));
-                if (!l_jobj_tsd_value) {
-                    json_object_put(l_jobj_tsd_type);
-                    json_object_put(l_jobj_tsd);
-                    json_object_put(l_tsd_array);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object_object_add(l_jobj_tsd, "type", l_jobj_tsd_type);
-                json_object_object_add(l_jobj_tsd, "value", l_jobj_tsd_value);
-                json_object_array_add(l_tsd_array, l_jobj_tsd);
-            } continue;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_VALID: {
-                json_object *l_jobj_tsd = json_object_new_object();
-                json_object *l_jobj_tsd_type = json_object_new_string("DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_VALID");
-                uint16_t l_flags = 0;
-                _dap_tsd_get_scalar(l_tsd, &l_flags);
-                json_object *l_jobj_value = json_object_new_uint64(l_flags);
-                json_object_object_add(l_jobj_tsd, "type", l_jobj_tsd_type);
-                json_object_object_add(l_jobj_tsd, "total_signs_valid", l_jobj_value);
-                json_object_array_add(l_tsd_array, l_jobj_tsd);
-            } continue;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_PKEYS_ADD: {
-                json_object *l_jobj_tsd = json_object_new_object();
-                if (!l_jobj_tsd) {
-                    json_object_put(l_tsd_array);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object *l_jobj_tsd_type = json_object_new_string("DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_PKEYS_ADD");
-                if (!l_jobj_tsd_type) {
-                    json_object_put(l_jobj_tsd);
-                    json_object_put(l_tsd_array);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object_object_add(l_jobj_tsd, "type", l_jobj_tsd_type);
-                if (l_tsd->size >= sizeof(dap_pkey_t)) {
-                    dap_pkey_t *l_pkey = (dap_pkey_t *) l_tsd->data;
-                    dap_hash_fast_t l_hf = {0};
-                    if (!dap_pkey_get_hash(l_pkey, &l_hf)) {
-                        json_object *l_wgn_text = json_object_new_string("total_pkeys_add: <WRONG CALCULATION FINGERPRINT>");
-                        if (!l_wgn_text) {
-                            json_object_put(l_jobj_tsd);
-                            json_object_put(l_tsd_array);
-                            dap_json_rpc_allocation_error;
-                            return NULL;
-                        }
-                        json_object_object_add(l_jobj_tsd, "warning", l_wgn_text);
-                    } else {
-                        json_object_object_add(l_jobj_tsd, "pkey",
-                            json_object_new_string(dap_chain_hash_fast_to_str_static(&l_hf)));
-                    }
-                } else {
-                    char *l_wgn_text = dap_strdup_printf("total_pkeys_add: <WRONG SIZE %u>\n", l_tsd->size);
-                    if (!l_wgn_text) {
-                        json_object_put(l_jobj_tsd);
-                        json_object_put(l_tsd_array);
-                        dap_json_rpc_allocation_error;
-                        return NULL;
-                    }
-                    json_object *l_jobj_wgn_text = json_object_new_string(l_wgn_text);
-                    DAP_DELETE(l_wgn_text);
-                    if (!l_jobj_wgn_text) {
-                        json_object_put(l_jobj_tsd);
-                        json_object_put(l_tsd_array);
-                        dap_json_rpc_allocation_error;
-                        return NULL;
-                    }
-                    json_object_object_add(l_jobj_tsd, "warning", l_jobj_wgn_text);
-                }
-                json_object_array_add(l_tsd_array, l_jobj_tsd);
-            } continue;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_PKEYS_REMOVE: {
-                json_object *l_jobj_tsd = json_object_new_object();
-                if (!l_jobj_tsd){
-                    json_object_put(l_tsd_array);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object *l_jobj_tsd_type = json_object_new_string("DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_PKEYS_REMOVE");
-                if (!l_jobj_tsd_type) {
-                    json_object_put(l_jobj_tsd);
-                    json_object_put(l_tsd_array);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object_object_add(l_jobj_tsd, "type", l_jobj_tsd_type);
-                if (l_tsd->size == sizeof(dap_chain_hash_fast_t)) {
-                    json_object_object_add(l_jobj_tsd, "pkey",
-                        json_object_new_string(dap_chain_hash_fast_to_str_static((dap_chain_hash_fast_t*) l_tsd->data)));
-                } else {
-                    char *l_wgn_text = dap_strdup_printf("total_pkeys_remove: <WRONG SIZE %u>\n", l_tsd->size);
-                    if (!l_wgn_text) {
-                        json_object_put(l_jobj_tsd);
-                        json_object_put(l_tsd_array);
-                        dap_json_rpc_allocation_error;
-                        return NULL;
-                    }
-                    json_object *l_jobj_wgn_text = json_object_new_string(l_wgn_text);
-                    DAP_DELETE(l_wgn_text);
-                    if (!l_jobj_wgn_text) {
-                        json_object_put(l_jobj_tsd);
-                        json_object_put(l_tsd_array);
-                        dap_json_rpc_allocation_error;
-                        return NULL;
-                    }
-                    json_object_object_add(l_jobj_tsd, "warning", l_jobj_wgn_text);
-                }
-                json_object_array_add(l_tsd_array, l_jobj_tsd);
-            } continue;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DELEGATE_EMISSION_FROM_STAKE_LOCK: {
-                json_object *l_jobj_tsd = json_object_new_object();
-                if (!l_jobj_tsd) {
-                    json_object_put(l_tsd_array);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object *l_jobj_tsd_type = json_object_new_string("DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DELEGATE_EMISSION_FROM_STAKE_LOCK");
-                if (!l_jobj_tsd_type) {
-                    json_object_put(l_jobj_tsd);
-                    json_object_put(l_tsd_array);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object_object_add(l_jobj_tsd, "type", l_jobj_tsd_type);
-                dap_chain_datum_token_tsd_delegate_from_stake_lock_t *l_tsd_section = _dap_tsd_get_object(l_tsd, dap_chain_datum_token_tsd_delegate_from_stake_lock_t);
-                json_object *l_jobj_ticker_token_from = json_object_new_string((char*)l_tsd_section->ticker_token_from);
-                if (!l_jobj_ticker_token_from) {
-                    json_object_put(l_jobj_ticker_token_from);
-                    json_object_put(l_jobj_tsd);
-                    json_object_put(l_tsd_array);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object_object_add(l_jobj_tsd, "ticker_token_from", l_jobj_ticker_token_from);
-                char *balance; dap_uint256_to_char(l_tsd_section->emission_rate, &balance);
-                json_object *l_jobj_emission_rate = json_object_new_string(balance);
-                if (!l_jobj_emission_rate) {
-                    json_object_put(l_jobj_tsd);
-                    json_object_put(l_tsd_array);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object_object_add(l_jobj_tsd, "emission_rate", l_jobj_emission_rate);
-                json_object_array_add(l_tsd_array, l_jobj_tsd);
-            } continue;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_ALLOWED_ADD: {
-                json_object *l_jobj_tsd = json_object_new_object();
-                if (!l_jobj_tsd) {
-                    json_object_put(l_tsd_array);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object *l_jobj_tsd_type = json_object_new_string("DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_ALLOWED_ADD");
-                if (!l_jobj_tsd_type) {
-                    json_object_put(l_jobj_tsd);
-                    json_object_put(l_tsd_array);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object_object_add(l_jobj_tsd, "type", l_jobj_tsd_type);
-                json_object *l_jobj_datum_type_allowed_add = json_object_new_string(dap_tsd_get_string_const(l_tsd));
-                if (!l_jobj_datum_type_allowed_add) {
-                    json_object_put(l_jobj_tsd);
-                    json_object_put(l_tsd_array);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object_object_add(l_jobj_tsd, "datum_type_allowed_add", l_jobj_datum_type_allowed_add);
-                json_object_array_add(l_tsd_array, l_jobj_tsd);
-            }continue;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_ALLOWED_REMOVE: {
-                json_object *l_jobj_tsd = json_object_new_object();
-                json_object *l_jobj_tsd_type = json_object_new_string("DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_ALLOWED_REMOVE");
-                json_object *l_jobj_datum_type_allowed_remove = json_object_new_string(dap_tsd_get_string_const(l_tsd));
-                if (!l_jobj_tsd || !l_jobj_tsd_type || !l_jobj_datum_type_allowed_remove) {
-                    json_object_put(l_jobj_datum_type_allowed_remove);
-                    json_object_put(l_jobj_tsd);
-                    json_object_put(l_tsd_array);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object_object_add(l_jobj_tsd, "type", l_jobj_tsd_type);
-                json_object_object_add(l_jobj_tsd, "datum_type_allowed_remove", l_jobj_datum_type_allowed_remove);
-                json_object_array_add(l_tsd_array, l_jobj_tsd);
-            }continue;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_BLOCKED_ADD: {
-                json_object *l_jobj_tsd = json_object_new_object();
-                json_object *l_jobj_tsd_type = json_object_new_string("DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_BLOCKED_ADD");
-                json_object *l_jobj_datum_type_blocked_add = json_object_new_string(dap_tsd_get_string_const(l_tsd));
-                if (!l_jobj_tsd || !l_jobj_tsd_type || !l_jobj_datum_type_blocked_add) {
-                    json_object_put(l_jobj_datum_type_blocked_add);
-                    json_object_put(l_jobj_tsd);
-                    json_object_put(l_tsd_array);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object_object_add(l_jobj_tsd, "type", l_jobj_tsd_type);
-                json_object_object_add(l_jobj_tsd, "datum_type_blocked_add", l_jobj_datum_type_blocked_add);
-                json_object_array_add(l_tsd_array, l_jobj_tsd);
-            } continue;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_BLOCKED_REMOVE: {
-                json_object *l_jobj_tsd = json_object_new_object();
-                json_object *l_jobj_tsd_type = json_object_new_string("DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_BLOCKED_REMOVE");
-                json_object *l_jobj_datum_type_blocked_remove = json_object_new_string(dap_tsd_get_string_const(l_tsd));
-                if (!l_jobj_tsd || !l_jobj_tsd_type || !l_jobj_datum_type_blocked_remove) {
-                    json_object_put(l_jobj_datum_type_blocked_remove);
-                    json_object_put(l_jobj_tsd);
-                    json_object_put(l_tsd_array);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object_object_add(l_jobj_tsd, "type", l_jobj_tsd_type);
-                json_object_object_add(l_jobj_tsd, "datum_type_blocked_remove", l_jobj_datum_type_blocked_remove);
-                json_object_array_add(l_tsd_array, l_jobj_tsd);
-            } continue;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_ADD: {
-                json_object *l_jobj_tsd = json_object_new_object();
-                json_object *l_jobj_tsd_type = json_object_new_string("DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_ADD");
-                json_object *l_jobj_tx_sender_allowed_add = json_object_new_string(dap_tsd_get_string_const(l_tsd));
-                if (!l_jobj_tsd || !l_jobj_tsd_type || !l_jobj_tx_sender_allowed_add) {
-                    json_object_put(l_jobj_tx_sender_allowed_add);
-                    json_object_put(l_jobj_tsd);
-                    json_object_put(l_tsd_array);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object_object_add(l_jobj_tsd, "type", l_jobj_tsd_type);
-                json_object_object_add(l_jobj_tsd, "tx_sender_allowed_add",l_jobj_tx_sender_allowed_add);
-                json_object_array_add(l_tsd_array, l_jobj_tsd);
-            } continue;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_REMOVE: {
-                json_object *l_jobj_tsd = json_object_new_object();
-                json_object *l_jobj_tsd_type = json_object_new_string("DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_REMOVE");
-                json_object *l_jobj_tx_sender_allowed_remove = json_object_new_string(dap_tsd_get_string_const(l_tsd));
-                if (!l_jobj_tsd || !l_jobj_tsd_type || !l_jobj_tx_sender_allowed_remove) {
-                    json_object_put(l_jobj_tx_sender_allowed_remove);
-                    json_object_put(l_jobj_tsd);
-                    json_object_put(l_tsd_array);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object_object_add(l_jobj_tsd, "type", l_jobj_tsd_type);
-                json_object_object_add(l_jobj_tsd, "tx_sender_allowed_remove",l_jobj_tx_sender_allowed_remove);
-                json_object_array_add(l_tsd_array, l_jobj_tsd);
-            }continue;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_ADD: {
-                json_object *l_jobj_tsd = json_object_new_object();
-                json_object *l_jobj_tsd_type = json_object_new_string("DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_ADD");
-                json_object *l_jobj_tx_sender_blocked_add = json_object_new_string(dap_tsd_get_string_const(l_tsd));
-                if (!l_jobj_tsd || !l_jobj_tsd_type || !l_jobj_tx_sender_blocked_add) {
-                    json_object_put(l_jobj_tx_sender_blocked_add);
-                    json_object_put(l_jobj_tsd);
-                    json_object_put(l_tsd_array);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object_object_add(l_jobj_tsd, "type", l_jobj_tsd_type);
-                json_object_object_add(l_jobj_tsd, "tx_sender_blocked_add", l_jobj_tx_sender_blocked_add);
-                json_object_array_add(l_tsd_array, l_jobj_tsd);
-            } continue;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_REMOVE: {
-                json_object *l_jobj_tsd = json_object_new_object();
-                json_object *l_jobj_tsd_type = json_object_new_string("DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_REMOVE");
-                json_object *l_jobj_tx_sender_blocked_remove = json_object_new_string(dap_tsd_get_string_const(l_tsd));
-                if (!l_jobj_tsd || !l_jobj_tsd_type || !l_jobj_tx_sender_blocked_remove) {
-                    json_object_put(l_jobj_tx_sender_blocked_remove);
-                    json_object_put(l_jobj_tsd);
-                    json_object_put(l_tsd_array);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object_object_add(l_jobj_tsd, "type", l_jobj_tsd_type);
-                json_object_object_add(l_jobj_tsd, "tx_sender_blocked_remove", l_jobj_tx_sender_blocked_remove);
-                json_object_array_add(l_tsd_array, l_jobj_tsd);
-            } continue;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_ADD: {
-                json_object *l_jobj_tsd = json_object_new_object();
-                json_object *l_jobj_tsd_type = json_object_new_string("DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_ADD");
-                json_object *l_tx_receiver_allowed_add = json_object_new_string(dap_tsd_get_string_const(l_tsd));
-                if (!l_jobj_tsd || !l_jobj_tsd_type || !l_tx_receiver_allowed_add) {
-                    json_object_put(l_tx_receiver_allowed_add);
-                    json_object_put(l_jobj_tsd);
-                    json_object_put(l_tsd_array);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object_object_add(l_jobj_tsd, "type", l_jobj_tsd_type);
-                json_object_object_add(l_jobj_tsd, "tx_receiver_allowed_add", l_tx_receiver_allowed_add);
-                json_object_array_add(l_tsd_array, l_jobj_tsd);
-            } continue;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_REMOVE: {
-                json_object *l_jobj_tsd = json_object_new_object();
-                json_object *l_jobj_tsd_type = json_object_new_string("DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_REMOVE");
-                json_object *l_jobj_tx_receiver_allowed_remove = json_object_new_string(dap_tsd_get_string_const(l_tsd));
-                if (!l_jobj_tsd || !l_jobj_tsd_type || !l_jobj_tx_receiver_allowed_remove){
-                    json_object_put(l_jobj_tx_receiver_allowed_remove);
-                    json_object_put(l_jobj_tsd);
-                    json_object_put(l_tsd_array);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object_object_add(l_jobj_tsd, "type", l_jobj_tsd_type);
-                json_object_object_add(l_jobj_tsd, "tx_receiver_allowed_remove", l_jobj_tx_receiver_allowed_remove);
-                json_object_array_add(l_tsd_array, l_jobj_tsd);
-            } continue;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_ADD: {
-                json_object *l_jobj_tsd = json_object_new_object();
-                json_object *l_jobj_tsd_type = json_object_new_string("DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_ADD");
-                json_object *l_jobj_tx_receiver_blocked_add = json_object_new_string(dap_tsd_get_string_const(l_tsd));
-                if (!l_jobj_tsd || !l_jobj_tsd_type || !l_jobj_tx_receiver_blocked_add){
-                    json_object_put(l_jobj_tx_receiver_blocked_add);
-                    json_object_put(l_jobj_tsd);
-                    json_object_put(l_tsd_array);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object_object_add(l_jobj_tsd, "type", l_jobj_tsd_type);
-                json_object_object_add(l_jobj_tsd, "tx_receiver_blocked_add", l_jobj_tx_receiver_blocked_add);
-                json_object_array_add(l_tsd_array, l_jobj_tsd);
-            } continue;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_REMOVE: {
-                json_object *l_jobj_tsd = json_object_new_object();
-                json_object *l_jobj_tsd_type = json_object_new_string("DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_REMOVE");
-                json_object *l_jobj_tx_receiver_blocked_remove = json_object_new_string(dap_tsd_get_string_const(l_tsd));
-                if (!l_jobj_tsd || !l_jobj_tsd_type || !l_jobj_tx_receiver_blocked_remove) {
-                    json_object_put(l_jobj_tx_receiver_blocked_remove);
-                    json_object_put(l_jobj_tsd);
-                    json_object_put(l_tsd_array);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object_object_add(l_jobj_tsd, "type", l_jobj_tsd_type);
-                json_object_object_add(l_jobj_tsd, "tx_receiver_blocked_remove", l_jobj_tx_receiver_blocked_remove);
-                json_object_array_add(l_tsd_array, l_jobj_tsd);
-            } continue;
-            default: {
-                char *l_wgn_text = dap_strdup_printf("<0x%04hX>: <size %u>\n", l_tsd->type, l_tsd->size);
-                if (!l_wgn_text){
-                    json_object_put(l_jobj_tsd);
-                    json_object_put(l_tsd_array);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object *l_jobj_wgn_text = json_object_new_string(l_wgn_text);
-                DAP_DELETE(l_wgn_text);
-                json_object *l_jobj_warning = json_object_new_object();
-                if (!l_jobj_wgn_text || !l_jobj_warning) {
-                    json_object_put(l_jobj_wgn_text);
-                    json_object_put(l_jobj_warning);
-                    json_object_put(l_jobj_tsd);
-                    json_object_put(l_tsd_array);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object_object_add(l_jobj_warning, "warning", l_jobj_wgn_text);
-                json_object_array_add(l_tsd_array, l_jobj_warning);
-            }
-        }
-    }
-    return l_tsd_array;
-}
-
-typedef enum dap_chain_datum_to_json_err_list {
-    CHAIN_DATUM_TO_JSON_ERR_CAN_NOT_SERIALIZATION_TX_TO_JSON = DAP_JSON_RPC_ERR_CODE_METHOD_ERR_START,
-    CHAIN_DATUM_TO_JSON_ERR_CAN_NOT_SERIALIZATION_DECL_TO_JSON,
-    CHAIN_DATUM_TO_JSON_ERR_CAN_NOT_READ_DECL,
-    CHAIN_DATUM_TO_JSON_ERR_CAN_NOT_SERIALIZATION_TSD_SECTION_DECL_TO_JSON,
-    CHAIN_DATUM_TO_JSON_ERR_CAN_NOT_SERIALIZATION_EMISSION_TO_JSON,
-    CHAIN_DATUM_TO_JSON_ERR_CAN_NOT_READ_EMISSION,
-    CHAIN_DATUM_TO_JSON_ERR_CAN_NOT_SERIALIZATION_ANCHOR_TO_JSON,
-    CHAIN_DATUM_TO_JSON_ERR_CAN_NOT_SERIALIZATION_DECREE_TO_JSON
-}dap_chain_datum_to_json_err_list_t;
-
-json_object * dap_chain_datum_to_json(dap_chain_datum_t* a_datum){
-    json_object *l_object = json_object_new_object();
-    if (!l_object){
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    char *l_hash_data_str;
-    dap_get_data_hash_str_static(a_datum->data, a_datum->header.data_size, l_hash_data_str);
-    json_object *l_obj_data_hash = json_object_new_string(l_hash_data_str);
-    if (!l_obj_data_hash) {
-        json_object_put(l_object);
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    json_object *l_obj_version = json_object_new_int(a_datum->header.version_id);
-    if (!l_obj_version) {
-        json_object_put(l_object);
-        json_object_put(l_obj_data_hash);
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    json_object *l_obj_size = json_object_new_int(a_datum->header.data_size);
-    if (!l_obj_size) {
-        json_object_put(l_object);
-        json_object_put(l_obj_data_hash);
-        json_object_put(l_obj_version);
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    json_object *l_obj_type = json_object_new_string(dap_chain_datum_type_id_to_str(a_datum->header.type_id));
-    if (!l_obj_type) {
-        json_object_put(l_object);
-        json_object_put(l_obj_data_hash);
-        json_object_put(l_obj_version);
-        json_object_put(l_obj_size);
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    json_object *l_obj_data = dap_chain_datum_data_to_json(a_datum);
-
-    json_object_object_add(l_object, "hash", l_obj_data_hash);
-    json_object_object_add(l_object, "data_size", l_obj_size);
-    json_object_object_add(l_object, "version", l_obj_version);
-
-    char l_time_str[DAP_TIME_STR_SIZE];
-    if (a_datum->header.ts_create) {
-        dap_time_to_str_rfc822(l_time_str, DAP_TIME_STR_SIZE, a_datum->header.ts_create); /* Convert ts to  "Sat May 17 01:17:08 2014\n" */
-        l_time_str[strlen(l_time_str)-1] = '\0';                    /* Remove "\n"*/
-    }
-    json_object *l_obj_ts_created = json_object_new_string(l_time_str);
-    json_object_object_add(l_object, "ts_create", l_obj_ts_created);
-    json_object_object_add(l_object, "type", l_obj_type);
-    if (a_datum->header.type_id == DAP_CHAIN_DATUM_TX) {
-        json_object_object_add(l_object, "items", l_obj_data);
-    } else {
-        json_object_object_add(l_object, "data", l_obj_data);
-    }
-    return l_object;
-}
-
-json_object * dap_chain_datum_data_to_json(dap_chain_datum_t *a_datum) {
-    if (!a_datum)
-        return json_object_new_null();
-    json_object *l_obj_data;
-    switch (a_datum->header.type_id) {
-        case DAP_CHAIN_DATUM_TX:
-            l_obj_data = dap_chain_datum_tx_to_json((dap_chain_datum_tx_t*)a_datum->data, NULL);
-            if (!l_obj_data) {
-                dap_json_rpc_error_add(CHAIN_DATUM_TO_JSON_ERR_CAN_NOT_SERIALIZATION_TX_TO_JSON,
-                                       "Can't convert DAP_CHAIN_DATUM_TX to JSON");
-                return NULL;
-            }
-            break;
-        case DAP_CHAIN_DATUM_DECREE:
-            l_obj_data = dap_chain_datum_decree_to_json((dap_chain_datum_decree_t*)a_datum->data);
-            if (!l_obj_data) {
-                dap_json_rpc_error_add(CHAIN_DATUM_TO_JSON_ERR_CAN_NOT_SERIALIZATION_DECREE_TO_JSON,
-                                       "Can't convert DAP_CHAIN_DATUM_DECREE to JSON");
-                return NULL;
-            }
-            break;
-        case DAP_CHAIN_DATUM_ANCHOR:
-            l_obj_data = dap_chain_datum_anchor_to_json((dap_chain_datum_anchor_t*)a_datum->data);
-            if (!l_obj_data) {
-                dap_json_rpc_error_add(CHAIN_DATUM_TO_JSON_ERR_CAN_NOT_SERIALIZATION_ANCHOR_TO_JSON,
-                                       "Can't convert DAP_CHAIN_DATUM_ANCHOR to JSON");
-                return NULL;
-            }
-            break;
-        case DAP_CHAIN_DATUM_TOKEN_DECL: {
-            size_t l_token_size = a_datum->header.data_size;
-            dap_chain_datum_token_t *l_token = dap_chain_datum_token_read(a_datum->data, &l_token_size);
-            if (!l_token) {
-                dap_json_rpc_error_add(CHAIN_DATUM_TO_JSON_ERR_CAN_NOT_READ_DECL,
-                                       "The contents of the token delcaration could not be read.");
-                return NULL;
-            }
-            l_obj_data = dap_chain_datum_token_to_json(l_token, l_token_size);
-            if (!l_obj_data) {
-                dap_json_rpc_error_add(CHAIN_DATUM_TO_JSON_ERR_CAN_NOT_SERIALIZATION_DECL_TO_JSON,
-                                       "Can't convert DAP_CHAIN_DATUM_TOKEN_DECL to JSON");
-                DAP_DELETE(l_token);
-                return NULL;
-            }
-            json_object *l_obj_tsd_data = s_dap_chain_datum_token_tsd_to_json(l_token, l_token_size);
-            if (!l_obj_tsd_data) {
-                json_object_put(l_obj_data);
-                DAP_DELETE(l_token);
-                log_it(L_ERROR, "It was not possible to read the contents of the TSD sections of the token delcaration.");
-                dap_json_rpc_error_add(CHAIN_DATUM_TO_JSON_ERR_CAN_NOT_SERIALIZATION_TSD_SECTION_DECL_TO_JSON,
-                                       "It was not possible to read the contents of the TSD sections of the token delcaration.");
-                return NULL;
-            }
-            json_object_object_add(l_obj_data, "TSD", l_obj_tsd_data);
-            DAP_DELETE(l_token);
-        } break;
-        case DAP_CHAIN_DATUM_TOKEN_EMISSION: {
-            size_t l_emission_size = a_datum->header.data_size;
-            dap_chain_datum_token_emission_t *l_emission = dap_chain_datum_emission_read(a_datum->data, &l_emission_size);
-            if (l_emission_size == 0 || !l_emission) {
-                log_it(L_ERROR, "Failed to read emission");
-                dap_json_rpc_error_add(CHAIN_DATUM_TO_JSON_ERR_CAN_NOT_READ_EMISSION,
-                                       "Failed to read emission.");
-                return NULL;
-            } else {
-                l_obj_data = dap_chain_datum_emission_to_json(l_emission, l_emission_size);
-                DAP_DELETE(l_emission);
-                if (!l_obj_data) {
-                    dap_json_rpc_error_add(CHAIN_DATUM_TO_JSON_ERR_CAN_NOT_SERIALIZATION_EMISSION_TO_JSON,
-                                           "Can't convert DAP_CHAIN_DATUM_TOKEN_DECL to JSON");
-                    return NULL;
-                }
-            }
-        } break;
-        default:
-            l_obj_data = json_object_new_null();
-            break;
-    }
-    return l_obj_data;
-}
diff --git a/modules/json_rpc/common/dap_json_rpc_chain_datum_anchor.c b/modules/json_rpc/common/dap_json_rpc_chain_datum_anchor.c
deleted file mode 100644
index e41c242d9755b3ed00a872d8a2d97b2c868a4e73..0000000000000000000000000000000000000000
--- a/modules/json_rpc/common/dap_json_rpc_chain_datum_anchor.c
+++ /dev/null
@@ -1,169 +0,0 @@
-#include "dap_json_rpc_chain_datum_anchor.h"
-#include "json.h"
-
-#define LOG_TAG "dap_json_rpc_chain_datum_anchor"
-
-
-json_object *s_dap_chain_datum_anchor_sign_to_json(byte_t * a_signs, size_t a_certs_size) {
-    json_object *l_jobs_signs = json_object_new_array();
-    size_t l_offset = 0;
-    for (int i = 1; l_offset < (a_certs_size); i++) {
-        json_object *l_jobj_sign = json_object_new_object();
-        dap_sign_t *l_sign = (dap_sign_t*)(a_signs + l_offset);
-        l_offset += dap_sign_get_size(l_sign);
-        if (l_sign->header.sign_size == 0) {
-            json_object *l_wrn_text = json_object_new_string("<CORRUPTED - 0 size signature>");
-            json_object_object_add(l_jobj_sign, "warning", l_wrn_text);
-            continue;
-        }
-
-        dap_chain_hash_fast_t l_pkey_hash = {0};
-        if (dap_sign_get_pkey_hash(l_sign, &l_pkey_hash) == false) {
-            json_object *l_wrn_text = json_object_new_string("<CORRUPTED - can't calc hash>");
-            json_object_object_add(l_jobj_sign, "warning", l_wrn_text);
-            continue;
-        }
-        json_object *l_jobj_hash_str = json_object_new_string(dap_chain_hash_fast_to_str_static(&l_pkey_hash));
-        json_object *l_jobj_type_str = json_object_new_string(dap_sign_type_to_str(l_sign->header.type));
-        json_object *l_jobj_sign_size = json_object_new_uint64(l_sign->header.sign_size);
-        json_object_object_add(l_jobj_sign, "hash", l_jobj_hash_str);
-        json_object_object_add(l_jobj_sign, "type", l_jobj_type_str);
-        json_object_object_add(l_jobj_sign, "size", l_jobj_sign_size);
-        json_object_array_add(l_jobs_signs, l_jobj_sign);
-    }
-    return l_jobs_signs;
-}
-
-json_object *dap_chain_datum_anchor_to_json(dap_chain_datum_anchor_t *a_anchor){
-    json_object *l_obj_anchor = json_object_new_object();
-    if (!l_obj_anchor) {
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    json_object *l_obj_version = json_object_new_uint64(a_anchor->anchor_version);
-    if (!l_obj_version){
-        json_object_put(l_obj_anchor);
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    json_object *l_obj_ts_created = json_object_new_uint64(a_anchor->header.ts_created);
-    if (!l_obj_ts_created) {
-        json_object_put(l_obj_version);
-        json_object_put(l_obj_anchor);
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    json_object *l_obj_tsd_array = json_object_new_array();
-    if(!l_obj_tsd_array) {
-        json_object_put(l_obj_ts_created);
-        json_object_put(l_obj_version);
-        json_object_put(l_obj_anchor);
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    size_t l_tsd_offset = 0, tsd_data_size = a_anchor->header.data_size;
-
-    while(l_tsd_offset < tsd_data_size){
-        json_object *l_jobj_tsd = json_object_new_object();
-        if (!l_jobj_tsd) {
-            json_object_put(l_obj_tsd_array);
-            json_object_put(l_obj_ts_created);
-            json_object_put(l_obj_version);
-            json_object_put(l_obj_anchor);
-            dap_json_rpc_allocation_error;
-            return NULL;
-        }
-        dap_tsd_t *l_tsd = (dap_tsd_t*)a_anchor->data_n_sign + l_tsd_offset;
-        size_t l_tsd_size = l_tsd->size + sizeof(dap_tsd_t);
-        if(l_tsd_size > tsd_data_size){
-            json_object *l_jobj_wgn = json_object_new_string("TSD size is greater than all data size. It's possible corrupt data.");
-            if (!l_jobj_wgn){
-                json_object_put(l_jobj_tsd);
-                json_object_put(l_obj_tsd_array);
-                json_object_put(l_obj_ts_created);
-                json_object_put(l_obj_ts_created);
-                json_object_put(l_obj_version);
-                json_object_put(l_obj_anchor);
-                dap_json_rpc_allocation_error;
-                return NULL;
-            }
-            json_object_object_add(l_jobj_tsd, "warning", l_jobj_wgn);
-            json_object_array_add(l_obj_tsd_array, l_jobj_tsd);
-            break;
-        }
-        if (l_tsd->type == DAP_CHAIN_DATUM_ANCHOR_TSD_TYPE_DECREE_HASH){
-            json_object *l_obj_tsd_type = json_object_new_string("DAP_CHAIN_DATUM_ANCHOR_TSD_TYPE_DECREE_HASH");
-            if (!l_obj_tsd_type){
-                json_object_put(l_jobj_tsd);
-                json_object_put(l_obj_tsd_array);
-                json_object_put(l_obj_ts_created);
-                json_object_put(l_obj_ts_created);
-                json_object_put(l_obj_version);
-                json_object_put(l_obj_anchor);
-                dap_json_rpc_allocation_error;
-                return NULL;
-            }
-            json_object_object_add(l_jobj_tsd, "type", l_obj_tsd_type);
-            if(l_tsd->size > sizeof(dap_hash_fast_t)){
-                json_object *l_jobj_wgn = json_object_new_string("Wrong fee tsd data size.");
-                if (!l_jobj_wgn){
-                    json_object_put(l_jobj_tsd);
-                    json_object_put(l_obj_tsd_array);
-                    json_object_put(l_obj_ts_created);
-                    json_object_put(l_obj_ts_created);
-                    json_object_put(l_obj_version);
-                    json_object_put(l_obj_anchor);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object_object_add(l_jobj_tsd, "warning", l_jobj_wgn);
-                json_object_array_add(l_obj_tsd_array, l_jobj_tsd);
-                break;
-            }
-            dap_hash_fast_t l_out_hash = {0};
-            _dap_tsd_get_scalar(l_tsd, &l_out_hash);
-            char *l_hash_str = dap_hash_fast_to_str_new(&l_out_hash);
-            if (!l_hash_str) {
-                json_object_put(l_jobj_tsd);
-                json_object_put(l_obj_tsd_array);
-                json_object_put(l_obj_ts_created);
-                json_object_put(l_obj_ts_created);
-                json_object_put(l_obj_version);
-                json_object_put(l_obj_anchor);
-                dap_json_rpc_allocation_error;
-                return NULL;
-            }
-            json_object *l_obj_tsd_hash = json_object_new_string(l_hash_str);
-            DAP_DELETE(l_hash_str);
-            if (!l_obj_tsd_hash){
-                json_object_put(l_jobj_tsd);
-                json_object_put(l_obj_tsd_array);
-                json_object_put(l_obj_ts_created);
-                json_object_put(l_obj_ts_created);
-                json_object_put(l_obj_version);
-                json_object_put(l_obj_anchor);
-                dap_json_rpc_allocation_error;
-                return NULL;
-            }
-            json_object_object_add(l_jobj_tsd, "hash", l_obj_tsd_hash);
-        }
-        json_object_array_add(l_obj_tsd_array, l_jobj_tsd);
-        l_tsd_offset += l_tsd_size;
-    }
-    json_object_object_add(l_obj_anchor, "version", l_obj_version);
-    json_object_object_add(l_obj_anchor, "ts_created", l_obj_ts_created);
-    json_object_object_add(l_obj_anchor, "TSD", l_obj_tsd_array);
-    json_object *l_jobj_signs = s_dap_chain_datum_anchor_sign_to_json(a_anchor->data_n_sign + a_anchor->header.data_size,
-                                                                      a_anchor->header.signs_size);
-    if (!l_jobj_signs) {
-        json_object_put(l_obj_tsd_array);
-        json_object_put(l_obj_ts_created);
-        json_object_put(l_obj_ts_created);
-        json_object_put(l_obj_version);
-        json_object_put(l_obj_anchor);
-        dap_json_rpc_error_add(DAP_JSON_RPC_ERR_CODE_SERIALIZATION_SIGN_TO_JSON, "I can't serialize the anchor signature in JSON.");
-        return NULL;
-    }
-    json_object_object_add(l_obj_anchor, "signs", l_jobj_signs);
-    return l_obj_anchor;
-}
diff --git a/modules/json_rpc/common/dap_json_rpc_chain_datum_decree.c b/modules/json_rpc/common/dap_json_rpc_chain_datum_decree.c
deleted file mode 100644
index 95d2cedcc88c33ec686dcacca946a23101dd593e..0000000000000000000000000000000000000000
--- a/modules/json_rpc/common/dap_json_rpc_chain_datum_decree.c
+++ /dev/null
@@ -1,550 +0,0 @@
-
-#include "dap_json_rpc_chain_datum_decree.h"
-#include "dap_json_rpc_chain_common.h"
-#include "json.h"
-
-
-#define LOG_TAG "dap_json_rpc_chain_datum_decree"
-
-json_object *s_dap_chain_datum_decree_certs_dump_json(byte_t * a_signs, size_t a_certs_size){
-    json_object *l_jobj_signatures = json_object_new_array();
-    if (!l_jobj_signatures) {
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    size_t l_offset = 0;
-    for (int i = 1; l_offset < (a_certs_size); i++) {
-        json_object *l_jobj_signature = json_object_new_object();
-        if (!l_jobj_signature) {
-            json_object_put(l_jobj_signatures);
-            dap_json_rpc_allocation_error;
-            return NULL;
-        }
-        dap_sign_t *l_sign = (dap_sign_t *) (a_signs + l_offset);
-        l_offset += dap_sign_get_size(l_sign);
-        if (l_sign->header.sign_size == 0) {
-            json_object *l_wrn_text = json_object_new_string("<CORRUPTED - 0 size signature>");
-            if(!l_wrn_text) {
-                json_object_put(l_jobj_signature);
-                json_object_put(l_jobj_signatures);
-                dap_json_rpc_allocation_error;
-                return NULL;
-            }
-            json_object_object_add(l_jobj_signature, "warning", l_wrn_text);
-            continue;
-        }
-
-        dap_chain_hash_fast_t l_pkey_hash = {0};
-        if (dap_sign_get_pkey_hash(l_sign, &l_pkey_hash) == false) {
-            json_object *l_wrn_text = json_object_new_string("<CORRUPTED - can't calc hash>");
-            if (!l_wrn_text){
-                json_object_put(l_jobj_signature);
-                json_object_put(l_jobj_signatures);
-                dap_json_rpc_allocation_error;
-                return NULL;
-            }
-            json_object_object_add(l_jobj_signature, "warning", l_wrn_text);
-            continue;
-        }
-
-        json_object *l_jobj_hash_str 
-            = json_object_new_string(dap_chain_hash_fast_to_str_static(&l_pkey_hash));
-        if (!l_jobj_hash_str) {
-            json_object_put(l_jobj_signature);
-            json_object_put(l_jobj_signatures);
-            dap_json_rpc_allocation_error;
-            return NULL;
-        }
-        json_object *l_jobj_type_str = json_object_new_string(dap_sign_type_to_str(l_sign->header.type));
-        if (!l_jobj_type_str) {
-            json_object_put(l_jobj_hash_str);
-            json_object_put(l_jobj_signature);
-            json_object_put(l_jobj_signatures);
-            dap_json_rpc_allocation_error;
-            return NULL;
-        }
-        json_object *l_jobj_sign_size = json_object_new_uint64(l_sign->header.sign_size);
-        if (!l_jobj_sign_size) {
-            json_object_put(l_jobj_hash_str);
-            json_object_put(l_jobj_type_str);
-            json_object_put(l_jobj_signature);
-            json_object_put(l_jobj_signatures);
-            dap_json_rpc_allocation_error;
-            return NULL;
-        }
-        json_object_object_add(l_jobj_signature, "hash", l_jobj_hash_str);
-        json_object_object_add(l_jobj_signature, "type", l_jobj_type_str);
-        json_object_object_add(l_jobj_signature, "size", l_jobj_sign_size);
-        json_object_array_add(l_jobj_signatures, l_jobj_signature);
-    }
-    return l_jobj_signatures;
-}
-
-json_object *dap_chain_datum_decree_to_json(dap_chain_datum_decree_t *a_decree){
-    json_object *l_jobj_decree = json_object_new_object();
-    if (!l_jobj_decree) {
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    char *l_type_str = "";
-    switch(a_decree->header.type)
-    {
-        case DAP_CHAIN_DATUM_DECREE_TYPE_COMMON:
-            l_type_str = "DECREE_TYPE_COMMON";
-            break;
-        case DAP_CHAIN_DATUM_DECREE_TYPE_SERVICE:
-            l_type_str = "DECREE_TYPE_SERVICE";
-            break;
-        default:
-            l_type_str = "DECREE_TYPE_UNKNOWN";
-    }
-    json_object *l_jobj_type = json_object_new_string(l_type_str);
-    if (!l_jobj_type) {
-        json_object_put(l_jobj_decree);
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    const char *l_subtype_str = dap_chain_datum_decree_subtype_to_str(a_decree->header.sub_type);
-    json_object *l_json_subtype = json_object_new_string(l_subtype_str);
-    if (!l_json_subtype) {
-        json_object_put(l_jobj_type);
-        json_object_put(l_jobj_decree);
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    json_object *l_json_tsd_array = json_object_new_array();
-    if (!l_json_tsd_array){
-        json_object_put(l_json_subtype);
-        json_object_put(l_jobj_type);
-        json_object_put(l_jobj_decree);
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    for (size_t l_offset = 0; l_offset < a_decree->header.data_size;) {
-        dap_tsd_t *l_tsd = (dap_tsd_t *)((byte_t*)a_decree->data_n_signs + l_offset);
-        l_offset += dap_tsd_size(l_tsd);
-        json_object *l_jobj_tsd = json_object_new_object();
-        if (!l_jobj_tsd) {
-            json_object_put(l_json_tsd_array);
-            json_object_put(l_json_subtype);
-            json_object_put(l_jobj_type);
-            json_object_put(l_jobj_decree);
-            dap_json_rpc_allocation_error;
-            return NULL;
-        }
-        switch(l_tsd->type) {
-            case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_SIGN: {
-                json_object *l_obj_tsd_type = json_object_new_string("DAP_CHAIN_DATUM_DECREE_TSD_TYPE_SIGN");
-                if (!l_obj_tsd_type) {
-                    json_object_put(l_json_tsd_array);
-                    json_object_put(l_json_subtype);
-                    json_object_put(l_jobj_type);
-                    json_object_put(l_jobj_decree);
-                    json_object_put(l_jobj_tsd);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object_object_add(l_jobj_tsd, "type", l_obj_tsd_type);
-            } break;
-            case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_FEE: {
-                json_object *l_obj_tsd_type = json_object_new_string("DAP_CHAIN_DATUM_DECREE_TSD_TYPE_FEE");
-                if (!l_obj_tsd_type) {
-                    json_object_put(l_json_tsd_array);
-                    json_object_put(l_json_subtype);
-                    json_object_put(l_jobj_type);
-                    json_object_put(l_jobj_decree);
-                    json_object_put(l_jobj_tsd);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object_object_add(l_jobj_tsd, "type", l_obj_tsd_type);
-                if (l_tsd->size > sizeof(uint256_t)) {
-                    json_object *l_text_wgn = json_object_new_string("Fee: <WRONG SIZE>");
-                    if (!l_text_wgn) {
-                        json_object_put(l_json_tsd_array);
-                        json_object_put(l_json_subtype);
-                        json_object_put(l_jobj_type);
-                        json_object_put(l_jobj_decree);
-                        json_object_put(l_jobj_tsd);
-                        dap_json_rpc_allocation_error;
-                        return NULL;
-                    }
-                    json_object_object_add(l_jobj_tsd, "warning", l_text_wgn);
-                    break;
-                }
-                uint256_t l_fee_value = uint256_0;
-                _dap_tsd_get_scalar(l_tsd, &l_fee_value);
-                json_object *l_jobj_fee = json_object_new_string(dap_uint256_to_char(l_fee_value, NULL));
-                if (!l_jobj_fee) {
-                    json_object_put(l_json_tsd_array);
-                    json_object_put(l_json_subtype);
-                    json_object_put(l_jobj_type);
-                    json_object_put(l_jobj_decree);
-                    json_object_put(l_jobj_tsd);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object_object_add(l_jobj_tsd, "value", l_jobj_fee);
-            } break;
-            case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_OWNER: {
-                json_object *l_obj_tsd_type = json_object_new_string("DAP_CHAIN_DATUM_DECREE_TSD_TYPE_OWNER");
-                if (!l_obj_tsd_type){
-                    json_object_put(l_json_tsd_array);
-                    json_object_put(l_json_subtype);
-                    json_object_put(l_jobj_type);
-                    json_object_put(l_jobj_decree);
-                    json_object_put(l_jobj_tsd);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object_object_add(l_jobj_tsd, "type", l_obj_tsd_type);
-                if (l_tsd->size < sizeof(dap_pkey_t)) {
-                    json_object *l_text_wgn = json_object_new_string("Owner fingerprint: <WRONG SIZE>");
-                    if (!l_text_wgn){
-                        json_object_put(l_json_tsd_array);
-                        json_object_put(l_json_subtype);
-                        json_object_put(l_jobj_type);
-                        json_object_put(l_jobj_decree);
-                        json_object_put(l_jobj_tsd);
-                        dap_json_rpc_allocation_error;
-                        return NULL;
-                    }
-                    json_object_object_add(l_jobj_tsd, "warning", l_text_wgn);
-                    break;
-                }
-                dap_pkey_t *l_owner_pkey = DAP_NEW_Z_SIZE(dap_pkey_t, l_tsd->size);
-                if(!l_owner_pkey) {
-                    json_object_put(l_json_tsd_array);
-                    json_object_put(l_json_subtype);
-                    json_object_put(l_jobj_type);
-                    json_object_put(l_jobj_decree);
-                    json_object_put(l_jobj_tsd);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                memcpy(l_owner_pkey, l_tsd->data, l_tsd->size);
-                dap_hash_fast_t l_owner_pkey_hash = {0};
-                dap_hash_fast(l_owner_pkey->pkey, l_owner_pkey->header.size, &l_owner_pkey_hash);
-                char l_owner_pkey_str[DAP_CHAIN_HASH_FAST_STR_SIZE];
-                dap_chain_hash_fast_to_str(&l_owner_pkey_hash, l_owner_pkey_str, sizeof(l_owner_pkey_str));
-                json_object *l_jobj_owner_pkey = json_object_new_string(l_owner_pkey_str);
-                if (!l_jobj_owner_pkey) {
-                    json_object_put(l_json_tsd_array);
-                    json_object_put(l_json_subtype);
-                    json_object_put(l_jobj_type);
-                    json_object_put(l_jobj_decree);
-                    json_object_put(l_jobj_tsd);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object_object_add(l_jobj_tsd, "owner_fingerprint", l_jobj_owner_pkey);
-                DAP_DELETE(l_owner_pkey);
-            } break;
-            case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_MIN_OWNER: {
-                json_object *l_obj_tsd_type = json_object_new_string("DAP_CHAIN_DATUM_DECREE_TSD_TYPE_MIN_OWNER");
-                if (!l_obj_tsd_type){
-                    json_object_put(l_json_tsd_array);
-                    json_object_put(l_json_subtype);
-                    json_object_put(l_jobj_type);
-                    json_object_put(l_jobj_decree);
-                    json_object_put(l_jobj_tsd);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object_object_add(l_jobj_tsd, "type", l_obj_tsd_type);
-                if (l_tsd->size > sizeof(uint256_t)){
-                    json_object *l_text_wgn = json_object_new_string("Owner min: <WRONG SIZE>");
-                    if (!l_text_wgn) {
-                        json_object_put(l_json_tsd_array);
-                        json_object_put(l_json_subtype);
-                        json_object_put(l_jobj_type);
-                        json_object_put(l_jobj_decree);
-                        json_object_put(l_jobj_tsd);
-                        dap_json_rpc_allocation_error;
-                        return NULL;
-                    }
-                    json_object_object_add(l_jobj_tsd, "warning", l_text_wgn);
-                    break;
-                }
-                uint256_t l_owner_min = {0};
-                _dap_tsd_get_scalar(l_tsd, &l_owner_min);
-                json_object *l_jobj_owner_min = json_object_new_string(dap_uint256_to_char(l_owner_min, NULL));
-                if (!l_jobj_owner_min) {
-                    json_object_put(l_json_tsd_array);
-                    json_object_put(l_json_subtype);
-                    json_object_put(l_jobj_type);
-                    json_object_put(l_jobj_decree);
-                    json_object_put(l_jobj_tsd);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object_object_add(l_jobj_tsd, "owner_min", l_jobj_owner_min);
-            } break;
-            case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_FEE_WALLET: {
-                json_object *l_obj_tsd_type = json_object_new_string("DAP_CHAIN_DATUM_DECREE_TSD_TYPE_FEE_WALLET");
-                if (!l_obj_tsd_type) {
-                    json_object_put(l_json_tsd_array);
-                    json_object_put(l_json_subtype);
-                    json_object_put(l_jobj_type);
-                    json_object_put(l_jobj_decree);
-                    json_object_put(l_jobj_tsd);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object_object_add(l_jobj_tsd, "type", l_obj_tsd_type);
-                if (l_tsd->size > sizeof(dap_chain_addr_t)) {
-                    json_object *l_text_wgn = json_object_new_string("Wallet for fee: <WRONG SIZE>");
-                    if (!l_text_wgn) {
-                        json_object_put(l_json_tsd_array);
-                        json_object_put(l_json_subtype);
-                        json_object_put(l_jobj_type);
-                        json_object_put(l_jobj_decree);
-                        json_object_put(l_jobj_tsd);
-                        dap_json_rpc_allocation_error;
-                        return NULL;
-                    }
-                    json_object_object_add(l_jobj_tsd, "warning", l_text_wgn);
-                    break;
-                }
-                dap_chain_addr_t l_addr_fee_wallet = {0};
-                _dap_tsd_get_scalar(l_tsd, &l_addr_fee_wallet);
-                json_object *l_jobj_addr_fee_wallet = dap_chain_addr_to_json(&l_addr_fee_wallet);
-                if (!l_jobj_addr_fee_wallet) {
-                    json_object_put(l_json_tsd_array);
-                    json_object_put(l_json_subtype);
-                    json_object_put(l_jobj_type);
-                    json_object_put(l_jobj_decree);
-                    json_object_put(l_jobj_tsd);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object_object_add(l_jobj_tsd, "addr", l_jobj_addr_fee_wallet);
-            } break;
-            case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_TX_HASH: {
-                json_object *l_obj_tsd_type = json_object_new_string("DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_TX_HASH");
-                json_object_object_add(l_jobj_tsd, "type", l_obj_tsd_type);
-                if (l_tsd->size > sizeof(dap_hash_fast_t)) {
-                    json_object *l_text_wgn = json_object_new_string("Stake tx: <WRONG SIZE>");
-                    json_object_object_add(l_jobj_tsd, "warning", l_text_wgn);
-                    break;
-                }
-                dap_hash_fast_t l_stake_tx = {0};
-                _dap_tsd_get_scalar(l_tsd, &l_stake_tx);
-                json_object *l_jobj_tx_hash =
-                    json_object_new_string(dap_chain_hash_fast_to_str_static(&l_stake_tx));
-                if (!l_jobj_tx_hash) {
-                    json_object_put(l_json_tsd_array);
-                    json_object_put(l_json_subtype);
-                    json_object_put(l_jobj_type);
-                    json_object_put(l_jobj_decree);
-                    json_object_put(l_jobj_tsd);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object_object_add(l_jobj_tsd, "hash", l_jobj_tx_hash);
-//                char *l_stake_tx_hash = dap_strcmp(a_hash_out_type, "hex")
-//                                        ? dap_enc_base58_encode_hash_to_str(&l_stake_tx)
-//                                        : dap_chain_hash_fast_to_str_new(&l_stake_tx);
-//                dap_string_append_printf(a_str_out, "\tStake tx: %s\n", l_stake_tx_hash);
-            } break;
-            case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_VALUE: {
-                json_object *l_obj_tsd_type = json_object_new_string("DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_VALUE");
-                if (!l_obj_tsd_type){
-                    json_object_put(l_json_tsd_array);
-                    json_object_put(l_json_subtype);
-                    json_object_put(l_jobj_type);
-                    json_object_put(l_jobj_decree);
-                    json_object_put(l_jobj_tsd);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object_object_add(l_jobj_tsd, "type", l_obj_tsd_type);
-                if (l_tsd->size > sizeof(uint256_t)) {
-                    json_object *l_text_wgn = json_object_new_string("Stake value: <WRONG SIZE>");
-                    if (!l_text_wgn){
-                        json_object_put(l_json_tsd_array);
-                        json_object_put(l_json_subtype);
-                        json_object_put(l_jobj_type);
-                        json_object_put(l_jobj_decree);
-                        json_object_put(l_jobj_tsd);
-                        dap_json_rpc_allocation_error;
-                        return NULL;
-                    }
-                    json_object_object_add(l_jobj_tsd, "warning", l_text_wgn);
-                    break;
-                }
-                uint256_t l_stake_value = uint256_0;
-                _dap_tsd_get_scalar(l_tsd, &l_stake_value);
-                json_object *l_jobj_stake_value = json_object_new_string(dap_uint256_to_char(l_stake_value, NULL));
-                if (!l_jobj_stake_value){
-                    json_object_put(l_json_tsd_array);
-                    json_object_put(l_json_subtype);
-                    json_object_put(l_jobj_type);
-                    json_object_put(l_jobj_decree);
-                    json_object_put(l_jobj_tsd);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object_object_add(l_jobj_tsd, "value", l_jobj_stake_value);
-            } break;
-            case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_SIGNING_ADDR: {
-                json_object *l_obj_tsd_type = json_object_new_string("DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_SIGNING_ADDR");
-                json_object_object_add(l_jobj_tsd, "type", l_obj_tsd_type);
-                if (l_tsd->size > sizeof(dap_chain_addr_t)) {
-                    json_object *l_text_wgn = json_object_new_string("Signing addr: <WRONG SIZE>");
-                    json_object_object_add(l_jobj_tsd, "warning", l_text_wgn);
-                    break;
-                }
-                dap_chain_addr_t l_stake_addr_signing = {0};
-                _dap_tsd_get_scalar(l_tsd, &l_stake_addr_signing);
-//                dap_string_append_printf(a_str_out, "\tSigning addr: %s\n", l_stake_addr_signing_str);
-                dap_chain_hash_fast_t l_pkey_signing = l_stake_addr_signing.data.hash_fast;
-                const char *l_pkey_signing_str = dap_chain_hash_fast_to_str_static(&l_pkey_signing);
-                json_object *l_jobj_stake_addr_signing = dap_chain_addr_to_json(&l_stake_addr_signing);
-                json_object *l_jobj_pkey_signing = json_object_new_string(l_pkey_signing_str);
-                json_object_object_add(l_jobj_tsd, "addr", l_jobj_stake_addr_signing);
-                json_object_object_add(l_jobj_tsd, "pkey", l_jobj_pkey_signing);
-//                char *l_pkey_signing_str = dap_strcmp(a_hash_out_type, "hex")
-//                                           ? dap_enc_base58_encode_hash_to_str(l_pkey_signing)
-//                                           : dap_chain_hash_fast_to_str_new(l_pkey_signing);
-//                dap_string_append_printf(a_str_out, "\tSigning pkey fingerprint: %s\n", l_pkey_signing_str);
-            } break;
-            case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_SIGNER_NODE_ADDR: {
-                json_object *l_obj_tsd_type = json_object_new_string(
-                        "DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_SIGNER_NODE_ADDR");
-                if (!l_obj_tsd_type) {
-                    json_object_put(l_json_tsd_array);
-                    json_object_put(l_json_subtype);
-                    json_object_put(l_jobj_type);
-                    json_object_put(l_jobj_decree);
-                    json_object_put(l_jobj_tsd);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object_object_add(l_jobj_tsd, "type", l_obj_tsd_type);
-                if(l_tsd->size > sizeof(dap_chain_node_addr_t)){
-                    json_object *l_text_wgn = json_object_new_string("Node addr: <WRONG SIZE>");
-                    if (!l_text_wgn){
-                        json_object_put(l_json_tsd_array);
-                        json_object_put(l_json_subtype);
-                        json_object_put(l_jobj_type);
-                        json_object_put(l_jobj_decree);
-                        json_object_put(l_jobj_tsd);
-                        dap_json_rpc_allocation_error;
-                        return NULL;
-                    }
-                    json_object_object_add(l_jobj_tsd, "warning", l_text_wgn);
-                    break;
-                }
-                dap_chain_node_addr_t l_node_addr = {0};
-                _dap_tsd_get_scalar(l_tsd, &l_node_addr);
-                char *l_node_addr_str = dap_strdup_printf(NODE_ADDR_FP_STR,NODE_ADDR_FP_ARGS_S(l_node_addr));
-                if (!l_node_addr_str) {
-                    json_object_put(l_json_tsd_array);
-                    json_object_put(l_json_subtype);
-                    json_object_put(l_jobj_type);
-                    json_object_put(l_jobj_decree);
-                    json_object_put(l_jobj_tsd);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object *l_jobj_node_addr = json_object_new_string(l_node_addr_str);
-                DAP_DELETE(l_node_addr_str);
-                if (!l_jobj_node_addr){
-                    json_object_put(l_json_tsd_array);
-                    json_object_put(l_json_subtype);
-                    json_object_put(l_jobj_type);
-                    json_object_put(l_jobj_decree);
-                    json_object_put(l_jobj_tsd);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object_object_add(l_jobj_tsd, "node", l_jobj_node_addr);
-            } break;
-            case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_MIN_VALUE: {
-                json_object *l_obj_tsd_type = json_object_new_string(
-                        "DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_MIN_VALUE");
-                json_object_object_add(l_jobj_tsd, "type", l_obj_tsd_type);
-                if (l_tsd->size > sizeof(uint256_t)) {
-                    json_object *l_text_wgn = json_object_new_string("Min value: <WRONG SIZE>");
-                    json_object_object_add(l_jobj_tsd, "warning", l_text_wgn);
-                    break;
-                }
-                uint256_t l_min_value = uint256_0;
-                _dap_tsd_get_scalar(l_tsd, &l_min_value);
-                json_object_object_add(l_jobj_tsd, "value", json_object_new_string(dap_uint256_to_char(l_min_value, NULL)));
-            } break;
-            case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_MIN_SIGNERS_COUNT: {
-                json_object *l_obj_tsd_type = json_object_new_string(
-                        "DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_MIN_SIGNERS_COUNT");
-                if (!l_obj_tsd_type) {
-                    json_object_put(l_json_tsd_array);
-                    json_object_put(l_json_subtype);
-                    json_object_put(l_jobj_type);
-                    json_object_put(l_jobj_decree);
-                    json_object_put(l_jobj_tsd);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object_object_add(l_jobj_tsd, "type", l_obj_tsd_type);
-                if (l_tsd->size > sizeof(uint256_t)) {
-                    json_object *l_text_wgn = json_object_new_string("Min signers count: <WRONG SIZE>");
-                    if(!l_text_wgn){
-                        json_object_put(l_json_tsd_array);
-                        json_object_put(l_json_subtype);
-                        json_object_put(l_jobj_type);
-                        json_object_put(l_jobj_decree);
-                        json_object_put(l_jobj_tsd);
-                        dap_json_rpc_allocation_error;
-                        return NULL;
-                    }
-                    json_object_object_add(l_jobj_tsd, "warning", l_text_wgn);
-                    break;
-                }
-                uint256_t l_min_signers_count = uint256_0;
-                _dap_tsd_get_scalar(l_tsd, &l_min_signers_count);
-                json_object *l_jobj_min_signers_count = json_object_new_string(dap_uint256_to_char(l_min_signers_count, NULL));
-                if (!l_jobj_min_signers_count) {
-                    json_object_put(l_json_tsd_array);
-                    json_object_put(l_json_subtype);
-                    json_object_put(l_jobj_type);
-                    json_object_put(l_jobj_decree);
-                    json_object_put(l_jobj_tsd);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object_object_add(l_jobj_tsd, "count", l_jobj_min_signers_count);
-            } break;
-            default: {
-                json_object *l_obj_tsd_type = json_object_new_string(
-                        "<UNKNOWN_TYPE_TSD_SECTION>");
-                if (!l_obj_tsd_type){
-                    json_object_put(l_json_tsd_array);
-                    json_object_put(l_json_subtype);
-                    json_object_put(l_jobj_type);
-                    json_object_put(l_jobj_decree);
-                    json_object_put(l_jobj_tsd);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object_object_add(l_jobj_tsd, "type", l_obj_tsd_type);
-            } break;
-        }
-        json_object_array_add(l_json_tsd_array, l_jobj_tsd);
-    }
-    json_object *l_jobj_signs = s_dap_chain_datum_decree_certs_dump_json(a_decree->data_n_signs + a_decree->header.data_size,
-                                                                         a_decree->header.signs_size);
-    if (!l_jobj_signs){
-        json_object_put(l_json_tsd_array);
-        json_object_put(l_json_subtype);
-        json_object_put(l_jobj_type);
-        json_object_put(l_jobj_decree);
-        dap_json_rpc_error_add(DAP_JSON_RPC_ERR_CODE_SERIALIZATION_SIGN_TO_JSON, "Can't serialize the decree signature in JSON.");
-        return NULL;
-    }
-    json_object_object_add(l_jobj_decree, "type", l_jobj_type);
-    json_object_object_add(l_jobj_decree, "subtype", l_json_subtype);
-    json_object_object_add(l_jobj_decree, "TSD", l_json_tsd_array);
-    json_object_object_add(l_jobj_decree, "signs", l_jobj_signs);
-    return l_jobj_decree;
-}
diff --git a/modules/json_rpc/common/dap_json_rpc_chain_datum_token.c b/modules/json_rpc/common/dap_json_rpc_chain_datum_token.c
deleted file mode 100644
index aa4139aa4ce2b4a7e2d264759098a4fd6e881eea..0000000000000000000000000000000000000000
--- a/modules/json_rpc/common/dap_json_rpc_chain_datum_token.c
+++ /dev/null
@@ -1,379 +0,0 @@
-
-
-#include "dap_json_rpc_chain_datum_token.h"
-#include "dap_json_rpc_chain_common.h"
-#include "dap_json_rpc_sign.h"
-#include "json.h"
-
-#define LOG_TAG "dap_json_rpc_chain_datum_token"
-
-json_object *dap_chain_datum_token_flags_to_json(uint16_t a_flags){
-    if (!a_flags) {
-        return json_object_new_null();
-    }
-    json_object *l_jobj_flags = json_object_new_array();
-    for (uint16_t i = 0; BIT(i) <= DAP_CHAIN_DATUM_TOKEN_FLAG_MAX; i++){
-        if(a_flags & (1 << i)){
-            json_object *l_jobj_flag_txt = json_object_new_string(c_dap_chain_datum_token_flag_str[BIT(i)]);
-            json_object_array_add(l_jobj_flags, l_jobj_flag_txt);
-        }
-    }
-    return l_jobj_flags;
-}
-
-
-json_object *dap_chain_datum_token_to_json(dap_chain_datum_token_t * a_token, size_t a_token_size){
-    json_object *l_jobj_token = json_object_new_object();
-    if (!l_jobj_token){
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    json_object *l_jobj_type;
-    json_object *l_jobj_version = json_object_new_uint64(a_token->version);
-    if (!l_jobj_version) {
-        json_object_put(l_jobj_token);
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    switch (a_token->type) {
-        case DAP_CHAIN_DATUM_TOKEN_TYPE_DECL:
-            l_jobj_type = json_object_new_string("DAP_CHAIN_DATUM_TOKEN_TYPE_DECL");
-            break;
-        case DAP_CHAIN_DATUM_TOKEN_TYPE_UPDATE:
-            l_jobj_type = json_object_new_string("DAP_CHAIN_DATUM_TOKEN_TYPE_UPDATE");
-            break;
-        default:
-            l_jobj_type = json_object_new_string("DAP_CHAIN_DATUM_TOKEN_TYPE_UNKNOWN");
-            break;
-    }
-    if (!l_jobj_type) {
-        json_object_put(l_jobj_version);
-        json_object_put(l_jobj_token);
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    json_object_object_add(l_jobj_token, "version", l_jobj_version);
-    json_object_object_add(l_jobj_token, "type", l_jobj_type);
-    json_object *l_jobj_subtype = NULL;
-    json_object *l_jobj_header = json_object_new_object();
-    if (!l_jobj_header){
-        json_object_put(l_jobj_token);
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    size_t l_tsd_total_size = 0;
-    switch (a_token->subtype) {
-        case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_SIMPLE: {
-            json_object *l_jobj_decimals  = json_object_new_uint64(a_token->header_simple.decimals);
-            if (!l_jobj_decimals){
-                json_object_put(l_jobj_header);
-                json_object_put(l_jobj_token);
-                dap_json_rpc_allocation_error;
-                return NULL;
-            }
-            json_object_object_add(l_jobj_header, "decimals", l_jobj_decimals);
-            l_jobj_subtype = json_object_new_string("DAP_CHAIN_DATUM_TOKEN_SUBTYPE_SIMPLE");
-        }break;
-        case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE: {
-            json_object *l_jobj_flags = NULL;
-            json_object *l_jobj_decimals  = NULL;
-            if (a_token->type == DAP_CHAIN_DATUM_TOKEN_TYPE_DECL) {
-                l_jobj_flags = json_object_new_string(s_flag_str_from_code(a_token->header_private_decl.flags));
-                if (!l_jobj_flags){
-                    json_object_put(l_jobj_header);
-                    json_object_put(l_jobj_token);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                l_jobj_decimals = json_object_new_uint64(a_token->header_private_decl.decimals);
-                if (!l_jobj_decimals) {
-                    json_object_put(l_jobj_flags);
-                    json_object_put(l_jobj_header);
-                    json_object_put(l_jobj_token);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                l_tsd_total_size = a_token->header_private_decl.tsd_total_size;
-            } else {
-                l_jobj_flags = json_object_new_string(s_flag_str_from_code(a_token->header_private_update.flags));
-                if (!l_jobj_flags) {
-                    json_object_put(l_jobj_header);
-                    json_object_put(l_jobj_token);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                l_jobj_decimals = json_object_new_uint64(a_token->header_private_update.decimals);
-                if (!l_jobj_decimals) {
-                    json_object_put(l_jobj_flags);
-                    json_object_put(l_jobj_header);
-                    json_object_put(l_jobj_token);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                l_tsd_total_size = a_token->header_private_update.tsd_total_size;
-            }
-            json_object_object_add(l_jobj_header, "flags", l_jobj_flags);
-            json_object_object_add(l_jobj_header, "decimals", l_jobj_decimals);
-            l_jobj_subtype = json_object_new_string("DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE");
-        } break;
-        case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE: {
-            json_object *l_jobj_flags = NULL;
-            json_object *l_jobj_decimals  = NULL;
-            if (a_token->type == DAP_CHAIN_DATUM_TOKEN_TYPE_DECL) {
-                l_jobj_flags = json_object_new_string(s_flag_str_from_code(a_token->header_native_decl.flags));
-                if (!l_jobj_flags) {
-                    json_object_put(l_jobj_header);
-                    json_object_put(l_jobj_token);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                l_jobj_decimals = json_object_new_uint64(a_token->header_native_decl.decimals);
-                if (!l_jobj_decimals){
-                    json_object_put(l_jobj_flags);
-                    json_object_put(l_jobj_header);
-                    json_object_put(l_jobj_token);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                l_tsd_total_size = a_token->header_native_decl.tsd_total_size;
-            } else {
-                l_jobj_flags = json_object_new_string(s_flag_str_from_code(a_token->header_native_update.flags));
-                if (!l_jobj_flags) {
-                    json_object_put(l_jobj_header);
-                    json_object_put(l_jobj_token);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                l_jobj_decimals = json_object_new_uint64(a_token->header_native_update.decimals);
-                if (!l_jobj_decimals) {
-                    json_object_put(l_jobj_flags);
-                    json_object_put(l_jobj_header);
-                    json_object_put(l_jobj_token);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                l_tsd_total_size = a_token->header_native_update.tsd_total_size;
-            }
-            json_object_object_add(l_jobj_header, "flags", l_jobj_flags);
-            json_object_object_add(l_jobj_header, "decimals", l_jobj_decimals);
-            l_jobj_subtype = json_object_new_string("DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE");
-        } break;
-        case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PUBLIC: {
-            json_object *l_jobj_flags = json_object_new_string(s_flag_str_from_code(a_token->header_public.flags));
-            if (!l_jobj_flags){
-                json_object_put(l_jobj_header);
-                json_object_put(l_jobj_token);
-                dap_json_rpc_allocation_error;
-                return NULL;
-            }
-            json_object *l_jobj_premine_supply = json_object_new_string(dap_uint256_to_char(a_token->header_public.premine_supply, NULL));
-            if (!l_jobj_premine_supply) {
-                json_object_put(l_jobj_flags);
-                json_object_put(l_jobj_header);
-                json_object_put(l_jobj_token);
-                dap_json_rpc_allocation_error;
-                return NULL;
-            }
-            json_object *l_jobj_premine_address = dap_chain_addr_to_json(&a_token->header_public.premine_address);
-            if (!l_jobj_premine_address) {
-                json_object_put(l_jobj_flags);
-                json_object_put(l_jobj_premine_supply);
-                json_object_put(l_jobj_header);
-                json_object_put(l_jobj_token);
-                dap_json_rpc_error_add(DAP_JSON_RPC_ERR_CODE_SERIALIZATION_ADDR_TO_JSON,
-                                       "Failed to convert address to JSON.");
-                return NULL;
-            }
-            json_object_object_add(l_jobj_header, "flags", l_jobj_flags);
-            json_object_object_add(l_jobj_header, "premine_supply", l_jobj_premine_supply);
-            json_object_object_add(l_jobj_header, "premine_address", l_jobj_premine_address);
-            l_jobj_subtype = json_object_new_string("DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PUBLIC");
-        } break;
-        default: {
-            l_jobj_subtype = json_object_new_string("DAP_CHAIN_DATUM_TOKEN_SUBTYPE_UNKNOWN");
-        } break;
-    }
-    if (!l_jobj_subtype) {
-        json_object_put(l_jobj_header);
-        json_object_put(l_jobj_token);
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    json_object_object_add(l_jobj_token, "subtype", l_jobj_subtype);
-    json_object_object_add(l_jobj_token, "header", l_jobj_header);
-    json_object *l_jobj_ticker = json_object_new_string(a_token->ticker);
-    if (!l_jobj_ticker) {
-        json_object_put(l_jobj_token);
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    json_object_object_add(l_jobj_token, "ticker", l_jobj_ticker);
-    json_object *l_jobj_signs_valid = json_object_new_uint64(a_token->signs_valid);
-    if (!l_jobj_signs_valid) {
-        json_object_put(l_jobj_token);
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    json_object_object_add(l_jobj_token, "signs_valid", l_jobj_signs_valid);
-    json_object *l_jobj_signs_total = json_object_new_uint64(a_token->signs_total);
-    if (!l_jobj_signs_total) {
-        json_object_put(l_jobj_token);
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    json_object_object_add(l_jobj_token, "signs_total", l_jobj_signs_total);
-    json_object *l_obj_signs = json_object_new_array();
-    if (!l_obj_signs) {
-        json_object_put(l_jobj_token);
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    size_t l_offset = 0;
-    size_t l_certs_field_size = a_token_size - sizeof(*a_token);
-    while ((l_offset + l_tsd_total_size) < l_certs_field_size) {
-        dap_sign_t *l_sign = (dap_sign_t *) ((byte_t*)a_token->data_n_tsd + l_tsd_total_size + l_offset);
-        l_offset += dap_sign_get_size(l_sign);
-        json_object *l_obj_sign = dap_sign_to_json(l_sign);
-        if (!l_obj_sign || !dap_sign_get_size(l_sign)) {
-            json_object_put(l_obj_signs);
-            json_object_put(l_jobj_token);
-            dap_json_rpc_error_add(DAP_JSON_RPC_ERR_CODE_SERIALIZATION_SIGN_TO_JSON, "Failed to convert signature to JSON.");
-            return NULL;
-        }
-        json_object_array_add(l_obj_signs, l_obj_sign);
-    }
-    json_object_object_add(l_jobj_token, "signs", l_obj_signs);
-    return l_jobj_token;
-}
-
-
-json_object *dap_chain_datum_emission_to_json(dap_chain_datum_token_emission_t *a_emission, size_t a_emission_size){
-    json_object *l_emi_obj = json_object_new_object();
-    json_object *l_emi_version = json_object_new_uint64(a_emission->hdr.version);
-    json_object *l_emi_type = json_object_new_string(c_dap_chain_datum_token_emission_type_str[a_emission->hdr.type]);
-    json_object *l_emi_address = dap_chain_addr_to_json(&a_emission->hdr.address);
-    json_object *l_emi_header = json_object_new_object();
-    json_object *l_emi_data = json_object_new_object();
-    if (!l_emi_obj || !l_emi_version || !l_emi_type || !l_emi_address || !l_emi_header || ! l_emi_data) {
-        json_object_put(l_emi_obj);
-        json_object_put(l_emi_version);
-        json_object_put(l_emi_type);
-        json_object_put(l_emi_address);
-        json_object_put(l_emi_header);
-        json_object_put(l_emi_data);
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    json_object_object_add(l_emi_header, "version", l_emi_version);
-    json_object_object_add(l_emi_header, "type", l_emi_type);
-    json_object_object_add(l_emi_header, "address", l_emi_address);
-    json_object_object_add(l_emi_obj, "header", l_emi_header);
-    switch (a_emission->hdr.type){
-        case DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_AUTH: {
-            json_object *l_obj_size = json_object_new_uint64(a_emission->data.type_auth.size);
-            json_object *l_obj_tsd_total_size = json_object_new_uint64(a_emission->data.type_auth.tsd_total_size);
-            json_object *l_obj_signs_count = json_object_new_uint64(a_emission->data.type_auth.signs_count);
-            if (!l_obj_size || !l_obj_tsd_total_size || !l_obj_signs_count) {
-                json_object_put(l_obj_size);
-                json_object_put(l_obj_tsd_total_size);
-                json_object_put(l_obj_signs_count);
-                json_object_put(l_emi_data);
-                json_object_put(l_emi_obj);
-                dap_json_rpc_allocation_error;
-                return NULL;
-            }
-            json_object_object_add(l_emi_data, "size", l_obj_size);
-            json_object_object_add(l_emi_data, "tsd_total_size", l_obj_tsd_total_size);
-            json_object_object_add(l_emi_data, "signs_count", l_obj_signs_count);
-            if (((void *) a_emission->tsd_n_signs + a_emission->data.type_auth.tsd_total_size) >
-                  ((void *) a_emission + a_emission_size)) {
-                char *l_err_str = dap_strdup_printf("Malformed DATUM type %d, TSD section is out-of-buffer (%" DAP_UINT64_FORMAT_U " vs %zu)",
-                                                            a_emission->hdr.type, a_emission->data.type_auth.tsd_total_size, a_emission_size);
-                if (!l_err_str){
-                    json_object_put(l_emi_data);
-                    json_object_put(l_emi_obj);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object *l_err_tsd = json_object_new_string(l_err_str);
-                DAP_DELETE(l_err_str);
-                if (!l_err_tsd) {
-                    json_object_put(l_emi_data);
-                    json_object_put(l_emi_obj);
-                    dap_json_rpc_allocation_error;
-                    return NULL;
-                }
-                json_object_object_add(l_emi_data, "ERROR", l_err_tsd);
-            }
-            json_object *l_obj_signs = json_object_new_array();
-            if (!l_obj_signs){
-                json_object_put(l_emi_data);
-                json_object_put(l_emi_obj);
-                dap_json_rpc_allocation_error;
-                return NULL;
-            }
-            size_t l_offset = a_emission->data.type_auth.tsd_total_size;
-            for (int i = 0; i < a_emission->data.type_auth.signs_count; i++) {
-                dap_sign_t *l_sign = (dap_sign_t *) ((byte_t*)a_emission->tsd_n_signs + l_offset);
-                l_offset += dap_sign_get_size(l_sign);
-                json_object *l_obj_sign = dap_sign_to_json(l_sign);
-                if (!l_obj_sign) {
-                    json_object_put(l_obj_signs);
-                    json_object_put(l_emi_data);
-                    json_object_put(l_emi_obj);
-                    dap_json_rpc_error_add(3, "Failed to serialize signature to JSON object.");
-                    return NULL;
-                }
-                json_object_array_add(l_obj_signs, l_obj_sign);
-            }
-            json_object_object_add(l_emi_data, "signs", l_obj_signs);
-
-        } break;
-        case DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_ALGO: {
-            json_object *l_code_name = json_object_new_string(a_emission->data.type_algo.codename);
-            if (!l_code_name) {
-                json_object_put(l_emi_data);
-                json_object_put(l_emi_obj);
-                dap_json_rpc_allocation_error;
-                return NULL;
-            }
-            json_object_object_add(l_emi_data, "codename", l_code_name);
-        } break;
-        case DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_ATOM_OWNER: {
-            json_object *l_value_start = json_object_new_uint64(a_emission->data.type_atom_owner.value_start);
-            json_object *l_value_change_algo_codename = json_object_new_string(
-                    a_emission->data.type_atom_owner.value_change_algo_codename);
-            if (!l_value_start || !l_value_change_algo_codename) {
-                json_object_put(l_value_start);
-                json_object_put(l_value_change_algo_codename);
-                json_object_put(l_emi_data);
-                json_object_put(l_emi_obj);
-                dap_json_rpc_allocation_error;
-                return NULL;
-            }
-            json_object_object_add(l_emi_data, "value_start", l_value_start);
-            json_object_object_add(l_emi_data, "value_change_algo_codename", l_value_change_algo_codename);
-        } break;
-        case DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_SMART_CONTRACT:
-        {
-            json_object *l_obj_addr = dap_chain_addr_to_json(&a_emission->data.type_presale.addr);
-            json_object *l_obj_flags = json_object_new_int64(a_emission->data.type_presale.flags);
-            json_object *l_obj_lock_time = json_object_new_uint64(a_emission->data.type_presale.lock_time);
-            if (!l_obj_addr || !l_obj_flags || !l_obj_lock_time) {
-                json_object_put(l_obj_addr);
-                json_object_put(l_obj_flags);
-                json_object_put(l_obj_lock_time);
-                json_object_put(l_emi_data);
-                json_object_put(l_emi_obj);
-                dap_json_rpc_allocation_error;
-                return NULL;
-            }
-            json_object_object_add(l_emi_data, "addr", l_obj_addr);
-            json_object_object_add(l_emi_data, "flags", l_obj_flags);
-            json_object_object_add(l_emi_data, "lock_time", l_obj_lock_time);
-        }break;
-    }
-    json_object_object_add(l_emi_obj, "data", l_emi_data);
-    return  l_emi_obj;
-}
-
diff --git a/modules/json_rpc/common/dap_json_rpc_chain_datum_tx.c b/modules/json_rpc/common/dap_json_rpc_chain_datum_tx.c
deleted file mode 100644
index 5df5fdb51304e87c431a9a3c84c274fbc718ff7f..0000000000000000000000000000000000000000
--- a/modules/json_rpc/common/dap_json_rpc_chain_datum_tx.c
+++ /dev/null
@@ -1,149 +0,0 @@
-#include <memory.h>
-#include <assert.h>
-#include "dap_common.h"
-#include "dap_sign.h"
-#include "dap_chain_datum_tx.h"
-#include "dap_chain_datum_tx_items.h"
-
-#include "dap_json_rpc_chain_datum_tx.h"
-#include "dap_json_rpc_chain_datum_tx_items.h"
-#include "dap_json_rpc_chain_datum_tx_receipt.h"
-#include "json.h"
-#include "dap_chain_datum_tx_voting.h"
-#include "dap_chain_net.h"
-
-#define LOG_TAG "dap_json_rpc_chain_datum_tx"
-
-
-
-json_object *dap_chain_datum_tx_to_json(dap_chain_datum_tx_t *a_tx, dap_chain_net_id_t *a_net_id){
-    json_object *l_obj_items = json_object_new_array();
-    if (!l_obj_items) {
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    uint32_t
-        l_tx_items_size_total = 0,
-        l_tx_items_size = a_tx->header.tx_items_size;
-    while(l_tx_items_size_total < l_tx_items_size) {
-        uint8_t *item = a_tx->tx_items + l_tx_items_size_total;
-        size_t l_tx_item_size = dap_chain_datum_item_tx_get_size(item);
-        if (l_tx_item_size == 0) {
-            json_object_put(l_obj_items);
-            l_obj_items = json_object_new_null();
-            break;
-        }
-        dap_chain_tx_item_type_t l_item_type = dap_chain_datum_tx_item_get_type(item);
-        json_object *l_obj_item_type = NULL, *l_obj_item_data = NULL;
-        switch (l_item_type) {
-            case TX_ITEM_TYPE_IN:
-                l_obj_item_type = json_object_new_string("TX_ITEM_TYPE_IN");
-                l_obj_item_data = dap_chain_datum_tx_item_in_to_json((dap_chain_tx_in_t*)item);
-                break;
-            case TX_ITEM_TYPE_OUT:
-                l_obj_item_type = json_object_new_string("TX_ITEM_TYPE_OUT");
-                l_obj_item_data = dap_chain_datum_tx_item_out_to_json((dap_chain_tx_out_t*)item);
-                break;
-            case TX_ITEM_TYPE_IN_REWARD:
-                l_obj_item_type = json_object_new_string("TX_ITEM_TYPE_IN_REWARD");
-                l_obj_item_data = dap_chain_datum_tx_item_in_reward_to_json((dap_chain_tx_in_reward_t*)item);
-                break;
-            case TX_ITEM_TYPE_IN_EMS:
-                l_obj_item_type = json_object_new_string("TX_ITEM_TYPE_IN_EMS");
-                l_obj_item_data = dap_chain_datum_tx_item_in_ems_to_json((dap_chain_tx_in_ems_t*)item);
-                break;
-            case TX_ITEM_TYPE_SIG:
-                l_obj_item_type = json_object_new_string("TX_ITEM_TYPE_SIG");
-                l_obj_item_data = dap_chain_datum_tx_item_sig_to_json((dap_chain_tx_sig_t*)item);
-                break;
-            case TX_ITEM_TYPE_RECEIPT:
-                l_obj_item_type = json_object_new_string("TX_ITEM_TYPE_RECEIPT");
-                l_obj_item_data = dap_chain_datum_tx_receipt_to_json((dap_chain_datum_tx_receipt_t*)item);
-                break;
-            case TX_ITEM_TYPE_IN_COND:
-                l_obj_item_type = json_object_new_string("TX_ITEM_TYPE_IN_COND");
-                l_obj_item_data = dap_chain_datum_tx_item_in_cond_to_json((dap_chain_tx_in_cond_t*)item);
-                break;
-            case TX_ITEM_TYPE_OUT_COND:
-                l_obj_item_type = json_object_new_string("TX_ITEM_TYPE_OUT_COND");
-                
-
-                switch (((dap_chain_tx_out_cond_t*)item)->header.subtype) {
-                    case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY:
-                        l_obj_item_data = dap_chain_datum_tx_item_out_cond_srv_pay_to_json((dap_chain_tx_out_cond_t*)item);
-                        break;
-                    case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK:
-                        l_obj_item_data = dap_chain_net_srv_stake_lock_cond_out_to_json((dap_chain_tx_out_cond_t*)item);
-                        break;
-                    case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE:
-                        l_obj_item_data = dap_chain_datum_tx_item_out_cond_srv_stake_to_json((dap_chain_tx_out_cond_t*)item);
-                        break;
-                    case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE:
-                        l_obj_item_data = dap_chain_datum_tx_item_out_cond_srv_xchange_to_json((dap_chain_tx_out_cond_t*)item);
-                        break;
-                    case DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE:
-                        l_obj_item_data = json_object_new_object();
-                        break;
-                   default:break;
-                }
-                // add time
-                dap_time_t l_ts_exp = ((dap_chain_tx_out_cond_t*)item)->header.ts_expires;
-                char l_time_str[32] = "never";
-                if (l_ts_exp) {
-                    dap_time_to_str_rfc822(l_time_str, DAP_TIME_STR_SIZE, l_ts_exp); /* Convert ts to  "Sat May 17 01:17:08 2014\n" */
-                    l_time_str[strlen(l_time_str)-1] = '\0';                    /* Remove "\n"*/
-                }
-                json_object_object_add(l_obj_item_data, "ts_expires", json_object_new_string(l_time_str));
-                json_object_object_add(l_obj_item_data, "subtype", json_object_new_string(dap_chain_tx_out_cond_subtype_to_str(((dap_chain_tx_out_cond_t*)item)->header.subtype)));
-                char *l_val_str, *l_val_datoshi_str = dap_uint256_to_char(((dap_chain_tx_out_cond_t*)item)->header.value, &l_val_str);
-                json_object_object_add(l_obj_item_data, "value", json_object_new_string(l_val_str));
-                json_object_object_add(l_obj_item_data, "value_datoshi", json_object_new_string(l_val_datoshi_str));
-                char uid_str[32];
-                sprintf(uid_str, "0x%016"DAP_UINT64_FORMAT_x"", ((dap_chain_tx_out_cond_t*)item)->header.srv_uid.uint64);
-                json_object_object_add(l_obj_item_data, "uid", json_object_new_string(uid_str));
-                break;
-            case TX_ITEM_TYPE_OUT_EXT:
-                l_obj_item_type = json_object_new_string("TX_ITEM_TYPE_OUT_EXT");
-                l_obj_item_data = dap_chain_datum_tx_item_out_ext_to_json((dap_chain_tx_out_ext_t*)item);
-                break;
-            case TX_ITEM_TYPE_TSD:
-                l_obj_item_type = json_object_new_string("TX_ITEM_TYPE_TSD");
-                l_obj_item_data = dap_chain_datum_tx_item_tsd_to_json((dap_chain_tx_tsd_t*)item);
-                break;
-            case TX_ITEM_TYPE_VOTE:
-                l_obj_item_type = json_object_new_string("TX_ITEM_TYPE_VOTE");
-                dap_chain_net_t *l_net = dap_chain_net_by_id(*a_net_id);
-                l_obj_item_data = dap_chain_datum_tx_item_vote_to_json((dap_chain_tx_vote_t*)item, l_net->pub.ledger);
-            break;
-            case TX_ITEM_TYPE_VOTING:
-                l_obj_item_type = json_object_new_string("TX_ITEM_TYPE_VOTING");
-                l_obj_item_data = dap_chain_datum_tx_item_voting_tsd_to_json(a_tx);
-            break;
-            default: {
-                char *l_hash_str;
-                dap_get_data_hash_str_static(a_tx, dap_chain_datum_tx_get_size(a_tx), l_hash_str);
-                log_it(L_NOTICE, "Transaction %s has an item whose type cannot be handled by the dap_chain_datum_tx_to_json function.", l_hash_str);
-                break;
-            }
-        }
-        if (!l_obj_item_type){
-            json_object_array_add(l_obj_items, json_object_new_null());
-        } else {
-            if (!l_obj_item_data)
-                l_obj_item_data = json_object_new_null();
-            json_object *l_obj_item = json_object_new_object();
-            if (!l_obj_item) {
-                json_object_put(l_obj_item_type);
-                json_object_put(l_obj_item_data);
-                json_object_put(l_obj_items);
-                dap_json_rpc_allocation_error;
-                return NULL;
-            }
-            json_object_object_add(l_obj_item, "type", l_obj_item_type);
-            json_object_object_add(l_obj_item, "data", l_obj_item_data);
-            json_object_array_add(l_obj_items, l_obj_item);
-        }
-        l_tx_items_size_total += l_tx_item_size;
-    }
-    return l_obj_items;
-}
diff --git a/modules/json_rpc/common/dap_json_rpc_chain_datum_tx_items.c b/modules/json_rpc/common/dap_json_rpc_chain_datum_tx_items.c
deleted file mode 100644
index 3e0c0cd28474cbaf6884ba71c76d4f13f45a9234..0000000000000000000000000000000000000000
--- a/modules/json_rpc/common/dap_json_rpc_chain_datum_tx_items.c
+++ /dev/null
@@ -1,305 +0,0 @@
-#include <stdint.h>
-#include <string.h>
-
-#include "dap_common.h"
-#include "dap_enc_key.h"
-#include "dap_chain_common.h"
-#include "dap_sign.h"
-#include "dap_hash.h"
-#include "dap_chain_datum_tx.h"
-#include "dap_chain_datum_tx_in.h"
-#include "dap_chain_datum_tx_out.h"
-#include "dap_chain_datum_tx_in_cond.h"
-#include "dap_chain_datum_tx_out_cond.h"
-#include "dap_chain_datum_tx_items.h"
-#include "dap_enc_base58.h"
-
-#include "dap_json_rpc_chain_datum_tx_items.h"
-#include "dap_json_rpc_chain_common.h"
-#include "dap_json_rpc_sign.h"
-#include "json.h"
-
-#define LOG_TAG "dap_json_rpc_chain_datum_tx_items"
-
-json_object *dap_chain_datum_tx_item_out_cond_srv_pay_to_json(dap_chain_tx_out_cond_t *item) {
-        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);
-        char *l_hash_str = dap_enc_base58_encode_hash_to_str_static(&((dap_chain_tx_out_cond_t*)item)->subtype.srv_pay.pkey_hash);
-        json_object *l_obj = json_object_new_object();
-        char unit_str[32];
-        snprintf(unit_str, 32, "0x%08x", ((dap_chain_tx_out_cond_t*)item)->subtype.srv_pay.unit.uint32);
-        json_object_object_add(l_obj, "unit", json_object_new_string(unit_str));
-        json_object_object_add(l_obj, "pkey", json_object_new_string(l_hash_str));
-        json_object_object_add(l_obj, "max_price", json_object_new_string(l_coins_str));
-        json_object_object_add(l_obj, "max_price_datoshi", json_object_new_string(l_value_str));
-        return l_obj;
-}
-
-json_object* dap_chain_datum_tx_item_out_cond_srv_xchange_to_json(dap_chain_tx_out_cond_t* a_srv_xchange) {
-    if (a_srv_xchange->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE){
-        json_object *l_object = json_object_new_object();
-        json_object_object_add(l_object, "value", json_object_new_string(dap_uint256_to_char(a_srv_xchange->header.value, NULL)));
-        json_object_object_add(l_object, "rate", ( { 
-            char *l_rate; dap_uint256_to_char(a_srv_xchange->subtype.srv_xchange.rate, &l_rate);
-            json_object_new_string(l_rate); } ));
-        json_object_object_add(l_object, "srv_uid", json_object_new_uint64(a_srv_xchange->header.srv_uid.uint64));
-        json_object_object_add(l_object, "buy_net_id", dap_chain_net_id_to_json(a_srv_xchange->subtype.srv_xchange.buy_net_id));
-        json_object_object_add(l_object, "sell_net_id", dap_chain_net_id_to_json(a_srv_xchange->subtype.srv_xchange.sell_net_id));
-        json_object_object_add(l_object, "buy_token", json_object_new_string(a_srv_xchange->subtype.srv_xchange.buy_token));
-        json_object_object_add(l_object, "seller_addr", dap_chain_addr_to_json(&a_srv_xchange->subtype.srv_xchange.seller_addr));
-        //TODO: Parse TSD
-        return l_object;
-    }
-    return NULL;
-}
-
-json_object *dap_chain_datum_tx_item_out_cond_srv_stake_to_json(dap_chain_tx_out_cond_t* a_srv_stake) {
-    if (a_srv_stake->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE) {
-        json_object *l_object = json_object_new_object();
-        json_object *l_obj_value = json_object_new_string(dap_uint256_to_char(a_srv_stake->header.value, NULL));
-        json_object *l_obj_srv_uid = json_object_new_uint64(a_srv_stake->header.srv_uid.uint64);
-        json_object *l_obj_signing_addr = dap_chain_addr_to_json(&a_srv_stake->subtype.srv_stake_pos_delegate.signing_addr);
-        char *l_signer_node_addr = dap_strdup_printf(
-                NODE_ADDR_FP_STR,
-                NODE_ADDR_FP_ARGS_S(a_srv_stake->subtype.srv_stake_pos_delegate.signer_node_addr));
-        json_object *l_obj_signer_node_addr = json_object_new_string(l_signer_node_addr);
-        DAP_DELETE(l_signer_node_addr);
-        json_object_object_add(l_object, "value", l_obj_value);
-        json_object_object_add(l_object, "srv_uid", l_obj_srv_uid);
-        json_object_object_add(l_object, "signind_addr", l_obj_signing_addr);
-        json_object_object_add(l_object, "signer_node_addr", l_obj_signer_node_addr);
-        return l_object;
-    }
-    return NULL;
-}
-
-
-json_object *dap_chain_net_srv_stake_lock_cond_out_to_json(dap_chain_tx_out_cond_t *a_stake_lock)
-{
-    if (a_stake_lock->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK) {
-        json_object *l_object = json_object_new_object();
-        json_object_object_add(l_object, "value", json_object_new_string(dap_uint256_to_char(a_stake_lock->header.value, NULL)));
-        json_object_object_add(l_object, "srv_uid", json_object_new_uint64(a_stake_lock->header.srv_uid.uint64));
-        json_object_object_add(l_object, "reinvest_percent",
-            json_object_new_string(dap_uint256_to_char(a_stake_lock->subtype.srv_stake_lock.reinvest_percent, NULL)));
-        json_object_object_add(l_object, "time_unlock", json_object_new_uint64(a_stake_lock->subtype.srv_stake_lock.time_unlock));
-        json_object_object_add(l_object, "flags", json_object_new_uint64(a_stake_lock->subtype.srv_stake_lock.flags));
-        return l_object;
-    }
-    return NULL;
-}
-
-
-json_object* dap_chain_datum_tx_item_out_to_json(const dap_chain_tx_out_t *a_out) {
-    json_object *l_object = json_object_new_object();
-    char *l_val_coins, *l_val_datoshi = dap_uint256_to_char(a_out->header.value, &l_val_coins);
-    json_object_object_add(l_object, "value", json_object_new_string(l_val_coins));
-    json_object_object_add(l_object, "value_datoshi", json_object_new_string(l_val_datoshi));
-    json_object_object_add(l_object, "address", dap_chain_addr_to_json(&a_out->addr));
-    return l_object;
-}
-
-
-json_object* dap_chain_datum_tx_item_out_ext_to_json(const dap_chain_tx_out_ext_t *a_out_ext) {
-    json_object *l_obj = json_object_new_object();
-    json_object_object_add(l_obj, "value", json_object_new_string(dap_uint256_to_char(a_out_ext->header.value, NULL)));
-    json_object_object_add(l_obj, "addr", dap_chain_addr_to_json(&a_out_ext->addr));
-    json_object_object_add(l_obj, "token", json_object_new_string(a_out_ext->token));
-    return l_obj;
-}
-
-json_object* dap_chain_datum_tx_item_in_cond_to_json(dap_chain_tx_in_cond_t *a_in_cond){
-    json_object *l_obj = json_object_new_object();
-    if (!l_obj) {
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    json_object *l_obj_receipt_idx = json_object_new_uint64(a_in_cond->header.receipt_idx);
-    if (!l_obj_receipt_idx) {
-        json_object_put(l_obj);
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    json_object *l_obj_out_prev_idx = json_object_new_uint64(a_in_cond->header.tx_out_prev_idx);
-    if (!l_obj_out_prev_idx) {
-        json_object_put(l_obj_receipt_idx);
-        json_object_put(l_obj);
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    json_object *l_obj_prev_hash = NULL;
-    if (dap_hash_fast_is_blank(&a_in_cond->header.tx_prev_hash)){
-        l_obj_prev_hash = json_object_new_null();
-    } else {
-        char *l_prev_hash = dap_hash_fast_to_str_new(&a_in_cond->header.tx_prev_hash);
-        if(!l_prev_hash) {
-            json_object_put(l_obj_out_prev_idx);
-            json_object_put(l_obj_receipt_idx);
-            json_object_put(l_obj);
-            dap_json_rpc_allocation_error;
-            return NULL;
-        }
-        l_obj_prev_hash = json_object_new_string(dap_strdup(l_prev_hash));
-        if (!l_obj_prev_hash) {
-            json_object_put(l_obj_out_prev_idx);
-            json_object_put(l_obj_receipt_idx);
-            json_object_put(l_obj);
-            DAP_DELETE(l_prev_hash);
-            dap_json_rpc_allocation_error;
-            return NULL;
-        }
-        DAP_DELETE(l_prev_hash);
-    }
-    json_object_object_add(l_obj, "receipt_idx", l_obj_receipt_idx);
-    json_object_object_add(l_obj, "out_prev_idx", l_obj_out_prev_idx);
-    json_object_object_add(l_obj, "tx_prev_hash", l_obj_prev_hash);
-    return l_obj;
-}
-
-json_object* dap_chain_datum_tx_item_in_to_json(dap_chain_tx_in_t *a_in){
-    json_object *l_obj_in = json_object_new_object();
-    if (!l_obj_in) {
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    json_object *l_obj_prev_idx = json_object_new_uint64(a_in->header.tx_out_prev_idx);
-    if (!l_obj_prev_idx) {
-        json_object_put(l_obj_in);
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    char l_hash[DAP_CHAIN_HASH_FAST_STR_SIZE];
-    dap_chain_hash_fast_to_str(&a_in->header.tx_prev_hash, l_hash, sizeof(l_hash));
-    json_object *l_obj_hash = json_object_new_string(l_hash);
-    if (!l_obj_hash) {
-        json_object_put(l_obj_in);
-        json_object_put(l_obj_prev_idx);
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    json_object_object_add(l_obj_in, "prev_idx", l_obj_prev_idx);
-    json_object_object_add(l_obj_in, "prev_hash", l_obj_hash);
-    return l_obj_in;
-}
-
-json_object* dap_chain_datum_tx_item_in_reward_to_json(dap_chain_tx_in_reward_t *a_in_reward){
-    json_object *l_jobj_ret = json_object_new_object();
-    char *l_hash_block = dap_hash_fast_to_str_new(&a_in_reward->block_hash);
-    if (!l_jobj_ret && !l_hash_block) {
-        json_object_put(l_jobj_ret);
-        DAP_DEL_Z(l_hash_block);
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    json_object *l_jobj_block_hash = json_object_new_string(l_hash_block);
-    DAP_DEL_Z(l_hash_block);
-    if (!l_jobj_block_hash) {
-        return NULL;
-    }
-    json_object_object_add(l_jobj_ret, "block_hash", l_jobj_block_hash);
-    return l_jobj_ret;
-}
-
-json_object* dap_chain_datum_tx_item_tsd_to_json(dap_chain_tx_tsd_t *a_tsd){
-    json_object *l_object = json_object_new_object();
-    if (!l_object) {
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    json_object *l_obj_tsd_type = json_object_new_int(a_tsd->header.type);
-    if(!l_obj_tsd_type) {
-        json_object_put(l_object);
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    json_object *l_obj_tsd_size = json_object_new_uint64(a_tsd->header.size);
-    if (!l_obj_tsd_size) {
-        json_object_put(l_obj_tsd_type);
-        json_object_put(l_object);
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    json_object *l_obj_data = json_object_new_string_len((char *)a_tsd->tsd, a_tsd->header.size);
-    if (!l_obj_data) {
-        json_object_put(l_obj_tsd_size);
-        json_object_put(l_obj_tsd_type);
-        json_object_put(l_object);
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    json_object_object_add(l_object, "type", l_obj_tsd_type);
-    json_object_object_add(l_object, "size", l_obj_tsd_size);
-    json_object_object_add(l_object, "data", l_obj_data);
-    return l_object;
-}
-
-json_object *dap_chain_datum_tx_item_in_ems_to_json(const dap_chain_tx_in_ems_t *a_in_ems)
-{
-    json_object *l_object = json_object_new_object();
-    if (!l_object) {
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    json_object *l_obj_ticker = json_object_new_string(a_in_ems->header.ticker);
-    if (!l_obj_ticker){
-        json_object_put(l_object);
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    json_object *l_obj_chain_id = json_object_new_uint64(a_in_ems->header.token_emission_chain_id.uint64);
-    if (!l_obj_chain_id) {
-        json_object_put(l_object);
-        json_object_put(l_obj_ticker);
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    char l_ehf[DAP_CHAIN_HASH_FAST_STR_SIZE];
-    dap_chain_hash_fast_to_str(&a_in_ems->header.token_emission_hash, l_ehf, sizeof(l_ehf));
-    json_object *l_obj_ehf = json_object_new_string(l_ehf);
-    if (!l_obj_ehf) {
-        json_object_put(l_object);
-        json_object_put(l_obj_chain_id);
-        json_object_put(l_obj_ticker);
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    json_object_object_add(l_object, "ticker", l_obj_ticker);
-    json_object_object_add(l_object, "chain_id", l_obj_chain_id);
-    json_object_object_add(l_object, "emission_hash", l_obj_ehf);
-    return l_object;
-}
-
-json_object *dap_chain_datum_tx_item_out_cond_fee_to_json(dap_chain_tx_out_cond_t *a_fee) {
-    return a_fee->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE
-        ? ( {
-                json_object *l_obj = json_object_new_object();
-                json_object_object_add(l_obj, "balance", json_object_new_string(dap_uint256_to_char(a_fee->header.value, NULL)));
-                l_obj;
-            } )
-        : NULL;
-}
-
-json_object* dap_chain_datum_tx_item_sig_to_json(const dap_chain_tx_sig_t *a_sig){
-    json_object *l_object = json_object_new_object();
-    if (!l_object) {
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    json_object *l_sign_size = json_object_new_uint64(a_sig->header.sig_size);
-    if (!l_sign_size) {
-        json_object_put(l_object);
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    json_object *l_sign = dap_sign_to_json((dap_sign_t*)a_sig->sig);
-    if (!l_sign) {
-        json_object_put(l_object);
-        json_object_put(l_sign_size);
-        dap_json_rpc_error_add(DAP_JSON_RPC_ERR_CODE_SERIALIZATION_SIGN_TO_JSON,
-                               "Error serializing signature to JSON.");
-        return NULL;
-    }
-    json_object_object_add(l_object, "sign_size", l_sign_size);
-    json_object_object_add(l_object, "sign", l_sign);
-    return l_object;
-}
diff --git a/modules/json_rpc/common/dap_json_rpc_chain_datum_tx_receipt.c b/modules/json_rpc/common/dap_json_rpc_chain_datum_tx_receipt.c
deleted file mode 100644
index 9e24faf6a2f7434bb39d4eec7a140310521d86a9..0000000000000000000000000000000000000000
--- a/modules/json_rpc/common/dap_json_rpc_chain_datum_tx_receipt.c
+++ /dev/null
@@ -1,80 +0,0 @@
-#include "dap_common.h"
-#include "dap_enc_key.h"
-#include "dap_sign.h"
-#include "dap_chain_datum_tx_receipt.h"
-
-#include "dap_json_rpc_sign.h"
-#include "dap_json_rpc_chain_datum_tx_receipt.h"
-#include "json.h"
-
-#define LOG_TAG "dap_json_rpc_chain_datum_tx_receipt"
-
-
-json_object* dap_chain_receipt_info_to_json(dap_chain_receipt_info_t *a_info){
-    json_object *l_obj = json_object_new_object();
-    if (!l_obj) {
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    json_object_object_add(l_obj, "uid", json_object_new_uint64(a_info->srv_uid.uint64));
-#if DAP_CHAIN_NET_SRV_UID_SIZE == 8
-    json_object_object_add(l_obj, "ext_size", json_object_new_uint64(a_info->addition));
-#endif
-    json_object_object_add(l_obj, "units", json_object_new_uint64(a_info->units));
-    json_object_object_add(l_obj, "units_type", json_object_new_string(dap_chain_srv_unit_enum_to_str(a_info->units_type.enm)));
-
-    char *l_value, *l_datoshi_value = dap_uint256_to_char(a_info->value_datoshi, &l_value);
-    json_object_object_add(l_obj, "value", json_object_new_string(l_value));
-    json_object_object_add(l_obj, "value_datoshi", json_object_new_string(l_datoshi_value));
-    return l_obj;
-}
-
-json_object *dap_chain_datum_tx_receipt_to_json(dap_chain_datum_tx_receipt_t *a_receipt) {
-    json_object *l_obj = json_object_new_object();
-    if (!l_obj) {
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    json_object *l_obj_info = dap_chain_receipt_info_to_json(&a_receipt->receipt_info);
-    if (!l_obj_info) {
-        json_object_put(l_obj);
-        return NULL;
-    }
-    json_object *l_obj_size = json_object_new_uint64(a_receipt->size);
-    if (!l_obj_size) {
-        json_object_put(l_obj);
-        json_object_put(l_obj_info);
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    //Provider
-    dap_sign_t *l_first_sign  = dap_chain_datum_tx_receipt_sign_get(a_receipt, a_receipt->size, 1);
-    //Client
-    dap_sign_t *l_second_sign  = dap_chain_datum_tx_receipt_sign_get(a_receipt, a_receipt->size, 2);
-    json_object *l_obj_signs = json_object_new_object();
-    if (!l_obj_signs) {
-        json_object_put(l_obj_size);
-        json_object_put(l_obj_info);
-        json_object_put(l_obj);
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    json_object *l_obj_provider_sign = dap_sign_to_json(l_first_sign);
-    json_object *l_obj_client_sign = dap_sign_to_json(l_second_sign);
-    json_object_object_add(l_obj_signs, "provider", l_obj_provider_sign);
-    json_object_object_add(l_obj_signs, "client", l_obj_client_sign);
-    json_object *l_exts_data = json_object_new_string_len((char *)a_receipt->exts_n_signs, a_receipt->exts_size);
-    if (!l_exts_data) {
-        json_object_put(l_obj_size);
-        json_object_put(l_obj_info);
-        json_object_put(l_obj_signs);
-        json_object_put(l_obj);
-        dap_json_rpc_allocation_error;
-        return NULL;
-    }
-    json_object_object_add(l_obj, "info", l_obj_info);
-    json_object_object_add(l_obj, "size", l_obj_size);
-    json_object_object_add(l_obj, "sings", l_obj_signs);
-    json_object_object_add(l_obj, "exts_data", l_exts_data);
-    return l_obj;
-}
diff --git a/modules/json_rpc/common/include/dap_json_rpc_chain_common.h b/modules/json_rpc/common/include/dap_json_rpc_chain_common.h
deleted file mode 100644
index d88b9b4a561a2fc74048ab397b443412781e9147..0000000000000000000000000000000000000000
--- a/modules/json_rpc/common/include/dap_json_rpc_chain_common.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Authors:
- * Alexey V. Stratulat <alexey.stratulat@demlabs.net>
- * Olzhas Zharasbaev <oljas.jarasbaev@demlabs.net>
- * DeM Labs Inc.   https://demlabs.net
- * DeM Labs Open source community https://gitlab.demlabs.net/cellframe/cellframe-sdk
- * Copyright  (c) 2017-2023
- * All rights reserved.
-
- This file is part of DAP (Demlabs Application Protocol) the open source project
-
-    DAP (Demlabs Application Protocol) is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    DAP is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#pragma once
-
-#include "dap_chain_common.h"
-#include "dap_json_rpc_errors.h"
-
-json_object *dap_chain_addr_to_json(const dap_chain_addr_t *a_addr);
-
-DAP_STATIC_INLINE json_object *dap_chain_net_id_to_json(dap_chain_net_id_t a_net_id) {
-    return json_object_new_uint64(a_net_id.uint64);
-}
diff --git a/modules/json_rpc/common/include/dap_json_rpc_chain_datum.h b/modules/json_rpc/common/include/dap_json_rpc_chain_datum.h
deleted file mode 100644
index 6f4767fae3425c250ceba167baea67016ed086f8..0000000000000000000000000000000000000000
--- a/modules/json_rpc/common/include/dap_json_rpc_chain_datum.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Authors:
- * Alexey V. Stratulat <alexey.stratulat@demlabs.net>
- * Olzhas Zharasbaev <oljas.jarasbaev@demlabs.net>
- * DeM Labs Inc.   https://demlabs.net
- * DeM Labs Open source community https://gitlab.demlabs.net/cellframe/cellframe-sdk
- * Copyright  (c) 2017-2023
- * All rights reserved.
-
- This file is part of DAP (Demlabs Application Protocol) the open source project
-
-    DAP (Demlabs Application Protocol) is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    DAP is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
-*/
-#pragma once 
-
-#include "dap_chain_datum.h"
-#include "dap_json_rpc_errors.h"
-
-json_object * dap_chain_datum_to_json(dap_chain_datum_t* a_datum);
-json_object * dap_chain_datum_data_to_json(dap_chain_datum_t *a_datum);
\ No newline at end of file
diff --git a/modules/json_rpc/common/include/dap_json_rpc_chain_datum_anchor.h b/modules/json_rpc/common/include/dap_json_rpc_chain_datum_anchor.h
deleted file mode 100644
index 64c2f0bf16e398b04be30417c0596f41c7ac1ac8..0000000000000000000000000000000000000000
--- a/modules/json_rpc/common/include/dap_json_rpc_chain_datum_anchor.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Authors:
- * Alexey V. Stratulat <alexey.stratulat@demlabs.net>
- * Olzhas Zharasbaev <oljas.jarasbaev@demlabs.net>
- * DeM Labs Inc.   https://demlabs.net
- * DeM Labs Open source community https://gitlab.demlabs.net/cellframe/cellframe-sdk
- * Copyright  (c) 2017-2023
- * All rights reserved.
-
- This file is part of DAP (Demlabs Application Protocol) the open source project
-
-    DAP (Demlabs Application Protocol) is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    DAP is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-
-#pragma once
-
-#include "dap_chain_datum_anchor.h"
-#include "dap_json_rpc_errors.h"
-
-json_object *dap_chain_datum_anchor_to_json(dap_chain_datum_anchor_t *a_anchor);
-
diff --git a/modules/json_rpc/common/include/dap_json_rpc_chain_datum_decree.h b/modules/json_rpc/common/include/dap_json_rpc_chain_datum_decree.h
deleted file mode 100644
index de30d1c0d5af54f5a153892bbfb0251021ef565b..0000000000000000000000000000000000000000
--- a/modules/json_rpc/common/include/dap_json_rpc_chain_datum_decree.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Authors:
- * Alexey V. Stratulat <alexey.stratulat@demlabs.net>
- * Olzhas Zharasbaev <oljas.jarasbaev@demlabs.net>
- * DeM Labs Inc.   https://demlabs.net
- * DeM Labs Open source community https://gitlab.demlabs.net/cellframe/cellframe-sdk
- * Copyright  (c) 2017-2023
- * All rights reserved.
-
- This file is part of DAP (Demlabs Application Protocol) the open source project
-
-    DAP (Demlabs Application Protocol) is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    DAP is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
-*/
-#pragma once
-
-#include "dap_chain_datum_decree.h"
-#include "dap_json_rpc_errors.h"
-
-/**
- * @brief dap_chain_datum_decree_to_json Convert dap_chain_datum_decree_t tp json_object
- * @param a_decree pointer to decree
- * @return pointer json_object
- */
-json_object *dap_chain_datum_decree_to_json(dap_chain_datum_decree_t *a_decree);
diff --git a/modules/json_rpc/common/include/dap_json_rpc_chain_datum_token.h b/modules/json_rpc/common/include/dap_json_rpc_chain_datum_token.h
deleted file mode 100644
index b63649e5471fa4251ca2b6a0e085f30beb6b0d83..0000000000000000000000000000000000000000
--- a/modules/json_rpc/common/include/dap_json_rpc_chain_datum_token.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Authors:
- * Alexey V. Stratulat <alexey.stratulat@demlabs.net>
- * Olzhas Zharasbaev <oljas.jarasbaev@demlabs.net>
- * DeM Labs Inc.   https://demlabs.net
- * DeM Labs Open source community https://gitlab.demlabs.net/cellframe/cellframe-sdk
- * Copyright  (c) 2017-2023
- * All rights reserved.
-
- This file is part of DAP (Demlabs Application Protocol) the open source project
-
-    DAP (Demlabs Application Protocol) is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    DAP is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#pragma once
-
-#include "dap_chain_datum_token.h"
-#include "dap_json_rpc_errors.h"
-
-json_object *dap_chain_datum_token_to_json(dap_chain_datum_token_t * a_token, size_t a_token_size);
-json_object *dap_chain_datum_token_flags_to_json(uint16_t a_flags);
-json_object *dap_chain_datum_emission_to_json(dap_chain_datum_token_emission_t *a_emission, size_t a_emission_size);
diff --git a/modules/json_rpc/common/include/dap_json_rpc_chain_datum_tx.h b/modules/json_rpc/common/include/dap_json_rpc_chain_datum_tx.h
deleted file mode 100644
index 7d4e64ef59e30c827278df7e0887127f99e8d202..0000000000000000000000000000000000000000
--- a/modules/json_rpc/common/include/dap_json_rpc_chain_datum_tx.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Authors:
- * Alexey V. Stratulat <alexey.stratulat@demlabs.net>
- * Olzhas Zharasbaev <oljas.jarasbaev@demlabs.net>
- * DeM Labs Inc.   https://demlabs.net
- * DeM Labs Open source community https://gitlab.demlabs.net/cellframe/cellframe-sdk
- * Copyright  (c) 2017-2023
- * All rights reserved.
-
- This file is part of DAP (Demlabs Application Protocol) the open source project
-
-    DAP (Demlabs Application Protocol) is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    DAP is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#pragma once
-
-#include "dap_chain_datum_tx.h"
-#include "dap_json_rpc_errors.h"
-
-json_object * dap_chain_datum_tx_to_json(dap_chain_datum_tx_t *a_tx, dap_chain_net_id_t *a_net_id);
diff --git a/modules/json_rpc/common/include/dap_json_rpc_chain_datum_tx_items.h b/modules/json_rpc/common/include/dap_json_rpc_chain_datum_tx_items.h
deleted file mode 100644
index 815c8e89b2557287aa4611f45c1335f96971575b..0000000000000000000000000000000000000000
--- a/modules/json_rpc/common/include/dap_json_rpc_chain_datum_tx_items.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Authors:
- * Alexey V. Stratulat <alexey.stratulat@demlabs.net>
- * Olzhas Zharasbaev <oljas.jarasbaev@demlabs.net>
- * DeM Labs Inc.   https://demlabs.net
- * DeM Labs Open source community https://gitlab.demlabs.net/cellframe/cellframe-sdk
- * Copyright  (c) 2017-2023
- * All rights reserved.
-
- This file is part of DAP (Demlabs Application Protocol) the open source project
-
-    DAP (Demlabs Application Protocol) is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    DAP is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
-*/
-#pragma once
-
-#include "dap_chain_datum_tx_items.h"
-#include "dap_json_rpc_errors.h"
-
-
-json_object *dap_chain_datum_tx_item_in_ems_to_json(const dap_chain_tx_in_ems_t *a_in_ems);
-json_object* dap_chain_datum_tx_item_in_to_json(dap_chain_tx_in_t *a_in);
-json_object* dap_chain_datum_tx_item_in_reward_to_json(dap_chain_tx_in_reward_t *a_in_reward);
-json_object* dap_chain_datum_tx_item_tsd_to_json(dap_chain_tx_tsd_t *a_tsd);
-json_object* dap_chain_datum_tx_item_in_cond_to_json(dap_chain_tx_in_cond_t *a_in_cond);
-json_object* dap_chain_datum_tx_item_out_to_json(const dap_chain_tx_out_t *a_out);
-json_object* dap_chain_datum_tx_item_out_ext_to_json(const dap_chain_tx_out_ext_t *a_out_ext);
-json_object *dap_chain_datum_tx_item_out_cond_fee_to_json(dap_chain_tx_out_cond_t *a_fee);
-json_object *dap_chain_datum_tx_item_out_cond_srv_pay_to_json(dap_chain_tx_out_cond_t *item);
-json_object* dap_chain_datum_tx_item_out_cond_srv_xchange_to_json(dap_chain_tx_out_cond_t* a_srv_xchange);
-json_object *dap_chain_datum_tx_item_out_cond_srv_stake_to_json(dap_chain_tx_out_cond_t* a_srv_stake);
-json_object *dap_chain_net_srv_stake_lock_cond_out_to_json(dap_chain_tx_out_cond_t *a_stake_lock);
-json_object* dap_chain_datum_tx_item_sig_to_json(const dap_chain_tx_sig_t *a_sig);
diff --git a/modules/json_rpc/common/include/dap_json_rpc_chain_datum_tx_receipt.h b/modules/json_rpc/common/include/dap_json_rpc_chain_datum_tx_receipt.h
deleted file mode 100644
index c27cfcfd0b79a1224068b055bd5480afa71f4b22..0000000000000000000000000000000000000000
--- a/modules/json_rpc/common/include/dap_json_rpc_chain_datum_tx_receipt.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Authors:
- * Alexey V. Stratulat <alexey.stratulat@demlabs.net>
- * Olzhas Zharasbaev <oljas.jarasbaev@demlabs.net>
- * DeM Labs Inc.   https://demlabs.net
- * DeM Labs Open source community https://gitlab.demlabs.net/cellframe/cellframe-sdk
- * Copyright  (c) 2017-2023
- * All rights reserved.
-
- This file is part of DAP (Demlabs Application Protocol) the open source project
-
-    DAP (Demlabs Application Protocol) is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    DAP is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
-*/
-#pragma once
-
-#include "dap_chain_datum_tx_receipt.h"
-#include "dap_json_rpc_errors.h"
-
-json_object *dap_chain_receipt_info_to_json(dap_chain_receipt_info_t *a_info);
-json_object *dap_chain_datum_tx_receipt_to_json(dap_chain_datum_tx_receipt_t *a_receipt);
\ No newline at end of file
diff --git a/modules/json_rpc/mempool/CMakeLists.txt b/modules/json_rpc/mempool/CMakeLists.txt
deleted file mode 100644
index 86dd39002f2fcdb106097bb8e27b241869f6b3ff..0000000000000000000000000000000000000000
--- a/modules/json_rpc/mempool/CMakeLists.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-cmake_minimum_required(VERSION 3.10)
-project (dap_json_rpc_chain_mempool)
-
-
-file(GLOB DAP_JSON_RPC_CHAIN_MEMPOOL_HEADERS include/*.h)
-file(GLOB DAP_JSON_RPC_CHAIN_MEMPOOL_SRCS  *.c)
-
-add_library(${PROJECT_NAME}  STATIC ${DAP_JSON_RPC_CHAIN_MEMPOOL_SRCS} ${DAP_JSON_RPC_CHAIN_MEMPOOL_HEADERS})
-
-target_link_libraries(dap_json_rpc_chain_mempool dap_http_server dap_client dap_chain_net dap_global_db dap_core dap_chain_cs_blocks dap_chain_mempool dap_json_rpc_core dap_chain_btc_rpc)
-target_include_directories(dap_json_rpc_chain_mempool PUBLIC include/ )
diff --git a/modules/json_rpc/mempool/dap_chain_mempool_rpc.c b/modules/json_rpc/mempool/dap_chain_mempool_rpc.c
deleted file mode 100644
index 3f97641be08af203e9d91170c3b8b033416c7795..0000000000000000000000000000000000000000
--- a/modules/json_rpc/mempool/dap_chain_mempool_rpc.c
+++ /dev/null
@@ -1,149 +0,0 @@
-#include <stddef.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdio.h>
-#include <assert.h>
-#include <memory.h>
-
-#ifdef _WIN32
-#include <winsock2.h>
-#include <windows.h>
-#include <mswsock.h>
-#include <ws2tcpip.h>
-#include <io.h>
-#include <time.h>
-#include <pthread.h>
-#endif
-
-#include "dap_common.h"
-#include "dap_hash.h"
-#include "dap_http_client.h"
-#include "dap_http_simple.h"
-#include "dap_enc_base58.h"
-#include "dap_enc_http.h"
-#include "http_status_code.h"
-#include "dap_chain_common.h"
-#include "dap_chain_node.h"
-#include "dap_global_db.h"
-#include "dap_enc.h"
-#include <dap_enc_http.h>
-#include <dap_enc_key.h>
-#include <dap_enc_ks.h>
-#include "dap_chain_mempool.h"
-
-#include "dap_common.h"
-#include "dap_list.h"
-#include "dap_chain.h"
-#include "dap_chain_net.h"
-#include "dap_chain_net_tx.h"
-#include "dap_sign.h"
-#include "dap_chain_datum_tx.h"
-#include "dap_chain_datum_tx_items.h"
-#include "dap_chain_net_srv.h"
-#include "dap_chain_cs_blocks.h"
-
-#include "dap_chain_mempool_rpc.h"
-#include "dap_json_rpc_chain_datum.h"
-#include "dap_json_rpc_request_handler.h"
-#include "dap_json_rpc_response_handler.h"
-#include "json.h"
-
-#define LOG_TAG "dap_chain_mempool_rpc"
-
-int dap_chain_mempool_rpc_init(void) {
-    dap_json_rpc_registration_request_handler("mempool_list", dap_chain_mempool_rpc_handler_list);
-    dap_json_rpc_registration_request_handler("memtest", dap_chain_mempool_rpc_handler_test);
-    return 0;
-}
-
-void dap_chain_mempool_rpc_handler_test(dap_json_rpc_params_t *a_params,
-                                        dap_json_rpc_response_t *a_response, const char *a_method) {
-    UNUSED(a_method);
-    char *l_tn = NULL;
-//    char *l_chain_str = NULL;
-    for (uint32_t i = 0; i < a_params->length; i++) {
-        dap_json_rpc_param_t *l_prm = a_params->params[i];
-        if (i == 0)
-            l_tn = l_prm->value_param;
-    }
-    if (dap_strcmp(l_tn, "NULL") == 0) {
-        a_response->type = TYPE_RESPONSE_NULL;
-    } else if (dap_strcmp(l_tn, "STRING") == 0) {
-        a_response->type = TYPE_RESPONSE_STRING;
-        a_response->result_string = dap_strdup("This test string");
-    } else if (dap_strcmp(l_tn, "INTEGER") == 0) {
-        a_response->type = TYPE_RESPONSE_INTEGER;
-        a_response->result_int = 4555745;
-    } else if (dap_strcmp(l_tn, "BOOLEAN") == 0) {
-        a_response->type = TYPE_RESPONSE_BOOLEAN;
-        a_response->result_boolean = true;
-    } else if (dap_strcmp(l_tn, "DOUBLE") == 0) {
-        a_response->type = TYPE_RESPONSE_DOUBLE;
-        a_response->result_double = 75.545;
-    } else if (dap_strcmp(l_tn, "JSON") == 0) {
-        a_response->type = TYPE_RESPONSE_JSON;
-        json_object *l_obj = json_object_new_object();
-        json_object *l_int = json_object_new_uint64(45577445);
-        json_object *l_boolean = json_object_new_boolean((json_bool)1);
-        json_object *l_double = json_object_new_double(457.74514);
-        json_object *l_arr = json_object_new_array();
-        for (int i = 1000; i < 1997; i++) {
-            json_object *l_cur = json_object_new_int(i);
-            json_object_array_add(l_arr, l_cur);
-        }
-        json_object_object_add(l_obj, "int", l_int);
-        json_object_object_add(l_obj, "boolean", l_boolean);
-        json_object_object_add(l_obj, "double", l_double);
-        json_object_object_add(l_obj, "array", l_arr);
-        a_response->result_json_object = json_object_get(l_obj);
-        json_object_put(l_obj);
-    } else {
-        //set ERR code
-    }
-}
-
-void dap_chain_mempool_rpc_handler_list(dap_json_rpc_params_t *a_params,
-                                        dap_json_rpc_response_t *a_response, const char *a_method) {
-    char *l_net_str = NULL;
-    char *l_chain_str = NULL;
-    for (uint32_t i = 0; i < a_params->length; i++) {
-        dap_json_rpc_param_t *l_prm = a_params->params[i];
-        if (i == 0)
-            l_net_str = l_prm->value_param;
-        if (i == 1)
-            l_chain_str = l_prm->value_param;
-    }
-    dap_chain_net_t  *l_net = dap_chain_net_by_name(l_net_str);
-    dap_chain_t *l_chain = dap_chain_net_get_chain_by_name(l_net, l_chain_str);
-    a_response->type = TYPE_RESPONSE_STRING;
-    char * l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool_new(l_chain);
-    if(!l_gdb_group_mempool){
-        a_response->result_string = "{\"datums\":[]}";
-        return;
-    }
-    size_t l_objs_size = 0;
-    dap_global_db_obj_t *l_objs = dap_global_db_get_all_sync(l_gdb_group_mempool, &l_objs_size);
-    json_object *l_object = json_object_new_object();
-    json_object *l_object_array = json_object_new_array();
-
-    for(size_t i = 0; i < l_objs_size; i++) {
-        dap_chain_datum_t *l_datum = (dap_chain_datum_t *)l_objs[i].value;
-        //dap_time_t l_ts_create = (dap_time_t) l_datum->header.ts_create;
-        if (!l_datum->header.data_size || (l_datum->header.data_size > l_objs[i].value_len)) {
-            log_it(L_ERROR, "Trash datum in GDB %s.%s, key: %s data_size:%u, value_len:%zu",
-                   l_net->pub.name, l_chain->name, l_objs[i].key, l_datum->header.data_size, l_objs[i].value_len);
-            dap_global_db_del(l_gdb_group_mempool, l_objs[i].key, NULL, NULL);
-            continue;
-        }
-
-        json_object *l_obj_datum = dap_chain_datum_to_json(l_datum);
-        json_object_array_add(l_object_array, l_obj_datum);
-    }
-    json_object_object_add(l_object, "datums", l_object_array);
-    a_response->type = TYPE_RESPONSE_JSON;
-    a_response->result_json_object = l_object;
-
-    DAP_DELETE(l_gdb_group_mempool);
-}
-
-#undef LOG_TAG
diff --git a/modules/json_rpc/mempool/include/dap_chain_mempool_rpc.h b/modules/json_rpc/mempool/include/dap_chain_mempool_rpc.h
deleted file mode 100644
index b9c0efa9bb0d768cb8e619e29a17003303967ce8..0000000000000000000000000000000000000000
--- a/modules/json_rpc/mempool/include/dap_chain_mempool_rpc.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Authors:
- * Alexey V. Stratulat <alexey.stratulat@demlabs.net>
- * Olzhas Zharasbaev <oljas.jarasbaev@demlabs.net>
- * DeM Labs Inc.   https://demlabs.net
- * DeM Labs Open source community https://gitlab.demlabs.net/cellframe/cellframe-sdk
- * Copyright  (c) 2017-2023
- * All rights reserved.
-
- This file is part of DAP (Demlabs Application Protocol) the open source project
-
-    DAP (Demlabs Application Protocol) is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    DAP is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#pragma once
-
-#include "dap_json_rpc_errors.h"
-#include "dap_json_rpc_response.h"
-#include "dap_json_rpc_params.h"
-
-
-int dap_chain_mempool_rpc_init(void);
-void dap_chain_mempool_rpc_handler_list(dap_json_rpc_params_t *a_params,
-                                        dap_json_rpc_response_t *a_response, const char *a_method);
-void dap_chain_mempool_rpc_handler_test(dap_json_rpc_params_t *a_params,
-                                        dap_json_rpc_response_t *a_response, const char *a_method);
diff --git a/modules/mempool/dap_chain_mempool.c b/modules/mempool/dap_chain_mempool.c
index 503e1d728167342629fc8aa5cf8a66f6d728a3ad..b5628e56bb07cd750e59cc6884c24d3d7be365af 100644
--- a/modules/mempool/dap_chain_mempool.c
+++ b/modules/mempool/dap_chain_mempool.c
@@ -125,7 +125,7 @@ char *dap_chain_mempool_datum_add(const dap_chain_datum_t *a_datum, dap_chain_t
     }
 
     char *l_gdb_group = dap_chain_net_get_gdb_group_mempool_new(a_chain);
-    int l_res = dap_global_db_set(l_gdb_group, l_key_str, a_datum, dap_chain_datum_size(a_datum), false, NULL, NULL);
+    int l_res = dap_global_db_set_sync(l_gdb_group, l_key_str, a_datum, dap_chain_datum_size(a_datum), false);//, NULL, NULL);
     if (l_res == DAP_GLOBAL_DB_RC_SUCCESS)
         log_it(L_NOTICE, "Datum %s with hash %s was placed in mempool group %s", l_type_str, l_key_str, l_gdb_group);
     else
@@ -383,7 +383,7 @@ char *dap_chain_mempool_tx_coll_fee_create(dap_chain_cs_blocks_t *a_blocks, dap_
 
     // Check and apply sovereign tax for this key
     uint256_t l_value_tax = {};
-    dap_chain_net_srv_stake_item_t *l_key_item = dap_chain_net_srv_stake_check_pkey_hash(&l_sign_pkey_hash);
+    dap_chain_net_srv_stake_item_t *l_key_item = dap_chain_net_srv_stake_check_pkey_hash(l_chain->net_id, &l_sign_pkey_hash);
     if (l_key_item && !IS_ZERO_256(l_key_item->sovereign_tax) &&
                 !dap_chain_addr_is_blank(&l_key_item->sovereign_addr)) {
         MULT_256_COIN(l_value_out, l_key_item->sovereign_tax, &l_value_tax);
@@ -512,7 +512,7 @@ char *dap_chain_mempool_tx_reward_create(dap_chain_cs_blocks_t *a_blocks, dap_en
     }
     // Check and apply sovereign tax for this key
     uint256_t l_value_tax = {};
-    dap_chain_net_srv_stake_item_t *l_key_item = dap_chain_net_srv_stake_check_pkey_hash(&l_sign_pkey_hash);
+    dap_chain_net_srv_stake_item_t *l_key_item = dap_chain_net_srv_stake_check_pkey_hash(l_chain->net_id, &l_sign_pkey_hash);
     if (l_key_item && !IS_ZERO_256(l_key_item->sovereign_tax) &&
                 !dap_chain_addr_is_blank(&l_key_item->sovereign_addr)) {
         MULT_256_COIN(l_value_out, l_key_item->sovereign_tax, &l_value_tax);
@@ -584,7 +584,7 @@ int dap_chain_mempool_tx_create_massive( dap_chain_t * a_chain, dap_enc_key_t *a
     uint256_t l_value_need = {};
     MULT_256_256(dap_chain_uint256_from(a_tx_num), l_single_val, &l_value_need);
     uint256_t l_value_transfer = {}; // how many coins to transfer
-    char *l_balance; dap_uint256_to_char(l_value_need, &l_balance);
+    const char *l_balance; dap_uint256_to_char(l_value_need, &l_balance);
     log_it(L_DEBUG, "Create %"DAP_UINT64_FORMAT_U" transactions, summary %s", a_tx_num, l_balance);
     dap_ledger_t *l_ledger = dap_chain_net_by_id(a_chain->net_id)->pub.ledger;
     dap_list_t *l_list_used_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, a_token_ticker,
@@ -627,7 +627,7 @@ int dap_chain_mempool_tx_create_massive( dap_chain_t * a_chain, dap_enc_key_t *a
         if (compare256(l_value_to_items, l_single_val) == -1) {
             char l_log_str[256] = { '\0' };
             l_balance = dap_uint256_to_char(l_value_to_items, NULL);
-            dap_snprintf(l_log_str, sizeof(l_log_str),
+            snprintf(l_log_str, sizeof(l_log_str),
                          "Not enough values on output to produce enough inputs: %s when need ", l_balance);
             strcat(l_log_str, dap_uint256_to_char(l_single_val, NULL));
             log_it(L_ERROR, "%s", l_log_str);
diff --git a/modules/mempool/include/dap_chain_mempool_rpc.h b/modules/mempool/include/dap_chain_mempool_rpc.h
index 60388908103c0d002071f8d2c90126914214c82c..90aca98b3214a954c9a7fe237cab42bf6188c597 100644
--- a/modules/mempool/include/dap_chain_mempool_rpc.h
+++ b/modules/mempool/include/dap_chain_mempool_rpc.h
@@ -2,7 +2,9 @@
 #include "dap_json_rpc.h"
 
 int dap_chain_mempool_rpc_init(void);
+
 void dap_chain_mempool_rpc_handler_list(dap_json_rpc_params_t *a_params,
                                         dap_json_rpc_response_t *a_response, const char *a_method);
 void dap_chain_mempool_rpc_handler_test(dap_json_rpc_params_t *a_params,
                                         dap_json_rpc_response_t *a_response, const char *a_method);
+                                        
diff --git a/modules/net/CMakeLists.txt b/modules/net/CMakeLists.txt
index 4cc53c5c4e335ae4ddd37c241026abad795140a8..f07876b697a07630c1f1270df99d5d0929b8b24b 100644
--- a/modules/net/CMakeLists.txt
+++ b/modules/net/CMakeLists.txt
@@ -29,8 +29,8 @@ endif()
 add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_NET_SRCS} ${DAP_CHAIN_NET_HEADERS} ${IPUTILS_SRCS} ${IPUTILS_HEADERS})
 
 target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_client dap_io dap_notify_srv dap_cli_server dap_chain dap_chain_wallet
-                                        dap_chain_net_srv dap_chain_mempool dap_global_db dap_chain_net_srv_xchange dap_chain_cs_none
-                                        dap_stream_ch_chain_net dap_chain_cs_esbocs dap_json_rpc dap_json_rpc_chain_common)
+                                        dap_chain_net_srv dap_chain_net_srv_voting dap_chain_mempool dap_global_db dap_chain_net_srv_xchange dap_chain_cs_none
+                                        dap_stream_ch_chain_net dap_chain_cs_esbocs dap_json_rpc )
 if(LINUX)
     target_link_libraries(${PROJECT_NAME} resolv)
 endif()
diff --git a/modules/net/dap_chain_ledger.c b/modules/net/dap_chain_ledger.c
index 1daae4728d93a6773aa040937f780a2972b43051..c65f1ccbff03e1901921b64ec018bd127cb83441 100644
--- a/modules/net/dap_chain_ledger.c
+++ b/modules/net/dap_chain_ledger.c
@@ -72,9 +72,18 @@ typedef struct dap_chain_ledger_votings_callbacks{
     dap_chain_ledger_voting_callback_t voting_callback;
     dap_chain_ledger_voting_delete_callback_t voting_delete_callback;
 } dap_chain_ledger_votings_callbacks_t;
+typedef struct dap_ledger_service_info {
+    dap_chain_net_srv_uid_t service_uid;    // hash key
+    char tag_str[32];   // tag string name
+    dap_ledger_tag_check_callback_t callback; //callback for check if a tx for particular service
+    UT_hash_handle hh;
+} dap_ledger_service_info_t;
 
 static dap_ledger_verificator_t *s_verificators;
+static dap_ledger_service_info_t *s_services;
+
 static  pthread_rwlock_t s_verificators_rwlock;
+static  pthread_rwlock_t s_services_rwlock;
 
 static dap_chain_ledger_votings_callbacks_t s_voting_callbacks;
 
@@ -217,6 +226,8 @@ typedef struct dap_ledger_tx_item {
         byte_t multichannel;
         dap_time_t ts_spent;
         byte_t pad[7];
+        dap_chain_net_srv_uid_t tag; //tag (or service this tx is belong to)
+        dap_chain_tx_tag_action_type_t action;
         // TODO dynamically allocates the memory in order not to limit the number of outputs in transaction
         dap_chain_hash_fast_t tx_hash_spent_fast[MAX_OUT_ITEMS]; // spent outs list
     } DAP_ALIGN_PACKED cache_data;
@@ -365,6 +376,157 @@ static size_t s_threshold_free_timer_tick = 900000; // 900000 ms = 15 minutes.
 
 struct json_object *wallet_info_json_collect(dap_ledger_t *a_ledger, dap_ledger_wallet_balance_t* a_bal);
 
+//add a service declaration for tx tagging and more
+static bool s_tag_check_block_reward(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx,  dap_chain_datum_tx_item_groups_t *a_items_grp, dap_chain_tx_tag_action_type_t *a_action)
+{
+    //reward tag
+    if (a_items_grp->items_in_reward)
+    {
+        if (a_action) *a_action = DAP_CHAIN_TX_TAG_ACTION_TRANSFER_REGULAR;
+        return true;
+    }
+    return false;
+}
+
+dap_chain_tx_out_cond_t* dap_chain_ledger_get_tx_out_cond_linked_to_tx_in_cond(dap_ledger_t *a_ledger, dap_chain_tx_in_cond_t *a_in_cond)
+{
+        dap_hash_fast_t *l_tx_prev_hash = &a_in_cond->header.tx_prev_hash;    
+        uint32_t l_tx_prev_out_idx = a_in_cond->header.tx_out_prev_idx;
+        dap_chain_datum_tx_t *l_tx_prev = dap_ledger_tx_find_by_hash (a_ledger,l_tx_prev_hash);
+        
+        if (!l_tx_prev) return NULL;
+        byte_t* l_item_res = dap_chain_datum_tx_item_get_nth(l_tx_prev, TX_ITEM_TYPE_OUT_ALL, l_tx_prev_out_idx);
+        dap_chain_tx_item_type_t l_type = *(uint8_t *)l_item_res;
+        
+        if (l_type != TX_ITEM_TYPE_OUT_COND) return NULL;
+
+        
+        return (dap_chain_tx_out_cond_t*)l_item_res;
+}
+
+static dap_chain_addr_t s_get_out_addr(byte_t *out_item) {
+    dap_chain_tx_item_type_t l_type = *(uint8_t *)out_item;
+    
+    switch (l_type) {
+        case TX_ITEM_TYPE_OUT: { 
+            dap_chain_tx_out_t *l_tx_out = (dap_chain_tx_out_t *)out_item;
+            return l_tx_out->addr;
+        } break;
+        case TX_ITEM_TYPE_OUT_EXT: { // 256
+            dap_chain_tx_out_ext_t *l_tx_out = (dap_chain_tx_out_ext_t *)out_item;
+            return l_tx_out->addr;
+        } break;
+    }
+
+    dap_chain_addr_t l_tx_out_to={0};
+    return l_tx_out_to;
+}
+
+static bool s_tag_check_transfer(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx,  dap_chain_datum_tx_item_groups_t *a_items_grp, dap_chain_tx_tag_action_type_t *a_action)
+{
+    //crosschain transfer
+    //regular transfer
+    //comission transfer
+    
+    // fee transfer: in_cond item linked to out_cond_fee
+    if (a_items_grp->items_in_cond) 
+    {
+       for (dap_list_t *it = a_items_grp->items_in_cond; it; it = it->next) {
+            dap_chain_tx_in_cond_t *l_tx_in = it->data;
+            dap_chain_tx_out_cond_t *l_tx_out_cond = dap_chain_ledger_get_tx_out_cond_linked_to_tx_in_cond(a_ledger, l_tx_in);
+
+            if (l_tx_out_cond && l_tx_out_cond->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE) {
+                if (a_action) *a_action = DAP_CHAIN_TX_TAG_ACTION_TRANSFER_COMISSION;
+                return true;
+            }   
+        }
+    }
+
+    //crosschain transfer: outs destination net-id differs from current net-id
+    // to differ with wrong stakes -> no ems in required
+
+    if (!a_items_grp->items_in_ems)
+    {
+        dap_chain_addr_t addr_to = {0};
+        for (dap_list_t *it =  a_items_grp->items_out_all; it; it = it->next) {
+            
+            dap_chain_addr_t l_tx_out_to = s_get_out_addr(it->data);
+        
+            //tag cross-chain _outputs_ transactions (recepient-tx is emission-based)
+            if (l_tx_out_to.net_id.uint64 != a_ledger->net->pub.id.uint64 && !dap_chain_addr_is_blank(&l_tx_out_to)) {
+                if (a_action) *a_action = DAP_CHAIN_TX_TAG_ACTION_TRANSFER_CROSSCHAIN;
+                return true;
+            }
+        }   
+    }
+
+
+    //regular transfers 
+    //have no other ins except regular in
+    //have no OUT_COND except fee
+    //have no vote
+    //no TSD!
+
+
+    //have any of those -> not regular transfer
+    if (a_items_grp->items_in_cond ||
+        a_items_grp->items_in_ems ||
+        a_items_grp->items_in_reward ) {
+        return false;   
+    }
+    
+    //have any of those -> not regular transfer
+    if ( 
+        a_items_grp->items_out_cond_srv_pay ||
+        a_items_grp->items_out_cond_srv_stake_lock ||
+        a_items_grp->items_out_cond_srv_stake_pos_delegate ||
+        a_items_grp->items_out_cond_srv_xchange) 
+    {
+        return false;
+    }
+    
+    //not voting or vote...
+    if (a_items_grp->items_vote || a_items_grp->items_voting || a_items_grp->items_tsd)
+        return false;
+
+    //not tsd sects (staking!)
+    if(a_action) *a_action = DAP_CHAIN_TX_TAG_ACTION_TRANSFER_REGULAR;
+    return true;
+}
+
+int dap_ledger_service_add(dap_chain_net_srv_uid_t a_uid, char *tag_str, dap_ledger_tag_check_callback_t a_callback)
+{
+    
+    dap_ledger_service_info_t *l_new_sinfo;
+    
+    int l_tmp = a_uid.raw_ui64;
+
+    pthread_rwlock_rdlock(&s_services_rwlock);
+    HASH_FIND_INT(s_services, &l_tmp, l_new_sinfo);
+    pthread_rwlock_unlock(&s_services_rwlock);
+    if (l_new_sinfo) {
+        l_new_sinfo->callback = a_callback;
+        return 1;
+    }
+
+    l_new_sinfo = DAP_NEW(dap_ledger_service_info_t);
+    if (!l_new_sinfo) {
+        log_it(L_CRITICAL, "Memory allocation error");
+        return -1;
+    }
+    l_new_sinfo->service_uid = a_uid;
+    l_new_sinfo->callback = a_callback;
+    strcpy(l_new_sinfo->tag_str, tag_str);
+    
+    pthread_rwlock_wrlock(&s_services_rwlock);
+    HASH_ADD_INT(s_services, service_uid.raw_ui64, l_new_sinfo);
+    pthread_rwlock_unlock(&s_services_rwlock);
+
+    log_it(L_NOTICE, "Successfully registered service tag %s with uid %02" DAP_UINT64_FORMAT_X, tag_str, a_uid.raw_ui64);
+
+    return 0;
+}
+
 /**
  * @brief dap_ledger_init
  * current function version set s_debug_more parameter, if it define in config, and returns 0
@@ -373,7 +535,16 @@ struct json_object *wallet_info_json_collect(dap_ledger_t *a_ledger, dap_ledger_
 int dap_ledger_init()
 {
     s_debug_more = dap_config_get_item_bool_default(g_config,"ledger","debug_more",false);
+    
     pthread_rwlock_init(&s_verificators_rwlock, NULL);
+    pthread_rwlock_init(&s_services_rwlock, NULL);
+
+    //register native ledger services
+    dap_chain_net_srv_uid_t l_uid_transfer = { .uint64 = DAP_CHAIN_NET_SRV_TRANSFER_ID };
+    dap_ledger_service_add(l_uid_transfer, "transfer", s_tag_check_transfer);
+
+    dap_chain_net_srv_uid_t l_uid_breward = { .uint64 = DAP_CHAIN_NET_SRV_BLOCK_REWARD_ID };
+    dap_ledger_service_add(l_uid_breward, "block_reward", s_tag_check_block_reward);
     return 0;
 }
 
@@ -384,6 +555,7 @@ int dap_ledger_init()
 void dap_ledger_deinit()
 {
     pthread_rwlock_destroy(&s_verificators_rwlock);
+    pthread_rwlock_destroy(&s_services_rwlock);
 }
 
 /**
@@ -462,7 +634,7 @@ struct json_object *wallet_info_json_collect(dap_ledger_t *a_ledger, dap_ledger_
     }
     struct json_object *l_token = json_object_new_object();
     json_object_object_add(l_token, "name", json_object_new_string(a_bal->token_ticker));
-    char *l_balance_coins, *l_balance_datoshi = dap_uint256_to_char(a_bal->balance, &l_balance_coins);
+    const char *l_balance_coins, *l_balance_datoshi = dap_uint256_to_char(a_bal->balance, &l_balance_coins);
     json_object_object_add(l_token, "full_balance", json_object_new_string(l_balance_coins));
     json_object_object_add(l_token, "datoshi", json_object_new_string(l_balance_datoshi));
     json_object_object_add(l_network, "tokens", l_token);
@@ -1051,7 +1223,7 @@ static bool s_ledger_token_supply_check_update(dap_ledger_t *a_ledger, dap_ledge
     else
         l_overflow = SUBTRACT_256_256(a_token_item->current_supply, a_value, &a_token_item->current_supply);
     assert(!l_overflow);
-    char *l_balance; dap_uint256_to_char(a_token_item->current_supply, &l_balance);
+    const char *l_balance; dap_uint256_to_char(a_token_item->current_supply, &l_balance);
     log_it(L_NOTICE, "New current supply %s for token %s", l_balance, a_token_item->ticker);
     s_ledger_token_cache_update(a_ledger, a_token_item);
     return true;
@@ -1228,7 +1400,7 @@ int dap_ledger_token_add(dap_ledger_t *a_ledger, dap_chain_datum_token_t *a_toke
     }
     int l_res_token_tsd_parse = 0;
 
-    char *l_balance_dbg = NULL;
+    const char *l_balance_dbg = NULL;
     if (s_debug_more)
         dap_uint256_to_char(l_token->total_supply, &l_balance_dbg);
 
@@ -1785,6 +1957,9 @@ static int s_tsd_sign_apply(dap_ledger_t *a_ledger, dap_ledger_token_item_t *a_t
         uint16_t l_tmp = 0;
         a_token_item->auth_signs_valid = _dap_tsd_get_scalar(l_new_signs_valid, &l_tmp);
     }
+
+    if (l_added_pkeys) dap_list_free(l_added_pkeys);
+    if (l_remove_pkeys) dap_list_free(l_remove_pkeys);
     return 0;
 }
 
@@ -1813,11 +1988,17 @@ json_object *dap_ledger_threshold_info(dap_ledger_t *a_ledger, size_t a_limit, s
     uint32_t l_counter = 0;
     pthread_rwlock_rdlock(&l_ledger_pvt->threshold_txs_rwlock);
     size_t l_arr_start = 0;
-    if (a_offset > 1) {
-        l_arr_start = a_limit * a_offset;
+    if (a_offset > 0) {
+        l_arr_start = a_offset;
+        json_object* json_obj_tx = json_object_new_object();
+        json_object_object_add(json_obj_tx, "offset", json_object_new_int(l_arr_start));
+        json_object_array_add(json_arr_out, json_obj_tx);
     }
     size_t l_arr_end = HASH_COUNT(l_ledger_pvt->threshold_txs);
     if (a_limit) {
+        json_object* json_obj_tx = json_object_new_object();
+        json_object_object_add(json_obj_tx, "limit", json_object_new_int(a_limit));
+        json_object_array_add(json_arr_out, json_obj_tx);
         l_arr_end = l_arr_start + a_limit;
         if (l_arr_end > HASH_COUNT(l_ledger_pvt->threshold_txs)) {
             l_arr_end = HASH_COUNT(l_ledger_pvt->threshold_txs);
@@ -1825,7 +2006,7 @@ json_object *dap_ledger_threshold_info(dap_ledger_t *a_ledger, size_t a_limit, s
     }
     size_t i_tmp = 0;
     HASH_ITER(hh, l_ledger_pvt->threshold_txs, l_tx_item, l_tx_tmp){
-        if (i_tmp < l_arr_start || i_tmp > l_arr_end) {
+        if (i_tmp < l_arr_start || i_tmp >= l_arr_end) {
             i_tmp++;
             continue;
         }
@@ -1885,11 +2066,17 @@ json_object *dap_ledger_threshold_hash_info(dap_ledger_t *a_ledger, dap_chain_ha
         return NULL;
     }
     size_t l_arr_start = 0;
-    if (a_offset > 1) {
-        l_arr_start = a_limit * a_offset;
+    if (a_offset > 0) {
+        l_arr_start = a_offset;
+        json_object* json_obj_tx = json_object_new_object();
+        json_object_object_add(json_obj_tx, "offset", json_object_new_int(l_arr_start));
+        json_object_array_add(json_arr_out, json_obj_tx);        
     }
     size_t l_arr_end = HASH_COUNT(l_ledger_pvt->threshold_txs);
     if (a_limit) {
+        json_object* json_obj_tx = json_object_new_object();
+        json_object_object_add(json_obj_tx, "limit", json_object_new_int(l_arr_start));
+        json_object_array_add(json_arr_out, json_obj_tx);
         l_arr_end = l_arr_start + a_limit;
         if (l_arr_end > HASH_COUNT(l_ledger_pvt->threshold_txs)) {
             l_arr_end = HASH_COUNT(l_ledger_pvt->threshold_txs);
@@ -1899,7 +2086,7 @@ json_object *dap_ledger_threshold_hash_info(dap_ledger_t *a_ledger, dap_chain_ha
     pthread_rwlock_rdlock(&l_ledger_pvt->threshold_txs_rwlock);
     HASH_ITER(hh, l_ledger_pvt->threshold_txs, l_tx_item, l_tx_tmp){
         if (!memcmp(l_threshold_hash, &l_tx_item->tx_hash_fast, sizeof(dap_chain_hash_fast_t))){
-            if (i_tmp < l_arr_start || i_tmp > l_arr_end) {
+            if (i_tmp < l_arr_start || i_tmp >= l_arr_end) {
                 i_tmp++;
                 continue;
             }
@@ -1918,7 +2105,7 @@ json_object *dap_ledger_threshold_hash_info(dap_ledger_t *a_ledger, dap_chain_ha
     dap_ledger_token_emission_item_t *l_emission_item, *l_emission_tmp;
     HASH_ITER(hh, l_ledger_pvt->threshold_emissions, l_emission_item, l_emission_tmp){
         if (!memcmp(&l_emission_item->datum_token_emission_hash,l_threshold_hash, sizeof(dap_chain_hash_fast_t))){
-            if (i_tmp < l_arr_start || i_tmp > l_arr_end) {
+            if (i_tmp < l_arr_start || i_tmp >= l_arr_end) {
                 i_tmp++;
                 continue;
             }
@@ -1946,10 +2133,16 @@ json_object *dap_ledger_balance_info(dap_ledger_t *a_ledger, size_t a_limit, siz
     dap_ledger_wallet_balance_t *l_balance_item, *l_balance_tmp;
     size_t l_arr_start = 0;
     if (a_offset > 1) {
-        l_arr_start = a_limit * a_offset;
+        l_arr_start = a_offset;
+        json_object* json_obj_tx = json_object_new_object();
+        json_object_object_add(json_obj_tx, "offset", json_object_new_int(l_arr_start));
+        json_object_array_add(json_arr_out, json_obj_tx);        
     }
     size_t l_arr_end = HASH_COUNT(l_ledger_pvt->balance_accounts);
     if (a_limit) {
+        json_object* json_obj_tx = json_object_new_object();
+        json_object_object_add(json_obj_tx, "limit", json_object_new_int(l_arr_start));
+        json_object_array_add(json_arr_out, json_obj_tx);
         l_arr_end = l_arr_start + a_limit;
         if (l_arr_end > HASH_COUNT(l_ledger_pvt->balance_accounts)) {
             l_arr_end = HASH_COUNT(l_ledger_pvt->balance_accounts);
@@ -1957,7 +2150,7 @@ json_object *dap_ledger_balance_info(dap_ledger_t *a_ledger, size_t a_limit, siz
     }
     size_t i_tmp = 0;
     HASH_ITER(hh, l_ledger_pvt->balance_accounts, l_balance_item, l_balance_tmp) {
-        if (i_tmp < l_arr_start || i_tmp > l_arr_end) {
+        if (i_tmp < l_arr_start || i_tmp >= l_arr_end) {
             i_tmp++;
             continue;
         }
@@ -2058,11 +2251,17 @@ json_object *dap_ledger_token_info(dap_ledger_t *a_ledger, size_t a_limit, size_
     dap_ledger_token_item_t *l_token_item, *l_tmp_item;
     pthread_rwlock_rdlock(&PVT(a_ledger)->tokens_rwlock);
     size_t l_arr_start = 0;
-    if (a_offset > 1) {
-        l_arr_start = a_limit * a_offset;
+    if (a_offset > 0) {
+        l_arr_start = a_offset;
+        json_object* json_obj_tx = json_object_new_object();
+        json_object_object_add(json_obj_tx, "offset", json_object_new_int(l_arr_start));
+        json_object_array_add(json_arr_out, json_obj_tx);        
     }
     size_t l_arr_end = HASH_COUNT(PVT(a_ledger)->tokens);
     if (a_limit) {
+        json_object* json_obj_tx = json_object_new_object();
+        json_object_object_add(json_obj_tx, "limit", json_object_new_int(a_limit));
+        json_object_array_add(json_arr_out, json_obj_tx);
         l_arr_end = l_arr_start + a_limit;
         if (l_arr_end > HASH_COUNT(PVT(a_ledger)->tokens)) {
             l_arr_end = HASH_COUNT(PVT(a_ledger)->tokens);
@@ -2070,7 +2269,7 @@ json_object *dap_ledger_token_info(dap_ledger_t *a_ledger, size_t a_limit, size_
     }
     size_t i_tmp = 0;
     HASH_ITER(hh, PVT(a_ledger)->tokens, l_token_item, l_tmp_item) {
-        if (i_tmp < l_arr_start || i_tmp > l_arr_end) {
+        if (i_tmp < l_arr_start || i_tmp >= l_arr_end) {
             i_tmp++;
             continue;
         }
@@ -2888,7 +3087,7 @@ int dap_ledger_token_emission_add(dap_ledger_t *a_ledger, byte_t *a_token_emissi
             // Add it to cache
             s_ledger_emission_cache_update(a_ledger, l_token_emission_item);
             if (s_debug_more) {
-                char *l_balance; dap_uint256_to_char(l_token_emission_item->datum_token_emission->hdr.value, &l_balance);
+                const char *l_balance; dap_uint256_to_char(l_token_emission_item->datum_token_emission->hdr.value, &l_balance);
                 log_it(L_NOTICE, "Added token emission datum to emissions cache: type=%s value=%s token=%s to_addr=%s ",
                                c_dap_chain_datum_token_emission_type_str[l_token_emission_item->datum_token_emission->hdr.type],
                                l_balance, c_token_ticker,
@@ -2908,7 +3107,7 @@ int dap_ledger_token_emission_add(dap_ledger_t *a_ledger, byte_t *a_token_emissi
             pthread_rwlock_unlock(&l_ledger_pvt->threshold_emissions_rwlock);
             l_ret = -5;
             if (s_debug_more) {
-                char *l_balance; dap_uint256_to_char(l_token_emission_item->datum_token_emission->hdr.value, &l_balance);
+                const char *l_balance; dap_uint256_to_char(l_token_emission_item->datum_token_emission->hdr.value, &l_balance);
                 log_it(L_NOTICE, "Added token emission datum to emissions threshold: type=%s value=%s token=%s to_addr=%s ",
                                c_dap_chain_datum_token_emission_type_str[l_token_emission_item->datum_token_emission->hdr.type],
                                l_balance, c_token_ticker,
@@ -3197,7 +3396,7 @@ void dap_ledger_addr_get_token_ticker_all(dap_ledger_t *a_ledger, dap_chain_addr
                 return;
             }
             l_count = 0;
-            char *l_addr = dap_chain_addr_to_str(a_addr);
+            const char *l_addr = dap_chain_addr_to_str(a_addr);
             pthread_rwlock_rdlock(&PVT(a_ledger)->balance_accounts_rwlock);
             HASH_ITER(hh, PVT(a_ledger)->balance_accounts, wallet_balance, tmp) {
                 char **l_keys = dap_strsplit(wallet_balance->key, " ", -1);
@@ -3215,7 +3414,11 @@ void dap_ledger_addr_get_token_ticker_all(dap_ledger_t *a_ledger, dap_chain_addr
     }
 }
 
-
+const char *dap_ledger_get_description_by_ticker(dap_ledger_t *a_ledger, const char *a_token_ticker){
+    if (!a_ledger || !a_token_ticker)
+        return NULL;
+    return s_ledger_find_token(a_ledger, a_token_ticker)->description_token;
+}
 
 /**
  * Get transaction in the cache by hash
@@ -3491,14 +3694,149 @@ inline static bool s_ledger_check_token_ticker(const char *a_ticker)
     return false;
 }
 
+/*
+services we know now
+0x01 - VPN
+0x02 - xchange
+0x03, 0x13 -  pos_delegate
+0x04 bridge
+0x.05 - custom datum
+0x06 voting
+0x12 - stake_lock 
+*/
+
+const char *dap_ledger_tx_action_str(dap_chain_tx_tag_action_type_t a_tag)
+{
+
+    if (a_tag == DAP_CHAIN_TX_TAG_ACTION_UNKNOWN) return "unknown";
+    if (a_tag == DAP_CHAIN_TX_TAG_ACTION_TRANSFER_REGULAR) return "regular";
+    if (a_tag == DAP_CHAIN_TX_TAG_ACTION_TRANSFER_COMISSION) return "comission";
+    if (a_tag == DAP_CHAIN_TX_TAG_ACTION_TRANSFER_CROSSCHAIN) return "crosschain";
+    if (a_tag == DAP_CHAIN_TX_TAG_ACTION_TRANSFER_REWARD) return "reward";
+    if (a_tag == DAP_CHAIN_TX_TAG_ACTION_OPEN) return "open";
+    if (a_tag == DAP_CHAIN_TX_TAG_ACTION_USE) return "use";
+    if (a_tag == DAP_CHAIN_TX_TAG_ACTION_EXTEND) return "extend";
+    if (a_tag == DAP_CHAIN_TX_TAG_ACTION_CLOSE) return "close";
+    if (a_tag == DAP_CHAIN_TX_TAG_ACTION_CHANGE) return "change";
+
+    return "WTFSUBTAG";
+
+}
+
+dap_chain_tx_tag_action_type_t dap_ledger_tx_action_str_to_action_t(const char *a_str)
+{
+    if (!a_str)
+        return DAP_CHAIN_TX_TAG_ACTION_UNKNOWN;
+    
+    if (strcmp("unknown", a_str) == 0) return DAP_CHAIN_TX_TAG_ACTION_UNKNOWN;
+    if (strcmp("regular", a_str) == 0) return DAP_CHAIN_TX_TAG_ACTION_TRANSFER_REGULAR;
+    if (strcmp("comission", a_str) == 0) return DAP_CHAIN_TX_TAG_ACTION_TRANSFER_COMISSION;
+    if (strcmp("crosschain", a_str) == 0) return DAP_CHAIN_TX_TAG_ACTION_TRANSFER_CROSSCHAIN;
+    if (strcmp("reward", a_str) == 0) return DAP_CHAIN_TX_TAG_ACTION_TRANSFER_REWARD;
+    if (strcmp("open", a_str) == 0) return DAP_CHAIN_TX_TAG_ACTION_OPEN;
+    if (strcmp("use", a_str) == 0) return DAP_CHAIN_TX_TAG_ACTION_USE;
+    if (strcmp("extend", a_str) == 0) return DAP_CHAIN_TX_TAG_ACTION_EXTEND;
+    if (strcmp("close", a_str) == 0) return DAP_CHAIN_TX_TAG_ACTION_CLOSE;
+    if (strcmp("change", a_str) == 0) return DAP_CHAIN_TX_TAG_ACTION_CHANGE;
+
+    return DAP_CHAIN_TX_TAG_ACTION_UNKNOWN;
+}
+
+bool dap_ledger_tx_service_info(dap_ledger_t *a_ledger, dap_hash_fast_t *a_tx_hash, 
+                                dap_chain_net_srv_uid_t *a_uid, char **a_service_name,  dap_chain_tx_tag_action_type_t *a_action)
+{
+    //find tx
+    dap_ledger_private_t *l_ledger_pvt = PVT(a_ledger);
+    dap_chain_datum_tx_t *l_tx_ret = NULL;
+    dap_ledger_tx_item_t *l_tx_item;
+    pthread_rwlock_rdlock(&l_ledger_pvt->ledger_rwlock);
+    HASH_FIND(hh, l_ledger_pvt->ledger_items, a_tx_hash, sizeof(dap_chain_hash_fast_t), l_tx_item);
+    pthread_rwlock_unlock(&l_ledger_pvt->ledger_rwlock);
+    
+    
+    if(l_tx_item) {
+        dap_ledger_service_info_t *l_sinfo;    
+        pthread_rwlock_rdlock(&s_services_rwlock);
+        HASH_FIND_INT(s_services, &l_tx_item->cache_data.tag, l_sinfo);
+        pthread_rwlock_unlock(&s_services_rwlock);
+        if (l_sinfo)
+        { 
+            if(a_uid) *a_uid = l_sinfo->service_uid;
+            if (a_service_name) *a_service_name = l_sinfo->tag_str;
+            if (a_action) *a_action = l_tx_item->cache_data.action;
+            return true; 
+        } 
+    }
+
+    if (a_action) *a_action = DAP_CHAIN_TX_TAG_ACTION_UNKNOWN;
+    return false;
+}
+
+
+bool dap_ledger_deduct_tx_tag(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_net_srv_uid_t *a_tag, dap_chain_tx_tag_action_type_t *a_action)
+{
+    dap_ledger_service_info_t *l_sinfo_current, *l_sinfo_tmp;
+
+    
+    dap_chain_datum_tx_item_groups_t l_items_groups = {0};
+    dap_chain_datum_tx_group_items(a_tx, &l_items_groups);
+
+    bool l_res = false;
+    int l_deductions_ok = 0;
+
+    pthread_rwlock_rdlock(&s_services_rwlock);
+    HASH_ITER(hh, s_services , l_sinfo_current, l_sinfo_tmp) {
+        dap_chain_tx_tag_action_type_t action = DAP_CHAIN_TX_TAG_ACTION_UNKNOWN;
+        if (l_sinfo_current->callback && l_sinfo_current->callback(a_ledger, a_tx, &l_items_groups, &action)){
+            if (a_tag) *a_tag =  l_sinfo_current->service_uid;
+            if (a_action) *a_action =  action;
+            l_res = true;
+            l_deductions_ok ++;
+        }
+    } 
+    pthread_rwlock_unlock(&s_services_rwlock);
+
+    if (l_deductions_ok > 1)
+    {
+        char l_tx_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE];
+        dap_chain_hash_fast_t * l_tx_hash = dap_chain_node_datum_tx_calc_hash(a_tx);
+        dap_chain_hash_fast_to_str(l_tx_hash, l_tx_hash_str, sizeof(l_tx_hash_str));
+
+
+        log_it(L_WARNING, "Transaction %s identyfied by multiple services (%d):", l_tx_hash_str, l_deductions_ok);
+    
+        pthread_rwlock_rdlock(&s_services_rwlock);
+        HASH_ITER(hh, s_services , l_sinfo_current, l_sinfo_tmp) {
+            dap_chain_tx_tag_action_type_t action = DAP_CHAIN_TX_TAG_ACTION_UNKNOWN;
+            if (l_sinfo_current->callback && l_sinfo_current->callback(a_ledger, a_tx, &l_items_groups,&action))  {
+                log_it(L_WARNING, "%s %s", l_sinfo_current->tag_str, dap_ledger_tx_action_str(action));
+            }
+        } 
+
+        pthread_rwlock_unlock(&s_services_rwlock);
+    }
+    
+    dap_chain_datum_tx_group_items_free(&l_items_groups);
+
+    return l_res;
+}
+
 /**
  * Checking a new transaction before adding to the cache
  *
  * return 0 OK, otherwise error
  */
 // Checking a new transaction before adding to the cache
-int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash,
-                                    bool a_from_threshold, dap_list_t **a_list_bound_items, dap_list_t **a_list_tx_out, char **a_main_ticker, bool a_check_for_removing)
+int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger,
+                                 dap_chain_datum_tx_t *a_tx,
+                                  dap_hash_fast_t *a_tx_hash,
+                                    bool a_from_threshold, 
+                                    dap_list_t **a_list_bound_items,
+                                     dap_list_t **a_list_tx_out,
+                                      char **a_main_ticker,
+                                      dap_chain_net_srv_uid_t *a_tag,
+                                      dap_chain_tx_tag_action_type_t *a_action, 
+                                      bool a_check_for_removing)
 {
     if (!a_tx) {
         log_it(L_DEBUG, "NULL transaction, check broken");
@@ -3514,6 +3852,8 @@ int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx
                 char l_tx_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE];
                 dap_chain_hash_fast_to_str(a_tx_hash, l_tx_hash_str, sizeof(l_tx_hash_str));
                 log_it(L_WARNING, "Transaction %s already present in the cache", l_tx_hash_str);
+                if (a_tag) *a_tag = l_ledger_item->cache_data.tag;
+                if (a_action) *a_action = l_ledger_item->cache_data.action;
             }
             return DAP_LEDGER_TX_ALREADY_CACHED;
         }
@@ -3561,6 +3901,8 @@ int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx
     dap_pkey_t *l_tx_first_sign_pkey = NULL;
     bool l_girdled_ems_used = false;
     uint256_t l_taxed_value = {};
+    
+    if(a_tag) dap_ledger_deduct_tx_tag(a_ledger, a_tx, a_tag, a_action);
 
     // find all previous transactions
     for (dap_list_t *it = l_list_in; it; it = it->next) {
@@ -3845,7 +4187,7 @@ int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx
                 l_tx_prev_hash = &l_tx_in->header.tx_prev_hash;
                 if (dap_hash_fast_is_blank(l_tx_prev_hash)) {
                     DAP_DELETE(l_bound_item);
-                    l_list_bound_items = dap_list_remove_link(l_list_bound_items, dap_list_last(l_list_bound_items));
+                    l_list_bound_items = dap_list_delete_link(l_list_bound_items, dap_list_last(l_list_bound_items));
                     continue; // old base tx compliance
                 }
                 l_tx_prev_out_idx = l_tx_in->header.tx_out_prev_idx;
@@ -3978,7 +4320,7 @@ int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx
                     if (!dap_chain_addr_is_blank(l_addr_from) && s_ledger_permissions_check(l_token_item,
                                                    DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_ADD, l_addr_from,
                                                   sizeof(*l_addr_from)) != 0 ){
-                        char *l_tmp_tx_in_from = dap_chain_addr_to_str(l_addr_from);
+                        const char *l_tmp_tx_in_from = dap_chain_addr_to_str(l_addr_from);
                         debug_if(s_debug_more, L_WARNING, "No permission for addr %s", l_tmp_tx_in_from ? l_tmp_tx_in_from : "(null)");
                         l_err_num = DAP_LEDGER_PERMISSION_CHECK_FAILED;
                         break;
@@ -3988,7 +4330,7 @@ int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx
                     (l_token_item->flags & DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_SENDER_UNFROZEN ) ){ // in black list
                     if (s_ledger_permissions_check(l_token_item, DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_ADD, l_addr_from,
                                                   sizeof(*l_addr_from)) == 0 ){
-                        char *l_tmp_tx_in_from = dap_chain_addr_to_str(l_addr_from);
+                        const char *l_tmp_tx_in_from = dap_chain_addr_to_str(l_addr_from);
                         debug_if(s_debug_more, L_WARNING, "No permission for addr %s", l_tmp_tx_in_from ? l_tmp_tx_in_from : "(null)");
                         l_err_num = DAP_LEDGER_PERMISSION_CHECK_FAILED;
                         break;
@@ -4130,7 +4472,7 @@ int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx
         HASH_ADD_STR(l_values_from_cur_tx, token_ticker, l_value_cur);
     }
 
-    dap_chain_net_srv_stake_item_t *l_key_item = dap_chain_net_srv_stake_check_pkey_hash(&l_tx_first_sign_pkey_hash);
+    dap_chain_net_srv_stake_item_t *l_key_item = dap_chain_net_srv_stake_check_pkey_hash(a_ledger->net->pub.id, &l_tx_first_sign_pkey_hash);
     bool l_tax_check = l_key_item && !dap_chain_addr_is_blank(&l_key_item->sovereign_addr) && !IS_ZERO_256(l_key_item->sovereign_tax);
 
     // find 'out' items
@@ -4236,7 +4578,7 @@ int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx
              (l_token_item->flags & DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_RECEIVER_FROZEN) ){ //  check if we're in white list
             if(!dap_chain_addr_is_blank(&l_tx_out_to) && s_ledger_permissions_check(l_token_item, DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_ADD,&l_tx_out_to ,
                                           sizeof (l_tx_out_to)) != 0 ){
-                char * l_tmp_tx_out_to = dap_chain_addr_to_str(&l_tx_out_to);
+                const char *l_tmp_tx_out_to = dap_chain_addr_to_str(&l_tx_out_to);
                 debug_if(s_debug_more, L_WARNING, "No permission for addr %s", l_tmp_tx_out_to?l_tmp_tx_out_to:"(null)");
                 l_err_num = -20;
                 break;
@@ -4247,7 +4589,7 @@ int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx
              ){ // If all is allowed - check if we're in black list
             if(s_ledger_permissions_check(l_token_item, DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_ADD ,&l_tx_out_to,
                                           sizeof (l_tx_out_to)) == 0 ){
-                char * l_tmp_tx_out_to = dap_chain_addr_to_str(&l_tx_out_to);
+                const char *l_tmp_tx_out_to = dap_chain_addr_to_str(&l_tx_out_to);
                 debug_if(s_debug_more, L_WARNING, "No permission for addr %s", l_tmp_tx_out_to?l_tmp_tx_out_to:"(null)");
                 l_err_num = -22;
                 break;
@@ -4387,7 +4729,7 @@ int dap_ledger_tx_add_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx,
     }
 
     int l_ret_check = dap_ledger_tx_cache_check(a_ledger, a_tx, a_datum_hash,
-                                                      false, NULL, NULL, NULL, false);
+                                                      false, NULL, NULL, NULL, NULL, NULL, false);
     if(s_debug_more) {
         char l_tx_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE];
         dap_chain_hash_fast_to_str(a_datum_hash, l_tx_hash_str, sizeof(l_tx_hash_str));
@@ -4474,9 +4816,12 @@ int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_ha
 
     int l_ret_check;
     l_item_tmp = NULL;
+    dap_chain_net_srv_uid_t l_tag =  { .uint64 = 0 }; 
+    dap_chain_tx_tag_action_type_t l_action = DAP_CHAIN_TX_TAG_ACTION_UNKNOWN;
+
     if( (l_ret_check = dap_ledger_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, 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) {
             if (!l_from_threshold) {
@@ -4515,6 +4860,10 @@ int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_ha
             debug_if(s_debug_more, L_WARNING, "dap_ledger_tx_add() tx %s not passed the check: %s ", l_tx_hash_str,
                         dap_ledger_tx_check_err_str(l_ret_check));
         }
+        
+        if ( l_list_bound_items )
+            dap_list_free_full(l_list_bound_items, NULL);
+        
         return l_ret_check;
     }
     debug_if(s_debug_more, L_DEBUG, "dap_ledger_tx_add() check passed for tx %s", l_tx_hash_str);
@@ -4591,7 +4940,7 @@ int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_ha
         case TX_ITEM_TYPE_IN: {
             dap_ledger_wallet_balance_t *wallet_balance = NULL;
             l_cur_token_ticker = l_bound_item->in.token_ticker;
-            char *l_addr_str = dap_chain_addr_to_str(&l_bound_item->in.addr_from);
+            const char *l_addr_str = dap_chain_addr_to_str(&l_bound_item->in.addr_from);
             char *l_wallet_balance_key = dap_strjoin(" ", l_addr_str, l_cur_token_ticker, (char*)NULL);
             pthread_rwlock_rdlock(&PVT(a_ledger)->balance_accounts_rwlock);
             HASH_FIND_STR(PVT(a_ledger)->balance_accounts, l_wallet_balance_key, wallet_balance);
@@ -4606,6 +4955,7 @@ int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_ha
                 if(s_debug_more)
                     log_it(L_ERROR,"!!! Attempt to SPEND from some non-existent balance !!!: %s %s", l_addr_str, l_cur_token_ticker);
             }
+            
             DAP_DELETE(l_wallet_balance_key);
         } break;
 
@@ -4704,7 +5054,7 @@ int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_ha
         else if (l_addr->net_id.uint64 != a_ledger->net->pub.id.uint64 &&
                  !dap_chain_addr_is_blank(l_addr))
             l_cross_network = true;
-        char *l_addr_str = dap_chain_addr_to_str(l_addr);
+        const char *l_addr_str = dap_chain_addr_to_str(l_addr);
         dap_ledger_wallet_balance_t *wallet_balance = NULL;
         char *l_wallet_balance_key = dap_strjoin(" ", l_addr_str, l_cur_token_ticker, (char*)NULL);
         debug_if(s_debug_more, L_DEBUG, "GOT %s to addr: %s",
@@ -4763,6 +5113,8 @@ int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_ha
     int l_outs_count = 0;
     dap_list_t *l_list_tmp = dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_OUT_ALL, &l_outs_count);
     l_tx_item->cache_data.n_outs = l_outs_count;
+    l_tx_item->cache_data.tag = l_tag;
+    l_tx_item->cache_data.action = l_action;
     // TODO: dump the UTXO in debug mode if need
 
     if(l_list_tmp)
@@ -5136,7 +5488,7 @@ int dap_ledger_tx_load(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_c
 {
     if (dap_chain_net_get_load_mode(a_ledger->net)) {
         if (PVT(a_ledger)->cache_tx_check_callback)
-            PVT(a_ledger)->cache_tx_check_callback(a_tx_hash);
+            PVT(a_ledger)->cache_tx_check_callback(a_ledger, a_tx_hash);
         dap_ledger_tx_item_t *l_tx_item;
         unsigned l_hash_value;
         HASH_VALUE(a_tx_hash, sizeof(dap_chain_hash_fast_t), l_hash_value);
@@ -5360,7 +5712,7 @@ uint256_t dap_ledger_calc_balance(dap_ledger_t *a_ledger, const dap_chain_addr_t
     uint256_t l_ret = uint256_0;
 
     dap_ledger_wallet_balance_t *l_balance_item = NULL;// ,* l_balance_item_tmp = NULL;
-    char *l_addr = dap_chain_addr_to_str(a_addr);
+    const char *l_addr = dap_chain_addr_to_str(a_addr);
     char *l_wallet_balance_key = dap_strjoin(" ", l_addr, a_token_ticker, (char*)NULL);
     pthread_rwlock_rdlock(&PVT(a_ledger)->balance_accounts_rwlock);
     HASH_FIND_STR(PVT(a_ledger)->balance_accounts, l_wallet_balance_key, l_balance_item);
@@ -6234,14 +6586,14 @@ void dap_ledger_set_cache_tx_check_callback(dap_ledger_t *a_ledger, dap_ledger_c
     PVT(a_ledger)->cache_tx_check_callback = a_callback;
 }
 
-const char *dap_ledger_tx_get_main_ticker(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, int *a_ledger_rc)
+const char *dap_ledger_tx_calculate_main_ticker(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, int *a_ledger_rc)
 {
-    const char *l_main_ticker = NULL;
-    dap_chain_hash_fast_t * l_tx_hash = dap_chain_node_datum_tx_calc_hash(a_tx);
-    int l_rc = dap_ledger_tx_cache_check(a_ledger, a_tx, l_tx_hash, false, NULL, NULL, (char **)&l_main_ticker, false);   
-
+    char *l_main_ticker = NULL;
+    dap_chain_hash_fast_t *l_tx_hash = dap_chain_node_datum_tx_calc_hash(a_tx);
+    int l_rc = dap_ledger_tx_cache_check(a_ledger, a_tx, l_tx_hash, false, NULL, NULL, &l_main_ticker, NULL, NULL, false);  
     if (l_rc == DAP_LEDGER_TX_ALREADY_CACHED)
-        l_main_ticker = dap_ledger_tx_get_token_ticker_by_hash(a_ledger, l_tx_hash);
+        l_main_ticker = (char *)dap_ledger_tx_get_token_ticker_by_hash(a_ledger, l_tx_hash);
+    DAP_DEL_Z(l_tx_hash);
 
     if (a_ledger_rc)
         *a_ledger_rc = l_rc;
diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c
index a2d37ba66ecb3f2e73a5337932441c4e05d84ef6..fbbf4809d3f5d66d702aced1689d77bbcb945ec2 100644
--- a/modules/net/dap_chain_net.c
+++ b/modules/net/dap_chain_net.c
@@ -71,14 +71,7 @@
 #include "dap_config.h"
 #include "dap_hash.h"
 #include "dap_cert.h"
-#include "dap_cert_file.h"
 #include "dap_chain_datum_tx.h"
-#include "dap_chain_datum_tx_in_cond.h"
-#include "dap_chain_datum_tx_items.h"
-#include "dap_chain_datum_tx_out.h"
-#include "dap_chain_datum_tx_out_cond.h"
-#include "dap_timerfd.h"
-#include "dap_stream_worker.h"
 #include "dap_worker.h"
 #include "dap_proc_thread.h"
 #include "dap_enc_http.h"
@@ -86,21 +79,16 @@
 #include "dap_chain_cell.h"
 #include "dap_chain_datum_decree.h"
 #include "dap_chain_datum_anchor.h"
-#include "dap_chain_tx.h"
 #include "dap_chain_net.h"
 #include "dap_chain_net_node_list.h"
 #include "dap_chain_net_tx.h"
 #include "dap_chain_net_anchor.h"
 #include "dap_chain_net_decree.h"
-#include "dap_chain_net_srv.h"
 #include "dap_chain_net_balancer.h"
 #include "dap_chain_node_client.h"
-#include "dap_chain_node_cli.h"
 #include "dap_chain_node_cli_cmd.h"
 #include "dap_notify_srv.h"
 #include "dap_chain_ledger.h"
-#include "dap_chain_cs_none.h"
-#include "dap_client_http.h"
 #include "dap_global_db.h"
 #include "dap_stream_ch_chain_net_pkt.h"
 #include "dap_stream_ch_chain_net.h"
@@ -108,19 +96,17 @@
 #include "dap_stream_ch.h"
 #include "dap_stream.h"
 #include "dap_stream_ch_pkt.h"
-#include "dap_chain_node_dns_client.h"
-#include "dap_module.h"
 #include "rand/dap_rand.h"
-#include "json.h"
 #include "json_object.h"
 #include "dap_chain_net_srv_stake_pos_delegate.h"
 #include "dap_chain_net_srv_xchange.h"
 #include "dap_chain_cs_esbocs.h"
-#include "dap_chain_net_voting.h"
+#include "dap_chain_net_srv_voting.h"
 #include "dap_global_db_cluster.h"
 #include "dap_link_manager.h"
 #include "dap_stream_cluster.h"
 #include "dap_http_ban_list_client.h"
+#include "dap_net.h"
 
 #include <stdio.h>
 #include <sys/types.h>
@@ -211,6 +197,9 @@ typedef struct dap_chain_net_item{
 #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 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;
 
 static const char *c_net_states[] = {
     [NET_STATE_OFFLINE]             = "NET_STATE_OFFLINE",
@@ -247,7 +236,7 @@ static void s_net_states_notify(dap_chain_net_t * l_net);
 static void s_nodelist_change_notify(dap_store_obj_t *a_obj, void *a_arg);
 //static void s_net_proc_kill( dap_chain_net_t * a_net );
 static int s_net_init(const char * a_net_name, uint16_t a_acl_idx);
-static int s_net_load(dap_chain_net_t *a_net);
+static bool s_net_load(void *a_arg);
 static int s_net_try_online(dap_chain_net_t *a_net);
 static int s_cli_net(int argc, char ** argv, void **a_str_reply);
 static uint8_t *s_net_set_acl(dap_chain_hash_fast_t *a_pkey_hash);
@@ -265,7 +254,7 @@ int dap_chain_net_init()
     dap_chain_ch_init();
     dap_stream_ch_chain_net_init();
     dap_chain_node_client_init();
-    dap_chain_net_voting_init();
+    dap_chain_net_srv_voting_init();
     dap_http_ban_list_client_init();
     dap_link_manager_init(&s_link_manager_callbacks);
     dap_chain_node_init();
@@ -307,7 +296,7 @@ int dap_chain_net_init()
                 continue;
             // don't search in directories
             char l_full_path[MAX_PATH + 1] = {0};
-            dap_snprintf(l_full_path, sizeof(l_full_path), "%s/%s", l_net_dir_str, l_dir_entry->d_name);
+            snprintf(l_full_path, sizeof(l_full_path), "%s/%s", l_net_dir_str, l_dir_entry->d_name);
             if(dap_dir_test(l_full_path)) {
                 continue;
             }
@@ -708,10 +697,6 @@ static dap_chain_net_t *s_net_new(dap_chain_net_id_t *a_id, const char *a_name,
     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;
-    pthread_mutexattr_t l_mutex_attr;
-    pthread_mutexattr_init(&l_mutex_attr);
-    pthread_mutexattr_settype(&l_mutex_attr, PTHREAD_MUTEX_RECURSIVE);
-    pthread_mutexattr_destroy(&l_mutex_attr);
 
     if (strcmp (a_node_role, "root_master")==0){
         PVT(l_ret)->node_role.enums = NODE_ROLE_ROOT_MASTER;
@@ -747,17 +732,19 @@ 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()
 {
-    int l_ret = 0;
-    if(!HASH_COUNT(s_net_items)){
+    pthread_mutex_lock(&s_net_cond_lock);
+    s_net_loading_count = HASH_COUNT(s_net_items);
+    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) {
-        if( (l_ret = s_net_load(l_net_items_current->chain_net)) ) {
-            log_it(L_ERROR, "Loading chains of net %s finished with (%d) error code.", l_net_items_current->name, l_ret);
-        }
-    }
+    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);
+    while (s_net_loading_count)
+        pthread_cond_wait(&s_net_cond, &s_net_cond_lock);
+    pthread_mutex_unlock(&s_net_cond_lock);
 }
 
 dap_string_t* dap_cli_list_net()
@@ -855,22 +842,6 @@ void s_set_reply_text_node_status(void **a_str_reply, dap_chain_net_t * a_net){
     DAP_DELETE(l_sync_current_link_text_block);
     DAP_DELETE(l_node_address_text_block);
 }
-
-/**
- * @brief get type of chain
- *
- * @param l_chain
- * @return char*
- */
-const char* dap_chain_net_get_type(dap_chain_t *l_chain)
-{
-    if (!l_chain){
-        log_it(L_DEBUG, "dap_get_chain_type. Chain object is 0");
-        return NULL;
-    }
-    return (const char*)DAP_CHAIN_PVT(l_chain)->cs_name;
-}
-
 /**
  * @brief reload ledger
  * command cellframe-node-cli net -net <network_name> ledger reload
@@ -878,7 +849,7 @@ const char* dap_chain_net_get_type(dap_chain_t *l_chain)
  * @return true
  * @return false
  */
-static void s_chain_net_ledger_cache_reload(dap_chain_net_t *l_net)
+void dap_chain_net_purge(dap_chain_net_t *l_net)
 {
     dap_ledger_purge(l_net->pub.ledger, false);
     dap_chain_net_srv_stake_purge(l_net);
@@ -887,8 +858,8 @@ static void s_chain_net_ledger_cache_reload(dap_chain_net_t *l_net)
     DL_FOREACH(l_net->pub.chains, l_chain) {
         if (l_chain->callback_purge)
             l_chain->callback_purge(l_chain);
-        if (l_chain->callback_set_min_validators_count)
-            l_chain->callback_set_min_validators_count(l_chain, 0);
+        if (!dap_strcmp(dap_chain_get_cs_type(l_chain), "esbocs"))
+            dap_chain_esbocs_set_min_validators_count(l_chain, 0);
         l_net->pub.fee_value = uint256_0;
         l_net->pub.fee_addr = c_dap_chain_addr_blank;
         dap_chain_load_all(l_chain);
@@ -1139,7 +1110,8 @@ static int s_cli_net(int argc, char **argv, void **reply)
         return 0;
     }
 
-    int l_ret = dap_chain_node_cli_cmd_values_parse_net_chain_for_json(&arg_index, argc, argv, NULL, &l_net);
+    int l_ret = dap_chain_node_cli_cmd_values_parse_net_chain_for_json(&arg_index, argc, argv, NULL, &l_net,
+                                                                       CHAIN_TYPE_INVALID);
 
     if ( l_net ) {
         const char *l_sync_str = NULL;
@@ -1303,7 +1275,7 @@ static int s_cli_net(int argc, char **argv, void **reply)
                 dap_json_rpc_error_add(DAP_CHAIN_NET_JSON_RPC_UNDEFINED_PARAMETER_COMMAND_STATS, "%s",
                  "Subcommand 'stats' requires one of parameter: tx");
 #endif
-                l_ret = DAP_CHAIN_NET_JSON_RPC_UNDEFINED_PARAMETER_COMMAND_STATS;
+                return DAP_CHAIN_NET_JSON_RPC_UNDEFINED_PARAMETER_COMMAND_STATS;
             }
         } else if ( l_go_str){
             json_object *l_jobj_net = json_object_new_string(l_net->pub.name);
@@ -1351,9 +1323,10 @@ static int s_cli_net(int argc, char **argv, void **reply)
                     dap_chain_net_state_go_to(l_net, NET_STATE_SYNC_CHAINS);
                 l_ret = DAP_CHAIN_NET_JSON_RPC_OK;
             } else {
+                json_object_put(l_jobj_return);
                 dap_json_rpc_error_add(DAP_CHAIN_NET_JSON_RPC_UNDEFINED_PARAMETER_COMMAND_GO, "%s",
                                        "Subcommand 'go' requires one of parameters: online, offline, sync\n");
-                l_ret = DAP_CHAIN_NET_JSON_RPC_UNDEFINED_PARAMETER_COMMAND_GO;
+                return DAP_CHAIN_NET_JSON_RPC_UNDEFINED_PARAMETER_COMMAND_GO;
             }
         } else if ( l_get_str){
             if ( strcmp(l_get_str,"status") == 0 ) {
@@ -1379,7 +1352,7 @@ static int s_cli_net(int argc, char **argv, void **reply)
                 uint256_t l_network_fee = {};
                 dap_chain_addr_t l_network_fee_addr = {};
                 dap_chain_net_tx_get_fee(l_net->pub.id, &l_network_fee, &l_network_fee_addr);
-                char *l_network_fee_coins_str, *l_network_fee_balance_str =
+                const char *l_network_fee_coins_str, *l_network_fee_balance_str =
                     dap_uint256_to_char(l_network_fee, &l_network_fee_coins_str);
                 json_object *l_jobj_network =  json_object_new_object();
                 json_object *l_jobj_fee_coins = json_object_new_string(l_network_fee_coins_str);
@@ -1493,9 +1466,10 @@ static int s_cli_net(int argc, char **argv, void **reply)
                 json_object_object_add(l_jobj_return, "message", l_jobj_ret);
                 l_ret = DAP_CHAIN_NET_JSON_RPC_OK;
             }else {
+                json_object_put(l_jobj_return);
                 dap_json_rpc_error_add(DAP_CHAIN_NET_JSON_RPC_UNDEFINED_PARAMETERS_COMMAND_LINK, "%s",
                                        "Subcommand 'link' requires one of parameters: list, add, del, info, disconnect_all");
-                l_ret = DAP_CHAIN_NET_JSON_RPC_UNDEFINED_PARAMETERS_COMMAND_LINK;
+                return DAP_CHAIN_NET_JSON_RPC_UNDEFINED_PARAMETERS_COMMAND_LINK;
             }
 
         } else if( l_sync_str) {
@@ -1676,7 +1650,7 @@ static int s_cli_net(int argc, char **argv, void **reply)
         } else if (l_ledger_str && !strcmp(l_ledger_str, "reload")) {
             int l_return_state = dap_chain_net_stop(l_net);
             sleep(1);   // wait to net going offline
-            s_chain_net_ledger_cache_reload(l_net);
+            dap_chain_net_purge(l_net);
             if (l_return_state)
                 dap_chain_net_start(l_net);
         } else if (l_list_str && !strcmp(l_list_str, "list")) {
@@ -2106,20 +2080,21 @@ int s_net_init(const char *a_net_name, uint16_t a_acl_idx)
     return 0;
 }
 
-int s_net_load(dap_chain_net_t *a_net)
+bool s_net_load(void *a_arg)
 {
-    dap_chain_net_t *l_net = a_net;
+    dap_chain_net_t *l_net = a_arg;
+    int l_err_code = 0;
 
-    dap_config_t *l_cfg = NULL;
-    char *l_cfg_path = dap_strdup_printf("network/%s", a_net->pub.name);
-    l_cfg = dap_config_open ( l_cfg_path );
+    char *l_cfg_path = dap_strdup_printf("network/%s", l_net->pub.name);
+    dap_config_t *l_cfg = dap_config_open(l_cfg_path);
     DAP_DELETE(l_cfg_path);
     if (!l_cfg) {
         log_it(L_ERROR,"Can't open default network config");
-        return -1;
+        l_err_code = -1;
+        goto ret;
     }
 
-    dap_chain_net_pvt_t * l_net_pvt = PVT(l_net);
+    dap_chain_net_pvt_t *l_net_pvt = PVT(l_net);
 
     // reload ledger cache at once
     if (s_chain_net_reload_ledger_cache_once(l_net)) {
@@ -2188,19 +2163,19 @@ int s_net_load(dap_chain_net_t *a_net)
         case NODE_ROLE_ROOT:{
             // Set to process only zerochain
             dap_chain_id_t l_chain_id = {{0}};
-            dap_chain_t * l_chain = dap_chain_find_by_id(l_net->pub.id,l_chain_id);
-            if (l_chain )
-               l_chain->is_datum_pool_proc = true;
+            dap_chain_t *l_chain = dap_chain_find_by_id(l_net->pub.id, l_chain_id);
+            if (l_chain)
+                l_chain->is_datum_pool_proc = true;
             log_it(L_INFO,"Root node role established");
         } break;
         case NODE_ROLE_CELL_MASTER:
         case NODE_ROLE_MASTER:{
             uint16_t l_proc_chains_count=0;
-            char ** l_proc_chains = dap_config_get_array_str(l_cfg,"role-master" , "proc_chains", &l_proc_chains_count );
-            for ( size_t i = 0; i< l_proc_chains_count ; i++) {
+            char **l_proc_chains = dap_config_get_array_str(l_cfg, "role-master", "proc_chains", &l_proc_chains_count);
+            for (size_t i = 0; i< l_proc_chains_count ; i++) {
                 dap_chain_id_t l_chain_id = {};
                 if (dap_chain_id_parse(l_proc_chains[i], &l_chain_id) == 0) {
-                    dap_chain_t * l_chain = dap_chain_find_by_id(l_net->pub.id, l_chain_id );
+                    dap_chain_t *l_chain = dap_chain_find_by_id(l_net->pub.id, l_chain_id );
                     if (l_chain)
                         l_chain->is_datum_pool_proc = true;
                     else
@@ -2232,10 +2207,11 @@ int s_net_load(dap_chain_net_t *a_net)
                                                     l_net->pub.name, dap_guuid_compose(l_net->pub.id.uint64, 0),
                                                     l_gdb_groups_mask, DAP_CHAIN_NET_MEMPOOL_TTL, true,
                                                     DAP_GDB_MEMBER_ROLE_USER,
-                                                    DAP_CLUSTER_ROLE_EMBEDDED);
+                                                    DAP_CLUSTER_TYPE_EMBEDDED);
         if (!l_cluster) {
             log_it(L_ERROR, "Can't initialize mempool cluster for network %s", l_net->pub.name);
-            return -1;
+            l_err_code = -2;
+            goto ret;
         }
         dap_chain_net_add_auth_nodes_to_cluster(l_net, l_cluster);
         DAP_DELETE(l_gdb_groups_mask);
@@ -2248,10 +2224,10 @@ int s_net_load(dap_chain_net_t *a_net)
                                                           l_net->pub.name, dap_guuid_compose(l_net->pub.id.uint64, 0),
                                                           l_gdb_groups_mask, 0, true,
                                                           DAP_GDB_MEMBER_ROLE_GUEST,
-                                                          DAP_CLUSTER_ROLE_EMBEDDED);
+                                                          DAP_CLUSTER_TYPE_EMBEDDED);
     if (!l_net_pvt->orders_cluster) {
         log_it(L_ERROR, "Can't initialize orders cluster for network %s", l_net->pub.name);
-        return -1;
+        goto ret;
     }
     dap_chain_net_add_auth_nodes_to_cluster(l_net, l_net_pvt->orders_cluster);
     DAP_DELETE(l_gdb_groups_mask);
@@ -2262,7 +2238,7 @@ int s_net_load(dap_chain_net_t *a_net)
         l_net->pub.name, dap_guuid_compose(l_net->pub.id.uint64, 0),
         l_gdb_groups_mask, 0, true,
         DAP_GDB_MEMBER_ROLE_USER,
-        DAP_CLUSTER_ROLE_EMBEDDED);
+        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);
@@ -2270,10 +2246,11 @@ int s_net_load(dap_chain_net_t *a_net)
                                                          l_net->pub.name, dap_guuid_compose(l_net->pub.id.uint64, 0),
                                                          l_net->pub.gdb_nodes, 0, true,
                                                          DAP_GDB_MEMBER_ROLE_GUEST,
-                                                         DAP_CLUSTER_ROLE_EMBEDDED);
+                                                         DAP_CLUSTER_TYPE_EMBEDDED);
     if (!l_net_pvt->nodes_cluster) {
         log_it(L_ERROR, "Can't initialize nodes cluster for network %s", l_net->pub.name);
-        return -1;
+        l_err_code = -3;
+        goto ret;
     }
     dap_chain_net_add_auth_nodes_to_cluster(l_net, l_net_pvt->nodes_cluster);
     dap_chain_net_add_nodelist_notify_callback(l_net, s_nodelist_change_notify, l_net);
@@ -2342,10 +2319,17 @@ int s_net_load(dap_chain_net_t *a_net)
     l_net_pvt->sync_context.sync_idle_time = dap_config_get_item_uint32_default(g_config, "chain", "sync_idle_time", 60);
     dap_proc_thread_timer_add(NULL, s_sync_timer_callback, l_net, 1000);
 
-    log_it(L_INFO, "Chain network \"%s\" initialized",l_net->pub.name);
-    dap_config_close(l_cfg);
-
-    return 0;
+    log_it(L_INFO, "Chain network \"%s\" initialized", l_net->pub.name);
+ret:
+    if (l_err_code)
+        log_it(L_ERROR, "Loading chains of net %s finished with (%d) error code.", l_net->pub.name, l_err_code);
+    if (l_cfg)
+        dap_config_close(l_cfg);
+    pthread_mutex_lock(&s_net_cond_lock);
+    s_net_loading_count--;
+    pthread_cond_signal(&s_net_cond);
+    pthread_mutex_unlock(&s_net_cond_lock);
+    return false;
 }
 
 static const uint64_t s_fork_sync_step = 20; // TODO get it from config
@@ -2356,6 +2340,18 @@ static void s_ch_in_pkt_callback(dap_stream_ch_t *a_ch, uint8_t a_type, const vo
                                                            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);
+
+    switch (a_type) {
+    case DAP_CHAIN_CH_PKT_TYPE_CHAIN_SUMMARY:
+    case DAP_CHAIN_CH_PKT_TYPE_CHAIN_MISS:
+    case DAP_CHAIN_CH_PKT_TYPE_CHAIN:
+    case DAP_CHAIN_CH_PKT_TYPE_SYNCED_CHAIN:
+        // TODO sync state & address checking
+        break;
+    default:
+        break;
+    }
+
     switch (a_type) {
     case DAP_CHAIN_CH_PKT_TYPE_ERROR:
         l_net_pvt->sync_context.state = SYNC_STATE_ERROR;
@@ -2373,11 +2369,11 @@ static void s_ch_in_pkt_callback(dap_stream_ch_t *a_ch, uint8_t a_type, const vo
             log_it(L_WARNING, "Get irrelevant chain sync MISSED packet with missed hash %s, but requested hash is %s",
                                                                         l_missed_hash_str,
                                                                         dap_hash_fast_to_str_static(&l_net_pvt->sync_context.requested_atom_hash));
-            dap_stream_ch_write_error_unsafe(a_ch, l_net->pub.id.uint64,
-                                             l_net_pvt->sync_context.cur_chain->id.uint64,
+            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
-                                             ? l_net_pvt->sync_context.cur_cell->id.uint64
-                                             : 0,
+                                             ? l_net_pvt->sync_context.cur_cell->id
+                                             : c_dap_chain_cell_id_null,
                                              DAP_CHAIN_CH_ERROR_INCORRECT_SYNC_SEQUENCE);
             return;
         }
@@ -2388,12 +2384,12 @@ static void s_ch_in_pkt_callback(dap_stream_ch_t *a_ch, uint8_t a_type, const vo
                                                                             : c_dap_chain_cell_id_null,
                                                                             NULL, false);
         if (!l_iter) {
-            log_it(L_CRITICAL, g_error_memory_alloc);
-            dap_stream_ch_write_error_unsafe(a_ch, l_net->pub.id.uint64,
-                                             l_net_pvt->sync_context.cur_chain->id.uint64,
+            log_it(L_CRITICAL, "%s", g_error_memory_alloc);
+            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
-                                             ? l_net_pvt->sync_context.cur_cell->id.uint64
-                                             : 0,
+                                             ? l_net_pvt->sync_context.cur_cell->id
+                                             : c_dap_chain_cell_id_null,
                                              DAP_CHAIN_CH_ERROR_OUT_OF_MEMORY);
             return;
         }
@@ -2419,13 +2415,14 @@ static void s_ch_in_pkt_callback(dap_stream_ch_t *a_ch, uint8_t a_type, const vo
                                                         dap_hash_fast_to_str_static(&l_request.hash_from), l_request.num_from);
         dap_chain_ch_pkt_write_unsafe(a_ch,
                                       DAP_CHAIN_CH_PKT_TYPE_CHAIN_REQ,
-                                      l_net->pub.id.uint64,
-                                      l_net_pvt->sync_context.cur_chain->id.uint64,
+                                      l_net->pub.id,
+                                      l_net_pvt->sync_context.cur_chain->id,
                                       l_net_pvt->sync_context.cur_cell
-                                      ? l_net_pvt->sync_context.cur_cell->id.uint64
-                                      : 0,
+                                      ? l_net_pvt->sync_context.cur_cell->id
+                                      : c_dap_chain_cell_id_null,
                                       &l_request,
-                                      sizeof(l_request));
+                                      sizeof(l_request),
+                                      DAP_CHAIN_CH_PKT_VERSION_CURRENT);
         l_net_pvt->sync_context.requested_atom_hash = l_request.hash_from;
         l_net_pvt->sync_context.requested_atom_num = l_request.num_from;
     }
@@ -2496,6 +2493,12 @@ static void s_sync_timer_callback(void *a_arg)
         }
         // TODO make correct working with cells
         assert(l_net_pvt->sync_context.cur_chain);
+        if (l_net_pvt->sync_context.cur_chain->callback_load_from_gdb) {
+            // This type of chain is GDB based and not synced by chains protocol
+            l_net_pvt->sync_context.cur_chain = l_net_pvt->sync_context.cur_chain->next;
+            l_net_pvt->sync_context.last_state = SYNC_STATE_SYNCED;
+            return;
+        }
         l_net_pvt->sync_context.cur_cell = l_net_pvt->sync_context.cur_chain->cells;
         l_net_pvt->sync_context.state = l_net_pvt->sync_context.last_state = SYNC_STATE_WAITING;
         dap_chain_ch_sync_request_t l_request = {};
@@ -2511,11 +2514,11 @@ static void s_sync_timer_callback(void *a_arg)
             return;
         }
         l_request.num_from = l_last_num;
-        dap_chain_ch_pkt_t *l_chain_pkt = dap_chain_ch_pkt_new(l_net->pub.id.uint64, l_net_pvt->sync_context.cur_chain->id.uint64,
-                                                               l_net_pvt->sync_context.cur_cell ? l_net_pvt->sync_context.cur_cell->id.uint64 : 0,
-                                                               &l_request, sizeof(l_request));
+        dap_chain_ch_pkt_t *l_chain_pkt = dap_chain_ch_pkt_new(l_net->pub.id, l_net_pvt->sync_context.cur_chain->id,
+                                                               l_net_pvt->sync_context.cur_cell ? l_net_pvt->sync_context.cur_cell->id : c_dap_chain_cell_id_null,
+                                                               &l_request, sizeof(l_request), DAP_CHAIN_CH_PKT_VERSION_CURRENT);
         if (!l_chain_pkt) {
-            log_it(L_CRITICAL, g_error_memory_alloc);
+            log_it(L_CRITICAL, "%s", g_error_memory_alloc);
             return;
         }
         log_it(L_INFO, "Start synchronization process with " NODE_ADDR_FP_STR
@@ -2963,7 +2966,7 @@ static bool s_net_check_acl(dap_chain_net_t *a_net, dap_chain_hash_fast_t *a_pke
 {
     const char l_path[] = "network/";
     char l_cfg_path[strlen(a_net->pub.name) + strlen(l_path) + 1];
-    dap_snprintf(l_cfg_path, sizeof(l_cfg_path), "%s%s", l_path, a_net->pub.name);
+    snprintf(l_cfg_path, sizeof(l_cfg_path), "%s%s", l_path, a_net->pub.name);
     dap_config_t *l_cfg = dap_config_open(l_cfg_path);
     const char *l_auth_type = dap_config_get_item_str(l_cfg, "auth", "type");
     bool l_authorized = true;
diff --git a/modules/net/dap_chain_net_anchor.c b/modules/net/dap_chain_net_anchor.c
index 4012dda4c1840a201af448b5bb93cdd79f3b9fec..3fdea387b5362f1fdfb86ff053b42e26c1d49e54 100644
--- a/modules/net/dap_chain_net_anchor.c
+++ b/modules/net/dap_chain_net_anchor.c
@@ -25,7 +25,6 @@
 #include <assert.h>
 #include "dap_common.h"
 #include "dap_sign.h"
-#include "dap_cert.h"
 #include "dap_pkey.h"
 #include "dap_chain.h"
 #include "dap_chain_cell.h"
@@ -33,6 +32,9 @@
 #include "dap_chain_ledger.h"
 #include "dap_chain_datum_decree.h"
 #include "dap_chain_net_srv_stake_pos_delegate.h"
+#include "dap_chain_net.h"
+#include "dap_chain_net_decree.h"
+#include "dap_chain_datum_anchor.h"
 
 #define LOG_TAG "chain_net_anchor"
 
diff --git a/modules/net/dap_chain_net_balancer.c b/modules/net/dap_chain_net_balancer.c
index 591778a033598775ac23700b6b1ed2aad8bbad78..1c0ed5b4ce56a3023ecdeb22c1f1f5e351f9a199 100644
--- a/modules/net/dap_chain_net_balancer.c
+++ b/modules/net/dap_chain_net_balancer.c
@@ -29,7 +29,9 @@ along with any CellFrame SDK based project.  If not, see <http://www.gnu.org/lic
 #include "http_status_code.h"
 #include "dap_chain_node_client.h"
 #include "dap_chain_node_dns_client.h"
-#include "rand/dap_rand.h"
+#include "dap_net.h"
+#include "dap_client_http.h"
+#include "dap_enc_base64.h"
 #include "dap_notify_srv.h"
 
 #define LOG_TAG "dap_chain_net_balancer"
@@ -153,7 +155,7 @@ static void s_balancer_link_prepare_error(dap_balancer_link_request_t *a_request
 {
     struct json_object *l_json = s_balancer_states_json_collect(a_request->net, a_host_addr, a_host_port);
     char l_err_str[512] = { '\0' };
-    dap_snprintf(l_err_str, sizeof(l_err_str)
+    snprintf(l_err_str, sizeof(l_err_str)
                  , "Link from balancer %s can't be prepared, errno %d"
                  , a_host_addr, a_errno);
     log_it(L_WARNING, "%s", l_err_str);
@@ -511,4 +513,4 @@ dap_string_t *dap_chain_net_balancer_get_node_str(dap_chain_net_t *a_net)
     dap_string_append(l_ret, "-----------------------------------------------------------------\n");
     DAP_DEL_Z(l_links_info_list);
     return l_ret;
-}
\ No newline at end of file
+}
diff --git a/modules/net/dap_chain_net_decree.c b/modules/net/dap_chain_net_decree.c
index 7069b07a373784216445536e8f3e115bc263a9c0..b805446d2a36bf5296659e9ebdb1001a7a30f65c 100644
--- a/modules/net/dap_chain_net_decree.c
+++ b/modules/net/dap_chain_net_decree.c
@@ -25,12 +25,11 @@
 #include <assert.h>
 #include "dap_common.h"
 #include "dap_sign.h"
-#include "dap_cert.h"
 #include "dap_pkey.h"
 #include "dap_chain_common.h"
 #include "dap_chain_net.h"
 #include "dap_chain_net_decree.h"
-#include "dap_chain_net_srv.h"
+#include "dap_chain_cs_esbocs.h"
 #include "dap_chain_net_tx.h"
 #include "dap_chain_net_srv_stake_pos_delegate.h"
 #include "dap_http_ban_list_client.h"
@@ -198,7 +197,7 @@ static int s_decree_verify(dap_chain_net_t *a_net, dap_chain_datum_decree_t *a_d
     DAP_DELETE(l_unique_signs);
 
     if (l_signs_verify_counter < l_min_signs) {
-        log_it(L_WARNING,"Not enough valid signatures, get %hu from %hu", l_signs_verify_counter, l_min_signs);
+        log_it(L_WARNING, "Not enough valid signatures, get %hu from %hu", l_signs_verify_counter, l_min_signs);
         return -107;
     }
 
@@ -367,12 +366,15 @@ 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)
 {
-    uint256_t l_uint256_buffer;
-    uint16_t l_uint16_buffer;
-    dap_chain_addr_t l_addr = {}; //????????
+    uint256_t l_value;
+    uint32_t l_sign_type;
+    uint16_t l_owners_num;
+    uint8_t l_action;
+    dap_chain_addr_t l_addr = {};
     dap_hash_fast_t l_hash = {};
     dap_chain_node_addr_t l_node_addr = {};
     dap_list_t *l_owners_list = NULL;
+    const char *l_ban_addr;
 
     dap_return_val_if_fail(a_decree && a_net, -112);
 
@@ -386,17 +388,17 @@ static int s_common_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain
                     } else
                         l_addr = a_net->pub.fee_addr;
                 }
-                if (dap_chain_datum_decree_get_fee(a_decree, &l_uint256_buffer)) {
+                if (dap_chain_datum_decree_get_fee(a_decree, &l_value)) {
                     log_it(L_WARNING,"Can't get fee value from decree.");
                     return -103;
                 }
                 if (!a_apply)
                     break;
-                if (!dap_chain_net_tx_set_fee(a_net->pub.id, l_uint256_buffer, l_addr))
+                if (!dap_chain_net_tx_set_fee(a_net->pub.id, l_value, l_addr))
                     log_it(L_ERROR, "Can't set fee value for network %s", a_net->pub.name);
             break;
         case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_OWNERS:
-            l_owners_list = dap_chain_datum_decree_get_owners(a_decree, &l_uint16_buffer);
+            l_owners_list = dap_chain_datum_decree_get_owners(a_decree, &l_owners_num);
             if (!l_owners_list){
                 log_it(L_WARNING,"Can't get ownners from decree.");
                 return -104;
@@ -405,26 +407,30 @@ static int s_common_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain
             if (!a_apply)
                 break;
 
-            a_net->pub.decree->num_of_owners = l_uint16_buffer;
+            a_net->pub.decree->num_of_owners = l_owners_num;
             dap_list_free_full(a_net->pub.decree->pkeys, NULL);
 
             a_net->pub.decree->pkeys = l_owners_list;
             break;
         case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_OWNERS_MIN:
-            if (dap_chain_datum_decree_get_min_owners(a_decree, &l_uint16_buffer)){
-                log_it(L_WARNING,"Can't get min number of ownners from decree.");
+            if (dap_chain_datum_decree_get_min_owners(a_decree, &l_value)) {
+                log_it(L_WARNING, "Can't get min number of ownners from decree.");
                 return -105;
             }
+            if (IS_ZERO_256(l_value) || compare256(l_value, GET_256_FROM_64(UINT16_MAX)) == 1) {
+                log_it(L_WARNING, "Illegal min number of owners %s", dap_uint256_to_char(l_value, NULL));
+                return -116;
+            }
             if (!a_apply)
                 break;
-            a_net->pub.decree->min_num_of_owners = l_uint16_buffer;
+            a_net->pub.decree->min_num_of_owners = dap_uint256_to_uint64(l_value);
             break;
         case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_APPROVE:
-            if (dap_chain_datum_decree_get_stake_tx_hash(a_decree, &l_hash)){
+            if (dap_chain_datum_decree_get_hash(a_decree, &l_hash)){
                 log_it(L_WARNING,"Can't get tx hash from decree.");
                 return -105;
             }
-            if (dap_chain_datum_decree_get_stake_value(a_decree, &l_uint256_buffer)){
+            if (dap_chain_datum_decree_get_stake_value(a_decree, &l_value)){
                 log_it(L_WARNING,"Can't get stake value from decree.");
                 return -106;
             }
@@ -446,7 +452,7 @@ static int s_common_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain
             }
             if (!a_apply)
                 break;
-            dap_chain_net_srv_stake_key_delegate(a_net, &l_addr, &l_hash, l_uint256_buffer, &l_node_addr);
+            dap_chain_net_srv_stake_key_delegate(a_net, &l_addr, &l_hash, l_value, &l_node_addr);
             break;
         case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_INVALIDATE:
             if (dap_chain_datum_decree_get_stake_signing_addr(a_decree, &l_addr)){
@@ -458,16 +464,16 @@ static int s_common_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain
             dap_chain_net_srv_stake_key_invalidate(&l_addr);
             break;
         case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_MIN_VALUE:
-            if (dap_chain_datum_decree_get_stake_min_value(a_decree, &l_uint256_buffer)){
+            if (dap_chain_datum_decree_get_stake_min_value(a_decree, &l_value)){
                 log_it(L_WARNING,"Can't get min stake value from decree.");
                 return -105;
             }
             if (!a_apply)
                 break;
-            dap_chain_net_srv_stake_set_allowed_min_value(l_uint256_buffer);
+            dap_chain_net_srv_stake_set_allowed_min_value(a_net->pub.id, l_value);
             break;
         case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_MIN_VALIDATORS_COUNT:
-            if (dap_chain_datum_decree_get_stake_min_signers_count(a_decree, &l_uint256_buffer)){
+            if (dap_chain_datum_decree_get_stake_min_signers_count(a_decree, &l_value)){
                 log_it(L_WARNING,"Can't get min stake value from decree.");
                 return -105;
             }
@@ -476,72 +482,44 @@ static int s_common_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain
                 log_it(L_WARNING, "Specified chain not found");
                 return -106;
             }
-            if (!l_chain->callback_set_min_validators_count) {
+            if (dap_strcmp(dap_chain_get_cs_type(l_chain), "esbocs")) {
                 log_it(L_WARNING, "Can't apply this decree to specified chain");
                 return -115;
             }
             if (!a_apply)
                 break;
-            l_chain->callback_set_min_validators_count(l_chain, (uint16_t)dap_chain_uint256_to(l_uint256_buffer));
+            dap_chain_esbocs_set_min_validators_count(l_chain, (uint16_t)dap_chain_uint256_to(l_value));
             break;
         case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_BAN: {
+            if (dap_chain_datum_decree_get_ban_addr(a_decree, &l_ban_addr)) {
+                log_it(L_WARNING, "Can't get ban address from decree.");
+                return -114;
+            }
+            if (dap_http_ban_list_client_check(l_ban_addr, NULL, NULL)) {
+                log_it(L_ERROR, "Can't ban addr %s: already banlisted", l_ban_addr);
+                return -112;
+            }
             if (!a_apply)
                 break;
-            size_t l_tsd_offset = 0, tsd_data_size = a_decree->header.data_size;
-            while(l_tsd_offset < tsd_data_size){
-                dap_tsd_t *l_tsd = (dap_tsd_t *)(a_decree->data_n_signs + l_tsd_offset);
-                size_t l_tsd_size = dap_tsd_size(l_tsd);
-                if(l_tsd_size > tsd_data_size){
-                    log_it(L_WARNING,"TSD size is greater than all data size. It's possible corrupt data.");
-                    return -2;
-                }
-                dap_hash_fast_t l_decree_hash = {0};
-                dap_hash_fast(a_decree, dap_chain_datum_decree_get_size(a_decree), &l_decree_hash);
-                char *l_addr = dap_tsd_get_string(l_tsd);
-                switch (l_tsd->type) {
-                case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_HOST:
-                case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_NODE_ADDR:
-                    if ( dap_http_ban_list_client_add(l_addr, l_decree_hash, a_decree->header.ts_created) ) {
-                        log_it(L_ERROR, "Can't ban addr %s: already banlisted", l_addr);
-                        return -4;
-                    } break;
-                default:
-                    log_it(L_WARNING, "Invalid section TSD type for sub-decree datum of type "
-                                      "DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_BAN.");
-                    return  -3;
-                }
-                l_tsd_offset += l_tsd_size;
-            }
+            dap_hash_fast_t l_decree_hash = {0};
+            dap_hash_fast(a_decree, dap_chain_datum_decree_get_size(a_decree), &l_decree_hash);
+            dap_http_ban_list_client_add(l_ban_addr, l_decree_hash, a_decree->header.ts_created);
         } break;
         case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_UNBAN: {
+            if (dap_chain_datum_decree_get_ban_addr(a_decree, &l_ban_addr)) {
+                log_it(L_WARNING, "Can't get ban address from decree.");
+                return -114;
+            }
+            if (!dap_http_ban_list_client_check(l_ban_addr, NULL, NULL)) {
+                log_it(L_ERROR, "Can't ban addr %s: already banlisted", l_ban_addr);
+                return -112;
+            }
             if (!a_apply)
                 break;
-            size_t l_tsd_offset = 0, tsd_data_size = a_decree->header.data_size;
-            while(l_tsd_offset < tsd_data_size){
-                dap_tsd_t *l_tsd = (dap_tsd_t *)(a_decree->data_n_signs + l_tsd_offset);
-                size_t l_tsd_size = dap_tsd_size(l_tsd);
-                if(l_tsd_size > tsd_data_size){
-                    log_it(L_WARNING,"TSD size is greater than all data size. It's possible corrupt data.");
-                    return -2;
-                }
-                char *l_addr = dap_tsd_get_string(l_tsd);
-                switch (l_tsd->type) {
-                case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_HOST:
-                case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_NODE_ADDR:
-                    if ( dap_http_ban_list_client_remove(l_addr) ) {
-                        log_it(L_ERROR, "Can't unban addr %s: not banlisted", l_addr);
-                        return -4;
-                    } break;
-                default:
-                    log_it(L_WARNING, "Invalid section TSD type for sub-decree datum of type "
-                                      "DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_BAN.");
-                    return  -3;
-                }
-                l_tsd_offset += l_tsd_size;
-            }
+            dap_http_ban_list_client_remove(l_ban_addr);
         } break;
         case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_REWARD: {
-            if (dap_chain_datum_decree_get_value(a_decree, &l_uint256_buffer)) {
+            if (dap_chain_datum_decree_get_value(a_decree, &l_value)) {
                 log_it(L_WARNING,"Can't get value from decree.");
                 return -103;
             }
@@ -550,10 +528,80 @@ static int s_common_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain
                 log_it(L_WARNING, "Specified chain not found");
                 return -106;
             }
+            if (dap_strcmp(dap_chain_get_cs_type(l_chain), "esbocs")) {
+                log_it(L_WARNING, "Can't apply this decree to specified chain");
+                return -115;
+            }
             if (!a_apply)
                 break;
             uint64_t l_cur_block_num = l_chain->callback_count_atom(l_chain);
-            dap_chain_net_add_reward(a_net, l_uint256_buffer, l_cur_block_num);
+            dap_chain_net_add_reward(a_net, l_value, l_cur_block_num);
+        } break;
+        case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_MAX_WEIGHT: {
+            if (dap_chain_datum_decree_get_value(a_decree, &l_value)) {
+                log_it(L_WARNING,"Can't get value from decree.");
+                return -103;
+            }
+            dap_chain_t *l_chain = dap_chain_find_by_id(a_net->pub.id, a_decree->header.common_decree_params.chain_id);
+            if (!l_chain) {
+                log_it(L_WARNING, "Specified chain not found");
+                return -106;
+            }
+            if (dap_strcmp(dap_chain_get_cs_type(l_chain), "esbocs")) {
+                log_it(L_WARNING, "Can't apply this decree to specified chain");
+                return -115;
+            }
+            if (compare256(l_value, dap_chain_coins_to_balance("1.0")) >= 0) {
+                log_it(L_WARNING, "Percent must be lower than 100%%");
+                return -116;
+            }
+            if (!a_apply)
+                break;
+            dap_chain_net_srv_stake_set_percent_max(a_net->pub.id, l_value);
+        } break;
+        case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_CHECK_SIGNS_STRUCTURE: {
+            if (dap_chain_datum_decree_get_action(a_decree, &l_action)) {
+                log_it(L_WARNING,"Can't get action from decree.");
+                return -103;
+            }
+            dap_chain_t *l_chain = dap_chain_find_by_id(a_net->pub.id, a_decree->header.common_decree_params.chain_id);
+            if (!l_chain) {
+                log_it(L_WARNING, "Specified chain not found");
+                return -106;
+            }
+            if (dap_strcmp(dap_chain_get_cs_type(l_chain), "esbocs")) {
+                log_it(L_WARNING, "Can't apply this decree to specified chain");
+                return -115;
+            }
+            if (!a_apply)
+                break;
+            dap_chain_esbocs_set_signs_struct_check(l_chain, l_action);
+        } break;
+        case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_EMERGENCY_VALIDATORS: {
+            if (dap_chain_datum_decree_get_action(a_decree, &l_action)) {
+                log_it(L_WARNING,"Can't get action from decree.");
+                return -103;
+            }
+            if (dap_chain_datum_decree_get_signature_type(a_decree, &l_sign_type)) {
+                log_it(L_WARNING,"Can't get signature type from decree.");
+                return -113;
+            }
+            if (dap_chain_datum_decree_get_hash(a_decree, &l_hash)){
+                log_it(L_WARNING,"Can't get validator hash from decree.");
+                return -105;
+            }
+            dap_chain_t *l_chain = dap_chain_find_by_id(a_net->pub.id, a_decree->header.common_decree_params.chain_id);
+            if (!l_chain) {
+                log_it(L_WARNING, "Specified chain not found");
+                return -106;
+            }
+            if (dap_strcmp(dap_chain_get_cs_type(l_chain), "esbocs")) {
+                log_it(L_WARNING, "Can't apply this decree to specified chain");
+                return -115;
+            }
+            if (!a_apply)
+                break;
+            dap_chain_esbocs_set_emergency_validator(l_chain, l_action, l_sign_type, &l_hash);
         } break;
         default:
             return -1;
diff --git a/modules/net/dap_chain_net_node_list.c b/modules/net/dap_chain_net_node_list.c
index 45a95c880653240d85e7f1e6f5b7bc26dc24a0fb..205a5bf2193ce6215302ad42108e1230eeedc2e3 100644
--- a/modules/net/dap_chain_net_node_list.c
+++ b/modules/net/dap_chain_net_node_list.c
@@ -105,7 +105,7 @@ void dap_chain_net_node_check_http_issue_link(dap_http_simple_t *a_http_simple,
         *l_return_code = Http_Status_MethodNotAllowed;
         return;
     }
-    char *l_key = dap_stream_node_addr_to_str_static( (dap_chain_node_addr_t){.uint64 = addr} );
+    const char *l_key = dap_stream_node_addr_to_str_static( (dap_chain_node_addr_t){.uint64 = addr} );
     if (!l_key) {
         log_it(L_ERROR, "Bad node address %zu", addr);
         *l_return_code = Http_Status_BadRequest;
diff --git a/modules/net/dap_chain_node.c b/modules/net/dap_chain_node.c
index fdfae11a181d1ecaedf5c6db630ae1342201614e..1500729a435cf319413ba9fd8102926d90135957 100644
--- a/modules/net/dap_chain_node.c
+++ b/modules/net/dap_chain_node.c
@@ -39,13 +39,11 @@
 #include <netinet/in.h>
 #endif
 
-#include "utlist.h"
 #include "dap_hash.h"
-#include "rand/dap_rand.h"
 #include "dap_chain_net.h"
 #include "dap_global_db.h"
 #include "dap_chain_node.h"
-#include "dap_chain_cell.h"
+#include "dap_chain_cs_esbocs.h"
 #include "dap_chain_ledger.h"
 
 #define LOG_TAG "dap_chain_node"
@@ -89,14 +87,14 @@ static void s_update_node_states_info(UNUSED_ARG void *a_arg)
             memcpy(l_info->links_addrs, l_linked_node_addrs, (l_info->uplinks_count + l_info->downlinks_count) * sizeof(dap_chain_node_addr_t));
             // DB write
             char *l_gdb_group = dap_strdup_printf("%s.nodes.states", l_net->pub.gdb_groups_prefix);
-            char *l_node_addr_str = dap_stream_node_addr_to_str_static(l_info->address);
+            const char *l_node_addr_str = dap_stream_node_addr_to_str_static(l_info->address);
             dap_global_db_set_sync(l_gdb_group, l_node_addr_str, l_info, l_info_size, false);
             DAP_DEL_MULTY(l_linked_node_addrs, l_info, l_gdb_group);
         }
     }
 }
 
-static void s_states_info_to_str(dap_chain_net_t *a_net, char *a_node_addr_str, dap_string_t *l_info_str)
+static void s_states_info_to_str(dap_chain_net_t *a_net, const char *a_node_addr_str, dap_string_t *l_info_str)
 {
 // sanity check
     dap_return_if_pass(!a_net || !a_node_addr_str || !l_info_str);
@@ -137,7 +135,7 @@ static void s_states_info_to_str(dap_chain_net_t *a_net, char *a_node_addr_str,
 dap_string_t *dap_chain_node_states_info_read(dap_chain_net_t *a_net, dap_stream_node_addr_t a_addr)
 {
     dap_string_t *l_ret = dap_string_new("");
-    char *l_node_addr_str = dap_stream_node_addr_to_str_static(a_addr.uint64 ? a_addr : g_node_addr);
+    const char *l_node_addr_str = dap_stream_node_addr_to_str_static(a_addr.uint64 ? a_addr : g_node_addr);
     if(!a_net) {
         for (dap_chain_net_t *l_net = dap_chain_net_iter_start(); l_net; l_net = dap_chain_net_iter_next(l_net)) {
             s_states_info_to_str(l_net, l_node_addr_str, l_ret);
@@ -227,7 +225,7 @@ int dap_chain_node_info_del(dap_chain_net_t *a_net, dap_chain_node_info_t *a_nod
  */
 dap_chain_node_info_t* dap_chain_node_info_read(dap_chain_net_t *a_net, dap_chain_node_addr_t *a_address)
 {
-    char *l_key = dap_stream_node_addr_to_str_static(*a_address);
+    const char *l_key = dap_stream_node_addr_to_str_static(*a_address);
     size_t l_node_info_size = 0;
     dap_chain_node_info_t *l_node_info
         = (dap_chain_node_info_t*)dap_global_db_get_sync(a_net->pub.gdb_nodes, l_key, &l_node_info_size, NULL, NULL);
@@ -302,7 +300,7 @@ void dap_chain_node_mempool_process_all(dap_chain_t *a_chain, bool a_force)
             if (dap_chain_node_mempool_need_process(a_chain, l_datum)) {
 
                 if (l_datum->header.type_id == DAP_CHAIN_DATUM_TX &&
-                        a_chain->callback_get_minimum_fee){
+                        !dap_strcmp(dap_chain_get_cs_type(a_chain), "esbocs")) {
                     uint256_t l_tx_fee = {};
                     dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t *)l_datum->data;
                     if (dap_chain_datum_tx_get_fee_value (l_tx, &l_tx_fee) ||
@@ -313,7 +311,7 @@ void dap_chain_node_mempool_process_all(dap_chain_t *a_chain, bool a_force)
                         } else
                             log_it(L_DEBUG, "Process service tx without fee");
                     } else {
-                        uint256_t l_min_fee = a_chain->callback_get_minimum_fee(a_chain);
+                        uint256_t l_min_fee = dap_chain_esbocs_get_fee(a_chain->net_id);
                         if (compare256(l_tx_fee, l_min_fee) < 0) {
                             char *l_tx_fee_str = dap_chain_balance_to_coins(l_tx_fee);
                             char *l_min_fee_str = dap_chain_balance_to_coins(l_min_fee);
diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c
index ee18fd50ca05fe7e50e01dee39e15ee9192e5894..68e8ce8e4cc3fbe1f9bd4f8891736d835a6d7da3 100644
--- a/modules/net/dap_chain_node_cli_cmd.c
+++ b/modules/net/dap_chain_node_cli_cmd.c
@@ -68,6 +68,7 @@
 #include "dap_cert_file.h"
 #include "dap_file_utils.h"
 #include "dap_enc_base58.h"
+#include "dap_enc_ks.h"
 #include "dap_chain_wallet.h"
 #include "dap_chain_wallet_internal.h"
 #include "dap_chain_node.h"
@@ -76,17 +77,13 @@
 #include "dap_chain_node_client.h"
 #include "dap_chain_node_cli_cmd.h"
 #include "dap_chain_node_cli_cmd_tx.h"
-#include "dap_chain_node_ping.h"
+#include "dap_net.h"
 #include "dap_chain_net_srv.h"
 #include "dap_chain_net_tx.h"
 #include "dap_chain_net_balancer.h"
-#include "dap_chain_block.h"
-#include "dap_chain_cs_blocks.h"
-
 #include "dap_chain_cell.h"
-
 #include "dap_enc_base64.h"
-#include "json.h"
+
 #ifdef DAP_OS_UNIX
 #include <dirent.h>
 #endif
@@ -98,25 +95,19 @@
 #include "dap_chain_ledger.h"
 #include "dap_chain_mempool.h"
 #include "dap_global_db.h"
-#include "dap_global_db_cluster.h"
 #include "dap_global_db_pkt.h"
-
-#include "dap_stream_ch_chain_net.h"
 #include "dap_chain_ch.h"
-#include "dap_stream_ch_chain_net_pkt.h"
 #include "dap_enc_base64.h"
-#include "dap_chain_net_srv_stake_pos_delegate.h"
 #include "dap_chain_net_node_list.h"
 
 #include "dap_json_rpc_errors.h"
-#include "dap_json_rpc_chain_datum.h"
 #include "dap_http_ban_list_client.h"
 #include "dap_chain_datum_tx_voting.h"
+#include "dap_enc_ks.h"
 
 
 #define LOG_TAG "chain_node_cli_cmd"
 
-static void s_dap_chain_net_purge(dap_chain_net_t *a_net);
 int _cmd_mempool_add_ca(dap_chain_net_t *a_net, dap_chain_t *a_chain, dap_cert_t *a_cert, void **a_str_reply);
 
 /**
@@ -382,31 +373,6 @@ static int s_node_info_list_with_reply(dap_chain_net_t *a_net, dap_chain_node_ad
     return l_ret;
 }
 
-/**
- * @brief purge ledger, stake, decree, all chains and remove chain files
- * @param a_net
- */
-void s_dap_chain_net_purge(dap_chain_net_t * a_net)
-{
-    if (!a_net)
-        return;
-    dap_chain_t *l_chain = NULL;
-    dap_ledger_purge(a_net->pub.ledger, false);
-    dap_chain_net_srv_stake_purge(a_net);
-    dap_chain_net_decree_purge(a_net);
-    DL_FOREACH(a_net->pub.chains, l_chain) {
-        if (l_chain->callback_purge)
-            l_chain->callback_purge(l_chain);
-        if (l_chain->callback_set_min_validators_count)
-            l_chain->callback_set_min_validators_count(l_chain, 0);
-        const char *l_chains_rm_path = dap_chain_get_path(l_chain);
-        dap_rm_rf(l_chains_rm_path);
-        a_net->pub.fee_value = uint256_0;
-        a_net->pub.fee_addr = c_dap_chain_addr_blank;
-        dap_chain_load_all(l_chain);
-    }
-}
-
 /**
  * @brief com_global_db
  * global_db command
@@ -455,7 +421,8 @@ int com_global_db(int a_argc, char ** a_argv, void **a_str_reply)
         dap_chain_t * l_chain = NULL;
         dap_chain_net_t * l_net = NULL;
 
-        if(dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index, a_argc, a_argv, a_str_reply, &l_chain, &l_net) < 0)
+        if(dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index, a_argc, a_argv, a_str_reply, &l_chain, &l_net,
+                                                         CHAIN_TYPE_INVALID) < 0)
             return -11;
 
         const char *l_cell_str = NULL, *l_chain_str = NULL;
@@ -813,7 +780,7 @@ int com_global_db(int a_argc, char ** a_argv, void **a_str_reply)
         size_t l_count = 0;
         for (dap_list_t *l_list = l_group_list; l_list; l_list = dap_list_next(l_list), ++l_count) {
             dap_string_append_printf(l_ret_str, "\t%-40s : %zu records\n", (char*)l_list->data,
-                                     dap_global_db_driver_count((char*)l_list->data, c_dap_global_db_driver_hash_blank));
+                                     dap_global_db_driver_count((char*)l_list->data, c_dap_global_db_driver_hash_blank, false));
         }
         dap_cli_server_cmd_set_reply_text(a_str_reply, "Group list:\n%sTotal count: %zu\n", l_ret_str->str, l_count);
         dap_string_free(l_ret_str, true);
@@ -828,9 +795,13 @@ int com_global_db(int a_argc, char ** a_argv, void **a_str_reply)
 
 static dap_tsd_t* s_chain_node_cli_com_node_create_tsd_addr(char **a_argv, int a_arg_start, int a_arg_end, void **a_str_reply, const char *a_specified_decree) {
     const char *l_ban_addr_str = NULL;
-    if (dap_cli_server_cmd_find_option_val(a_argv, a_arg_start, a_arg_end, "-addr", &l_ban_addr_str))
-        return dap_tsd_create_string(DAP_CHAIN_DATUM_DECREE_TSD_TYPE_NODE_ADDR, l_ban_addr_str);
-    else if (dap_cli_server_cmd_find_option_val(a_argv, a_arg_start, a_arg_end, "-host", &l_ban_addr_str))
+    if (dap_cli_server_cmd_find_option_val(a_argv, a_arg_start, a_arg_end, "-addr", &l_ban_addr_str)) {
+        dap_chain_addr_t *l_format = dap_chain_addr_from_str(l_ban_addr_str);
+        if (!l_format)
+            return dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't convert the -addr option value to node address"), NULL;
+        DAP_DELETE(l_format);
+        return dap_tsd_create_string(DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STRING, l_ban_addr_str);
+    } else if (dap_cli_server_cmd_find_option_val(a_argv, a_arg_start, a_arg_end, "-host", &l_ban_addr_str))
         return dap_tsd_create_string(DAP_CHAIN_DATUM_DECREE_TSD_TYPE_HOST, l_ban_addr_str);
     else
         return dap_cli_server_cmd_set_reply_text(a_str_reply, "The -host or -addr option was not "
@@ -891,7 +862,7 @@ int com_node(int a_argc, char ** a_argv, void **a_str_reply)
     // find net
     dap_chain_net_t *l_net = NULL;
 
-    if(dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index, a_argc, a_argv, a_str_reply, NULL, &l_net) < 0) {
+    if(dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index, a_argc, a_argv, a_str_reply, NULL, &l_net, CHAIN_TYPE_INVALID) < 0) {
         if (cmd_num != CMD_BANLIST && cmd_num != CMD_CONNECTIONS && cmd_num != CMD_DUMP)
             return -11;
     }
@@ -1259,6 +1230,7 @@ int com_node(int a_argc, char ** a_argv, void **a_str_reply)
     } break;
 
     case CMD_CONNECTIONS: {
+
         if (l_net) {
             dap_cluster_t *l_links_cluster = dap_cluster_by_mnemonim(l_net->pub.name);
             if (!l_links_cluster) {
@@ -1271,8 +1243,14 @@ int com_node(int a_argc, char ** a_argv, void **a_str_reply)
             dap_cluster_t *l_cluster = NULL;
             dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-cluster", &l_guuid_str);
             if (l_guuid_str) {
-                dap_guuid_t l_guuid = dap_guuid_from_hex_str(l_guuid_str);
+                bool l_success = false;
+                dap_guuid_t l_guuid = dap_guuid_from_hex_str(l_guuid_str, &l_success);
+                if (!l_success) {
+                    dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't parse cluster guid %s", l_guuid_str);
+                    break;
+                }
                 l_cluster = dap_cluster_find(l_guuid);
+                
                 if (!l_cluster) {
                     dap_cli_server_cmd_set_reply_text(a_str_reply, "Not found cluster with ID %s", l_guuid_str);
                     break;
@@ -1285,7 +1263,8 @@ int com_node(int a_argc, char ** a_argv, void **a_str_reply)
     case  CMD_BAN: {
         dap_chain_net_t *l_netl = NULL;
         dap_chain_t *l_chain = NULL;
-        if(dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index, a_argc, a_argv, a_str_reply, &l_chain, &l_netl) < 0)
+        if(dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index, a_argc, a_argv, a_str_reply, &l_chain, &l_netl,
+                                                         CHAIN_TYPE_DECREE) < 0)
             return -11;
         const char * l_hash_out_type = NULL;
         dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-H", &l_hash_out_type);
@@ -1347,7 +1326,8 @@ int com_node(int a_argc, char ** a_argv, void **a_str_reply)
     case CMD_UNBAN: {
         dap_chain_net_t *l_netl = NULL;
         dap_chain_t *l_chain = NULL;
-        if(dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index, a_argc, a_argv, a_str_reply, &l_chain, &l_netl) < 0)
+        if(dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index, a_argc, a_argv, a_str_reply, &l_chain, &l_net,
+                                                         CHAIN_TYPE_DECREE) < 0)
             return -11;
         const char * l_hash_out_type = NULL;
         dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-H", &l_hash_out_type);
@@ -1842,10 +1822,10 @@ int l_arg_index = 1, l_rc, cmd_num = CMD_NONE;
 
                         if (l_wallet) {
                             l_addr = l_net ? dap_chain_wallet_get_addr(l_wallet, l_net->pub.id) : NULL;
-                            char *l_addr_str = dap_chain_addr_to_str(l_addr);
+                            const char *l_addr_str = dap_chain_addr_to_str(l_addr);
                             json_object_object_add(json_obj_wall, "Wallet", json_object_new_string(l_file_name));
                             if(l_wallet->flags & DAP_WALLET$M_FL_ACTIVE)
-                                json_object_object_add(json_obj_wall, "status", json_object_new_string("Active"));
+                                json_object_object_add(json_obj_wall, "status", json_object_new_string("active"));
                             else
                                 json_object_object_add(json_obj_wall, "status", json_object_new_string("not active"));
                             json_object_object_add(json_obj_wall, "sign_status", json_object_new_string(
@@ -1914,7 +1894,7 @@ int l_arg_index = 1, l_rc, cmd_num = CMD_NONE;
                 }
             }
             json_object * json_obj_wall = json_object_new_object();
-            char *l_l_addr_str = dap_chain_addr_to_str((dap_chain_addr_t*) l_addr);
+            const char *l_l_addr_str = dap_chain_addr_to_str((dap_chain_addr_t*) l_addr);
             if(l_wallet)
             {
                 json_object_object_add(json_obj_wall, "sign", json_object_new_string(
@@ -1935,7 +1915,7 @@ int l_arg_index = 1, l_rc, cmd_num = CMD_NONE;
                 if(l_l_addr_tokens[i]) {
                     json_object * j_balance_data = json_object_new_object();
                     uint256_t l_balance = dap_ledger_calc_balance(l_ledger, l_addr, l_l_addr_tokens[i]);
-                    char *l_balance_coins, *l_balance_datoshi = dap_uint256_to_char(l_balance, &l_balance_coins);
+                    const char *l_balance_coins, *l_balance_datoshi = dap_uint256_to_char(l_balance, &l_balance_coins);
                     json_object_object_add(j_balance_data, "balance", json_object_new_string(""));
                     json_object_object_add(j_balance_data, "coins", json_object_new_string(l_balance_coins));
                     json_object_object_add(j_balance_data, "datoshi", json_object_new_string(l_balance_datoshi));
@@ -2160,7 +2140,7 @@ int l_arg_index = 1, l_rc, cmd_num = CMD_NONE;
 
                     l_addr = l_net ? dap_chain_wallet_get_addr(l_wallet,l_net->pub.id ) : NULL;
 
-                    char *l_addr_str = dap_chain_addr_to_str(l_addr);
+                    const char *l_addr_str = dap_chain_addr_to_str(l_addr);
                     json_object * json_obj_wall = json_object_new_object();
                     json_object_object_add(json_obj_wall, "Wallet name", json_object_new_string(l_wallet->name));
                     json_object_object_add(json_obj_wall, "Sign type", json_object_new_string(l_sign_type_str));
@@ -2193,11 +2173,13 @@ typedef enum dap_chain_node_cli_cmd_values_parse_net_chain_err_to_json {
     DAP_CHAIN_NODE_CLI_CMD_VALUES_PARSE_NET_CHAIN_ERR_CHAIN_STR_IS_NULL = 105,
     DAP_CHAIN_NODE_CLI_CMD_VALUES_PARSE_NET_CHAIN_ERR_CONFIG_DEFAULT_DATUM = 106,
     DAP_CHAIN_NODE_CLI_CMD_VALUE_PARSE_CONVERT_BASE58_TO_ADDR_WALLET = 107,
-    DAP_CHAIN_NODE_CLI_CMD_VALUE_PARSE_FAST_AND_BASE58_ADDR
+    DAP_CHAIN_NODE_CLI_CMD_VALUE_PARSE_FAST_AND_BASE58_ADDR,
+    DAP_CHAIN_NODE_CLI_CMD_VALUE_PARSE_CAN_NOT_FIND_DEFAULT_CHAIN_WITH_TYPE
 } dap_chain_node_cli_cmd_values_parse_net_chain_err_to_json;
 int dap_chain_node_cli_cmd_values_parse_net_chain_for_json(int *a_arg_index, int a_argc,
                                                            char **a_argv,
-                                                           dap_chain_t **a_chain, dap_chain_net_t **a_net) {
+                                                           dap_chain_t **a_chain, dap_chain_net_t **a_net,
+                                                           dap_chain_type_t a_default_chain_type) {
     const char * l_chain_str = NULL;
     const char * l_net_str = NULL;
 
@@ -2250,13 +2232,15 @@ int dap_chain_node_cli_cmd_values_parse_net_chain_for_json(int *a_arg_index, int
                 dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_CMD_VALUES_PARSE_NET_CHAIN_ERR_CHAIN_NOT_FOUND, l_str_to_reply);
                 return DAP_CHAIN_NODE_CLI_CMD_VALUES_PARSE_NET_CHAIN_ERR_CHAIN_NOT_FOUND;
             }
-        }
-        else if (!strcmp(a_argv[0], "token_decl")  || !strcmp(a_argv[0], "token_decl_sign")) {
-            if (	(*a_chain = dap_chain_net_get_default_chain_by_chain_type(*a_net, CHAIN_TYPE_TOKEN)) == NULL )
-            {
-                dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_CMD_VALUES_PARSE_NET_CHAIN_ERR_CONFIG_DEFAULT_DATUM, "%s requires parameter '-chain' or set default datum "
-                                             "type in chain configuration file");
-                return DAP_CHAIN_NODE_CLI_CMD_VALUES_PARSE_NET_CHAIN_ERR_CONFIG_DEFAULT_DATUM;
+        } else if (a_default_chain_type != CHAIN_TYPE_INVALID) {
+            if ((*a_chain = dap_chain_net_get_default_chain_by_chain_type(*a_net, a_default_chain_type)) != NULL) {
+                return 0;
+            } else {
+                dap_json_rpc_error_add(
+                        DAP_CHAIN_NODE_CLI_CMD_VALUE_PARSE_CAN_NOT_FIND_DEFAULT_CHAIN_WITH_TYPE,
+                        "Unable to get the default chain of type %s for the network.", dap_chain_type_to_str(a_default_chain_type));
+                return DAP_CHAIN_NODE_CLI_CMD_VALUE_PARSE_CAN_NOT_FIND_DEFAULT_CHAIN_WITH_TYPE;
+
             }
         }
     }
@@ -2274,7 +2258,7 @@ int dap_chain_node_cli_cmd_values_parse_net_chain_for_json(int *a_arg_index, int
  * @return
  */
 int dap_chain_node_cli_cmd_values_parse_net_chain(int *a_arg_index, int a_argc, char **a_argv, void **a_str_reply,
-        dap_chain_t **a_chain, dap_chain_net_t **a_net)
+        dap_chain_t **a_chain, dap_chain_net_t **a_net, dap_chain_type_t a_default_chain_type)
 {
     const char * l_chain_str = NULL;
     const char * l_net_str = NULL;
@@ -2326,15 +2310,13 @@ int dap_chain_node_cli_cmd_values_parse_net_chain(int *a_arg_index, int a_argc,
                 dap_cli_server_cmd_set_reply_text(a_str_reply, "%s", l_str_to_reply);
                 return -103;
             }
-        }
-        else if (	!strcmp(a_argv[0], "token_decl")
-        ||			!strcmp(a_argv[0], "token_decl_sign")) {
-            if (	(*a_chain = dap_chain_net_get_default_chain_by_chain_type(*a_net, CHAIN_TYPE_TOKEN)) == NULL )
-            {
-                dap_cli_server_cmd_set_reply_text(a_str_reply,
-                                                  "%s requires parameter '-chain' or set default datum type in chain configuration file",
-                                                  a_argv[0]);
-                return -105;
+        } else if (a_default_chain_type != CHAIN_TYPE_INVALID) {
+            if ((*a_chain = dap_chain_net_get_default_chain_by_chain_type(*a_net, a_default_chain_type)) != NULL) {
+                return 0;
+            } else {
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "Unable to get the default chain of type %s for the network.",
+                                                  dap_chain_type_to_str(a_default_chain_type));
+                return -104;
             }
         } else {
             dap_cli_server_cmd_set_reply_text(a_str_reply, "%s requires parameter '-chain'", a_argv[0]);
@@ -2426,7 +2408,8 @@ int com_token_decl_sign(int a_argc, char **a_argv, void **a_str_reply)
         dap_chain_t * l_chain = NULL;
         dap_chain_net_t * l_net = NULL;
 
-        dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index, a_argc, a_argv, a_str_reply, &l_chain, &l_net);
+        dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index, a_argc, a_argv, a_str_reply, &l_chain, &l_net,
+                                                      CHAIN_TYPE_TOKEN);
         if(!l_net)
             return -1;
         else {
@@ -2488,7 +2471,7 @@ int com_token_decl_sign(int a_argc, char **a_argv, void **a_str_reply)
                 l_datum_token->signs_total = 0;
                 for (i = 1; i <= l_tmp_signs_total; i++){
                     dap_sign_t *l_sign = (dap_sign_t *)(l_datum_token->data_n_tsd + l_tsd_size + l_signs_size);
-                    if( dap_sign_verify(l_sign, l_datum_token, sizeof(*l_datum_token) + l_tsd_size) != 1) {
+                    if( dap_sign_verify(l_sign, l_datum_token, sizeof(*l_datum_token) + l_tsd_size) ) {
                         log_it(L_WARNING, "Wrong signature %zu for datum_token with key %s in mempool!", i, l_datum_hash_out_str);
                         dap_cli_server_cmd_set_reply_text(a_str_reply,
                                 "Datum %s with datum token has wrong signature %zu, break process and exit",
@@ -2623,7 +2606,7 @@ void s_com_mempool_list_print_for_chain(dap_chain_net_t * a_net, dap_chain_t * a
     size_t l_objs_count = 0;
     dap_global_db_obj_t * l_objs = dap_global_db_get_all_sync(l_gdb_group_mempool, &l_objs_count);
     json_object  *l_jobj_datums;
-    size_t l_offset = a_limit * a_offset;
+    size_t l_offset = a_offset;
     if (l_objs_count == 0 || l_objs_count < l_offset) {
         l_jobj_datums = json_object_new_null();
     } else {
@@ -2741,7 +2724,7 @@ void s_com_mempool_list_print_for_chain(dap_chain_net_t * a_net, dap_chain_t * a
                         dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t *) l_datum->data;
 
                         int l_ledger_rc = DAP_LEDGER_TX_CHECK_NULL_TX;
-                        const char *l_main_ticker = dap_ledger_tx_get_main_ticker(a_net->pub.ledger, l_tx,
+                        const char *l_main_ticker = dap_ledger_tx_calculate_main_ticker(a_net->pub.ledger, l_tx,
                                                                                   &l_ledger_rc);
                         char *l_ledger_rc_str = dap_ledger_tx_check_err_str(l_ledger_rc);
 
@@ -2928,7 +2911,7 @@ void s_com_mempool_list_print_for_chain(dap_chain_net_t * a_net, dap_chain_t * a
                                 dap_json_rpc_allocation_error;
                                 return;
                             }
-                            char *l_value_coins_str, *l_value_str = dap_uint256_to_char(l_value, &l_value_coins_str);
+                            const char *l_value_coins_str, *l_value_str = dap_uint256_to_char(l_value, &l_value_coins_str);
                             json_object_object_add(l_jobj_money, "value", json_object_new_string(l_value_str));
                             json_object_object_add(l_jobj_money, "coins", json_object_new_string(l_value_coins_str));
                             if (l_dist_token) {
@@ -3090,11 +3073,11 @@ void s_com_mempool_list_print_for_chain(dap_chain_net_t * a_net, dap_chain_t * a
                         if (l_wallet_addr && l_emi && dap_chain_addr_compare(l_wallet_addr, &l_emi->hdr.address))
                             datum_is_accepted_addr = true;
                         DAP_DELETE(l_emi);
-                        json_object_object_add(l_jobj_datum, "data", dap_chain_datum_data_to_json(l_datum));
+                        dap_chain_datum_dump_json(l_jobj_datum,l_datum,a_hash_out_type,a_net->pub.id);
                     }
                         break;
                     default:
-                        json_object_object_add(l_jobj_datum, "data", dap_chain_datum_data_to_json(l_datum));
+                        dap_chain_datum_dump_json(l_jobj_datum,l_datum,a_hash_out_type,a_net->pub.id);
                 }
             }
             if (l_wallet_addr) {
@@ -3340,8 +3323,10 @@ int _cmd_mempool_check(dap_chain_net_t *a_net, dap_chain_t *a_chain, const char
             json_object_object_add(l_obj_atom, "hash", l_jobj_atom_hash);
             json_object_object_add(l_obj_atom, "ledger_response_code", l_jobj_atom_err);
             json_object_object_add(l_jobj_datum, "atom", l_obj_atom);
-        }
-        json_object *l_datum_obj_inf = dap_chain_datum_to_json(l_datum);
+        }        
+
+        json_object *l_datum_obj_inf = json_object_new_object();
+        dap_chain_datum_dump_json(l_datum_obj_inf, l_datum, a_hash_out_type, a_net->pub.id);
         if (!l_datum_obj_inf) {
             if (!l_found_in_chains)
                 DAP_DELETE(l_datum);
@@ -3350,6 +3335,7 @@ int _cmd_mempool_check(dap_chain_net_t *a_net, dap_chain_t *a_chain, const char
                                     "Failed to serialize datum to JSON.");
             return DAP_JSON_RPC_ERR_CODE_SERIALIZATION_DATUM_TO_JSON;
         }
+        json_object_object_add(l_jobj_datum, "datum", l_datum_obj_inf);
         if (!l_found_in_chains)
             DAP_DELETE(l_datum);
         json_object_array_add(*a_json_reply, l_jobj_datum);
@@ -3638,15 +3624,12 @@ int _cmd_mempool_dump_from_group(dap_chain_net_id_t a_net_id, const char *a_grou
         return COM_DUMP_ERROR_LIST_CORRUPTED_SIZE;
     }
     if (!l_datum) {
-        char *l_msg_str = dap_strdup_printf("Error! Can't find datum %s in %s", a_datum_hash, a_group_gdb);
-        if (!l_msg_str) {
-            dap_json_rpc_allocation_error;
-            return -1;
-        }
-        json_object *l_jobj_message = json_object_new_string(l_msg_str);
+        dap_json_rpc_error_add(COM_DUMP_ERROR_LIST_CORRUPTED_SIZE, "Error! Can't find datum %s in %s", a_datum_hash, a_group_gdb);
         return COM_DUMP_ERROR_CAN_NOT_FIND_DATUM;
     }
-    json_object *l_jobj_datum = dap_chain_datum_to_json(l_datum);
+
+    json_object *l_jobj_datum = json_object_new_object();
+    dap_chain_datum_dump_json(l_jobj_datum, l_datum, a_hash_out_type, a_net_id);
     json_object_array_add(*a_json_reply, l_jobj_datum);
     return 0;
 }
@@ -3683,7 +3666,8 @@ int com_mempool(int a_argc, char **a_argv, void **a_str_reply)
     int arg_index = 1;
     dap_chain_net_t *l_net = NULL;
     dap_chain_t *l_chain = NULL;
-    enum _subcmd {SUBCMD_LIST, SUBCMD_PROC, SUBCMD_PROC_ALL, SUBCMD_DELETE, SUBCMD_ADD_CA, SUBCMD_CHECK, SUBCMD_DUMP};
+    enum _subcmd {SUBCMD_LIST, SUBCMD_PROC, SUBCMD_PROC_ALL, SUBCMD_DELETE, SUBCMD_ADD_CA, SUBCMD_CHECK, SUBCMD_DUMP,
+            SUBCMD_COUNT};
     enum _subcmd l_cmd = 0;
     if (a_argv[1]) {
         if (!dap_strcmp(a_argv[1], "list")) {
@@ -3700,8 +3684,10 @@ int com_mempool(int a_argc, char **a_argv, void **a_str_reply)
             l_cmd = SUBCMD_DUMP;
         } else if (!dap_strcmp(a_argv[1], "check")) {
             l_cmd = SUBCMD_CHECK;
+        } else if (!dap_strcmp(a_argv[1], "count")) {
+            l_cmd = SUBCMD_COUNT;
         } else {
-            char *l_str_err = dap_strdup_printf("Invalid sub command specified. Ыub command %s "
+            char *l_str_err = dap_strdup_printf("Invalid sub command specified. Sub command %s "
                                                            "is not supported.", a_argv[1]);
             if (!l_str_err) {
                 dap_json_rpc_allocation_error;
@@ -3717,7 +3703,7 @@ int com_mempool(int a_argc, char **a_argv, void **a_str_reply)
             return -2;
         }
     }
-    dap_chain_node_cli_cmd_values_parse_net_chain_for_json(&arg_index, a_argc, a_argv, &l_chain, &l_net);
+    dap_chain_node_cli_cmd_values_parse_net_chain_for_json(&arg_index, a_argc, a_argv, &l_chain, &l_net, CHAIN_TYPE_INVALID);
     const char *l_hash_out_type = "hex";
     dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-H", &l_hash_out_type);
     const char *l_datum_hash_in = NULL;
@@ -3771,7 +3757,7 @@ int com_mempool(int a_argc, char **a_argv, void **a_str_reply)
             const char *l_limit_str = NULL, *l_offset_str = NULL;
             dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-limit", &l_limit_str);
             dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-offset", &l_offset_str);
-            l_limit = l_limit_str ? strtoul(l_limit_str, NULL, 10) : 0;
+            l_limit = l_limit_str ? strtoul(l_limit_str, NULL, 10) : 1000;
             l_offset = l_offset_str ? strtoul(l_offset_str, NULL, 10) : 0;
             if(l_chain) {
                 s_com_mempool_list_print_for_chain(l_net, l_chain, l_wallet_addr, l_jobj_chains, l_hash_out_type, l_fast, l_limit, l_offset);
@@ -3823,6 +3809,72 @@ int com_mempool(int a_argc, char **a_argv, void **a_str_reply)
         case SUBCMD_DUMP: {
             ret = _cmd_mempool_dump(l_net, l_chain, l_datum_hash, l_hash_out_type, a_json_reply);
         } break;
+        case SUBCMD_COUNT: {
+            char *l_mempool_group;
+            json_object *obj_ret = json_object_new_object();
+            json_object *obj_net = json_object_new_string(l_net->pub.name);
+            if (!obj_ret || !obj_net) {
+                json_object_put(obj_ret);
+                json_object_put(obj_net);
+                dap_json_rpc_allocation_error;
+                return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED;
+            }
+            json_object_object_add(obj_ret, "net", obj_net);
+            json_object *l_jobj_chains = json_object_new_array();
+            if (!l_jobj_chains) {
+                json_object_put(obj_ret);
+                dap_json_rpc_allocation_error;
+                return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED;
+            }
+            if(l_chain) {
+                l_mempool_group = dap_chain_net_get_gdb_group_mempool_new(l_chain);
+                size_t l_objs_count = 0;
+                dap_global_db_obj_t *l_objs = dap_global_db_get_all_sync(l_mempool_group, &l_objs_count);
+                dap_global_db_objs_delete(l_objs, l_objs_count);
+                DAP_DELETE(l_mempool_group);
+                json_object *l_jobj_chain = json_object_new_object();
+                json_object *l_jobj_chain_name = json_object_new_string(l_chain->name);
+                json_object *l_jobj_count = json_object_new_uint64(l_objs_count);
+                if (!l_jobj_chain || !l_jobj_chain_name || !l_jobj_count) {
+                    json_object_put(l_jobj_chains);
+                    json_object_put(l_jobj_chain);
+                    json_object_put(l_jobj_chain_name);
+                    json_object_put(l_jobj_count);
+                    json_object_put(obj_ret);
+                    dap_json_rpc_allocation_error;
+                    return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED;
+                }
+                json_object_object_add(l_jobj_chain, "name", l_jobj_chain_name);
+                json_object_object_add(l_jobj_chain, "count", l_jobj_count);
+                json_object_array_add(l_jobj_chains, l_jobj_chain);
+            } else {
+                DL_FOREACH(l_net->pub.chains, l_chain) {
+                    l_mempool_group = dap_chain_net_get_gdb_group_mempool_new(l_chain);
+                    size_t l_objs_count = 0;
+                    dap_global_db_obj_t *l_objs = dap_global_db_get_all_sync(l_mempool_group, &l_objs_count);
+                    dap_global_db_objs_delete(l_objs, l_objs_count);
+                    DAP_DELETE(l_mempool_group);
+                    json_object *l_jobj_chain = json_object_new_object();
+                    json_object *l_jobj_chain_name = json_object_new_string(l_chain->name);
+                    json_object *l_jobj_count = json_object_new_uint64(l_objs_count);
+                    if (!l_jobj_chain || !l_jobj_chain_name || !l_jobj_count) {
+                        json_object_put(l_jobj_chains);
+                        json_object_put(l_jobj_chain);
+                        json_object_put(l_jobj_chain_name);
+                        json_object_put(l_jobj_count);
+                        json_object_put(obj_ret);
+                        dap_json_rpc_allocation_error;
+                        return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED;
+                    }
+                    json_object_object_add(l_jobj_chain, "name", l_jobj_chain_name);
+                    json_object_object_add(l_jobj_chain, "count", l_jobj_count);
+                    json_object_array_add(l_jobj_chains, l_jobj_chain);
+                }
+            }
+            json_object_object_add(obj_ret, "chains", l_jobj_chains);
+            json_object_array_add(*a_json_reply, obj_ret);
+            ret = 0;
+        } break;
     }
     DAP_DEL_Z(l_datum_hash);
     return ret;
@@ -3914,7 +3966,8 @@ static int s_parse_common_token_decl_arg(int a_argc, char ** a_argv, void **a_st
     }
 
     int l_arg_index = 0;
-    int l_res = dap_chain_node_cli_cmd_values_parse_net_chain(&l_arg_index, a_argc, a_argv, a_str_reply, &a_params->chain, &a_params->net);
+    int l_res = dap_chain_node_cli_cmd_values_parse_net_chain(&l_arg_index, a_argc, a_argv, a_str_reply,
+                                                              &a_params->chain, &a_params->net, CHAIN_TYPE_TOKEN);
 
     if(!a_params->net || !a_params->chain)
         return l_res;
@@ -4096,8 +4149,7 @@ static int s_parse_additional_token_decl_arg(int a_argc, char ** a_argv, void **
         DAP_DEL_Z(l_new_certs);
     }
     if (l_description_token) {
-        dap_tsd_t *l_desc_token = dap_tsd_create(DAP_CHAIN_DATUM_TOKEN_TSD_TOKEN_DESCRIPTION, l_description_token,
-                                                 dap_strlen(l_description_token));//dap_tsd_create_string(DAP_CHAIN_DATUM_TOKEN_TSD_TOKEN_DESCRIPTION, l_description_token);
+        dap_tsd_t *l_desc_token = dap_tsd_create_string(DAP_CHAIN_DATUM_TOKEN_TSD_TOKEN_DESCRIPTION, l_description_token);
         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);
@@ -4301,6 +4353,12 @@ int com_token_decl(int a_argc, char ** a_argv, void **a_str_reply)
                     DAP_DEL_Z(l_params);
 					return -91;
 				}
+                if (!dap_strcmp(l_ticker, l_params->ext.delegated_token_from)) {
+                    dap_cli_server_cmd_set_reply_text(a_str_reply, "Delegated token ticker cannot match the original ticker");
+                    DAP_DEL_Z(l_params);
+                    return -92;
+                }
+
 				dap_chain_datum_token_tsd_delegate_from_stake_lock_t l_tsd_section;
                 strcpy((char *)l_tsd_section.ticker_token_from, l_params->ext.delegated_token_from);
 //				l_tsd_section.token_from = dap_hash_fast();
@@ -4754,7 +4812,7 @@ int com_token_emit(int a_argc, char **a_argv, void **a_str_reply)
         return -1;
     }
 
-    dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index,a_argc,a_argv,a_str_reply,NULL, &l_net);
+    dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index,a_argc,a_argv,a_str_reply,NULL, &l_net, CHAIN_TYPE_INVALID);
     if( ! l_net) { // Can't find such network
         return -43;
     }
@@ -5725,7 +5783,7 @@ int com_chain_ca_pub( int a_argc,  char ** a_argv, void **a_str_reply)
     dap_chain_t * l_chain = NULL;
 
     dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-ca_name", &l_ca_name);
-    dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index,a_argc, a_argv, a_str_reply, &l_chain, &l_net);
+    dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index,a_argc, a_argv, a_str_reply, &l_chain, &l_net, CHAIN_TYPE_CA);
 
     dap_cert_t * l_cert = dap_cert_find_by_name( l_ca_name );
     if( l_cert == NULL ){
@@ -6018,7 +6076,6 @@ int com_tx_create_json(int a_argc, char ** a_argv, void **reply)
     }
     l_tx->header.ts_created = time(NULL);
     size_t l_items_ready = 0;
-    size_t l_receipt_count = 0;
     dap_list_t *l_sign_list = NULL;// list 'sing' items
     dap_list_t *l_in_list = NULL;// list 'in' items
     dap_list_t *l_tsd_list = NULL;// list tsd sections
@@ -6316,9 +6373,7 @@ int com_tx_create_json(int a_argc, char ** a_argv, void **reply)
             size_t l_params_size = dap_strlen(l_params_str);
             dap_chain_datum_tx_receipt_t *l_receipt = dap_chain_datum_tx_receipt_create(l_srv_uid, l_price_unit, l_units, l_value, l_params_str, l_params_size);
             l_item = (const uint8_t*) l_receipt;
-            if(l_item)
-                l_receipt_count++;
-            else {
+            if (!l_item) {
                 char *l_str_err = dap_strdup_printf("Unable to create receipt out for transaction "
                                                     "described by item %zu.", i);
                 json_object *l_jobj_err = json_object_new_string(l_str_err);
@@ -6828,10 +6883,21 @@ int com_tx_create(int a_argc, char **a_argv, void **reply)
     const dap_chain_addr_t *addr_from = (const dap_chain_addr_t *) dap_chain_wallet_get_addr(l_wallet, l_net->pub.id);
 
     if(!addr_from) {
+        DAP_DELETE(l_addr_to);
+        dap_chain_wallet_close(l_wallet);
+        dap_enc_key_delete(l_priv_key);
         dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_TX_CREATE_SOURCE_ADDRESS_INVALID, "source address is invalid");
         return DAP_CHAIN_NODE_CLI_COM_TX_CREATE_SOURCE_ADDRESS_INVALID;
     }
 
+    if (addr_from && dap_chain_addr_compare(l_addr_to, addr_from)) {
+        DAP_DELETE(l_addr_to);
+        dap_chain_wallet_close(l_wallet);
+        dap_enc_key_delete(l_priv_key);
+        dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_TX_CREATE_EQ_SOURCE_DESTINATION_ADDRESS, "The transaction cannot be directed to the same address as the source.");
+        return DAP_CHAIN_NODE_CLI_COM_TX_CREATE_EQ_SOURCE_DESTINATION_ADDRESS;
+    }
+
     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) {
@@ -6911,7 +6977,8 @@ int com_tx_verify(int a_argc, char **a_argv, void **reply)
         dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_TX_VERIFY_REQUIRE_PARAMETER_TX, "tx_verify requires parameter '-tx'");
         return DAP_CHAIN_NODE_CLI_COM_TX_VERIFY_REQUIRE_PARAMETER_TX;
     }
-    dap_chain_node_cli_cmd_values_parse_net_chain_for_json(&l_arg_index, a_argc, a_argv, &l_chain, &l_net);
+    dap_chain_node_cli_cmd_values_parse_net_chain_for_json(&l_arg_index, a_argc, a_argv, &l_chain, &l_net,
+                                                           CHAIN_TYPE_INVALID);
     if (!l_net || !l_chain) {
         return DAP_CHAIN_NODE_CLI_COM_TX_VERIFY_NET_CHAIN_UNDEFINED;
     }
@@ -6986,6 +7053,8 @@ int com_tx_history(int a_argc, char ** a_argv, void **a_str_reply)
     const char *l_net_str = NULL;
     const char *l_chain_str = NULL;
     const char *l_tx_hash_str = NULL;
+    const char *l_tx_srv_str = NULL;
+    const char *l_tx_act_str = NULL;
     const char *l_limit_str = NULL;
     const char *l_offset_str = NULL;
 
@@ -7008,6 +7077,18 @@ int com_tx_history(int a_argc, char ** a_argv, void **a_str_reply)
     dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-net", &l_net_str);
     dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-chain", &l_chain_str);
     dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-tx", &l_tx_hash_str);
+    dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-srv", &l_tx_srv_str);
+    dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-act", &l_tx_act_str);
+    
+    dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-limit", &l_limit_str);
+    dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-offset", &l_offset_str);
+    size_t l_limit = l_limit_str ? strtoul(l_limit_str, NULL, 10) : 1000;
+    size_t l_offset = l_offset_str ? strtoul(l_offset_str, NULL, 10) : 0;
+
+    //default is ALL/ANY
+    dap_chain_tx_tag_action_type_t l_action = dap_ledger_tx_action_str_to_action_t(l_tx_act_str); 
+
+    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);
 
@@ -7053,7 +7134,15 @@ int com_tx_history(int a_argc, char ** a_argv, void **a_str_reply)
                                                         "Wallet address not recognized");
             return DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_WALLET_ADDR_ERR;
         }
-        l_net = dap_chain_net_by_id(l_addr->net_id);
+        if (l_net) {
+            if (l_net->pub.id.uint64 != l_addr->net_id.uint64) {
+                dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_ID_NET_ADDR_DIF_ERR,
+                                        "Network ID with '-net' param and network ID with '-addr' param are different");
+                DAP_DELETE(l_addr);
+                return DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_ID_NET_ADDR_DIF_ERR;
+            }
+        } else
+            l_net = dap_chain_net_by_id(l_addr->net_id);
     }
     if (l_wallet_name) {
         const char *c_wallets_path = dap_chain_wallet_get_path(g_config);
@@ -7110,35 +7199,29 @@ int com_tx_history(int a_argc, char ** a_argv, void **a_str_reply)
         }
     } else if (l_addr) {
         // history addr and wallet
-        dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-limit", &l_limit_str);
-        dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-offset", &l_offset_str);
-        size_t l_limit = l_limit_str ? strtoul(l_limit_str, NULL, 10) : 0;
-        size_t l_offset = l_offset_str ? strtoul(l_offset_str, NULL, 10) : 0;
-        json_obj_out = dap_db_history_addr(l_addr, l_chain, l_hash_out_type, dap_chain_addr_to_str(l_addr), l_limit, l_offset);
+        json_object * json_obj_summary = json_object_new_object();
+        if (!json_obj_summary) {
+            return DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_MEMORY_ERR;
+        }
+        json_obj_out = dap_db_history_addr(l_addr, l_chain, l_hash_out_type, dap_chain_addr_to_str(l_addr), json_obj_summary, l_limit, l_offset, l_brief, l_tx_srv_str, l_action);
         if (!json_obj_out) {
             dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_DAP_DB_HISTORY_ADDR_ERR,
                                     "something went wrong in tx_history");
+            json_object_put(json_obj_summary);
             return DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_DAP_DB_HISTORY_ADDR_ERR;
-        }
-        
+        }        
+        json_object_array_add(*json_arr_reply, json_obj_out);        
+        json_object_array_add(*json_arr_reply, json_obj_summary);        
+        return DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_OK;        
     } else if (l_is_tx_all) {
         // history all
-        const char * l_brief_type = NULL;
-        bool l_brief_out = false;
-        if (dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-brief", &l_brief_type))
-            l_brief_out = true;
-        
- 
         json_object * json_obj_summary = json_object_new_object();
         if (!json_obj_summary) {
             return DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_MEMORY_ERR;
         }
-        dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-limit", &l_limit_str);
-        dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-offset", &l_offset_str);
-        size_t l_limit = l_limit_str ? strtoul(l_limit_str, NULL, 10) : 0;
-        size_t l_offset = l_offset_str ? strtoul(l_offset_str, NULL, 10) : 0;
+
         json_object* json_arr_history_all = dap_db_history_tx_all(l_chain, l_net, l_hash_out_type, json_obj_summary,
-                                                                  l_limit, l_offset, l_brief_out);
+                                                                l_limit, l_offset, l_brief,  l_tx_srv_str, l_action);
         if (!json_arr_history_all) {
             dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_DAP_DB_HISTORY_ALL_ERR,
                                     "something went wrong in tx_history");
@@ -7609,7 +7692,7 @@ int cmd_remove(int a_argc, char **a_argv, void **a_str_reply)
             if (NULL == l_gdb_path)
                 l_net_returns = s_go_all_nets_offline();
             for (dap_chain_net_t *it = dap_chain_net_iter_start(); it; it = dap_chain_net_iter_next(it)) {
-                s_dap_chain_net_purge(it);
+                dap_chain_net_purge(it);
             }
             if (!error)
                 successful |= REMOVED_CHAINS;
@@ -7620,7 +7703,7 @@ int cmd_remove(int a_argc, char **a_argv, void **a_str_reply)
             } else {
                 error |= NET_NOT_VALID;
             }
-            s_dap_chain_net_purge(l_net);
+            dap_chain_net_purge(l_net);
             if (!error)
                 successful |= REMOVED_CHAINS;
 
@@ -8066,7 +8149,6 @@ static int s_sign_file(const char *a_filename, dap_sign_signer_file_t a_flags, c
 {
     uint32_t l_shift = 1;
     int l_count_meta = 0;
-    int l_index_meta = 0;
     char *l_buffer = NULL;
 
     if (a_flags == SIGNER_ALL_FLAGS) {
@@ -8095,7 +8177,6 @@ static int s_sign_file(const char *a_filename, dap_sign_signer_file_t a_flags, c
             dap_tsd_t *l_item = s_alloc_metadata(a_filename, l_shift & a_flags);
             if (l_item) {
                 l_std_list = dap_list_append(l_std_list, l_item);
-                l_index_meta++;
             }
         }
         l_shift <<= 1;
diff --git a/modules/net/dap_chain_node_cli_cmd_tx.c b/modules/net/dap_chain_node_cli_cmd_tx.c
index 99fb3090a1118e6d809f778d4673ae649433a5c6..d90d2f12e96fd334d4b8b49a4a678cfa766bdbbb 100644
--- a/modules/net/dap_chain_node_cli_cmd_tx.c
+++ b/modules/net/dap_chain_node_cli_cmd_tx.c
@@ -26,7 +26,7 @@
 #include <stddef.h>
 #include <pthread.h>
 
-#include "dap_chain_wallet.h"
+#include "dap_cli_server.h"
 #include "dap_common.h"
 #include "dap_enc_base58.h"
 #include "dap_strfuncs.h"
@@ -40,14 +40,14 @@
 #include "dap_chain_datum_token.h"
 #include "dap_chain_datum_decree.h"
 #include "dap_chain_datum_tx_items.h"
-#include "dap_chain_node_cli.h"
+#include "dap_chain_datum_anchor.h"
 #include "dap_chain_node_cli_cmd_tx.h"
 #include "dap_chain_net_tx.h"
+#include "dap_chain_net_decree.h"
 #include "dap_chain_mempool.h"
 #include "dap_math_convert.h"
 
 #include "dap_json_rpc_errors.h"
-#include "dap_json_rpc_chain_datum_tx.h"
 
 #define LOG_TAG "chain_node_cli_cmd_tx"
 
@@ -92,7 +92,7 @@ void s_dap_chain_tx_hash_processed_ht_free(dap_chain_tx_hash_processed_ht_t **l_
  * @param l_tx_num
  */
 
-static bool s_dap_chain_datum_tx_out_data(dap_chain_datum_tx_t *a_datum,
+bool s_dap_chain_datum_tx_out_data(dap_chain_datum_tx_t *a_datum,
                                           dap_ledger_t *a_ledger,
                                           json_object * json_obj_out,
                                           const char *a_hash_out_type,
@@ -106,13 +106,16 @@ static bool s_dap_chain_datum_tx_out_data(dap_chain_datum_tx_t *a_datum,
             : NULL;
     if (!l_ticker)
         return false;
+    const char *l_description = dap_ledger_get_description_by_ticker(a_ledger, l_ticker);
     dap_time_to_str_rfc822(l_tmp_buf, DAP_TIME_STR_SIZE, l_ts_create);
     dap_chain_hash_fast_to_str(a_tx_hash,l_tx_hash_str,sizeof(l_tx_hash_str));
     json_object_object_add(json_obj_out, "Datum_tx_hash", json_object_new_string(l_tx_hash_str));
     json_object_object_add(json_obj_out, "TS_Created", json_object_new_string(l_tmp_buf));
     json_object_object_add(json_obj_out, "Token_ticker", json_object_new_string(l_ticker));
-    json_object* datum_tx = dap_chain_datum_tx_to_json(a_datum,&a_ledger->net->pub.id);
-    json_object_object_add(json_obj_out, "Datum_tx", datum_tx);
+    json_object_object_add(json_obj_out, "Token_description", l_description ? json_object_new_string(l_description)
+                                                                            : json_object_new_null());
+    dap_chain_datum_dump_tx_json(a_datum, l_ticker, json_obj_out, a_hash_out_type, a_tx_hash, a_ledger->net->pub.id);
+
     dap_list_t *l_out_items = dap_chain_datum_tx_items_get(a_datum, TX_ITEM_TYPE_OUT_ALL, NULL);
     int l_out_idx = 0;
     json_object* json_arr_items = json_object_new_array();
@@ -156,6 +159,7 @@ json_object * dap_db_tx_history_to_json(dap_chain_hash_fast_t* a_tx_hash,
                                         bool brief_out)
 {
     const char *l_tx_token_ticker = NULL;
+    const char *l_tx_token_description = NULL;
     json_object* json_obj_datum = json_object_new_object();
     if (!json_obj_datum) {
         return NULL;
@@ -165,6 +169,7 @@ json_object * dap_db_tx_history_to_json(dap_chain_hash_fast_t* a_tx_hash,
     l_tx_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);
         *accepted_tx = true;
     } else {
         json_object_object_add(json_obj_datum, "status", json_object_new_string("DECLINED"));
@@ -185,10 +190,27 @@ json_object * dap_db_tx_history_to_json(dap_chain_hash_fast_t* a_tx_hash,
 
     json_object_object_add(json_obj_datum, "token_ticker", l_tx_token_ticker ? json_object_new_string(l_tx_token_ticker) 
                                                                              : json_object_new_null());
+    json_object_object_add(json_obj_datum, "token_description", l_tx_token_description ? json_object_new_string(l_tx_token_description)
+                                                                                       : json_object_new_null());
 
     json_object_object_add(json_obj_datum, "ret_code", json_object_new_int(l_ret_code));
     json_object_object_add(json_obj_datum, "ret_code_str", json_object_new_string(dap_ledger_tx_check_err_str(l_ret_code)));
 
+    dap_chain_net_srv_uid_t uid;
+    char *service_name;
+    dap_chain_tx_tag_action_type_t action;
+
+    if (dap_ledger_tx_service_info(l_ledger, a_tx_hash, &uid, &service_name, &action))
+    {
+        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, "action", json_object_new_string("UNKNOWN"));
+    }
+
     char l_time_str[DAP_TIME_STR_SIZE];
     if (l_tx->header.ts_created) {
         dap_time_to_str_rfc822(l_time_str, DAP_TIME_STR_SIZE, l_tx->header.ts_created);/* Convert ts to  "Sat May 17 01:17:08 2014\n" */
@@ -198,9 +220,8 @@ json_object * dap_db_tx_history_to_json(dap_chain_hash_fast_t* a_tx_hash,
     json_object_object_add(json_obj_datum, "tx_created", l_obj_ts_created);
     
     if(!brief_out)
-    {
-        json_object* datum_tx = dap_chain_datum_tx_to_json(l_tx,&a_chain->net_id);
-        json_object_object_add(json_obj_datum, "items", datum_tx);
+    {        
+        dap_chain_datum_dump_tx_json(l_tx,NULL,json_obj_datum,a_hash_out_type,a_tx_hash,a_chain->net_id);        
     }
 
     return json_obj_datum;
@@ -277,6 +298,23 @@ static void s_tx_header_print(json_object* json_obj_datum, dap_chain_tx_hash_pro
     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_tx_check_err_str(a_ret_code)));
+
+
+    dap_chain_net_srv_uid_t uid;
+    char *service_name;
+    dap_chain_tx_tag_action_type_t action;
+    
+    if (dap_ledger_tx_service_info(a_ledger, a_tx_hash, &uid, &service_name, &action))
+    {
+        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, "action", json_object_new_string("UNKNOWN"));
+    }
+
     json_object_object_add(json_obj_datum, "tx_created", json_object_new_string(l_time_str));
 
     DAP_DELETE(l_tx_hash_str);
@@ -295,7 +333,8 @@ static void s_tx_header_print(json_object* json_obj_datum, dap_chain_tx_hash_pro
  * @return char*
  */
 json_object* dap_db_history_addr(dap_chain_addr_t *a_addr, dap_chain_t *a_chain, 
-                                 const char *a_hash_out_type, const char * l_addr_str, size_t a_limit, size_t a_offset)
+                                 const char *a_hash_out_type, const char * l_addr_str, json_object *json_obj_summary,
+                                 size_t a_limit, size_t a_offset, bool a_brief, const char *a_srv, dap_chain_tx_tag_action_type_t a_action)
 {
     json_object* json_obj_datum = json_object_new_array();
     if (!json_obj_datum){
@@ -329,29 +368,48 @@ json_object* dap_db_history_addr(dap_chain_addr_t *a_addr, dap_chain_t *a_chain,
     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;
-    uint256_t l_corr_value = {}, l_unstake_value = {};
-    json_object *l_corr_object = NULL;
-
-    size_t
-        l_count = 0,
-        l_count_tx = 0;
+    uint256_t l_corr_value = {}, l_unstake_value = {};    
+    bool look_for_unknown_service = (a_srv && strcmp(a_srv,"unknown") == 0);
+
+    json_object* json_obj_lim = json_object_new_object();
+    size_t l_arr_start = 0;
+    if (a_offset){
+        l_arr_start = a_offset;
+        json_object_object_add(json_obj_lim, "offset", json_object_new_int(l_arr_start));
+    }        
+    size_t l_arr_end = a_chain->callback_count_atom(a_chain);
+    if (a_limit) {
+        json_object_object_add(json_obj_lim, "limit", json_object_new_int(a_limit));        
+        l_arr_end = l_arr_start + a_limit;
+        size_t l_length = a_chain->callback_count_atom(a_chain);
+        if (l_arr_end > l_length)
+            l_arr_end = l_length;
+    }
+    json_object_array_add(json_obj_datum, json_obj_lim);
+    size_t i_tmp = 0;
     // load transactions
     dap_chain_datum_iter_t *l_datum_iter = a_chain->callback_datum_iter_create(a_chain);
 
     for (dap_chain_datum_t *l_datum = a_chain->callback_datum_iter_get_first(l_datum_iter);
-                            l_datum && (a_limit ? l_count_tx < a_limit : true);
+                            l_datum;
                             l_datum = a_chain->callback_datum_iter_get_next(l_datum_iter))
     {
+        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
+            continue;        
+        // it's a transaction        
         bool l_is_unstake = false;
         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
             continue;
         // all in items should be from the same address
+        if (i_tmp >= l_arr_end || i_tmp < l_arr_start) {
+            i_tmp++;
+            continue;                    
+        }
+        i_tmp++;
         dap_chain_addr_t *l_src_addr = NULL;
         bool l_base_tx = false, l_reward_collect = false;
         const char *l_noaddr_token = NULL;
@@ -421,7 +479,8 @@ json_object* dap_db_history_addr(dap_chain_addr_t *a_addr, dap_chain_t *a_chain,
             }
             if (l_src_addr && !dap_chain_addr_compare(l_src_addr, a_addr))
                 break;  //it's not our addr
-        }
+            
+        }        
         dap_list_free(l_list_in_items);
 
         // find OUT items
@@ -432,6 +491,8 @@ json_object* dap_db_history_addr(dap_chain_addr_t *a_addr, dap_chain_t *a_chain,
         json_object * j_obj_tx = json_object_new_object();
         if (!j_obj_tx || !j_arr_data) {
             dap_json_rpc_allocation_error;
+            json_object_put(j_obj_tx);
+            json_object_put(j_arr_data);
             return NULL;
         }
         if (!l_src_addr) {
@@ -454,9 +515,14 @@ json_object* dap_db_history_addr(dap_chain_addr_t *a_addr, dap_chain_t *a_chain,
                 }
             }
             if (!l_dst_addr_present)
+            {
+                json_object_put(j_arr_data);
+                json_object_put(j_obj_tx);
+                dap_list_free(l_list_out_items);
                 continue;
+            }                
         }
-        bool l_count_bool = false;
+
         for (dap_list_t *it = l_list_out_items; it; it = it->next) {
             dap_chain_addr_t *l_dst_addr = NULL;
             uint8_t l_type = *(uint8_t *)it->data;
@@ -491,32 +557,55 @@ json_object* dap_db_history_addr(dap_chain_addr_t *a_addr, dap_chain_t *a_chain,
 
             if (l_dst_addr && l_net_fee_used && dap_chain_addr_compare(&l_net_fee_addr, l_dst_addr))
                 SUM_256_256(l_fee_sum, l_value, &l_fee_sum);
+            
+            //tag
+            char *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);
+            if (!(l_action & a_action))
+                continue;
+
+            if (a_srv)
+            {
+              
+                //skip if looking for UNKNOWN + it is known
+                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))
+                {
+                    continue;
+                }
+            }
+
             if (l_dst_addr && dap_chain_addr_compare(l_dst_addr, a_addr)) {
-                if (l_count++ < a_offset)
-                    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);
                     l_header_printed = true;
                 }
-                char *l_src_str = NULL;
+                const char *l_src_str = NULL;
                 if (l_base_tx)
                     l_src_str = l_reward_collect ? "reward collecting" : "emission";
                 else if (l_src_addr && dap_strcmp(l_dst_token, l_noaddr_token))
                     l_src_str = dap_chain_addr_to_str(l_src_addr);
                 else
-                    l_src_str = (char*)dap_chain_tx_out_cond_subtype_to_str(l_src_subtype);
+                    l_src_str = dap_chain_tx_out_cond_subtype_to_str(l_src_subtype);
                 if (l_is_unstake)
                     l_value = l_unstake_value;
                 else if (!dap_strcmp(l_native_ticker, l_noaddr_token)) {
                     l_is_need_correction = true;
                     l_corr_value = l_value;
                 }
-                char *l_coins_str, *l_value_str = dap_uint256_to_char(l_value, &l_coins_str);
+                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();
                 if (!j_obj_data) {
                     dap_json_rpc_allocation_error;
                     json_object_put(j_obj_tx);
+                    json_object_put(j_arr_data);
                     return NULL;
                 }
                 json_object_object_add(j_obj_data, "tx_type", json_object_new_string("recv"));
@@ -529,14 +618,12 @@ json_object* dap_db_history_addr(dap_chain_addr_t *a_addr, dap_chain_t *a_chain,
                     l_corr_object = j_obj_data;
                 else
                     json_object_array_add(j_arr_data, j_obj_data);
-                l_count_bool = true;
+                
             } 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)
                     continue;
                 if (!l_src_addr && l_dst_addr && !dap_chain_addr_compare(l_dst_addr, &l_net_fee_addr))
-                    continue;
-                if (l_count++ < a_offset)
-                    break;
+                    continue;                
                 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);
@@ -546,11 +633,12 @@ json_object* dap_db_history_addr(dap_chain_addr_t *a_addr, dap_chain_t *a_chain,
                 const char *l_dst_addr_str = l_dst_addr ? dap_chain_addr_to_str(l_dst_addr)
                                                         : dap_chain_tx_out_cond_subtype_to_str(
                                                               ((dap_chain_tx_out_cond_t *)it->data)->header.subtype);
-                char *l_coins_str, *l_value_str = dap_uint256_to_char(l_value, &l_coins_str);
+                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();
                 if (!j_obj_data) {
                     dap_json_rpc_allocation_error;
                     json_object_put(j_obj_tx);
+                    json_object_put(j_arr_data);
                     return NULL;
                 }
                 json_object_object_add(j_obj_data, "tx_type", json_object_new_string("send"));
@@ -559,8 +647,7 @@ json_object* dap_db_history_addr(dap_chain_addr_t *a_addr, dap_chain_t *a_chain,
                 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);
-                l_count_bool = true;
+                json_object_array_add(j_arr_data, j_obj_data);                
             }
         }
         if (json_object_array_length(j_arr_data) > 0) {
@@ -568,9 +655,9 @@ json_object* dap_db_history_addr(dap_chain_addr_t *a_addr, dap_chain_t *a_chain,
             json_object_array_add(json_obj_datum, j_obj_tx);
         }
         dap_list_free(l_list_out_items);
-        if (l_is_need_correction) {
+        if (l_is_need_correction && l_corr_object) {
             SUM_256_256(l_corr_value, l_fee_sum, &l_corr_value);
-            char *l_coins_str, *l_value_str = dap_uint256_to_char(l_corr_value, &l_coins_str);
+            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 (!j_arr_data) {
@@ -579,11 +666,11 @@ json_object* dap_db_history_addr(dap_chain_addr_t *a_addr, dap_chain_t *a_chain,
             json_object_array_add(j_arr_data, l_corr_object);
             l_is_need_correction = false;
         }
-        l_count_tx += l_count_bool;
     }
     a_chain->callback_datum_iter_delete(l_datum_iter);
     // delete hashes
     s_dap_chain_tx_hash_processed_ht_free(&l_tx_data_ht);
+    
     // if no history
     if (json_object_array_length(json_obj_datum) == 1) {
         json_object * json_empty_tx = json_object_new_object();
@@ -592,15 +679,20 @@ json_object* dap_db_history_addr(dap_chain_addr_t *a_addr, dap_chain_t *a_chain,
             json_object_put(json_obj_datum);
             return NULL;
         }
-        json_object_object_add(json_empty_tx, "status", json_object_new_string("empty"));
+        json_object_object_add(json_empty_tx, "status", json_object_new_string("empty"));        
         json_object_array_add(json_obj_datum, json_empty_tx);
-    }
+    }    
+    json_object_object_add(json_obj_summary, "network", json_object_new_string(l_net->pub.name));
+    json_object_object_add(json_obj_summary, "chain", json_object_new_string(a_chain->name));
+    json_object_object_add(json_obj_summary, "tx_sum", json_object_new_int(i_tmp));    
     return json_obj_datum;
 }
 
 json_object *dap_db_history_tx_all(dap_chain_t *l_chain, dap_chain_net_t *l_net,
                                    const char *l_hash_out_type, json_object *json_obj_summary,
-                                   size_t a_limit, size_t a_offset, bool out_brief)
+                                   size_t a_limit, size_t a_offset, bool out_brief,
+					const char *a_srv, 
+                                    dap_chain_tx_tag_action_type_t a_action)
 {
         log_it(L_DEBUG, "Start getting tx from chain");
         size_t
@@ -613,23 +705,65 @@ json_object *dap_db_history_tx_all(dap_chain_t *l_chain, dap_chain_net_t *l_net,
                             *l_cell_tmp = NULL;
         dap_chain_atom_iter_t *l_iter = NULL;
         json_object * json_arr_out = json_object_new_array();
+        json_object* json_obj_lim = json_object_new_object();
+        size_t l_arr_start = 0;
+        if (a_offset) {
+            l_arr_start = a_offset;
+            json_object_object_add(json_obj_lim, "offset", json_object_new_int(l_arr_start));            
+        }
+        size_t l_arr_end =  l_chain->callback_count_atom(l_chain);
+        l_arr_end = a_limit ? l_arr_start + a_limit : l_arr_start + 1000;
+        json_object_object_add(json_obj_lim, "limit", json_object_new_int(l_arr_end - l_arr_start));
+        json_object_array_add(json_arr_out, json_obj_lim);
+        if (l_arr_end > l_chain->callback_count_atom(l_chain)) {
+            l_arr_end = l_chain->callback_count_atom(l_chain);
+        }
+
+        bool look_for_unknown_service = (a_srv && strcmp(a_srv,"unknown") == 0);
+
         HASH_ITER(hh, l_chain->cells, l_cell, l_cell_tmp) {
-            if (a_limit && l_count_tx >= a_limit)
+            if (l_count_tx >= l_arr_end)
                 break;
             l_iter = l_chain->callback_atom_iter_create(l_chain, l_cell->id, NULL, false);
             size_t l_atom_size = 0;
             dap_chain_atom_ptr_t l_ptr = l_chain->callback_atom_iter_get(l_iter, DAP_CHAIN_ITER_OP_FIRST, &l_atom_size);
-            while (l_ptr && l_atom_size && (a_limit ? l_count_tx < a_limit : true)) {
+            while (l_ptr && l_atom_size && (l_count_tx < 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 && (a_limit ? l_count_tx < a_limit : true); i++) {
+                for (size_t i = 0; i < l_datums_count && (l_count_tx < l_arr_end); i++) {
                     if (l_datums[i]->header.type_id == DAP_CHAIN_DATUM_TX) {
-                        if (l_count++ < a_offset) {
+                        if (l_count_tx < l_arr_start) {
+                            l_count_tx++;
                             continue;
                         }
                         dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t*)l_datums[i]->data;
                         dap_hash_fast_t l_ttx_hash = {0};
                         dap_hash_fast(l_tx, l_datums[i]->header.data_size, &l_ttx_hash);
+
+                        char *service_name = NULL;
+                        dap_chain_tx_tag_action_type_t l_action;
+                        dap_ledger_t *l_ledger = l_net->pub.ledger;
+                        bool srv_found = dap_ledger_tx_service_info(l_ledger, &l_ttx_hash, NULL, &service_name, &l_action);
+                        
+                        if (!(l_action & a_action))
+                            continue;
+
+                        if (a_srv)
+                        {
+                            char *service_name = NULL;
+                            bool srv_found = dap_ledger_tx_service_info(l_ledger, &l_ttx_hash, NULL, &service_name, NULL);
+                            //skip if looking for UNKNOWN + it is known
+                            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))
+                            {
+                                continue;
+                            }
+                        }        
+                        
                         bool accepted_tx;
                         json_object* json_obj_datum = dap_db_tx_history_to_json(&l_ttx_hash, NULL, l_tx, l_chain, l_hash_out_type, l_net, 0, &accepted_tx, out_brief);
                         if (!json_obj_datum) {
@@ -642,8 +776,9 @@ json_object *dap_db_history_tx_all(dap_chain_t *l_chain, dap_chain_net_t *l_net,
                             ++l_tx_ledger_rejected;
                         }
                         json_object_array_add(json_arr_out, json_obj_datum);
-                        const char * debug_json_string = json_object_to_json_string(json_obj_datum);
+                        //const char * debug_json_string = json_object_to_json_string(json_obj_datum);
                         ++l_count_tx;
+                        l_count++;
                     }
                 }
                 DAP_DEL_Z(l_datums);
@@ -655,7 +790,7 @@ json_object *dap_db_history_tx_all(dap_chain_t *l_chain, dap_chain_net_t *l_net,
 
         json_object_object_add(json_obj_summary, "network", json_object_new_string(l_net->pub.name));
         json_object_object_add(json_obj_summary, "chain", json_object_new_string(l_chain->name));
-        json_object_object_add(json_obj_summary, "tx_sum", json_object_new_int(l_count_tx));
+        json_object_object_add(json_obj_summary, "tx_sum", json_object_new_int(l_count));
         json_object_object_add(json_obj_summary, "accepted_tx", json_object_new_int(l_tx_ledger_accepted));
         json_object_object_add(json_obj_summary, "rejected_tx", json_object_new_int(l_tx_ledger_rejected));
         return json_arr_out;
@@ -967,7 +1102,7 @@ int com_ledger(int a_argc, char ** a_argv, void **reply)
         dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-net", &l_net_str);
         dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-limit", &l_limit_str);
         dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-offset", &l_offset_str);
-        size_t l_limit = l_limit_str ? strtoul(l_limit_str, NULL, 10) : 0;
+        size_t l_limit = l_limit_str ? strtoul(l_limit_str, NULL, 10) : 1000;
         size_t l_offset = l_offset_str ? strtoul(l_offset_str, NULL, 10) : 0;
         if (l_net_str == NULL){
             dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_LEDGER_NET_PARAM_ERR, "Command 'list' requires key -net");
diff --git a/modules/net/dap_chain_node_client.c b/modules/net/dap_chain_node_client.c
index f83c08f57d84a831a9e33140696f064eb687b022..08fcc563b419df58372f26aafd4a3c438b3cdcc1 100644
--- a/modules/net/dap_chain_node_client.c
+++ b/modules/net/dap_chain_node_client.c
@@ -75,12 +75,6 @@
 static void s_stage_connected_callback(dap_client_t *a_client, void *a_arg);
 static bool s_timer_update_states_callback(void *a_arg);
 static int s_node_client_set_notify_callbacks(dap_client_t *a_client, uint8_t a_ch_id);
-static void s_ch_chain_callback_notify_packet_out(dap_chain_ch_t*, uint8_t a_pkt_type,
-        dap_chain_ch_pkt_t *a_pkt, size_t a_pkt_data_size,
-        void * a_arg);
-static void s_ch_chain_callback_notify_packet_in(dap_chain_ch_t* a_ch_chain, uint8_t a_pkt_type,
-        dap_chain_ch_pkt_t *a_pkt, size_t a_pkt_data_size,
-        void * a_arg);
 
 /**
  * @brief dap_chain_node_client_init
@@ -349,7 +343,7 @@ void dap_chain_node_client_close_unsafe(dap_chain_node_client_t *a_node_client)
     DAP_DELETE(a_node_client);
 }
 
-void s_close_on_worker_callback(dap_worker_t UNUSED_ARG *a_worker, void *a_arg)
+void s_close_on_worker_callback(void *a_arg)
 {
     assert(a_arg);
     dap_chain_node_client_close_unsafe(a_arg);
diff --git a/modules/net/include/dap_chain_ledger.h b/modules/net/include/dap_chain_ledger.h
index e9aca94a6d0314377b6f9d255622f66b6bfc360e..f39bee757e3a0be0ab49769d084d9b8c848bed22 100644
--- a/modules/net/include/dap_chain_ledger.h
+++ b/modules/net/include/dap_chain_ledger.h
@@ -37,6 +37,9 @@
 #include "dap_chain_datum_tx_items.h"
 #include "dap_chain_net.h"
 
+#define DAP_CHAIN_NET_SRV_TRANSFER_ID 0x07
+#define DAP_CHAIN_NET_SRV_BLOCK_REWARD_ID 0x08
+
 typedef struct dap_ledger {
     dap_chain_net_t *net;
     void *_internal;
@@ -118,6 +121,27 @@ typedef enum dap_chan_ledger_notify_opcodes{
     DAP_LEDGER_NOTIFY_OPCODE_ADDED = 'a', // 0x61
     DAP_LEDGER_NOTIFY_OPCODE_DELETED = 'd', // 0x64 
 } dap_chan_ledger_notify_opcodes_t;
+typedef enum dap_chain_tx_tag_action_type {    
+
+    //subtags, till 32
+    DAP_CHAIN_TX_TAG_ACTION_UNKNOWN  =              1 << 1,
+    
+    DAP_CHAIN_TX_TAG_ACTION_TRANSFER_REGULAR =      1 << 2,
+    DAP_CHAIN_TX_TAG_ACTION_TRANSFER_COMISSION =    1 << 3,
+    DAP_CHAIN_TX_TAG_ACTION_TRANSFER_CROSSCHAIN =   1 << 4,
+    DAP_CHAIN_TX_TAG_ACTION_TRANSFER_REWARD =       1 << 5,
+
+    DAP_CHAIN_TX_TAG_ACTION_OPEN =                  1 << 6,
+    DAP_CHAIN_TX_TAG_ACTION_USE =                   1 << 7,
+    DAP_CHAIN_TX_TAG_ACTION_EXTEND =                1 << 8,
+    DAP_CHAIN_TX_TAG_ACTION_CHANGE =                1 << 9,
+    DAP_CHAIN_TX_TAG_ACTION_CLOSE =                 1 << 10,
+    
+    
+    DAP_CHAIN_TX_TAG_ACTION_ALL =                          ~0,
+} dap_chain_tx_tag_action_type_t;
+
+
 typedef struct dap_ledger_datum_iter {
     dap_chain_net_t *net;
     dap_chain_datum_tx_t *cur;
@@ -131,10 +155,12 @@ typedef bool (*dap_ledger_verificator_callback_t)(dap_ledger_t *a_ledger, dap_ch
 typedef void (*dap_ledger_updater_callback_t)(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_tx_out_cond_t *a_prev_cond);
 typedef void (* dap_ledger_tx_add_notify_t)(void *a_arg, dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chan_ledger_notify_opcodes_t a_opcode);
 typedef void (* dap_ledger_bridged_tx_notify_t)(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash, void *a_arg, dap_chan_ledger_notify_opcodes_t a_opcode);
-typedef bool (*dap_ledger_cache_tx_check_callback_t)(dap_hash_fast_t *a_tx_hash);
+typedef bool (*dap_ledger_cache_tx_check_callback_t)(dap_ledger_t *a_ledger, dap_hash_fast_t *a_tx_hash);
 typedef struct dap_chain_net dap_chain_net_t;
 typedef bool (*dap_chain_ledger_voting_callback_t)(dap_ledger_t *a_ledger, dap_chain_tx_item_type_t a_type, dap_chain_datum_tx_t *a_tx, bool a_apply);
 typedef bool (*dap_chain_ledger_voting_delete_callback_t)(dap_ledger_t *a_ledger, dap_chain_tx_item_type_t a_type, dap_chain_datum_tx_t *a_tx);
+typedef bool (*dap_ledger_tag_check_callback_t)(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_datum_tx_item_groups_t *a_items_grp, dap_chain_tx_tag_action_type_t *a_action);
+
 
 //Change this UUID to automatically reload ledger cache on next node startup
 #define DAP_LEDGER_CACHE_RELOAD_ONCE_UUID "0c92b759-a565-448f-b8bd-99103dacf7fc"
@@ -272,13 +298,34 @@ void dap_ledger_addr_get_token_ticker_all_depricated(dap_ledger_t *a_ledger, dap
 void dap_ledger_addr_get_token_ticker_all(dap_ledger_t *a_ledger, dap_chain_addr_t * a_addr,
         char *** a_tickers, size_t * a_tickers_size);
 
+const char *dap_ledger_get_description_by_ticker(dap_ledger_t *a_ledger, const char *a_token_ticker);
+
 bool dap_ledger_tx_poa_signed(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx);
 
-// Checking a new transaction before adding to the cache
-int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash,
-                                    bool a_from_threshold, dap_list_t **a_list_bound_items, dap_list_t **a_list_tx_out, char **a_main_ticker, bool a_check_for_removing);
+//TX service-tags
+bool dap_ledger_deduct_tx_tag(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_net_srv_uid_t *uid, dap_chain_tx_tag_action_type_t *action);
+const char *dap_ledger_tx_action_str(dap_chain_tx_tag_action_type_t a_tag);
+dap_chain_tx_tag_action_type_t dap_ledger_tx_action_str_to_action_t(const char *a_str);
 
-const char *dap_ledger_tx_get_main_ticker(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, int *a_ledger_rc);
+bool dap_ledger_tx_service_info(dap_ledger_t *a_ledger, dap_hash_fast_t *a_tx_hash, 
+                                dap_chain_net_srv_uid_t *a_uid, char **a_service_name,  dap_chain_tx_tag_action_type_t *a_action);
+
+
+int dap_ledger_service_add(dap_chain_net_srv_uid_t a_uid, char *tag_str, dap_ledger_tag_check_callback_t a_callback);
+
+
+// Checking a new transaction before adding to the cache
+int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger, 
+                                        dap_chain_datum_tx_t *a_tx, 
+                                        dap_hash_fast_t *a_tx_hash,
+                                        bool a_from_threshold, 
+                                        dap_list_t **a_list_bound_items, 
+                                        dap_list_t **a_list_tx_out, 
+                                        char **a_main_ticker,
+                                        dap_chain_net_srv_uid_t *a_tag,
+                                        dap_chain_tx_tag_action_type_t *a_action, bool a_check_for_removing);
+
+const char *dap_ledger_tx_calculate_main_ticker(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, int *a_ledger_rc);
 
 /**
  * Delete all transactions from the cache
@@ -379,3 +426,4 @@ void dap_ledger_bridged_tx_notify_add(dap_ledger_t *a_ledger, dap_ledger_bridged
 
 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);
+dap_chain_tx_out_cond_t* dap_chain_ledger_get_tx_out_cond_linked_to_tx_in_cond(dap_ledger_t *a_ledger, dap_chain_tx_in_cond_t *a_in_cond);
diff --git a/modules/net/include/dap_chain_net.h b/modules/net/include/dap_chain_net.h
index f2c77d3522bc61c9d9ef5966f7522ca2c8aca553..5c669c06e9484d2936ff31db25a8e62b688d2959 100644
--- a/modules/net/include/dap_chain_net.h
+++ b/modules/net/include/dap_chain_net.h
@@ -27,32 +27,24 @@ along with any CellFrame SDK based project.  If not, see <http://www.gnu.org/lic
 
 #include <stdint.h>
 #include <string.h>
-#include "dap_net.h"
-#include "dap_time.h"
 #include "dap_math_ops.h"
-#include "dap_stream_ch.h"
 #include "dap_strfuncs.h"
 #include "dap_string.h"
 #include "dap_list.h"
 #include "dap_chain_common.h"
 #include "dap_chain.h"
 #include "dap_chain_node.h"
-#include "dap_chain_net_decree.h"
-#include "dap_chain_net_tx.h"
-#include "dap_chain_datum_decree.h"
-#include "dap_chain_datum_anchor.h"
-#include "dap_chain_datum_tx.h"
-#include "uthash.h"
-#include "dap_json_rpc.h"
+#include "dap_global_db_cluster.h"
+#include "dap_json_rpc_errors.h"
 
 #define DAP_CHAIN_NET_NAME_MAX 32
 #define DAP_CHAIN_NET_MEMPOOL_TTL 48 // Hours
 
-struct dap_chain_node_info;
 typedef struct dap_chain_node_client dap_chain_node_client_t;
 typedef struct dap_ledger dap_ledger_t;
+typedef struct dap_chain_net_decree dap_chain_net_decree_t;
 
-typedef enum dap_chain_net_state{
+typedef enum dap_chain_net_state {
     NET_STATE_OFFLINE = 0,
     NET_STATE_LINKS_PREPARE,
     NET_STATE_LINKS_CONNECTING,
@@ -140,7 +132,6 @@ dap_chain_t *dap_chain_net_get_chain_by_id(dap_chain_net_t *l_net, dap_chain_id_
 
 uint64_t dap_chain_net_get_cur_addr_int(dap_chain_net_t * l_net);
 dap_chain_cell_id_t * dap_chain_net_get_cur_cell( dap_chain_net_t * l_net);
-const char* dap_chain_net_get_type(dap_chain_t *l_chain);
 
 // Get inintial authorized nodes pointed by config
 dap_chain_node_role_t dap_chain_net_get_role(dap_chain_net_t * a_net);
@@ -158,6 +149,8 @@ void dap_chain_net_remove_last_reward(dap_chain_net_t *a_net);
 uint256_t dap_chain_net_get_reward(dap_chain_net_t *a_net, uint64_t a_block_num);
 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);
 
+void dap_chain_net_purge(dap_chain_net_t *l_net);
+
 /**
  * @brief dap_chain_net_get_gdb_group_mempool
  * @param l_chain
diff --git a/modules/net/include/dap_chain_net_decree.h b/modules/net/include/dap_chain_net_decree.h
index 6628794128d91b4bbb9e0208fceafc633334346a..95b035c5650e961a774ba519e5672cf793716442 100644
--- a/modules/net/include/dap_chain_net_decree.h
+++ b/modules/net/include/dap_chain_net_decree.h
@@ -25,7 +25,7 @@
 #include "dap_list.h"
 #include "dap_chain_net.h"
 
-typedef struct decree_params {
+typedef struct dap_chain_net_decree {
     dap_list_t *pkeys;
     uint16_t num_of_owners;
     uint16_t min_num_of_owners;
diff --git a/modules/net/include/dap_chain_node.h b/modules/net/include/dap_chain_node.h
index 2ee68992d839a99a6e19553f689722505feafa11..6426048417ebf5ea4846130fd009f5b48f9eaea9 100644
--- a/modules/net/include/dap_chain_node.h
+++ b/modules/net/include/dap_chain_node.h
@@ -24,11 +24,7 @@
 #include <limits.h>
 #include "dap_common.h"
 #include "dap_list.h"
-#include "dap_worker.h"
-#include "dap_events_socket.h"
-#include "dap_stream.h"
 #include "dap_chain_common.h"
-#include "dap_global_db.h"
 #include "dap_chain.h"
 #include "dap_client.h"
 
@@ -92,4 +88,4 @@ void dap_chain_node_mempool_process_all(dap_chain_t *a_chain, bool a_force);
 bool dap_chain_node_mempool_autoproc_init();
 inline static void dap_chain_node_mempool_autoproc_deinit() {}
 dap_list_t *dap_chain_node_get_states_list_sort(dap_chain_net_t *a_net, dap_chain_node_addr_t *a_ignored, size_t a_ignored_count);
-dap_string_t *dap_chain_node_states_info_read(dap_chain_net_t *a_net, dap_stream_node_addr_t a_addr);
\ No newline at end of file
+dap_string_t *dap_chain_node_states_info_read(dap_chain_net_t *a_net, dap_stream_node_addr_t a_addr);
diff --git a/modules/net/include/dap_chain_node_cli_cmd.h b/modules/net/include/dap_chain_node_cli_cmd.h
index a20814b648b5d3162caf984e0b69cce16eb58862..f3a2400fa28d45ae7b0f230ffe25f95bb8a336ae 100644
--- a/modules/net/include/dap_chain_node_cli_cmd.h
+++ b/modules/net/include/dap_chain_node_cli_cmd.h
@@ -33,11 +33,24 @@
 
 int dap_chain_node_cli_cmd_values_parse_net_chain_for_json(int *a_arg_index, int a_argc,
                                                            char **a_argv,
-                                                           dap_chain_t **a_chain, dap_chain_net_t **a_net);
+                                                           dap_chain_t **a_chain, dap_chain_net_t **a_net,
+                                                           dap_chain_type_t a_default_chain_type);
 
 
 int dap_chain_node_cli_cmd_values_parse_net_chain(int *a_arg_index, int a_argc, char **a_argv, void **a_str_reply,
-                             dap_chain_t ** a_chain, dap_chain_net_t ** a_net);
+                             dap_chain_t ** a_chain, dap_chain_net_t ** a_net, dap_chain_type_t a_default_chain_type);
+
+typedef enum s_com_parse_net_chain_err{
+    DAP_CHAIN_NODE_CLI_COM_PARSE_NET_NET_STR_ERR = 100,
+    DAP_CHAIN_NODE_CLI_COM_PARSE_NET_NET_PARAM_ERR,
+    DAP_CHAIN_NODE_CLI_COM_PARSE_NET_NOT_FOUND_ERR,
+    DAP_CHAIN_NODE_CLI_COM_PARSE_NET_CHAIN_PARAM_ERR,
+
+    /* add custom codes here */
+
+    DAP_CHAIN_NODE_CLI_COM_PARSE_NET_UNKNOWN /* MAX */
+} s_com_parse_net_chain_err_t;
+
 
 /**
  * global_db command
@@ -159,7 +172,8 @@ typedef enum s_com_tx_create_err{
     DAP_CHAIN_NODE_CLI_COM_TX_CREATE_WALLET_DOES_NOT_EXIST,
     DAP_CHAIN_NODE_CLI_COM_TX_CREATE_SOURCE_ADDRESS_INVALID,
     DAP_CHAIN_NODE_CLI_COM_TX_CREATE_DESTINATION_NETWORK_IS_UNREACHEBLE,
-    DAP_CHAIN_NODE_CLI_COM_TX_CREATE_CAN_NOT_CREATE_TRANSACTION
+    DAP_CHAIN_NODE_CLI_COM_TX_CREATE_CAN_NOT_CREATE_TRANSACTION,
+    DAP_CHAIN_NODE_CLI_COM_TX_CREATE_EQ_SOURCE_DESTINATION_ADDRESS
 }s_com_tx_create_err_t;
 int com_tx_create(int a_argc, char **a_argv, void **a_str_reply);
 typedef enum s_com_tx_create_json_err {
@@ -314,4 +328,4 @@ int com_chain_ca_pub( int a_argc,  char **a_argv, void **a_str_reply);
 int com_chain_ca_copy( int a_argc,  char **a_argv, void **a_str_reply);
 int com_signer(int a_argc, char **a_argv, void **a_str_reply);
 //remove func
-int cmd_remove(int a_argc, char **a_argv, void **a_str_reply);
\ No newline at end of file
+int cmd_remove(int a_argc, char **a_argv, void **a_str_reply);
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 54d784bd94952f9fd1e6581d87e7dce4c978c813..6bc3dd7582425a6c7628085b5c75da5c700a2f1a 100644
--- a/modules/net/include/dap_chain_node_cli_cmd_tx.h
+++ b/modules/net/include/dap_chain_node_cli_cmd_tx.h
@@ -25,8 +25,9 @@
 #pragma once
 
 #include "dap_chain.h"
+#include "dap_chain_ledger.h"
 #include "dap_chain_common.h"
-#include "json.h"
+#include "dap_chain_net.h"
 
 typedef struct dap_chain_tx_hash_processed_ht{
     dap_chain_hash_fast_t hash;
@@ -40,7 +41,10 @@ void s_dap_chain_tx_hash_processed_ht_free(dap_chain_tx_hash_processed_ht_t **l_
  * return history json
  */
 json_object * dap_db_history_tx(dap_chain_hash_fast_t* a_tx_hash, dap_chain_t * a_chain, const char *a_hash_out_type, dap_chain_net_t * l_net);
-json_object * dap_db_history_addr(dap_chain_addr_t * a_addr, dap_chain_t * a_chain, const char *a_hash_out_type, const char * l_addr_str, size_t a_limit, size_t a_offset);
+json_object * dap_db_history_addr(dap_chain_addr_t * a_addr, dap_chain_t * a_chain, const char *a_hash_out_type, const char * l_addr_str, json_object *json_obj_summary, size_t a_limit, size_t a_offset,
+bool a_brief,
+const char *a_srv,
+dap_chain_tx_tag_action_type_t a_action);
 json_object * dap_db_tx_history_to_json(dap_chain_hash_fast_t* a_tx_hash,
                                         dap_hash_fast_t * l_atom_hash,
                                         dap_chain_datum_tx_t * l_tx,
@@ -52,8 +56,17 @@ json_object * dap_db_tx_history_to_json(dap_chain_hash_fast_t* a_tx_hash,
                                         bool out_brief);
 
 json_object *dap_db_history_tx_all(dap_chain_t *l_chain, dap_chain_net_t *l_net,
-                                   const char *l_hash_out_type, json_object *json_obj_summary,
-                                   size_t a_limit, size_t a_offset, bool out_brief);
+                                    const char *l_hash_out_type, json_object *json_obj_summary,
+                                    size_t a_limit, size_t a_offset, bool out_brief,
+                                    const char *a_srv,
+                                    dap_chain_tx_tag_action_type_t a_action);
+
+bool s_dap_chain_datum_tx_out_data(dap_chain_datum_tx_t *a_datum,
+                                          dap_ledger_t *a_ledger,
+                                          json_object * json_obj_out,
+                                          const char *a_hash_out_type,
+                                          dap_chain_hash_fast_t *a_tx_hash);
+
 /**
  * ledger command
  *
diff --git a/modules/net/srv/dap_chain_net_srv.c b/modules/net/srv/dap_chain_net_srv.c
index 8eb2b1fe5d1832f78c4ab271e77c7eb7e09bbdd1..cae9fe12202b1dddd1ef0ac74157ef4d06d239d8 100644
--- a/modules/net/srv/dap_chain_net_srv.c
+++ b/modules/net/srv/dap_chain_net_srv.c
@@ -129,7 +129,7 @@ void s_load_all()
                 continue;
             // don't search in directories
             char l_full_path[MAX_PATH + 1] = {0};
-            dap_snprintf(l_full_path, sizeof(l_full_path), "%s/%s", l_net_dir_str, l_dir_entry->d_name);
+            snprintf(l_full_path, sizeof(l_full_path), "%s/%s", l_net_dir_str, l_dir_entry->d_name);
             if(dap_dir_test(l_full_path)) {
                 continue;
             }
@@ -203,7 +203,8 @@ static int s_cli_net_srv( int argc, char **argv, void **a_str_reply)
         return 0;
     }
 
-    int l_ret = dap_chain_node_cli_cmd_values_parse_net_chain( &arg_index, argc, argv, a_str_reply, NULL, &l_net );
+    int l_ret = dap_chain_node_cli_cmd_values_parse_net_chain( &arg_index, argc, argv, a_str_reply, NULL, &l_net,
+                                                               CHAIN_TYPE_INVALID);
     if ( l_net ) {
         //char * l_orders_group = dap_chain_net_srv_order_get_gdb_group( l_net );
 
@@ -287,124 +288,118 @@ static int s_cli_net_srv( int argc, char **argv, void **a_str_reply)
                 dap_string_append_printf(l_string_ret, "%s\n", l_string_err->str);
                 dap_string_free(l_string_err, true);
                 l_ret = -1;
-            }
-            // Update order
-            else if(!dap_strcmp(l_order_str, "update")) {
-
-            if(!l_order_hash_str) {
-                l_ret = -1;
-                dap_string_append(l_string_ret, "Can't find option '-hash'\n");
-            }
-            else {
-                dap_chain_net_srv_order_t * l_order = dap_chain_net_srv_order_find_by_hash_str(l_net, l_order_hash_hex_str);
-                if(!l_order) {
-                    l_ret = -2;
-                    if(!dap_strcmp(l_hash_out_type,"hex"))
-                        dap_string_append_printf(l_string_ret, "Can't find order with hash %s\n", l_order_hash_hex_str);
-                    else
-                        dap_string_append_printf(l_string_ret, "Can't find order with hash %s\n", l_order_hash_base58_str);
-                }
-                else {
-                    if(l_ext) {
-                        l_order->ext_size = strlen(l_ext) + 1;
-                        l_order = DAP_REALLOC(l_order, sizeof(dap_chain_net_srv_order_t) + l_order->ext_size);
-                        memcpy(l_order->ext_n_sign, l_ext, l_order->ext_size);
-                    }
-                    else
-                        dap_chain_net_srv_order_set_continent_region(&l_order, l_continent_num, l_region_str);
-                    /*if(l_region_str) {
-                        strncpy(l_order->region, l_region_str, dap_min(sizeof(l_order->region) - 1, strlen(l_region_str) + 1));
+            } else if(!dap_strcmp(l_order_str, "update")) {
+                if (!l_order_hash_str) {
+                    l_ret = -1;
+                    dap_string_append(l_string_ret, "Can't find option '-hash'\n");
+                } else {
+                    dap_chain_net_srv_order_t * l_order = dap_chain_net_srv_order_find_by_hash_str(l_net, l_order_hash_hex_str);
+                    if(!l_order) {
+                        l_ret = -2;
+                        if(!dap_strcmp(l_hash_out_type,"hex"))
+                            dap_string_append_printf(l_string_ret, "Can't find order with hash %s\n", l_order_hash_hex_str);
+                        else
+                            dap_string_append_printf(l_string_ret, "Can't find order with hash %s\n", l_order_hash_base58_str);
+                    } else {
+                        if (l_ext) {
+                            l_order->ext_size = strlen(l_ext) + 1;
+                            l_order = DAP_REALLOC(l_order, sizeof(dap_chain_net_srv_order_t) + l_order->ext_size);
+                            memcpy(l_order->ext_n_sign, l_ext, l_order->ext_size);
+                        } else
+                            dap_chain_net_srv_order_set_continent_region(&l_order, l_continent_num, l_region_str);
+                        /*if(l_region_str) {
+                            strncpy(l_order->region, l_region_str, dap_min(sizeof(l_order->region) - 1, strlen(l_region_str) + 1));
+                        }
+                        if(l_continent_num>=0)
+                            l_order->continent = l_continent_num;*/
+                        char *l_new_order_hash_str = dap_chain_net_srv_order_save(l_net, l_order, false);
+                        if (l_new_order_hash_str) {
+                            // delete prev order
+                            if(dap_strcmp(l_new_order_hash_str, l_order_hash_hex_str))
+                                dap_chain_net_srv_order_delete_by_hash_str_sync(l_net, l_order_hash_hex_str);
+                            DAP_DELETE(l_new_order_hash_str);
+                            dap_string_append_printf(l_string_ret, "order updated\n");
+                        } else
+                            dap_string_append_printf(l_string_ret, "Order did not updated\n");
+                        DAP_DELETE(l_order);
                     }
-                    if(l_continent_num>=0)
-                        l_order->continent = l_continent_num;*/
-                    char *l_new_order_hash_str = dap_chain_net_srv_order_save(l_net, l_order, false);
-                    if (l_new_order_hash_str) {
-                        // delete prev order
-                        if(dap_strcmp(l_new_order_hash_str, l_order_hash_hex_str))
-                            dap_chain_net_srv_order_delete_by_hash_str_sync(l_net, l_order_hash_hex_str);
-                        DAP_DELETE(l_new_order_hash_str);
-                        dap_string_append_printf(l_string_ret, "order updated\n");
-                    } else
-                        dap_string_append_printf(l_string_ret, "Order did not updated\n");
-                    DAP_DELETE(l_order);
                 }
-            }
-
-        }
-        else if (!dap_strcmp( l_order_str, "find" )) {
-
+            } else if (!dap_strcmp( l_order_str, "find" )) {
             // Order direction
-            const char *l_direction_str = NULL;
-            dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-direction", &l_direction_str);
+                const char *l_direction_str = NULL;
+                dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-direction", &l_direction_str);
 
             // Select with specified service uid
-            const char *l_srv_uid_str = NULL;
-            dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-srv_uid", &l_srv_uid_str);
-
+                const char *l_srv_uid_str = NULL;
+                dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-srv_uid", &l_srv_uid_str);
 
             // Select with specified price units
-            const char*  l_price_unit_str = NULL;
-            dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-price_unit", &l_price_unit_str);
+                const char*  l_price_unit_str = NULL;
+                dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-price_unit", &l_price_unit_str);
 
             // Token ticker
-            const char*  l_price_token_str = NULL;
-            dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-price_token", &l_price_token_str);
+                const char*  l_price_token_str = NULL;
+                dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-price_token", &l_price_token_str);
 
             // Select with price not more than price_min
-            const char*  l_price_min_str = NULL;
-            dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-price_min", &l_price_min_str);
+                const char*  l_price_min_str = NULL;
+                dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-price_min", &l_price_min_str);
 
             // Select with price not more than price_max
-            const char*  l_price_max_str = NULL;
-            dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-price_max", &l_price_max_str);
-
-            dap_chain_net_srv_order_direction_t l_direction = SERV_DIR_UNDEFINED;
-            dap_chain_net_srv_uid_t l_srv_uid={{0}};
-            uint256_t l_price_min = {};
-            uint256_t l_price_max = {};
-            dap_chain_net_srv_price_unit_uid_t l_price_unit={{0}};
-
-            if ( l_direction_str ){
-                if (!strcmp(l_direction_str, "sell"))
-                    l_direction = SERV_DIR_SELL;
-                else if (!strcmp(l_direction_str, "buy"))
-                    l_direction = SERV_DIR_BUY;
-                else {
-                    dap_string_free(l_string_ret, true);
-                    dap_cli_server_cmd_set_reply_text(a_str_reply, "Wrong direction of the token was "
-                                                                   "specified, possible directions: buy, sell.");
-                    return -18;
+                const char*  l_price_max_str = NULL;
+                dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-price_max", &l_price_max_str);
+
+                dap_chain_net_srv_order_direction_t l_direction = SERV_DIR_UNDEFINED;
+                dap_chain_net_srv_uid_t l_srv_uid={{0}};
+                uint256_t l_price_min = {};
+                uint256_t l_price_max = {};
+                dap_chain_net_srv_price_unit_uid_t l_price_unit={{0}};
+
+                if ( l_direction_str ) {
+                    if (!strcmp(l_direction_str, "sell"))
+                        l_direction = SERV_DIR_SELL;
+                    else if (!strcmp(l_direction_str, "buy"))
+                        l_direction = SERV_DIR_BUY;
+                    else {
+                        dap_string_free(l_string_ret, true);
+                        dap_cli_server_cmd_set_reply_text(a_str_reply, "Wrong direction of the token was "
+                                                                       "specified, possible directions: buy, sell.");
+                        return -18;
+                    }
                 }
-            }
 
-            if (l_srv_uid_str && dap_id_uint64_parse(l_srv_uid_str ,&l_srv_uid.uint64)) {
-                dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't recognize '%s' string as 64-bit id, hex or dec.", l_srv_uid_str);
-                return -21;
-            }
-
-            if ( l_price_min_str )
-                l_price_min = dap_chain_balance_scan(l_price_min_str);
-
-            if ( l_price_max_str )
-                l_price_max = dap_chain_balance_scan(l_price_max_str);
-
-            l_price_unit.uint32 = dap_chain_srv_str_to_unit_enum(l_price_unit_str);
+                if (l_srv_uid_str && dap_id_uint64_parse(l_srv_uid_str ,&l_srv_uid.uint64)) {
+                    dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't recognize '%s' string as 64-bit id, hex or dec.", l_srv_uid_str);
+                    return -21;
+                }
 
-            dap_list_t * l_orders;
-            size_t l_orders_num = 0;
-            if( dap_chain_net_srv_order_find_all_by( l_net, l_direction,l_srv_uid,l_price_unit,l_price_token_str,l_price_min, l_price_max,&l_orders,&l_orders_num) == 0 ){
-                dap_string_append_printf(l_string_ret, "Found %zu orders:\n", l_orders_num);
-                for (dap_list_t *l_temp = l_orders;l_temp; l_temp = l_orders->next){
-                    dap_chain_net_srv_order_t *l_order =(dap_chain_net_srv_order_t *) l_temp->data;
-                    dap_chain_net_srv_order_dump_to_string(l_order, l_string_ret, l_hash_out_type, l_net->pub.native_ticker);
-                    dap_string_append(l_string_ret,"\n");
+                if ( l_price_min_str )
+                    l_price_min = dap_chain_balance_scan(l_price_min_str);
+
+                if ( l_price_max_str )
+                    l_price_max = dap_chain_balance_scan(l_price_max_str);
+
+                l_price_unit.uint32 = dap_chain_srv_str_to_unit_enum(l_price_unit_str);
+
+                dap_list_t *l_orders;
+                size_t l_orders_num = 0;
+                if( !dap_chain_net_srv_order_find_all_by(l_net, l_direction, l_srv_uid,
+                                                        l_price_unit, l_price_token_str,
+                                                        l_price_min, l_price_max,
+                                                        &l_orders, &l_orders_num) )
+                {
+                    dap_string_append_printf(l_string_ret, "Found %zu orders:\n", l_orders_num);
+                    for (dap_list_t *l_temp = l_orders; l_temp; l_temp = l_temp->next){
+                        dap_chain_net_srv_order_t *l_order = (dap_chain_net_srv_order_t*)l_temp->data;
+                        dap_chain_net_srv_order_dump_to_string(l_order, l_string_ret, l_hash_out_type, l_net->pub.native_ticker);
+                        dap_string_append(l_string_ret,"\n");
+                    }
+                    l_ret = 0;
+                    dap_list_free_full(l_orders, NULL);
+                } else {
+                    l_ret = -5 ;
+                    dap_string_append(l_string_ret,"Can't get orders: some internal error or wrong params\n");
                 }
-                l_ret = 0;
-                dap_list_free_full(l_orders, NULL);
-            }else{
-                l_ret = -5 ;
-                dap_string_append(l_string_ret,"Can't get orders: some internal error or wrong params\n");
-            }
             } else if(!dap_strcmp( l_order_str, "dump" )) {
                 // Select with specified service uid
                 if ( l_order_hash_str ){
@@ -558,31 +553,30 @@ static int s_cli_net_srv( int argc, char **argv, void **a_str_reply)
                             dap_string_free(l_string_ret, true);
                             return -19;
                         }
-                } else {
-                    dap_cli_server_cmd_set_reply_text(a_str_reply, "The certificate name was not "
-                                                                   "specified. Since version 5.2 it is not possible to "
-                                                                   "create unsigned orders.");
-                    dap_string_free(l_string_ret, true);
-                    return -20;
-                }
+                    } else {
+                        dap_cli_server_cmd_set_reply_text(a_str_reply, "The certificate name was not "
+                                                                       "specified. Since version 5.2 it is not possible to "
+                                                                       "create unsigned orders.");
+                        dap_string_free(l_string_ret, true);
+                        return -20;
+                    }
                 // create order
-                char * l_order_new_hash_str = dap_chain_net_srv_order_create(
-                            l_net,l_direction, l_srv_uid, l_node_addr,l_tx_cond_hash, &l_price, l_price_unit,
-                            l_price_token, l_expires, (uint8_t *)l_ext, l_ext_len, l_units, l_region_str, l_continent_num, l_key);
-                if(l_cert)
-                    dap_cert_delete(l_cert);
-                if (l_order_new_hash_str)
-                    dap_string_append_printf( l_string_ret, "Created order %s\n", l_order_new_hash_str);
-                else{
-                    dap_string_append_printf( l_string_ret, "Error! Can't created order\n");
-                    l_ret = -4;
+                    char * l_order_new_hash_str = dap_chain_net_srv_order_create(
+                                l_net,l_direction, l_srv_uid, l_node_addr,l_tx_cond_hash, &l_price, l_price_unit,
+                                l_price_token, l_expires, (uint8_t *)l_ext, l_ext_len, l_units, l_region_str, l_continent_num, l_key);
+                    if(l_cert)
+                        dap_cert_delete(l_cert);
+                    if (l_order_new_hash_str)
+                        dap_string_append_printf( l_string_ret, "Created order %s\n", l_order_new_hash_str);
+                    else {
+                        dap_string_append_printf( l_string_ret, "Error! Can't created order\n");
+                        l_ret = -4;
+                    }
+                } else {
+                    dap_string_append_printf( l_string_ret, "Missed some required params\n");
+                    l_ret=-5;
                 }
-            } else {
-                dap_string_append_printf( l_string_ret, "Missed some required params\n");
-                l_ret=-5;
-            }
-            }
-            else if (l_order_str) {
+            } else if (l_order_str) {
                 dap_string_append_printf(l_string_ret, "Unrecognized subcommand '%s'", l_order_str);
                 l_ret = -14;
             }
@@ -645,10 +639,7 @@ static int s_cli_net_srv( int argc, char **argv, void **a_str_reply)
             dap_string_free(l_string_ret, true);
             return -17;
         }
-
     }
-
-
     return l_ret;
 }
 
diff --git a/modules/net/srv/dap_chain_net_srv_order.c b/modules/net/srv/dap_chain_net_srv_order.c
index bd072bd1cac5dfbeea1589ddade6bbf2dc77b077..e81bda4bd2797581d256366b80df284d4adbac97 100644
--- a/modules/net/srv/dap_chain_net_srv_order.c
+++ b/modules/net/srv/dap_chain_net_srv_order.c
@@ -558,7 +558,7 @@ void dap_chain_net_srv_order_dump_to_string(dap_chain_net_srv_order_t *a_order,d
         dap_string_append_printf(a_str_out, "  created:          %s\n", buf_time);
         dap_string_append_printf(a_str_out, "  srv_uid:          0x%016"DAP_UINT64_FORMAT_X"\n", a_order->srv_uid.uint64 );
         
-        char *l_balance_coins, *l_balance = dap_uint256_to_char(a_order->price, &l_balance_coins);
+        const char *l_balance_coins, *l_balance = dap_uint256_to_char(a_order->price, &l_balance_coins);
         dap_string_append_printf(a_str_out, "  price:            %s (%s)\n", l_balance_coins, l_balance);
         dap_string_append_printf(a_str_out, "  price_token:      %s\n",  (*a_order->price_ticker) ? a_order->price_ticker: a_native_ticker);
         dap_string_append_printf(a_str_out, "  units:            %zu\n", a_order->units);
diff --git a/modules/net/srv/include/dap_chain_net_srv.h b/modules/net/srv/include/dap_chain_net_srv.h
index 938efa969a2a03a43213839dff6d53dbc8685ded..c524cb3a91872d44780ed1e4f799d845fe01f0a1 100755
--- a/modules/net/srv/include/dap_chain_net_srv.h
+++ b/modules/net/srv/include/dap_chain_net_srv.h
@@ -27,9 +27,8 @@ along with any CellFrame SDK based project.  If not, see <http://www.gnu.org/lic
 #include "dap_chain_net.h"
 #include "dap_chain_common.h"
 #include "dap_chain_datum_decree.h"
-#include "dap_chain_wallet.h"
+#include "dap_chain_datum_tx_receipt.h"
 #include "dap_common.h"
-#include "dap_config.h"
 #include "dap_stream_ch.h"
 #include "dap_time.h"
 
diff --git a/modules/net/srv/include/dap_chain_net_srv_order.h b/modules/net/srv/include/dap_chain_net_srv_order.h
index 29906fce088c362056f327d459453de63cbaae6b..fe1c8031d5193d47fac54fdb987c87466813debd 100644
--- a/modules/net/srv/include/dap_chain_net_srv_order.h
+++ b/modules/net/srv/include/dap_chain_net_srv_order.h
@@ -106,7 +106,7 @@ int dap_chain_net_srv_order_find_all_by(
     dap_list_t** a_output_orders,
     size_t* a_output_orders_count);
 
-int dap_chain_net_srv_order_delete_by_hash_str_sync( dap_chain_net_t * a_net,const char * a_hash_str );
+int dap_chain_net_srv_order_delete_by_hash_str_sync(dap_chain_net_t *a_net, const char *a_hash_str);
 
 /**
  * @brief dap_chain_net_srv_order_delete_by_hash
diff --git a/modules/service/bridge/CMakeLists.txt b/modules/service/bridge/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..6c68b74fa5d2bc04e8b5506da10ed5ed7c7dcafb
--- /dev/null
+++ b/modules/service/bridge/CMakeLists.txt
@@ -0,0 +1,22 @@
+cmake_minimum_required(VERSION 3.10)
+project (dap_chain_net_srv_bridge)
+
+file(GLOB DAP_SRV_BRG_SRCS *.c)
+
+file(GLOB DAP_SRV_BRG_HEADERS include/*.h)
+
+add_library(${PROJECT_NAME} STATIC ${DAP_SRV_BRG_SRCS} ${DAP_SRV_BRG_HEADERS})
+
+target_include_directories(${PROJECT_NAME} INTERFACE .)
+target_include_directories(${PROJECT_NAME} PUBLIC include)
+target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_chain dap_chain_net dap_chain_net_srv)
+target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../../dap-sdk/3rdparty/json-c)
+
+if (INSTALL_SDK)
+set_target_properties(${PROJECT_NAME}  PROPERTIES PUBLIC_HEADER "${DAP_SRV_BRG_HEADERS}")
+INSTALL(TARGETS ${PROJECT_NAME} 
+        LIBRARY DESTINATION lib/modules/service/bridge/
+        ARCHIVE DESTINATION lib/modules/service/bridge/
+        PUBLIC_HEADER DESTINATION include/modules/service/bridge/
+)
+endif()
\ No newline at end of file
diff --git a/modules/service/bridge/dap_chain_net_srv_bridge.c b/modules/service/bridge/dap_chain_net_srv_bridge.c
new file mode 100644
index 0000000000000000000000000000000000000000..439d0556d046e6b02be8511127dc2a2944e1a82c
--- /dev/null
+++ b/modules/service/bridge/dap_chain_net_srv_bridge.c
@@ -0,0 +1,161 @@
+/*
+ * Authors:
+ * Roman Khlopkov <roman.khlopkov@demlabs.net>
+ * DeM Labs Inc.   https://demlabs.net
+ * DeM Labs Open source community https://gitlab.demlabs.net
+ * Copyright  (c) 2017-2020
+ * All rights reserved.
+
+ This file is part of DAP (Deus Applications Prototypes) the open source project
+
+    DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    DAP is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <math.h>
+#include <pthread.h>
+#include <stdbool.h>
+#include "dap_chain_net.h"
+#include "dap_chain_datum_tx.h"
+#include "dap_chain_datum_tx_out_cond.h"
+#include "dap_chain_datum_tx_sig.h"
+#include "dap_list.h"
+#include "dap_sign.h"
+#include "dap_time.h"
+#include "dap_chain_net_srv.h"
+#include "dap_chain_ledger.h"
+#include "dap_chain_node_cli.h"
+#include "dap_common.h"
+#include "dap_hash.h"
+#include "dap_math_ops.h"
+#include "dap_string.h"
+#include "dap_chain_common.h"
+#include "dap_chain_mempool.h"
+#include "dap_chain_datum_decree.h"
+#include "dap_tsd.h"
+#include "dap_chain_net_tx.h"
+#include "dap_chain_net_srv.h"
+#include "dap_chain_net_srv_bridge.h"
+#include "uthash.h"
+
+#define LOG_TAG "dap_chain_net_srv_bridge"
+
+
+static inline int s_tsd_str_cmp(const byte_t *a_tsdata, size_t a_tsdsize,  const char *str ) {
+    size_t l_strlen = (size_t)strlen(str);
+    if (l_strlen != a_tsdsize) return -1;
+    return memcmp(a_tsdata, str, l_strlen);
+}
+
+//emission tags
+//inherits from emission tsd section for engine-produced auth emissions
+bool s_get_ems_bridge_action(dap_chain_datum_token_emission_t *a_ems, dap_chain_tx_tag_action_type_t *a_action)
+{
+    if (!a_ems || !a_action)
+        return false;
+
+    if (a_action)
+        *a_action = DAP_CHAIN_TX_TAG_ACTION_UNKNOWN;
+
+    size_t src_tsd_size = 0;
+    
+    src_tsd_size = 0;
+    size_t subsrc_tsd_size = 0;
+    
+    byte_t *ems_src = dap_chain_emission_get_tsd(a_ems, DAP_CHAIN_DATUM_EMISSION_TSD_TYPE_SOURCE, &src_tsd_size);
+    byte_t *ems_subsrc = dap_chain_emission_get_tsd(a_ems, DAP_CHAIN_DATUM_EMISSION_TSD_TYPE_SOURCE_SUBTYPE, &subsrc_tsd_size);
+
+    if (ems_src && src_tsd_size)
+    {   
+        //old bridge ems
+        if (s_tsd_str_cmp(ems_src, src_tsd_size, DAP_CHAIN_DATUM_TOKEN_EMISSION_SOURCE_SUBTYPE_BRIDGE_COMMISSION_OLD) == 0)
+        {
+            *a_action =  DAP_CHAIN_TX_TAG_ACTION_TRANSFER_COMISSION;
+            return true;      
+        }
+        
+        //not bridge
+        if (s_tsd_str_cmp(ems_src, src_tsd_size, DAP_CHAIN_DATUM_TOKEN_EMISSION_SOURCE_BRIDGE) != 0)
+            return false;
+    }
+    else
+    {
+        //special case for old bridge datums
+        //no SOURCE, but have all this
+        //if emission has 5, 8, 6 section (it's enough) -> this is old bridge tx
+        if (dap_chain_emission_get_tsd(a_ems, DAP_CHAIN_DATUM_EMISSION_TSD_TYPE_NET_ID, &src_tsd_size) &&
+            dap_chain_emission_get_tsd(a_ems, DAP_CHAIN_DATUM_EMISSION_TSD_TYPE_BLOCK_NUM, &src_tsd_size) &&
+            dap_chain_emission_get_tsd(a_ems, DAP_CHAIN_DATUM_EMISSION_TSD_TYPE_OUTER_TX_HASH, &src_tsd_size))
+        {
+            *a_action = DAP_CHAIN_TX_TAG_ACTION_TRANSFER_REGULAR;
+            return true;
+        }
+    }
+
+    if (ems_subsrc && subsrc_tsd_size)
+    {
+        if (s_tsd_str_cmp(ems_subsrc, subsrc_tsd_size, DAP_CHAIN_DATUM_TOKEN_EMISSION_SOURCE_SUBTYPE_BRIDGE_COMMISSION)==0)
+        {
+            *a_action =  DAP_CHAIN_TX_TAG_ACTION_TRANSFER_COMISSION;
+            return true;
+        }
+
+        if (s_tsd_str_cmp(ems_subsrc, subsrc_tsd_size, DAP_CHAIN_DATUM_TOKEN_EMISSION_SOURCE_SUBTYPE_BRIDGE_TRANSFER)==0)
+        {
+            *a_action =  DAP_CHAIN_TX_TAG_ACTION_TRANSFER_REGULAR;
+            return true;
+        }    
+
+        if (s_tsd_str_cmp(ems_subsrc, subsrc_tsd_size, DAP_CHAIN_DATUM_TOKEN_EMISSION_SOURCE_SUBTYPE_BRIDGE_CROSSCHAIN)==0)
+        {   
+            *a_action =  DAP_CHAIN_TX_TAG_ACTION_TRANSFER_CROSSCHAIN;
+            return true;
+        }
+    }
+    return false;
+}
+
+
+static bool s_tag_check_bridge(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx,  dap_chain_datum_tx_item_groups_t *a_items_grp, dap_chain_tx_tag_action_type_t *a_action)
+{
+    //bridged native transfer: destination addr netid differs from net we get datum
+    //such tx are marked by TRANSFER service as CROSSCHAIN_TRANSFER
+    //bridge txs are only received one
+    
+
+    //crosschain bridge AUTH emissions 
+    
+    if (!a_items_grp->items_in_ems)
+        return false;
+
+    dap_chain_tx_in_ems_t *l_tx_in_ems = a_items_grp->items_in_ems->data;
+    dap_hash_fast_t ems_hash = l_tx_in_ems->header.token_emission_hash;
+    dap_chain_datum_token_emission_t *l_emission = dap_ledger_token_emission_find(a_ledger, &ems_hash);
+    if(l_emission)
+        return s_get_ems_bridge_action(l_emission, a_action);
+
+    return false;
+}
+
+int dap_chain_net_srv_bridge_init()
+{
+    dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_BRIDGE_ID };
+    dap_ledger_service_add(l_uid, "bridge", s_tag_check_bridge);
+    return 0;
+}
+
+void dap_chain_net_srv_bridge_deinit()
+{
+    
+}
+
diff --git a/modules/service/bridge/include/dap_chain_net_srv_bridge.h b/modules/service/bridge/include/dap_chain_net_srv_bridge.h
new file mode 100644
index 0000000000000000000000000000000000000000..c5d9cb013f5577cef83c8a5c9ad24b0f70922195
--- /dev/null
+++ b/modules/service/bridge/include/dap_chain_net_srv_bridge.h
@@ -0,0 +1,5 @@
+#define DAP_CHAIN_NET_SRV_BRIDGE_ID 0x04
+
+int dap_chain_net_srv_bridge_init();
+
+void dap_chain_net_srv_bridge_deinit();
diff --git a/modules/service/datum/dap_chain_net_srv_datum.c b/modules/service/datum/dap_chain_net_srv_datum.c
index 0132dbef97913fa24cbc0d380ee65d6546054dbd..83cb89b1ec6ac1fe10a797f5819b3ec22f1cd65f 100644
--- a/modules/service/datum/dap_chain_net_srv_datum.c
+++ b/modules/service/datum/dap_chain_net_srv_datum.c
@@ -38,6 +38,12 @@ static int s_srv_datum_cli(int argc, char ** argv, void **a_str_reply);
 
 void s_order_notficator(dap_store_obj_t *a_obj, void *a_arg);
 
+static bool s_tag_check_datum(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx,  dap_chain_datum_tx_item_groups_t *a_items_grp, dap_chain_tx_tag_action_type_t *a_action)
+{
+    //datum service do not produce transactions for now.
+    return false;
+}
+
 int dap_chain_net_srv_datum_init()
 {
     dap_cli_server_cmd_add("srv_datum", s_srv_datum_cli, "Service Datum commands", 
@@ -51,6 +57,10 @@ int dap_chain_net_srv_datum_init()
         return -1;
     }
     s_srv_datum->uid.uint64 = DAP_CHAIN_NET_SRV_DATUM_ID;
+
+    dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_DATUM_ID };
+    dap_ledger_service_add(l_uid, "datum", s_tag_check_datum);
+    
     return 0;
 }
 
@@ -100,7 +110,7 @@ static int s_srv_datum_cli(int argc, char ** argv, void **a_str_reply)
     dap_chain_net_t * l_chain_net = NULL;
     dap_chain_t * l_chain = NULL;
 
-    if (dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index,argc,argv,a_str_reply,&l_chain,&l_chain_net)) {
+    if (dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index,argc,argv,a_str_reply,&l_chain,&l_chain_net, CHAIN_TYPE_INVALID)) {
         return -3;
     }
 
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 a2ca43f5b781dd711543ab48668881520d9e9274..47f2127497a39564490e96e82f2ac9e4919232f7 100644
--- a/modules/service/stake/dap_chain_net_srv_stake_lock.c
+++ b/modules/service/stake/dap_chain_net_srv_stake_lock.c
@@ -27,10 +27,11 @@
 #include "dap_time.h"
 #include "dap_chain_ledger.h"
 #include "dap_chain_net_srv_stake_lock.h"
-#include "dap_chain_node_cli.h"
+#include "dap_chain_net_tx.h"
 #include "dap_chain_wallet.h"
 #include "dap_chain_mempool.h"
 #include "dap_chain_net_srv.h"
+#include "dap_cli_server.h"
 
 static bool s_debug_more = false;
 
@@ -108,6 +109,140 @@ dap_chain_datum_t *s_stake_unlock_datum_create(dap_chain_net_t *a_net, dap_enc_k
 // Callbacks
 static void s_stake_lock_callback_updater(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_tx_out_cond_t *a_prev_out_item);
 static bool s_stake_lock_callback_verificator(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_t *a_cond, dap_chain_datum_tx_t *a_tx_in, bool a_owner);
+
+static inline int s_tsd_str_cmp(const byte_t *a_tsdata, size_t a_tsdsize,  const char *str ) {
+    size_t l_strlen = (size_t)strlen(str);
+    if (l_strlen != a_tsdsize) return -1;
+    return memcmp(a_tsdata, str, l_strlen);
+}
+
+//emission tags
+//inherits from emission tsd section for engine-produced auth emissions
+bool s_get_ems_staking_action(dap_chain_datum_token_emission_t *a_ems, dap_chain_tx_tag_action_type_t *a_action)
+{
+    if (!a_ems || !a_action)
+        return false;
+
+    *a_action = DAP_CHAIN_TX_TAG_ACTION_UNKNOWN;
+
+    
+    size_t src_tsd_size = 0;
+    size_t subsrc_tsd_size = 0;
+    
+    byte_t *ems_src = dap_chain_emission_get_tsd(a_ems, DAP_CHAIN_DATUM_EMISSION_TSD_TYPE_SOURCE, &src_tsd_size);
+    byte_t *ems_subsrc = dap_chain_emission_get_tsd(a_ems, DAP_CHAIN_DATUM_EMISSION_TSD_TYPE_SOURCE_SUBTYPE, &subsrc_tsd_size);
+
+    if (ems_src && src_tsd_size)
+    {
+        if (s_tsd_str_cmp(ems_src, src_tsd_size, DAP_CHAIN_DATUM_TOKEN_EMISSION_SOURCE_STAKING) != 0)
+            return false;
+    }
+
+    //special processing for old stakes: they have only STAKING in tsd 9 and no subtype. it is opening stakes
+    if (ems_src && !ems_subsrc)
+    {
+        *a_action = DAP_CHAIN_TX_TAG_ACTION_OPEN;
+        return true;
+    }
+
+    if (ems_subsrc && subsrc_tsd_size)
+    {
+        if (s_tsd_str_cmp(ems_subsrc, subsrc_tsd_size, DAP_CHAIN_DATUM_TOKEN_EMISSION_SOURCE_SUBTYPE_STAKING_STAKE_CROSSCHAIN)==0)
+            *a_action =  DAP_CHAIN_TX_TAG_ACTION_OPEN;
+
+        if (s_tsd_str_cmp(ems_subsrc, subsrc_tsd_size, DAP_CHAIN_DATUM_TOKEN_EMISSION_SOURCE_SUBTYPE_STAKING_STAKE_CROSSCHAINV2)==0)
+            *a_action =  DAP_CHAIN_TX_TAG_ACTION_OPEN;
+
+        if (s_tsd_str_cmp(ems_subsrc, subsrc_tsd_size, DAP_CHAIN_DATUM_TOKEN_EMISSION_SOURCE_SUBTYPE_STAKING_HARVEST)==0) 
+            *a_action =  DAP_CHAIN_TX_TAG_ACTION_TRANSFER_REWARD;
+
+        if (s_tsd_str_cmp(ems_subsrc, subsrc_tsd_size, DAP_CHAIN_DATUM_TOKEN_EMISSION_SOURCE_SUBTYPE_STAKING_ADDLIQ)==0) 
+            *a_action =  DAP_CHAIN_TX_TAG_ACTION_EXTEND;
+
+        if (s_tsd_str_cmp(ems_subsrc, subsrc_tsd_size, DAP_CHAIN_DATUM_TOKEN_EMISSION_SOURCE_SUBTYPE_STAKING_EMSFIX)==0) 
+            *a_action =  DAP_CHAIN_TX_TAG_ACTION_CHANGE;
+    
+        if (s_tsd_str_cmp(ems_subsrc, subsrc_tsd_size, DAP_CHAIN_DATUM_TOKEN_EMISSION_SOURCE_SUBTYPE_STAKING_BONUS)==0) 
+            *a_action =  DAP_CHAIN_TX_TAG_ACTION_CHANGE;
+        
+
+        if (s_tsd_str_cmp(ems_subsrc, subsrc_tsd_size, DAP_CHAIN_DATUM_TOKEN_EMISSION_SOURCE_SUBTYPE_STAKING_UNSTAKE_FINALIZATION)==0)
+            *a_action = DAP_CHAIN_TX_TAG_ACTION_TRANSFER_REWARD;
+    
+        if (*a_action == DAP_CHAIN_TX_TAG_ACTION_UNKNOWN)
+        {
+            log_it(L_WARNING, "Unknown action for staking: %s", ems_subsrc);
+        }     
+        return true;
+    }
+
+    return false;
+}
+
+static bool s_tag_check_staking(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx,  dap_chain_datum_tx_item_groups_t *a_items_grp, dap_chain_tx_tag_action_type_t *a_action)
+{
+    //staking native open: have SRV_STAKE_LOCK out
+    
+    if (a_items_grp->items_out_cond_srv_stake_lock) {
+        *a_action = DAP_CHAIN_TX_TAG_ACTION_OPEN;
+        return true;
+    }
+    
+    //staking native close: have IN_COND linked with SRV_STAKE_LOCK out
+    if (a_items_grp->items_in_cond) 
+    {
+       for (dap_list_t *it = a_items_grp->items_in_cond; it; it = it->next) {
+            dap_chain_tx_in_cond_t *l_tx_in = it->data;
+            dap_chain_tx_out_cond_t *l_tx_out_cond = dap_chain_ledger_get_tx_out_cond_linked_to_tx_in_cond(a_ledger, l_tx_in);
+
+            if (l_tx_out_cond && l_tx_out_cond->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK) {
+                if (a_action) *a_action = DAP_CHAIN_TX_TAG_ACTION_CLOSE;
+                return true;
+            }   
+        }
+    }
+
+    //m-token burn: have TSD-items with "STAKING type UNSTAKE subtype"
+    
+    if (a_items_grp->items_tsd) {
+        
+        bool src_staking = false;
+        bool subtype_unstake = false;
+        for (dap_list_t *it = a_items_grp->items_tsd; it; it = it->next) {
+            dap_chain_tx_tsd_t *l_tx_tsd = it->data;
+            int l_type;
+            size_t l_size;
+            byte_t *l_data = dap_chain_datum_tx_item_get_data(l_tx_tsd, &l_type, &l_size);
+            
+            
+            if (l_type == DAP_CHAIN_DATUM_EMISSION_TSD_TYPE_SOURCE && s_tsd_str_cmp(l_data, l_size, DAP_CHAIN_DATUM_TOKEN_EMISSION_SOURCE_STAKING) == 0)
+                src_staking = true;
+            
+            if (l_type == DAP_CHAIN_DATUM_EMISSION_TSD_TYPE_SOURCE_SUBTYPE && s_tsd_str_cmp(l_data, l_size, DAP_CHAIN_DATUM_TOKEN_EMISSION_SOURCE_SUBTYPE_STAKING_UNSTAKE_FINALIZATION) == 0)
+                subtype_unstake = true;
+        }
+        if (subtype_unstake && src_staking)
+        {
+            if(a_action) *a_action = DAP_CHAIN_TX_TAG_ACTION_CLOSE;
+            return true;
+        }
+    }
+
+    //crosschain staking AUTH emissions 
+    if (!a_items_grp->items_in_ems)
+        return false;
+
+    dap_chain_tx_in_ems_t *l_tx_in_ems = a_items_grp->items_in_ems->data;
+    dap_hash_fast_t ems_hash = l_tx_in_ems->header.token_emission_hash;
+    dap_chain_datum_token_emission_t *l_emission = dap_ledger_token_emission_find(a_ledger, &ems_hash);
+    if(l_emission) {   
+        bool success = s_get_ems_staking_action(l_emission, a_action);
+        return success;
+    }
+
+    return false;
+}
+
 /**
  * @brief dap_chain_net_srv_external_stake_init
  * @return
@@ -131,6 +266,10 @@ int dap_chain_net_srv_stake_lock_init()
                 "-chain <chain>\n"
     );
     s_debug_more = dap_config_get_item_bool_default(g_config, "ledger", "debug_more", false);
+
+    dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_STAKE_LOCK_ID };
+    dap_ledger_service_add(l_uid, "staking", s_tag_check_staking);
+
     return 0;
 }
 
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 0263288f64d748658c2d155bff1a9a9a9ddd3896..5ad85b61bf1798d2835a33b1aafe163b256674ff 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
@@ -23,13 +23,14 @@
 */
 
 #include <math.h>
-#include "dap_chain_node_cli.h"
+#include "dap_chain_wallet.h"
 #include "dap_config.h"
 #include "dap_string.h"
 #include "dap_list.h"
 #include "dap_enc_base58.h"
 #include "dap_chain_common.h"
 #include "dap_chain_mempool.h"
+#include "dap_chain_net_decree.h"
 #include "dap_chain_net_tx.h"
 #include "dap_chain_net_srv.h"
 #include "dap_chain_net_srv_stake_pos_delegate.h"
@@ -37,8 +38,9 @@
 #include "rand/dap_rand.h"
 #include "dap_chain_node_client.h"
 #include "dap_stream_ch_chain_net_pkt.h"
-#include "dap_chain_node_cli_cmd.h"
 #include "json_object.h"
+#include "dap_cli_server.h"
+#include "dap_chain_net_srv_order.h"
 
 #define LOG_TAG "dap_chain_net_srv_stake_pos_delegate"
 
@@ -55,11 +57,33 @@ static void s_stake_deleted_callback(dap_ledger_t *a_ledger, dap_chain_datum_tx_
 static void s_cache_data(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_addr_t *a_signing_addr);
 static void s_uncache_data(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_addr_t *a_signing_addr);
 
-static void s_stake_clear();
+static dap_list_t *s_srv_stake_list = NULL;
 
-static void s_stake_net_clear(dap_chain_net_t *a_net);
+static bool s_tag_check_key_delegation(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_datum_tx_item_groups_t *a_items_grp, dap_chain_tx_tag_action_type_t *a_action)
+{
+    // keydelegation open: have STAK_POS_DELEGATE out
+    
+    if (a_items_grp->items_out_cond_srv_stake_pos_delegate) {
+        if (a_action) *a_action = DAP_CHAIN_TX_TAG_ACTION_OPEN;
+        return true;
+    }
+
+    //key delegation invalidation (close): have IN_COND linked with STAKE_POS_DELEGATE out
+    if (a_items_grp->items_in_cond) 
+    {
+       for (dap_list_t *it = a_items_grp->items_in_cond; it; it = it->next) {
+            dap_chain_tx_in_cond_t *l_tx_in = it->data;
+            dap_chain_tx_out_cond_t *l_tx_out_cond = dap_chain_ledger_get_tx_out_cond_linked_to_tx_in_cond(a_ledger, l_tx_in);
+
+            if (l_tx_out_cond && l_tx_out_cond->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE) {
+                if (a_action) *a_action = DAP_CHAIN_TX_TAG_ACTION_CLOSE;
+                return true;
+            }   
+        }
+    }
 
-static dap_chain_net_srv_stake_t *s_srv_stake = NULL;
+    return false;
+}
 
 /**
  * @brief dap_stream_ch_vpn_init Init actions for VPN stream channel
@@ -100,70 +124,84 @@ int dap_chain_net_srv_stake_pos_delegate_init()
          "\tShow the list of active stake keys (optional delegated with specified cert).\n"
     "srv_stake list tx -net <net_name> \n"
          "\tShow the list of key delegation transactions.\n"
-    "srv_stake min_value -net <net_name> -cert <cert_name> -value <value>"
+    "srv_stake min_value -net <net_name> [-chain <chain_name>] -poa_cert <poa_cert_name> -value <value>\n"
          "\tSets the minimum stake value\n"
+    "srv_stake max_weight -net <net_name> [-chain <chain_name>] -poa_cert <poa_cert_name> -percent <value>\n"
+        "\tSets maximum validator related weight (in percent)\n"
     "srv_stake check -net <net_name> -tx <tx_hash>"
          "\tCheck remote validator"
     );
 
-    s_srv_stake = DAP_NEW_Z(dap_chain_net_srv_stake_t);
-    if (!s_srv_stake) {
-        log_it(L_CRITICAL, "%s", g_error_memory_alloc);
-        return -1;
+    dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_STAKE_POS_DELEGATE_ID };
+    dap_ledger_service_add(l_uid, "pos_delegate", s_tag_check_key_delegation);
+    return 0;
+}
+
+static dap_chain_net_srv_stake_t *s_srv_stake_by_net_id(dap_chain_net_id_t a_net_id)
+{
+    for (dap_list_t *it = s_srv_stake_list; it; it = it->next) {
+        dap_chain_net_srv_stake_t *l_srv_stake = it->data;
+        if (l_srv_stake->net_id.uint64 == a_net_id.uint64)
+            return l_srv_stake;
     }
-    s_srv_stake->delegate_allowed_min = dap_chain_coins_to_balance("1.0");
+    return NULL;
+}
 
+int dap_chain_net_srv_stake_net_add(dap_chain_net_id_t a_net_id)
+{
+    dap_chain_net_srv_stake_t *l_srv_stake;
+    DAP_NEW_Z_RET_VAL(l_srv_stake, dap_chain_net_srv_stake_t, -1, NULL);
+    l_srv_stake->net_id = a_net_id;
+    l_srv_stake->delegate_allowed_min = dap_chain_coins_to_balance("1.0");
+    dap_list_t *l_list_new = dap_list_append(s_srv_stake_list, l_srv_stake);
+    if (dap_list_last(l_list_new) == dap_list_last(s_srv_stake_list)) {
+        log_it(L_ERROR, "Can't add net %" DAP_UINT64_FORMAT_x "to stake service net list", a_net_id.uint64);
+        DAP_DELETE(l_srv_stake);
+        return -2;
+    }
+    s_srv_stake_list = l_list_new;
+    log_it(L_NOTICE, "Successfully added net ID 0x%016" DAP_UINT64_FORMAT_x, a_net_id.uint64);
     return 0;
 }
 
 /**
  * @brief delete ht and hh concretic net from s_srv_stake 
  */
-void s_stake_net_clear(dap_chain_net_t *a_net)
+static void s_stake_net_clear(dap_chain_net_t *a_net)
 {
+    dap_chain_net_srv_stake_t *l_srv_stake = s_srv_stake_by_net_id(a_net->pub.id);
+    dap_return_if_fail(l_srv_stake);
     dap_chain_net_srv_stake_item_t *l_stake = NULL, *l_tmp = NULL;
-    HASH_ITER(ht, s_srv_stake->tx_itemlist, l_stake, l_tmp) {
+    HASH_ITER(ht, l_srv_stake->tx_itemlist, l_stake, l_tmp) {
         // Clang bug at this, l_stake should change at every loop cycle
-        if (l_stake->net->pub.id.uint64 == a_net->pub.id.uint64)
-            HASH_DELETE(ht, s_srv_stake->tx_itemlist, l_stake);
+        HASH_DELETE(ht, l_srv_stake->tx_itemlist, l_stake);
     }
-    HASH_ITER(hh, s_srv_stake->itemlist, l_stake, l_tmp) {
+    HASH_ITER(hh, l_srv_stake->itemlist, l_stake, l_tmp) {
         // Clang bug at this, l_stake should change at every loop cycle
-        if (l_stake->net->pub.id.uint64 == a_net->pub.id.uint64) {
-            HASH_DEL(s_srv_stake->itemlist, l_stake);
-            DAP_DELETE(l_stake);
-        }
+        HASH_DEL(l_srv_stake->itemlist, l_stake);
+        DAP_DELETE(l_stake);
     }
     dap_chain_net_srv_stake_cache_item_t *l_cache_item = NULL, *l_cache_tmp = NULL;
-    HASH_ITER(hh, s_srv_stake->cache, l_cache_item, l_cache_tmp) {
+    HASH_ITER(hh, l_srv_stake->cache, l_cache_item, l_cache_tmp) {
         // Clang bug at this, l_stake should change at every loop cycle
-        if (l_cache_item->signing_addr.net_id.uint64 == a_net->pub.id.uint64) {
-            HASH_DEL(s_srv_stake->cache, l_cache_item);
-            DAP_DELETE(l_cache_item);
-        }
-    }
-}
-
-/**
- * @brief delete all nets ht and hh from s_srv_stake 
- */
-void s_stake_clear()
-{
-    for (dap_chain_net_t *it = dap_chain_net_iter_start(); it; it = dap_chain_net_iter_next(it)) {
-        s_stake_net_clear(it);
+        HASH_DEL(l_srv_stake->cache, l_cache_item);
+        DAP_DELETE(l_cache_item);
     }
 }
 
 void dap_chain_net_srv_stake_pos_delegate_deinit()
 {
-    s_stake_clear();
-    DAP_DEL_Z(s_srv_stake);
+    for (dap_chain_net_t *it = dap_chain_net_iter_start(); it; it = dap_chain_net_iter_next(it))
+        s_stake_net_clear(it);
+    dap_list_free_full(s_srv_stake_list, NULL);
+    s_srv_stake_list = NULL;
 }
 
-static bool s_stake_verificator_callback(dap_ledger_t UNUSED_ARG *a_ledger, dap_chain_tx_out_cond_t *a_cond,
+static bool s_stake_verificator_callback(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_t *a_cond,
                                          dap_chain_datum_tx_t *a_tx_in, bool a_owner)
 {
-    assert(s_srv_stake);
+    dap_chain_net_srv_stake_t *l_srv_stake = s_srv_stake_by_net_id(a_ledger->net->pub.id);
+    dap_return_val_if_fail(l_srv_stake, false);
     // It's a order conditional TX
     if (dap_chain_addr_is_blank(&a_cond->subtype.srv_stake_pos_delegate.signing_addr) ||
             a_cond->subtype.srv_stake_pos_delegate.signer_node_addr.uint64 == 0) {
@@ -178,7 +216,7 @@ static bool s_stake_verificator_callback(dap_ledger_t UNUSED_ARG *a_ledger, dap_
         if (compare256(l_tx_out_cond->header.value, a_cond->header.value)) {
             char *l_in_value = dap_chain_balance_to_coins(l_tx_out_cond->header.value);
             char *l_out_value = dap_chain_balance_to_coins(a_cond->header.value);
-            log_it(L_WARNING, "In value %s is not eqal to out value %s", l_in_value, l_out_value);
+            log_it(L_WARNING, "In value %s is not equal to out value %s", l_in_value, l_out_value);
             DAP_DELETE(l_in_value);
             DAP_DELETE(l_out_value);
             return false;
@@ -237,7 +275,7 @@ static bool s_stake_verificator_callback(dap_ledger_t UNUSED_ARG *a_ledger, dap_
     if (a_tx_in->header.ts_created < 1706227200) // Jan 26 2024 00:00:00 GMT, old policy rules
         return true;
     dap_chain_net_srv_stake_item_t *l_stake;
-    HASH_FIND(ht, s_srv_stake->tx_itemlist, l_prev_hash, sizeof(dap_hash_t), l_stake);
+    HASH_FIND(ht, l_srv_stake->tx_itemlist, l_prev_hash, sizeof(dap_hash_t), l_stake);
     if (l_stake) {
         log_it(L_WARNING, "Key is active with delegation decree, need to revoke it first");
         return false;
@@ -247,7 +285,8 @@ static bool s_stake_verificator_callback(dap_ledger_t UNUSED_ARG *a_ledger, dap_
 
 static void s_stake_updater_callback(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_tx_out_cond_t *a_cond)
 {
-    assert(s_srv_stake);
+    dap_chain_net_srv_stake_t *l_srv_stake = s_srv_stake_by_net_id(a_ledger->net->pub.id);
+    dap_return_if_fail(l_srv_stake);
     if (!a_cond)
         return;
     dap_chain_addr_t *l_signing_addr = &a_cond->subtype.srv_stake_pos_delegate.signing_addr;
@@ -278,31 +317,80 @@ static bool s_srv_stake_is_poa_cert(dap_chain_net_t *a_net, dap_enc_key_t *a_key
     return l_is_poa_cert;
 }
 
+#define LIMIT_DELTA UINT64_C(1000000000000) // 1.0e-6
+static bool s_weights_truncate(dap_chain_net_srv_stake_t *l_srv_stake, const uint256_t a_limit)
+{
+    uint256_t l_sum = uint256_0;
+    for (dap_chain_net_srv_stake_item_t *it = l_srv_stake->itemlist; it; it = it->hh.next)
+        SUM_256_256(l_sum, it->value, &l_sum);
+    uint256_t l_weight_max;
+    MULT_256_COIN(l_sum, a_limit, &l_weight_max);
+    size_t l_exceeds_count = 0;
+    uint256_t l_sum_others = l_sum;
+    for (dap_chain_net_srv_stake_item_t *it = l_srv_stake->itemlist; it; it = it->hh.next) {
+        uint256_t l_weight_with_delta;
+        SUBTRACT_256_256(it->value, GET_256_FROM_64(LIMIT_DELTA), &l_weight_with_delta);
+        if (compare256(l_weight_with_delta, l_weight_max) == 1) {
+            SUBTRACT_256_256(l_sum_others, it->value, &l_sum_others);
+            it->value = uint256_0;
+            l_exceeds_count++;
+        }
+    }
+    if (l_exceeds_count) {
+        uint256_t delta = dap_uint256_decimal_from_uint64(l_exceeds_count);
+        uint256_t kappa;
+        DIV_256_COIN(dap_uint256_decimal_from_uint64(1), a_limit, &kappa);
+        SUBTRACT_256_256(kappa, delta, &kappa);
+        DIV_256_COIN(l_sum_others, kappa, &kappa);
+        for (dap_chain_net_srv_stake_item_t *it = l_srv_stake->itemlist; it; it = it->hh.next)
+            if (IS_ZERO_256(it->value))
+                it->value = kappa;
+    }
+    return l_exceeds_count;
+}
+
+static void s_stake_recalculate_weights(dap_chain_net_id_t a_net_id)
+{
+    dap_chain_net_srv_stake_t *l_srv_stake = s_srv_stake_by_net_id(a_net_id);
+    dap_return_if_fail(l_srv_stake);
+    if (IS_ZERO_256(l_srv_stake->delegate_percent_max))
+        return;
+    size_t l_validators_count = HASH_COUNT(l_srv_stake->itemlist);
+    uint256_t l_limit_min;
+    DIV_256(dap_uint256_decimal_from_uint64(1), GET_256_FROM_64(l_validators_count), &l_limit_min);
+    if (compare256(l_srv_stake->delegate_percent_max, l_limit_min) == 1)
+        l_limit_min = l_srv_stake->delegate_percent_max;
+    for (dap_chain_net_srv_stake_item_t *it = l_srv_stake->itemlist; it; it = it->hh.next)
+        it->value = it->locked_value;       // restore original locked values
+    while (s_weights_truncate(l_srv_stake, l_limit_min));
+}
+
 void dap_chain_net_srv_stake_key_delegate(dap_chain_net_t *a_net, dap_chain_addr_t *a_signing_addr, dap_hash_fast_t *a_stake_tx_hash,
                                           uint256_t a_value, dap_chain_node_addr_t *a_node_addr)
 {
-    assert(s_srv_stake);
     dap_return_if_fail(a_net && a_signing_addr && a_node_addr && a_stake_tx_hash);
+    dap_chain_net_srv_stake_t *l_srv_stake = s_srv_stake_by_net_id(a_net->pub.id);
+    dap_return_if_fail(l_srv_stake);
 
     dap_chain_net_srv_stake_item_t *l_stake = NULL;
     bool l_found = false;
-    HASH_FIND(hh, s_srv_stake->itemlist, a_signing_addr, sizeof(dap_chain_addr_t), l_stake);
+    HASH_FIND(hh, l_srv_stake->itemlist, &a_signing_addr->data.hash_fast, sizeof(dap_hash_fast_t), l_stake);
     if (!l_stake)
         l_stake = DAP_NEW_Z(dap_chain_net_srv_stake_item_t);
     else {
         l_found = true;
-        HASH_DELETE(ht, s_srv_stake->tx_itemlist, l_stake);
+        HASH_DELETE(ht, l_srv_stake->tx_itemlist, l_stake);
     }
     l_stake->net = a_net;
     l_stake->node_addr = *a_node_addr;
     l_stake->signing_addr = *a_signing_addr;
-    l_stake->value = a_value;
+    l_stake->value = l_stake->locked_value = a_value;
     l_stake->tx_hash = *a_stake_tx_hash;
     l_stake->is_active = true;
     if (!l_found)
-        HASH_ADD(hh, s_srv_stake->itemlist, signing_addr, sizeof(dap_chain_addr_t), l_stake);
+        HASH_ADD(hh, l_srv_stake->itemlist, signing_addr.data.hash_fast, sizeof(dap_hash_fast_t), l_stake);
     if (!dap_hash_fast_is_blank(a_stake_tx_hash)) {
-        HASH_ADD(ht, s_srv_stake->tx_itemlist, tx_hash, sizeof(dap_chain_hash_fast_t), l_stake);
+        HASH_ADD(ht, l_srv_stake->tx_itemlist, tx_hash, sizeof(dap_hash_fast_t), l_stake);
         dap_chain_datum_tx_t *l_tx = dap_ledger_tx_find_by_hash(a_net->pub.ledger, a_stake_tx_hash);
         if (l_tx) {
             dap_chain_tx_out_cond_t *l_cond = dap_chain_datum_tx_out_cond_get(l_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE, NULL);
@@ -320,80 +408,126 @@ void dap_chain_net_srv_stake_key_delegate(dap_chain_net_t *a_net, dap_chain_addr
     char l_key_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE];
     dap_chain_hash_fast_to_str(&a_signing_addr->data.hash_fast,
                                l_key_hash_str, DAP_CHAIN_HASH_FAST_STR_SIZE);
-    char *l_value_str; dap_uint256_to_char(a_value, &l_value_str);
-    log_it(L_NOTICE, "Added key with fingerprint %s and value %s for node "NODE_ADDR_FP_STR,
+    const char *l_value_str; dap_uint256_to_char(a_value, &l_value_str);
+    log_it(L_NOTICE, "Added key with fingerprint %s and locked value %s for node "NODE_ADDR_FP_STR,
                         l_key_hash_str, l_value_str, NODE_ADDR_FP_ARGS(a_node_addr));
+    s_stake_recalculate_weights(a_signing_addr->net_id);
 }
 
 void dap_chain_net_srv_stake_key_invalidate(dap_chain_addr_t *a_signing_addr)
 {
-    assert(s_srv_stake);
     if (!a_signing_addr)
         return;
+    dap_chain_net_srv_stake_t *l_srv_stake = s_srv_stake_by_net_id(a_signing_addr->net_id);
+    dap_return_if_fail(l_srv_stake);
     dap_chain_net_srv_stake_item_t *l_stake = NULL;
-    HASH_FIND(hh, s_srv_stake->itemlist, a_signing_addr, sizeof(dap_chain_addr_t), l_stake);
+    HASH_FIND(hh, l_srv_stake->itemlist, &a_signing_addr->data.hash_fast, sizeof(dap_hash_fast_t), l_stake);
     if (l_stake) {
         dap_chain_esbocs_remove_validator_from_clusters(l_stake->signing_addr.net_id, &l_stake->node_addr);
-        HASH_DEL(s_srv_stake->itemlist, l_stake);
-        HASH_DELETE(ht, s_srv_stake->tx_itemlist, l_stake);
+        HASH_DEL(l_srv_stake->itemlist, l_stake);
+        HASH_DELETE(ht, l_srv_stake->tx_itemlist, l_stake);
         char l_key_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE];
         dap_chain_hash_fast_to_str(&a_signing_addr->data.hash_fast,
                                    l_key_hash_str, DAP_CHAIN_HASH_FAST_STR_SIZE);
-        char *l_value_str; dap_uint256_to_char(l_stake->value, &l_value_str);
-        log_it(L_NOTICE, "Removed key with fingerprint %s and value %s for node "NODE_ADDR_FP_STR,
+        const char *l_value_str; dap_uint256_to_char(l_stake->locked_value, &l_value_str);
+        log_it(L_NOTICE, "Removed key with fingerprint %s and locked value %s for node "NODE_ADDR_FP_STR,
                             l_key_hash_str, l_value_str, NODE_ADDR_FP_ARGS_S(l_stake->node_addr));
         DAP_DELETE(l_stake);
     }
+    s_stake_recalculate_weights(a_signing_addr->net_id);
 }
 
-void dap_chain_net_srv_stake_set_allowed_min_value(uint256_t a_value)
+void dap_chain_net_srv_stake_set_allowed_min_value(dap_chain_net_id_t a_net_id, uint256_t a_value)
 {
-    assert(s_srv_stake);
-    s_srv_stake->delegate_allowed_min = a_value;
-    for (dap_chain_net_srv_stake_item_t *it = s_srv_stake->itemlist; it; it = it->hh.next)
+    dap_chain_net_srv_stake_t *l_srv_stake = s_srv_stake_by_net_id(a_net_id);
+    dap_return_if_fail(l_srv_stake);
+    l_srv_stake->delegate_allowed_min = a_value;
+    for (dap_chain_net_srv_stake_item_t *it = l_srv_stake->itemlist; it; it = it->hh.next)
         if (dap_hash_fast_is_blank(&it->tx_hash))
             it->value = a_value;
 }
 
-uint256_t dap_chain_net_srv_stake_get_allowed_min_value()
+void dap_chain_net_srv_stake_set_percent_max(dap_chain_net_id_t a_net_id, uint256_t a_value)
 {
-    assert(s_srv_stake);
-    return s_srv_stake->delegate_allowed_min;
+    dap_chain_net_srv_stake_t *l_srv_stake = s_srv_stake_by_net_id(a_net_id);
+    dap_return_if_fail(l_srv_stake);
+    l_srv_stake->delegate_percent_max = a_value;
+    s_stake_recalculate_weights(a_net_id);
 }
 
-int dap_chain_net_srv_stake_key_delegated(dap_chain_addr_t *a_signing_addr)
+uint256_t dap_chain_net_srv_stake_get_allowed_min_value(dap_chain_net_id_t a_net_id)
 {
-    assert(s_srv_stake);
-    if (!a_signing_addr)
-        return 0;
+    dap_chain_net_srv_stake_t *l_srv_stake = s_srv_stake_by_net_id(a_net_id);
+    dap_return_val_if_fail(l_srv_stake, uint256_0);
+    return l_srv_stake->delegate_allowed_min;
+}
 
+uint256_t dap_chain_net_srv_stake_get_percent_max(dap_chain_net_id_t a_net_id)
+{
+    dap_chain_net_srv_stake_t *l_srv_stake = s_srv_stake_by_net_id(a_net_id);
+    dap_return_val_if_fail(l_srv_stake, uint256_0);
+    return l_srv_stake->delegate_percent_max;
+}
+
+int dap_chain_net_srv_stake_key_delegated(dap_chain_addr_t *a_signing_addr)
+{
+    dap_return_val_if_fail(a_signing_addr, 0);
+    dap_chain_net_srv_stake_t *l_srv_stake = s_srv_stake_by_net_id(a_signing_addr->net_id);
+    dap_return_val_if_fail(l_srv_stake, 0);
     dap_chain_net_srv_stake_item_t *l_stake = NULL;
-    HASH_FIND(hh, s_srv_stake->itemlist, a_signing_addr, sizeof(dap_chain_addr_t), l_stake);
+    HASH_FIND(hh, l_srv_stake->itemlist, &a_signing_addr->data.hash_fast, sizeof(dap_hash_fast_t), l_stake);
     if (l_stake) // public key delegated for this network
         return l_stake->is_active ? 1 : -1;
     return 0;
 }
 
-dap_list_t *dap_chain_net_srv_stake_get_validators(dap_chain_net_id_t a_net_id, bool a_only_active)
+dap_list_t *dap_chain_net_srv_stake_get_validators(dap_chain_net_id_t a_net_id, bool a_only_active, uint16_t **a_excluded_list)
 {
+    dap_chain_net_srv_stake_t *l_srv_stake = s_srv_stake_by_net_id(a_net_id);
+    dap_return_val_if_fail(l_srv_stake, NULL);
+    if (!l_srv_stake->itemlist)
+        return NULL;
     dap_list_t *l_ret = NULL;
-    if (!s_srv_stake || !s_srv_stake->itemlist)
-        return l_ret;
-    for (dap_chain_net_srv_stake_item_t *l_stake = s_srv_stake->itemlist; l_stake; l_stake = l_stake->hh.next)
-        if (a_net_id.uint64 == l_stake->signing_addr.net_id.uint64 &&
-                a_only_active ? l_stake->is_active : true)
-            l_ret = dap_list_append(l_ret, DAP_DUP(l_stake));
+    const uint16_t l_arr_resize_step = 64;
+    size_t l_arr_size = l_arr_resize_step, l_arr_idx = 1, l_list_idx = 0;
+    if (a_excluded_list)
+        DAP_NEW_Z_COUNT_RET_VAL(*a_excluded_list, uint16_t, l_arr_size, NULL, NULL);
+    for (dap_chain_net_srv_stake_item_t *l_stake = l_srv_stake->itemlist; l_stake; l_stake = l_stake->hh.next) {
+        if (l_stake->is_active || !a_only_active) {
+            void *l_data = DAP_DUP(l_stake);
+            if (!l_data)
+                goto fail_ret;
+            l_ret = dap_list_append(l_ret, l_data);
+        }
+        if (!l_stake->is_active && a_excluded_list) {
+            *a_excluded_list[l_arr_idx++] = l_list_idx;
+            if (l_arr_idx == l_arr_size) {
+                l_arr_size += l_arr_resize_step;
+                void *l_new_arr = DAP_REALLOC(*a_excluded_list, l_arr_size * sizeof(uint16_t));
+                if (l_new_arr)
+                    goto fail_ret;
+                else
+                    *a_excluded_list = l_new_arr;
+            }
+        }
+        l_list_idx++;
+    }
     return l_ret;
+fail_ret:
+    log_it(L_CRITICAL, "%s", g_error_memory_alloc);
+    dap_list_free_full(l_ret, NULL);
+    if (a_excluded_list)
+        DAP_DELETE(*a_excluded_list);
+    return NULL;
 }
 
 int dap_chain_net_srv_stake_mark_validator_active(dap_chain_addr_t *a_signing_addr, bool a_on_off)
 {
-    assert(s_srv_stake);
-    if (!a_signing_addr)
-        return -1;
-
+    dap_return_val_if_fail(a_signing_addr, -1);
+    dap_chain_net_srv_stake_t *l_srv_stake = s_srv_stake_by_net_id(a_signing_addr->net_id);
+    dap_return_val_if_fail(l_srv_stake, -3);
     dap_chain_net_srv_stake_item_t *l_stake = NULL;
-    HASH_FIND(hh, s_srv_stake->itemlist, a_signing_addr, sizeof(dap_chain_addr_t), l_stake);
+    HASH_FIND(hh, l_srv_stake->itemlist, &a_signing_addr->data.hash_fast, sizeof(dap_hash_fast_t), l_stake);
     if (l_stake) { // public key delegated for this network
         l_stake->is_active = a_on_off;
         return 0;
@@ -403,11 +537,9 @@ int dap_chain_net_srv_stake_mark_validator_active(dap_chain_addr_t *a_signing_ad
 
 int dap_chain_net_srv_stake_verify_key_and_node(dap_chain_addr_t *a_signing_addr, dap_chain_node_addr_t *a_node_addr)
 {
-    assert(s_srv_stake);
-    if (!a_signing_addr || !a_node_addr){
-        log_it(L_WARNING, "Bad srv_stake_verify arguments");
-        return -100;
-    }
+    dap_return_val_if_fail(a_signing_addr && a_node_addr, -100);
+    dap_chain_net_srv_stake_t *l_srv_stake = s_srv_stake_by_net_id(a_signing_addr->net_id);
+    dap_return_val_if_fail(l_srv_stake, -104);
 
     if (dap_chain_addr_is_blank(a_signing_addr) || a_node_addr->uint64 == 0) {
         log_it(L_WARNING, "Trying to approve bad delegating TX. Node or key addr is blank");
@@ -415,7 +547,7 @@ int dap_chain_net_srv_stake_verify_key_and_node(dap_chain_addr_t *a_signing_addr
     }
 
     dap_chain_net_srv_stake_item_t *l_stake = NULL, *l_tmp = NULL;
-    HASH_ITER(hh, s_srv_stake->itemlist, l_stake, l_tmp){
+    HASH_ITER(hh, l_srv_stake->itemlist, l_stake, l_tmp){
         //check key not activated for other node
         if(dap_chain_addr_compare(a_signing_addr, &l_stake->signing_addr)){
             char l_key_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE];
@@ -440,10 +572,12 @@ int dap_chain_net_srv_stake_verify_key_and_node(dap_chain_addr_t *a_signing_addr
     return 0;
 }
 
-static bool s_stake_cache_check_tx(dap_hash_fast_t *a_tx_hash)
+static bool s_stake_cache_check_tx(dap_ledger_t *a_ledger, dap_hash_fast_t *a_tx_hash)
 {
+    dap_chain_net_srv_stake_t *l_srv_stake = s_srv_stake_by_net_id(a_ledger->net->pub.id);
+    dap_return_val_if_fail(l_srv_stake, false);
     dap_chain_net_srv_stake_cache_item_t *l_stake;
-    HASH_FIND(hh, s_srv_stake->cache, a_tx_hash, sizeof(*a_tx_hash), l_stake);
+    HASH_FIND(hh, l_srv_stake->cache, a_tx_hash, sizeof(*a_tx_hash), l_stake);
     if (l_stake) {
         dap_chain_net_srv_stake_key_invalidate(&l_stake->signing_addr);
         return true;
@@ -470,6 +604,9 @@ int dap_chain_net_srv_stake_load_cache(dap_chain_net_t *a_net)
         log_it(L_DEBUG, "Stake cache data not found");
         return -2;
     }
+    dap_chain_net_srv_stake_t *l_srv_stake = s_srv_stake_by_net_id(a_net->pub.id);
+    dap_return_val_if_fail(l_srv_stake, -4);
+
     for (size_t i = 0; i < l_objs_count; i++){
         dap_chain_net_srv_stake_cache_data_t *l_cache_data =
                 (dap_chain_net_srv_stake_cache_data_t *)l_objs[i].value;
@@ -480,7 +617,7 @@ int dap_chain_net_srv_stake_load_cache(dap_chain_net_t *a_net)
         }
         l_cache->signing_addr   = l_cache_data->signing_addr;
         l_cache->tx_hash        = l_cache_data->tx_hash;
-        HASH_ADD(hh, s_srv_stake->cache, tx_hash, sizeof(dap_hash_fast_t), l_cache);
+        HASH_ADD(hh, l_srv_stake->cache, tx_hash, sizeof(dap_hash_fast_t), l_cache);
     }
     dap_global_db_objs_delete(l_objs, l_objs_count);
     dap_ledger_set_cache_tx_check_callback(l_ledger, s_stake_cache_check_tx);
@@ -679,7 +816,7 @@ dap_chain_datum_decree_t *dap_chain_net_srv_stake_decree_approve(dap_chain_net_t
         log_it(L_WARNING, "Requested conditional transaction have another ticker (not %s)", l_delegated_ticker);
         return NULL;
     }
-    if (compare256(l_tx_out_cond->header.value, s_srv_stake->delegate_allowed_min) == -1) {
+    if (compare256(l_tx_out_cond->header.value, dap_chain_net_srv_stake_get_allowed_min_value(a_net->pub.id)) == -1) {
         log_it(L_WARNING, "Requested conditional transaction have not enough funds");
         return NULL;
     }
@@ -701,7 +838,7 @@ dap_chain_datum_decree_t *dap_chain_net_srv_stake_decree_approve(dap_chain_net_t
         log_it(L_CRITICAL, "%s", g_error_memory_alloc);
         return NULL;
     }
-    l_tsd->type = DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_TX_HASH;
+    l_tsd->type = DAP_CHAIN_DATUM_DECREE_TSD_TYPE_HASH;
     l_tsd->size = sizeof(dap_hash_fast_t);
     *(dap_hash_fast_t*)(l_tsd->data) = *a_stake_tx_hash;
     l_tsd_list = dap_list_append(l_tsd_list, l_tsd);
@@ -737,7 +874,7 @@ dap_chain_datum_decree_t *dap_chain_net_srv_stake_decree_approve(dap_chain_net_t
         dap_list_free_full(l_tsd_list, NULL);
         return NULL;
     }
-    l_tsd->type = DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_SIGNER_NODE_ADDR;
+    l_tsd->type = DAP_CHAIN_DATUM_DECREE_TSD_TYPE_NODE_ADDR;
     l_tsd->size = sizeof(dap_chain_node_addr_t);
     *(dap_chain_node_addr_t*)(l_tsd->data) = l_tx_out_cond->subtype.srv_stake_pos_delegate.signer_node_addr;
     l_tsd_list = dap_list_append(l_tsd_list, l_tsd);
@@ -1032,85 +1169,31 @@ static dap_chain_datum_decree_t *s_stake_decree_invalidate(dap_chain_net_t *a_ne
     return l_decree;
 }
 
-static dap_chain_datum_decree_t *s_stake_decree_set_min_stake(dap_chain_net_t *a_net, uint256_t a_value, dap_cert_t *a_cert)
+static dap_chain_datum_decree_t *s_stake_decree_set_max_weight(dap_chain_net_t *a_net, dap_chain_t *a_chain,
+                                                                uint256_t a_value, dap_cert_t *a_cert)
 {
-    size_t l_total_tsd_size = 0;
-    dap_chain_datum_decree_t *l_decree = NULL;
-    dap_list_t *l_tsd_list = NULL;
-    dap_tsd_t *l_tsd = NULL;
-
-    l_total_tsd_size += sizeof(dap_tsd_t) + sizeof(uint256_t);
-    l_tsd = DAP_NEW_Z_SIZE(dap_tsd_t, l_total_tsd_size);
-    if (!l_tsd) {
-        log_it(L_CRITICAL, "%s", g_error_memory_alloc);
+    size_t l_total_tsd_size = sizeof(dap_tsd_t) + sizeof(uint256_t);
+    dap_chain_datum_decree_t *l_decree = dap_chain_datum_decree_new(a_net->pub.id, a_chain->id,
+                                                                    *dap_chain_net_get_cur_cell(a_net), l_total_tsd_size);
+    if (!l_decree)
         return NULL;
-    }
-    l_tsd->type = DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_MIN_VALUE;
-    l_tsd->size = sizeof(uint256_t);
-    *(uint256_t*)(l_tsd->data) = a_value;
-    l_tsd_list = dap_list_append(l_tsd_list, l_tsd);
-
-    l_decree = DAP_NEW_Z_SIZE(dap_chain_datum_decree_t, sizeof(dap_chain_datum_decree_t) + l_total_tsd_size);
-    if (!l_decree) {
-        log_it(L_CRITICAL, "%s", g_error_memory_alloc);
-        dap_list_free_full(l_tsd_list, NULL);
-        return NULL;
-    }
-    l_decree->decree_version = DAP_CHAIN_DATUM_DECREE_VERSION;
-    l_decree->header.ts_created = dap_time_now();
-    l_decree->header.type = DAP_CHAIN_DATUM_DECREE_TYPE_COMMON;
-    l_decree->header.common_decree_params.net_id = a_net->pub.id;
-    dap_chain_t *l_chain = dap_chain_net_get_default_chain_by_chain_type(a_net, CHAIN_TYPE_ANCHOR);
-    if (!l_chain)
-        l_chain =  dap_chain_net_get_chain_by_chain_type(a_net, CHAIN_TYPE_ANCHOR);
-    if (!l_chain) {
-        log_it(L_ERROR, "No chain supported anchor datum type");
-        DAP_DEL_Z(l_decree);
-        dap_list_free_full(l_tsd_list, NULL);
-        return NULL;
-    }
-    l_decree->header.common_decree_params.chain_id = l_chain->id;
-    l_decree->header.common_decree_params.cell_id = *dap_chain_net_get_cur_cell(a_net);
-    l_decree->header.sub_type = DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_MIN_VALUE;
-    l_decree->header.data_size = l_total_tsd_size;
-    l_decree->header.signs_size = 0;
-
-    size_t l_data_tsd_offset = 0;
-    for ( dap_list_t* l_iter=dap_list_first(l_tsd_list); l_iter; l_iter=l_iter->next){
-        dap_tsd_t * l_b_tsd = (dap_tsd_t *) l_iter->data;
-        size_t l_tsd_size = dap_tsd_size(l_b_tsd);
-        memcpy((byte_t*)l_decree->data_n_signs + l_data_tsd_offset, l_b_tsd, l_tsd_size);
-        l_data_tsd_offset += l_tsd_size;
-    }
-    dap_list_free_full(l_tsd_list, NULL);
+    l_decree->header.sub_type = DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_MAX_WEIGHT;
+    dap_tsd_write(l_decree->data_n_signs, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_VALUE, &a_value, sizeof(uint256_t));
+    return dap_chain_datum_decree_sign_in_cycle(&a_cert, l_decree, 1, NULL);
+}
 
-    size_t l_cur_sign_offset = l_decree->header.data_size + l_decree->header.signs_size;
-    size_t l_total_signs_size = l_decree->header.signs_size;
 
-    dap_sign_t * l_sign = dap_cert_sign(a_cert,  l_decree,
-       sizeof(dap_chain_datum_decree_t) + l_decree->header.data_size, 0);
-
-    if (l_sign) {
-        size_t l_sign_size = dap_sign_get_size(l_sign);
-        l_decree = DAP_REALLOC(l_decree, sizeof(dap_chain_datum_decree_t) + l_cur_sign_offset + l_sign_size);
-        if (!l_decree) {
-            log_it(L_CRITICAL, "%s", g_error_memory_alloc);
-            DAP_DELETE(l_sign);
-            return NULL;
-        }
-        memcpy((byte_t*)l_decree->data_n_signs + l_cur_sign_offset, l_sign, l_sign_size);
-        l_total_signs_size += l_sign_size;
-        l_cur_sign_offset += l_sign_size;
-        l_decree->header.signs_size = l_total_signs_size;
-        DAP_DELETE(l_sign);
-        log_it(L_DEBUG,"<-- Signed with '%s'", a_cert->name);
-    }else{
-        log_it(L_ERROR, "Decree signing failed");
-        DAP_DELETE(l_decree);
+static dap_chain_datum_decree_t *s_stake_decree_set_min_stake(dap_chain_net_t *a_net, dap_chain_t *a_chain,
+                                                              uint256_t a_value, dap_cert_t *a_cert)
+{
+    size_t l_total_tsd_size = sizeof(dap_tsd_t) + sizeof(uint256_t);
+    dap_chain_datum_decree_t *l_decree = dap_chain_datum_decree_new(a_net->pub.id, a_chain->id,
+                                                                    *dap_chain_net_get_cur_cell(a_net), l_total_tsd_size);
+    if (!l_decree)
         return NULL;
-    }
-
-    return l_decree;
+    l_decree->header.sub_type = DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_MIN_VALUE;
+    dap_tsd_write(l_decree->data_n_signs, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_MIN_VALUE, &a_value, sizeof(uint256_t));
+    return dap_chain_datum_decree_sign_in_cycle(&a_cert, l_decree, 1, NULL);
 }
 
 char *s_fee_order_create(dap_chain_net_t *a_net, uint256_t *a_fee, dap_enc_key_t *a_key, const char *a_hash_out_type)
@@ -1286,7 +1369,7 @@ static int s_cli_srv_stake_order(int a_argc, char **a_argv, int a_arg_index, voi
         uint256_t l_tax = dap_chain_coins_to_balance(l_tax_str);
         if (compare256(l_tax, dap_chain_coins_to_balance("100.0")) == 1 ||
                 compare256(l_tax, GET_256_FROM_64(100)) == -1) {
-            dap_cli_server_cmd_set_reply_text(a_str_reply, "Tax must be lower or eqal than 100%% and higher or eqal than 1.0e-16%%");
+            dap_cli_server_cmd_set_reply_text(a_str_reply, "Tax must be lower or equal than 100%% and higher or equal than 1.0e-16%%");
             return -10;
         }
         const char *l_cert_str = NULL;
@@ -1361,7 +1444,7 @@ static int s_cli_srv_stake_order(int a_argc, char **a_argv, int a_arg_index, voi
         uint256_t l_tax = dap_chain_coins_to_balance(l_tax_str);
         if (compare256(l_tax, dap_chain_coins_to_balance("100.0")) == 1 ||
                 compare256(l_tax, GET_256_FROM_64(100)) == -1) {
-            dap_cli_server_cmd_set_reply_text(a_str_reply, "Tax must be lower or eqal than 100%% and higher or eqal than 1.0e-16%%");
+            dap_cli_server_cmd_set_reply_text(a_str_reply, "Tax must be lower or equal than 100%% and higher or equal than 1.0e-16%%");
             return -10;
         }
         dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-w", &l_wallet_str);
@@ -1526,7 +1609,7 @@ static int s_cli_srv_stake_order(int a_argc, char **a_argv, int a_arg_index, voi
                         dap_string_append(l_reply_str, "Value in this order type means minimum value of m-tokens for validator acceptable for key delegation with supplied tax\n"
                                                        "Order external params:\n");
                         struct validator_odrer_ext *l_ext = (struct validator_odrer_ext *)l_order->ext_n_sign;
-                        char *l_coins_str;
+                        const char *l_coins_str;
                         dap_uint256_to_char(l_ext->tax, &l_coins_str);
                         dap_string_append_printf(l_reply_str, "  tax:              %s%%\n", l_coins_str);
                         dap_uint256_to_char(l_ext->value_max, &l_coins_str);
@@ -1550,7 +1633,7 @@ static int s_cli_srv_stake_order(int a_argc, char **a_argv, int a_arg_index, voi
                             }
                         }
                         if (!l_error) {
-                            char *l_tax_str; dap_uint256_to_char(l_tax, &l_tax_str);
+                            const char *l_tax_str; dap_uint256_to_char(l_tax, &l_tax_str);
                             dap_string_append_printf(l_reply_str, "  sovereign_tax:    %s%%\n  sovereign_addr:   %s\n",
                                 l_tax_str, dap_chain_addr_to_str(&l_addr));
                         } else
@@ -1764,7 +1847,7 @@ static int s_cli_srv_stake_delegate(int a_argc, char **a_argv, int a_arg_index,
             struct validator_odrer_ext *l_ext = (struct validator_odrer_ext *)l_order->ext_n_sign;
             l_sovereign_tax = l_ext->tax;
             if (l_order_hash_str && compare256(l_value, l_order->price) == -1) {
-                char *l_coin_min_str, *l_value_min_str =
+                const char *l_coin_min_str, *l_value_min_str =
                     dap_uint256_to_char(l_order->price, &l_coin_min_str);
                 dap_cli_server_cmd_set_reply_text(a_str_reply, "Number in '-value' param %s is lower than order minimum allowed value %s(%s)",
                                                   l_value_str, l_coin_min_str, l_value_min_str);
@@ -1772,7 +1855,7 @@ static int s_cli_srv_stake_delegate(int a_argc, char **a_argv, int a_arg_index,
                 return -13;
             }
             if (l_order_hash_str && compare256(l_value, l_ext->value_max) == 1) {
-                char *l_coin_max_str, *l_value_max_str =
+                const char *l_coin_max_str, *l_value_max_str =
                     dap_uint256_to_char(l_ext->value_max, &l_coin_max_str);
                 dap_cli_server_cmd_set_reply_text(a_str_reply, "Number in '-value' param %s is higher than order minimum allowed value %s(%s)",
                                                   l_value_str, l_coin_max_str, l_value_max_str);
@@ -1800,7 +1883,7 @@ static int s_cli_srv_stake_delegate(int a_argc, char **a_argv, int a_arg_index,
         DAP_DELETE(l_order);
         if (compare256(l_sovereign_tax, dap_chain_coins_to_balance("100.0")) == 1 ||
                 compare256(l_sovereign_tax, GET_256_FROM_64(100)) == -1) {
-            dap_cli_server_cmd_set_reply_text(a_str_reply, "Tax must be lower or eqal than 100%% and higher or eqal than 1.0e-16%%");
+            dap_cli_server_cmd_set_reply_text(a_str_reply, "Tax must be lower or equal than 100%% and higher or equal than 1.0e-16%%");
             dap_enc_key_delete(l_enc_key);
             return -29;
         }
@@ -1813,8 +1896,9 @@ static int s_cli_srv_stake_delegate(int a_argc, char **a_argv, int a_arg_index,
         dap_chain_wallet_close(l_wallet);
         return l_check_result;
     }
-    if (compare256(l_value, s_srv_stake->delegate_allowed_min) == -1) {
-        char *l_coin_min_str, *l_value_min_str = dap_uint256_to_char(s_srv_stake->delegate_allowed_min, &l_coin_min_str);
+    uint256_t l_allowed_min = dap_chain_net_srv_stake_get_allowed_min_value(l_net->pub.id);
+    if (compare256(l_value, l_allowed_min) == -1) {
+        const char *l_coin_min_str, *l_value_min_str = dap_uint256_to_char(l_allowed_min, &l_coin_min_str);
         dap_cli_server_cmd_set_reply_text(a_str_reply, "Number in '-value' param %s is lower than minimum allowed value %s(%s)",
                                           l_value_str, l_coin_min_str, l_value_min_str);
         dap_enc_key_delete(l_enc_key);
@@ -1922,6 +2006,10 @@ static int s_cli_srv_stake_invalidate(int a_argc, char **a_argv, int a_arg_index
                 dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified certificate not found");
                 return -18;
             }
+            if (!l_cert->enc_key->priv_key_data || l_cert->enc_key->priv_key_data_size == 0) {
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "It is not possible to invalidate a stake using a public key.");
+                return -31;
+            }
             if (dap_chain_addr_fill_from_key(&l_signing_addr, l_cert->enc_key, l_net->pub.id)) {
                 dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified certificate is wrong");
                 return -22;
@@ -1934,8 +2022,13 @@ static int s_cli_srv_stake_invalidate(int a_argc, char **a_argv, int a_arg_index
             }
             dap_chain_addr_fill(&l_signing_addr, dap_sign_type_from_str(l_signing_pkey_type_str), &l_pkey_hash, l_net->pub.id);
         }
+        dap_chain_net_srv_stake_t *l_srv_stake = s_srv_stake_by_net_id(l_net->pub.id);
+        if (!l_srv_stake) {
+            dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified net have no stake service activated");
+            return -25;
+        }
         dap_chain_net_srv_stake_item_t *l_stake;
-        HASH_FIND(hh, s_srv_stake->itemlist, &l_signing_addr, sizeof(dap_chain_addr_t), l_stake);
+        HASH_FIND(hh, l_srv_stake->itemlist, &l_signing_addr.data.hash_fast, sizeof(dap_hash_fast_t), l_stake);
         if (!l_stake) {
             dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified certificate/pkey hash is not delegated nor this delegating is approved."
                                                            " Try to invalidate with tx hash instead");
@@ -1966,8 +2059,13 @@ static int s_cli_srv_stake_invalidate(int a_argc, char **a_argv, int a_arg_index
         }
     }
     if (l_tx_hash_str || l_cert_str) {
+        dap_chain_net_srv_stake_t *l_srv_stake = s_srv_stake_by_net_id(l_net->pub.id);
+        if (!l_srv_stake) {
+            dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified net have no stake service activated");
+            return -25;
+        }
         dap_chain_net_srv_stake_item_t *l_stake;
-        HASH_FIND(ht, s_srv_stake->tx_itemlist, &l_tx_hash, sizeof(dap_hash_t), l_stake);
+        HASH_FIND(ht, l_srv_stake->tx_itemlist, &l_tx_hash, sizeof(dap_hash_t), l_stake);
         if (l_stake) {
             char l_pkey_hash_str[DAP_HASH_FAST_STR_SIZE]; 
             dap_hash_fast_to_str(&l_stake->signing_addr.data.hash_fast, l_pkey_hash_str, DAP_HASH_FAST_STR_SIZE);
@@ -2031,17 +2129,6 @@ static int s_cli_srv_stake_invalidate(int a_argc, char **a_argv, int a_arg_index
     return 0;
 }
 
-DAP_STATIC_INLINE bool s_chain_esbocs_started(dap_chain_net_t *a_net)
-{
-    dap_chain_t *l_chain;
-    DL_FOREACH(a_net->pub.chains, l_chain) {
-        if (!strcmp(DAP_CHAIN_PVT(l_chain)->cs_name, "esbocs") &&
-                DAP_CHAIN_PVT(l_chain)->cs_started)
-            return true;
-    }
-    return false;
-}
-
 static void s_srv_stake_print(dap_chain_net_srv_stake_item_t *a_stake, uint256_t a_total_weight, dap_string_t *a_string)
 {
     char l_tx_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE], l_pkey_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE];
@@ -2053,9 +2140,9 @@ static void s_srv_stake_print(dap_chain_net_srv_stake_item_t *a_stake, uint256_t
     DIV_256_COIN(l_tmp, a_total_weight, &l_rel_weight);
     char *l_rel_weight_str = dap_chain_balance_to_coins(l_rel_weight);
     char l_active_str[32] = {};
-    if (s_chain_esbocs_started(a_stake->net))
+    if (dap_chain_esbocs_started(a_stake->signing_addr.net_id))
         snprintf(l_active_str, 32, "\tActive: %s\n", a_stake->is_active ? "true" : "false");
-    char *l_sov_addr_str = dap_chain_addr_is_blank(&a_stake->sovereign_addr) ?
+    const char *l_sov_addr_str = dap_chain_addr_is_blank(&a_stake->sovereign_addr) ?
                 "null" : dap_chain_addr_to_str(&a_stake->sovereign_addr);
     uint256_t l_sov_tax_percent = uint256_0;
     MULT_256_256(a_stake->sovereign_tax, GET_256_FROM_64(100), &l_sov_tax_percent);
@@ -2105,8 +2192,11 @@ static void s_get_tx_filter_callback(dap_chain_net_t* a_net, dap_chain_datum_tx_
     dap_hash_fast_t l_datum_hash = *a_tx_hash;
     if (dap_ledger_tx_hash_is_used_out_item(a_net->pub.ledger, &l_datum_hash, l_out_idx_tmp, NULL))
         return;
+    dap_chain_net_srv_stake_t *l_srv_stake = s_srv_stake_by_net_id(a_net->pub.id);
+    if (!l_srv_stake)
+        return;
     dap_chain_net_srv_stake_item_t *l_stake = NULL;
-    HASH_FIND(ht, s_srv_stake->tx_itemlist, &l_datum_hash, sizeof(dap_hash_fast_t), l_stake);
+    HASH_FIND(ht, l_srv_stake->tx_itemlist, &l_datum_hash, sizeof(dap_hash_fast_t), l_stake);
     if (!l_stake)
         l_args->ret = dap_list_append(l_args->ret,a_tx);
 }
@@ -2213,9 +2303,11 @@ int dap_chain_net_srv_stake_check_validator(dap_chain_net_t * a_net, dap_hash_fa
 
 uint256_t dap_chain_net_srv_stake_get_total_weight(dap_chain_net_id_t a_net_id)
 {
+    dap_chain_net_srv_stake_t *l_srv_stake = s_srv_stake_by_net_id(a_net_id);
+    dap_return_val_if_fail(l_srv_stake, uint256_0);
     uint256_t l_total_weight = uint256_0;
-    for (dap_chain_net_srv_stake_item_t *it = s_srv_stake->itemlist; it; it = it->hh.next) {
-        if (it->net->pub.id.uint64 != a_net_id.uint64)
+    for (dap_chain_net_srv_stake_item_t *it = l_srv_stake->itemlist; it; it = it->hh.next) {
+        if (it->signing_addr.net_id.uint64 != a_net_id.uint64)
             continue;
         SUM_256_256(l_total_weight, it->value, &l_total_weight);
     }
@@ -2225,7 +2317,7 @@ uint256_t dap_chain_net_srv_stake_get_total_weight(dap_chain_net_id_t a_net_id)
 static int s_cli_srv_stake(int a_argc, char **a_argv, void **a_str_reply)
 {
     enum {
-        CMD_NONE, CMD_ORDER, CMD_DELEGATE, CMD_APPROVE, CMD_LIST, CMD_INVALIDATE, CMD_MIN_VALUE, CMD_CHECK
+        CMD_NONE, CMD_ORDER, CMD_DELEGATE, CMD_APPROVE, CMD_LIST, CMD_INVALIDATE, CMD_MIN_VALUE, CMD_CHECK, CMD_MAX_WEIGHT
     };
     int l_arg_index = 1;
 
@@ -2257,10 +2349,13 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, void **a_str_reply)
     else if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "invalidate", NULL)) {
         l_cmd_num = CMD_INVALIDATE;
     }
-    // RSetss stake minimum value
+    // Set stake minimum value
     else if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "min_value", NULL)) {
         l_cmd_num = CMD_MIN_VALUE;
     }
+    else if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "max_weight", NULL)) {
+        l_cmd_num = CMD_MAX_WEIGHT;
+    }
     else if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "check", NULL)) {
         l_cmd_num = CMD_CHECK;
     }
@@ -2422,6 +2517,11 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, void **a_str_reply)
                     dap_cli_server_cmd_set_reply_text(a_str_reply, "Network %s not found", l_net_str);
                     return -4;
                 }
+                dap_chain_net_srv_stake_t *l_srv_stake = s_srv_stake_by_net_id(l_net->pub.id);
+                if (!l_srv_stake) {
+                    dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified net have no stake service activated");
+                    return -25;
+                }
                 dap_chain_net_srv_stake_item_t *l_stake = NULL;
                 dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-cert", &l_cert_str);
                 if (l_cert_str) {
@@ -2435,7 +2535,7 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, void **a_str_reply)
                         dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified certificate is wrong");
                         return -20;
                     }
-                    HASH_FIND(hh, s_srv_stake->itemlist, &l_signing_addr, sizeof(dap_chain_addr_t), l_stake);
+                    HASH_FIND(hh, l_srv_stake->itemlist, &l_signing_addr.data.hash_fast, sizeof(dap_hash_fast_t), l_stake);
                     if (!l_stake) {
                         dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified certificate isn't delegated nor approved");
                         return -21;
@@ -2449,7 +2549,7 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, void **a_str_reply)
                         dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified pkey hash is wrong");
                         return -20;
                     }
-                    l_stake = dap_chain_net_srv_stake_check_pkey_hash(&l_pkey_hash);
+                    l_stake = dap_chain_net_srv_stake_check_pkey_hash(l_net->pub.id, &l_pkey_hash);
                     if (!l_stake) {
                         dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified pkey hash isn't delegated nor approved");
                         return -21;
@@ -2462,31 +2562,38 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, void **a_str_reply)
                 if (l_stake)
                     s_srv_stake_print(l_stake, l_total_weight, l_reply_str);
                 else
-                    for (l_stake = s_srv_stake->itemlist; l_stake; l_stake = l_stake->hh.next) {
-                        if (l_stake->net->pub.id.uint64 != l_net->pub.id.uint64)
-                            continue;
+                    for (l_stake = l_srv_stake->itemlist; l_stake; l_stake = l_stake->hh.next) {
                         l_total_count++;
                         if (!l_stake->is_active)
                             l_inactive_count++;
                         s_srv_stake_print(l_stake, l_total_weight, l_reply_str);
                     }
-                if (!HASH_CNT(hh, s_srv_stake->itemlist)) {
+                if (!HASH_CNT(hh, l_srv_stake->itemlist)) {
                     dap_string_append(l_reply_str, "No keys found\n");
                 } else {
                     if (!l_cert_str && !l_pkey_hash_str)
                         dap_string_append_printf(l_reply_str, "Total keys count: %zu\n", l_total_count);
-                    if (s_chain_esbocs_started(l_net))
+                    if (dap_chain_esbocs_started(l_net->pub.id))
                         dap_string_append_printf(l_reply_str, "Inactive keys count: %zu\n", l_inactive_count);
-                    char *l_total_weight_coins, *l_total_weight_str =
+                    const char *l_total_weight_coins, *l_total_weight_str =
                             dap_uint256_to_char(l_total_weight, &l_total_weight_coins);
                     dap_string_append_printf(l_reply_str, "Total weight: %s (%s)\n", l_total_weight_coins, l_total_weight_str);
                 }
 
-                char *l_delegate_min_str; dap_uint256_to_char(s_srv_stake->delegate_allowed_min, &l_delegate_min_str);
+                const char *l_delegate_min_str; dap_uint256_to_char(dap_chain_net_srv_stake_get_allowed_min_value(l_net->pub.id),
+                                                                    &l_delegate_min_str);
                 char l_delegated_ticker[DAP_CHAIN_TICKER_SIZE_MAX];
                 dap_chain_datum_token_get_delegated_ticker(l_delegated_ticker, l_net->pub.native_ticker);
-                dap_string_append_printf(l_reply_str, "Minimum value for key delegating: %s %s",
+                dap_string_append_printf(l_reply_str, "Minimum value for key delegating: %s %s\n",
                                          l_delegate_min_str, l_delegated_ticker);
+                uint256_t l_percent_max = dap_chain_net_srv_stake_get_percent_max(l_net->pub.id);
+                const char *l_percent_max_str = NULL;
+                if (!IS_ZERO_256(l_percent_max)) {
+                    MULT_256_256(l_percent_max, GET_256_FROM_64(100), &l_percent_max);
+                    dap_uint256_to_char(l_percent_max, &l_percent_max_str);
+                }
+                dap_string_append_printf(l_reply_str, "Maximum related weight of each validator: %s%%\n",
+                                         IS_ZERO_256(l_percent_max) ? "100" : l_percent_max_str);
                 *a_str_reply = dap_string_free(l_reply_str, false);
             } else if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "tx", NULL)) {
                 const char *l_net_str = NULL;
@@ -2513,9 +2620,7 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, void **a_str_reply)
                 dap_chain_tx_out_cond_t *l_tx_out_cond = NULL;
                 int l_out_idx_tmp = 0;
                 char *spaces = {"--------------------------------------------------------------------------------------------------------------------"};
-                char *l_signing_addr_str = NULL;
-                char *l_balance = NULL;
-                char *l_coins = NULL;
+                const char *l_signing_addr_str = NULL, *l_balance = NULL, *l_coins = NULL;
                 char* l_node_address_text_block = NULL;
                 dap_chain_net_get_tx_all(l_net,TX_SEARCH_TYPE_NET,s_get_tx_filter_callback, l_args);
                 l_args->ret = dap_list_sort(l_args->ret, s_callback_compare_tx_list);
@@ -2569,10 +2674,16 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, void **a_str_reply)
                 dap_cli_server_cmd_set_reply_text(a_str_reply, "Network %s not found", l_net_str);
                 return -4;
             }
-
-            dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-cert", &l_cert_str);
+            dap_chain_t *l_chain = dap_chain_net_get_default_chain_by_chain_type(l_net, CHAIN_TYPE_ANCHOR);
+            if (!l_chain)
+                l_chain =  dap_chain_net_get_chain_by_chain_type(l_net, CHAIN_TYPE_ANCHOR);
+            if (!l_chain) {
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "No chain supported anchor datum type");
+                return -2;
+            }
+            dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-poa_cert", &l_cert_str);
             if (!l_cert_str) {
-                dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'min_value' requires parameter -cert");
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'min_value' requires parameter -poa_cert");
                 return -3;
             }
             dap_cert_t *l_poa_cert = dap_cert_find_by_name(l_cert_str);
@@ -2596,7 +2707,7 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, void **a_str_reply)
                 return -10;
             }
 
-            dap_chain_datum_decree_t *l_decree = s_stake_decree_set_min_stake(l_net, l_value, l_poa_cert);
+            dap_chain_datum_decree_t *l_decree = s_stake_decree_set_min_stake(l_net, l_chain, l_value, l_poa_cert);
             char *l_decree_hash_str = NULL;
             if (l_decree && (l_decree_hash_str = s_stake_decree_put(l_decree, l_net))) {
                 dap_cli_server_cmd_set_reply_text(a_str_reply, "Minimum stake value has been set."
@@ -2610,6 +2721,72 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, void **a_str_reply)
             }
         } break;
 
+        case CMD_MAX_WEIGHT: {
+            const char *l_net_str = NULL,
+                       *l_cert_str = NULL,
+                       *l_value_str = NULL;
+            l_arg_index++;
+            dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-net", &l_net_str);
+            if (!l_net_str) {
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'min_value' requires parameter -net");
+                return -3;
+            }
+            dap_chain_net_t *l_net = dap_chain_net_by_name(l_net_str);
+            if (!l_net) {
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "Network %s not found", l_net_str);
+                return -4;
+            }
+            dap_chain_t *l_chain = dap_chain_net_get_default_chain_by_chain_type(l_net, CHAIN_TYPE_ANCHOR);
+            if (!l_chain)
+                l_chain =  dap_chain_net_get_chain_by_chain_type(l_net, CHAIN_TYPE_ANCHOR);
+            if (!l_chain) {
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "No chain supported anchor datum type");
+                return -2;
+            }
+            dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-poa_cert", &l_cert_str);
+            if (!l_cert_str) {
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'min_value' requires parameter -poa_cert");
+                return -3;
+            }
+            dap_cert_t *l_poa_cert = dap_cert_find_by_name(l_cert_str);
+            if (!l_poa_cert) {
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified certificate not found");
+                return -25;
+            }
+            if (!s_srv_stake_is_poa_cert(l_net, l_poa_cert->enc_key)) {
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified certificate is not PoA root one");
+                return -26;
+            }
+
+            dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-percent", &l_value_str);
+            if (!l_value_str) {
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'min_value' requires parameter -percent");
+                return -9;
+            }
+            uint256_t l_value = dap_chain_balance_scan(l_value_str);
+            if (IS_ZERO_256(l_value)) {
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "Unrecognized number in '-percent' param");
+                return -10;
+            }
+            if (compare256(l_value, dap_chain_coins_to_balance("100.0")) >= 0) {
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "Percent must be lower than 100%%");
+                return -29;
+            }
+            DIV_256(l_value, GET_256_FROM_64(100), &l_value);
+            dap_chain_datum_decree_t *l_decree = s_stake_decree_set_max_weight(l_net, l_chain, l_value, l_poa_cert);
+            char *l_decree_hash_str = NULL;
+            if (l_decree && (l_decree_hash_str = s_stake_decree_put(l_decree, l_net))) {
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "Maximum weight has been set."
+                                                                " Decree hash %s", l_decree_hash_str);
+                DAP_DELETE(l_decree);
+                DAP_DELETE(l_decree_hash_str);
+            } else {
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "Maximum weight setting failed");
+                DAP_DEL_Z(l_decree);
+                return -21;
+            }
+        } break;
+
         default: {
             dap_cli_server_cmd_set_reply_text(a_str_reply, "Command %s not recognized", a_argv[l_arg_index]);
             return -1;
@@ -2681,7 +2858,7 @@ void dap_chain_net_srv_stake_get_fee_validators_str(dap_chain_net_t *a_net, dap_
     uint256_t l_min = uint256_0, l_max = uint256_0, l_average = uint256_0, l_median = uint256_0;
     dap_chain_net_srv_stake_get_fee_validators(a_net, &l_max, &l_average, &l_min, &l_median);
     const char *l_native_token  = a_net->pub.native_ticker;
-    char *l_coins_str,
+    const char *l_coins_str,
     *l_min_balance      = dap_strdup(dap_uint256_to_char(l_min, &l_coins_str)),     *l_min_coins    = dap_strdup(l_coins_str),
     *l_max_balance      = dap_strdup(dap_uint256_to_char(l_max, &l_coins_str)),     *l_max_coins    = dap_strdup(l_coins_str),
     *l_average_balance  = dap_strdup(dap_uint256_to_char(l_average, &l_coins_str)), *l_average_coins= dap_strdup(l_coins_str),
@@ -2708,7 +2885,7 @@ json_object *dap_chain_net_srv_stake_get_fee_validators_json(dap_chain_net_t  *a
                 *l_jobj_average = json_object_new_object(), *l_jobj_median  = json_object_new_object(),
                 *l_jobj_ret     = json_object_new_object();
                 
-    char *l_coins_str;
+    const char *l_coins_str;
     json_object_object_add( l_jobj_min,     "balance",  json_object_new_string(dap_uint256_to_char(l_min, &l_coins_str)) );
     json_object_object_add( l_jobj_min,     "coin",     json_object_new_string(l_coins_str) );
 
@@ -2757,12 +2934,13 @@ static void s_uncache_data(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, d
         log_it(L_WARNING, "Stake service cache mismatch");
 }
 
-dap_chain_net_srv_stake_item_t *dap_chain_net_srv_stake_check_pkey_hash(dap_hash_fast_t *a_pkey_hash)
+dap_chain_net_srv_stake_item_t *dap_chain_net_srv_stake_check_pkey_hash(dap_chain_net_id_t a_net_id, dap_hash_fast_t *a_pkey_hash)
 {
-    if (!s_srv_stake)
+    dap_chain_net_srv_stake_t *l_srv_stake = s_srv_stake_by_net_id(a_net_id);
+    if (!l_srv_stake)
         return NULL;
     dap_chain_net_srv_stake_item_t *l_stake, *l_tmp;
-    HASH_ITER(hh, s_srv_stake->itemlist, l_stake, l_tmp) {
+    HASH_ITER(hh, l_srv_stake->itemlist, l_stake, l_tmp) {
         if (dap_hash_fast_compare(&l_stake->signing_addr.data.hash_fast, a_pkey_hash))
             return l_stake;
     }
diff --git a/modules/service/stake/include/dap_chain_net_srv_stake_pos_delegate.h b/modules/service/stake/include/dap_chain_net_srv_stake_pos_delegate.h
index d8fea0a16e67d7554772ed8bdc30411388847ace..9772663f553ca3b7d7ac53fe6c52ecf83ef84ba6 100644
--- a/modules/service/stake/include/dap_chain_net_srv_stake_pos_delegate.h
+++ b/modules/service/stake/include/dap_chain_net_srv_stake_pos_delegate.h
@@ -25,10 +25,9 @@
 #pragma once
 
 #include "dap_chain_ledger.h"
-#include "dap_chain_net_srv.h"
-#include "dap_chain_net_srv_order.h"
 #include "dap_math_ops.h"
 #include "dap_stream_ch_chain_net.h"
+#include "dap_chain_datum_decree.h"
 
 #define DAP_CHAIN_NET_SRV_STAKE_POS_DELEGATE_ID 0x13
 #define DAP_CHAIN_NET_SRV_STAKE_POS_DELEGATE_ORDERS 0x14
@@ -36,6 +35,7 @@
 typedef struct dap_chain_net_srv_stake_item {
     bool is_active;
     dap_chain_net_t *net;
+    uint256_t locked_value;
     uint256_t value;
     dap_chain_addr_t signing_addr;
     dap_chain_hash_fast_t tx_hash;
@@ -58,7 +58,9 @@ typedef struct dap_chain_net_srv_stake_cache_item {
 } dap_chain_net_srv_stake_cache_item_t;
 
 typedef struct dap_chain_net_srv_stake {
+    dap_chain_net_id_t net_id;
     uint256_t delegate_allowed_min;
+    uint256_t delegate_percent_max;
     dap_chain_net_srv_stake_item_t *itemlist;
     dap_chain_net_srv_stake_item_t *tx_itemlist;
     dap_chain_net_srv_stake_cache_item_t *cache;
@@ -67,15 +69,18 @@ typedef struct dap_chain_net_srv_stake {
 int dap_chain_net_srv_stake_pos_delegate_init();
 void dap_chain_net_srv_stake_pos_delegate_deinit();
 
+int dap_chain_net_srv_stake_net_add(dap_chain_net_id_t a_net_id);
 void dap_chain_net_srv_stake_key_delegate(dap_chain_net_t *a_net, dap_chain_addr_t *a_signing_addr, dap_hash_fast_t *a_stake_tx_hash,
                                           uint256_t a_value, dap_chain_node_addr_t *a_node_addr);
 void dap_chain_net_srv_stake_key_invalidate(dap_chain_addr_t *a_signing_addr);
-void dap_chain_net_srv_stake_set_allowed_min_value(uint256_t a_value);
-uint256_t dap_chain_net_srv_stake_get_allowed_min_value();
+void dap_chain_net_srv_stake_set_allowed_min_value(dap_chain_net_id_t a_net_id, uint256_t a_value);
+uint256_t dap_chain_net_srv_stake_get_allowed_min_value(dap_chain_net_id_t a_net_id);
+void dap_chain_net_srv_stake_set_percent_max(dap_chain_net_id_t a_net_id, uint256_t a_value);
+uint256_t dap_chain_net_srv_stake_get_percent_max(dap_chain_net_id_t a_net_id);
 
 int dap_chain_net_srv_stake_key_delegated(dap_chain_addr_t *a_addr);
 int dap_chain_net_srv_stake_verify_key_and_node(dap_chain_addr_t* a_signing_addr, dap_chain_node_addr_t* a_node_addr);
-dap_list_t *dap_chain_net_srv_stake_get_validators(dap_chain_net_id_t a_net_id, bool a_only_active);
+dap_list_t *dap_chain_net_srv_stake_get_validators(dap_chain_net_id_t a_net_id, bool a_only_active, uint16_t **a_excluded_list);
 
 bool dap_chain_net_srv_stake_get_fee_validators(dap_chain_net_t *a_net,
                                                 uint256_t *a_max_fee, uint256_t *a_average_fee, uint256_t *a_min_fee, uint256_t *a_median_fee);
@@ -93,5 +98,5 @@ dap_chain_datum_decree_t *dap_chain_net_srv_stake_decree_approve(dap_chain_net_t
                                                                  dap_hash_fast_t *a_stake_tx_hash, dap_cert_t *a_cert);
 int dap_chain_net_srv_stake_mark_validator_active(dap_chain_addr_t *a_signing_addr, bool a_on_off);
 
-dap_chain_net_srv_stake_item_t *dap_chain_net_srv_stake_check_pkey_hash(dap_hash_fast_t *a_pkey_hash);
+dap_chain_net_srv_stake_item_t *dap_chain_net_srv_stake_check_pkey_hash(dap_chain_net_id_t a_net_id, dap_hash_fast_t *a_pkey_hash);
 uint256_t dap_chain_net_srv_stake_get_total_weight(dap_chain_net_id_t a_net_id);
diff --git a/modules/service/voting/CMakeLists.txt b/modules/service/voting/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..544179bc63005255c679a62abb4c059d879096c2
--- /dev/null
+++ b/modules/service/voting/CMakeLists.txt
@@ -0,0 +1,22 @@
+cmake_minimum_required(VERSION 3.10)
+project (dap_chain_net_srv_voting)
+
+file(GLOB DAP_SRV_VTNG_SRCS *.c)
+
+file(GLOB DAP_SRV_VTNG_HEADERS include/*.h)
+
+add_library(${PROJECT_NAME} STATIC ${DAP_SRV_VTNG_SRCS} ${DAP_SRV_VTNG_HEADERS})
+
+target_include_directories(${PROJECT_NAME} INTERFACE .)
+target_include_directories(${PROJECT_NAME} PUBLIC include)
+target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_chain dap_chain_net dap_chain_net_srv)
+target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../../dap-sdk/3rdparty/json-c)
+
+if (INSTALL_SDK)
+set_target_properties(${PROJECT_NAME}  PROPERTIES PUBLIC_HEADER "${DAP_SRV_BRG_HEADERS}")
+INSTALL(TARGETS ${PROJECT_NAME} 
+        LIBRARY DESTINATION lib/modules/service/voting/
+        ARCHIVE DESTINATION lib/modules/service/voting/
+        PUBLIC_HEADER DESTINATION include/modules/service/voting/
+)
+endif()
\ No newline at end of file
diff --git a/modules/net/dap_chain_net_voting.c b/modules/service/voting/dap_chain_net_srv_voting.c
similarity index 98%
rename from modules/net/dap_chain_net_voting.c
rename to modules/service/voting/dap_chain_net_srv_voting.c
index dde9f80b69df14fb8b08ada49c613772e943b128..ffecdaf7cf139585cbbdf1fed9db023c86084722 100644
--- a/modules/net/dap_chain_net_voting.c
+++ b/modules/service/voting/dap_chain_net_srv_voting.c
@@ -30,12 +30,13 @@
 #include <errno.h>
 #include <pthread.h>
 
-#include "dap_chain_net_voting.h"
+#include "dap_chain_net_srv_voting.h"
 #include "dap_chain_net_srv_stake_pos_delegate.h"
-#include "dap_chain_node_cli.h"
+#include "dap_chain_net_tx.h"
 #include "dap_chain_mempool.h"
 #include "uthash.h"
 #include "utlist.h"
+#include "dap_cli_server.h"
 
 #define LOG_TAG "chain_net_voting"
 
@@ -97,7 +98,24 @@ static bool s_datum_tx_voting_verification_callback(dap_ledger_t *a_ledger, dap_
 static bool s_datum_tx_voting_verification_delete_callback(dap_ledger_t *a_ledger, dap_chain_tx_item_type_t a_type, dap_chain_datum_tx_t *a_tx_in);
 static int s_cli_voting(int argc, char **argv, void **a_str_reply);
 
-int dap_chain_net_voting_init()
+static bool s_tag_check_voting(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx,  dap_chain_datum_tx_item_groups_t *a_items_grp, dap_chain_tx_tag_action_type_t *a_action)
+{
+    //voting open 
+    if (a_items_grp->items_voting) {
+        *a_action = DAP_CHAIN_TX_TAG_ACTION_OPEN;
+        return true;
+    }
+
+    //voting use
+    if (a_items_grp->items_vote) {
+        *a_action = DAP_CHAIN_TX_TAG_ACTION_USE;
+        return true;
+    }
+
+    return false;
+}
+
+int dap_chain_net_srv_voting_init()
 {
     pthread_rwlock_init(&s_votings_rwlock, NULL);
     dap_chain_ledger_voting_verificator_add(s_datum_tx_voting_verification_callback, s_datum_tx_voting_verification_delete_callback);
@@ -106,9 +124,19 @@ int dap_chain_net_voting_init()
                             "voting vote -net <net_name> -hash <voting_hash> -option_idx <option_index> [-cert <delegate_cert_name>] -fee <value_datoshi> -w <fee_wallet_name>\n"
                             "voting list -net <net_name>\n"
                             "voting dump -net <net_name> -hash <voting_hash>\n");
+
+    
+    dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_VOTING_ID };
+    dap_ledger_service_add(l_uid, "voting", s_tag_check_voting);
+
     return 0;
 }
 
+void dap_chain_net_srv_voting_deinit()
+{
+
+}
+
 uint64_t* dap_chain_net_voting_get_result(dap_ledger_t* a_ledger, dap_chain_hash_fast_t* a_voting_hash)
 {
     if(!a_voting_hash){
@@ -295,7 +323,7 @@ bool s_datum_tx_voting_verification_callback(dap_ledger_t *a_ledger, dap_chain_t
             dap_sign_get_pkey_hash((dap_sign_t*)l_vote_sig->sig, &pkey_hash);
             if (l_voting->voting_params.delegate_key_required_offset &&
                 *(bool*)((byte_t*)l_voting->voting_params.voting_tx + l_voting->voting_params.delegate_key_required_offset)){
-                if (!dap_chain_net_srv_stake_check_pkey_hash(&pkey_hash)){
+                if (!dap_chain_net_srv_stake_check_pkey_hash(a_ledger->net->pub.id, &pkey_hash)){
                     log_it(L_ERROR, "The voting required a delegated key.");
                     dap_list_free(l_signs_list);
                     return false;
@@ -998,14 +1026,14 @@ static int s_cli_voting(int a_argc, char **a_argv, void **a_str_reply)
 
             DIV_256_COIN(l_results[i].weights, l_total_weight, &l_weight_percentage);
             MULT_256_COIN(l_weight_percentage, dap_chain_coins_to_balance("100.0"), &l_weight_percentage);
-            char *l_weight_percentage_str = dap_uint256_decimal_to_round_char(l_weight_percentage, 2, true);
-            char *l_w_coins, *l_w_datoshi = dap_uint256_to_char(l_results[i].weights, &l_w_coins);
+            const char *l_weight_percentage_str = dap_uint256_decimal_to_round_char(l_weight_percentage, 2, true);
+            const char *l_w_coins, *l_w_datoshi = dap_uint256_to_char(l_results[i].weights, &l_w_coins);
             dap_string_append_printf(l_str_out, "\nVotes: %"DAP_UINT64_FORMAT_U" (%.2f%%)\nWeight: %s (%s) %s (%s%%)\n",
                                      l_results[i].num_of_votes, l_percentage, l_w_coins, l_w_datoshi, l_net->pub.native_ticker, l_weight_percentage_str);
         }
         DAP_DELETE(l_results);
         dap_string_append_printf(l_str_out, "\nTotal number of votes: %"DAP_UINT64_FORMAT_U, l_votes_count);
-        char *l_tw_coins, *l_tw_datoshi = dap_uint256_to_char(l_total_weight, &l_tw_coins);
+        const char *l_tw_coins, *l_tw_datoshi = dap_uint256_to_char(l_total_weight, &l_tw_coins);
         dap_string_append_printf(l_str_out, "\nTotal weight: %s (%s) %s\n\n", l_tw_coins, l_tw_datoshi, l_net->pub.native_ticker);
         dap_cli_server_cmd_set_reply_text(a_str_reply, "%s", l_str_out->str);
         dap_string_free(l_str_out, true);
@@ -1420,7 +1448,7 @@ int dap_chain_net_vote_voting(dap_cert_t *a_cert, uint256_t a_fee, dap_chain_wal
             dap_hash_fast_t l_pkey_hash = {0};
 
             dap_hash_fast(l_pub_key, l_pub_key_size, &l_pkey_hash);
-            if (!dap_chain_net_srv_stake_check_pkey_hash(&l_pkey_hash)) {
+            if (!dap_chain_net_srv_stake_check_pkey_hash(a_net->pub.id, &l_pkey_hash)) {
                 return DAP_CHAIN_NET_VOTE_VOTING_KEY_IS_NOT_DELEGATED;
             }
             dap_list_t *l_temp = l_voting->votes;
diff --git a/modules/net/include/dap_chain_net_voting.h b/modules/service/voting/include/dap_chain_net_srv_voting.h
similarity index 89%
rename from modules/net/include/dap_chain_net_voting.h
rename to modules/service/voting/include/dap_chain_net_srv_voting.h
index c045605f3025dcb11a41572d7e05b26bb876d6e9..df90751a3e4fee216a65340f413154f13948caa2 100644
--- a/modules/net/include/dap_chain_net_voting.h
+++ b/modules/service/voting/include/dap_chain_net_srv_voting.h
@@ -28,6 +28,15 @@
 #include "dap_chain_common.h"
 #include "dap_chain_wallet.h"
 
+#define DAP_CHAIN_NET_SRV_VOTING_ID 0x06
+
+
+//typedef struct dap_chain_net_vote_info_result {
+//    uint64_t answer_idx;
+//    uint64_t votes_count;
+//}dap_chain_net_vote_result_t;
+
+
 typedef struct dap_chain_net_vote_info_option{
     uint64_t option_idx;
     uint64_t votes_count;
@@ -36,7 +45,6 @@ typedef struct dap_chain_net_vote_info_option{
     char *description;
     dap_list_t *hashes_tx_votes;
 }dap_chain_net_vote_info_option_t;
-
 typedef struct dap_chain_net_vote_info{
     dap_hash_fast_t hash;
     dap_chain_net_id_t net_id;
@@ -56,9 +64,8 @@ typedef struct dap_chain_net_vote_info{
     } options;
 }dap_chain_net_vote_info_t;
 
-
-int dap_chain_net_voting_init();
-
+int dap_chain_net_srv_voting_init();
+void dap_chain_net_srv_voting_deinit();
 
 uint64_t* dap_chain_net_voting_get_result(dap_ledger_t* a_ledger, dap_chain_hash_fast_t* a_voting_hash);
 
@@ -80,9 +87,9 @@ enum DAP_CHAIN_NET_VOTE_CREATE_ERROR {
     DAP_CHAIN_NET_VOTE_CREATE_CAN_NOT_POOL_DATUM_IN_MEMPOOL
 };
 int dap_chain_net_vote_create(const char *a_question, dap_list_t *a_options, dap_time_t a_expire_vote,
-                              uint64_t a_max_vote, uint256_t a_fee, bool a_delegated_key_required,
-                              bool a_vote_changing_allowed, dap_chain_wallet_t *a_wallet,
-                              dap_chain_net_t *a_net, const char *a_hash_out_type, char **a_hash_output);
+                             uint64_t a_max_vote, uint256_t a_fee, bool a_delegated_key_required,
+                             bool a_vote_changing_allowed, dap_chain_wallet_t *a_wallet,
+                             dap_chain_net_t *a_net, const char *a_hash_out_type, char **a_hash_output);
 
 enum DAP_CHAIN_NET_VOTE_VOTING_ERROR{
     DAP_CHAIN_NET_VOTE_VOTING_OK,
@@ -111,3 +118,4 @@ int dap_chain_net_vote_voting(dap_cert_t *a_cert, uint256_t a_fee, dap_chain_wal
 dap_list_t *dap_chain_net_vote_list(dap_chain_net_t *a_net);
 dap_chain_net_vote_info_t *dap_chain_net_vote_extract_info(dap_chain_net_t *a_net, dap_hash_fast_t *a_vote_hash);
 void dap_chain_net_vote_info_free(dap_chain_net_vote_info_t *a_info);
+
diff --git a/modules/service/vpn/CMakeLists.txt b/modules/service/vpn/CMakeLists.txt
index 04be24a936012b5d8c5276799184d26c8aa01eb4..8f5ffe7b7dc7357f35d716f2af3387147b76aa15 100644
--- a/modules/service/vpn/CMakeLists.txt
+++ b/modules/service/vpn/CMakeLists.txt
@@ -1,16 +1,20 @@
 cmake_minimum_required(VERSION 3.10)
 project (dap_chain_net_srv_vpn)
   
-file(GLOB DAP_CHAIN_NET_SRV_VPN_SRCS *.c)
-
-file(GLOB DAP_CHAIN_NET_SRV_VPN_HEADERS include/*.h)
 
 if(WIN32)
+  file(GLOB DAP_CHAIN_NET_SRV_VPN_SRCS *common.c)
+  file(GLOB DAP_CHAIN_NET_SRV_VPN_HEADERS include/*common.h)
+
   include_directories(../../../os/win32/)
   include_directories(../3rdparty/wepoll/include/)
   include_directories(../3rdparty/uthash/src/)
   include_directories(../../dap-sdk/3rdparty/json-c/)
   include_directories(../3rdparty/libmagic/src/)
+else()
+  file(GLOB DAP_CHAIN_NET_SRV_VPN_SRCS *.c)
+  file(GLOB DAP_CHAIN_NET_SRV_VPN_HEADERS include/*.h)
+
 endif()
 
 add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_NET_SRV_VPN_SRCS} ${DAP_CHAIN_NET_SRV_VPN_HEADERS})
@@ -28,4 +32,4 @@ INSTALL(TARGETS ${PROJECT_NAME}
         ARCHIVE DESTINATION lib/modules/service/vpn/
         PUBLIC_HEADER DESTINATION include/modules/service/vpn/
 )
-endif()
\ No newline at end of file
+endif()
diff --git a/modules/service/vpn/dap_chain_net_srv_vpn.c b/modules/service/vpn/dap_chain_net_srv_vpn.c
index 4aaf501d40ee48a5689702f47c1af2df31493afa..500e48001f6760dc3ed0edba8e03ac45745bef33 100644
--- a/modules/service/vpn/dap_chain_net_srv_vpn.c
+++ b/modules/service/vpn/dap_chain_net_srv_vpn.c
@@ -1690,6 +1690,11 @@ static void s_ch_packet_in_vpn_address_request(dap_stream_ch_t* a_ch, dap_chain_
 static bool s_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg)
 {
     dap_stream_ch_pkt_t * l_pkt = (dap_stream_ch_pkt_t *) a_arg;
+    ch_vpn_pkt_t *l_vpn_pkt = (ch_vpn_pkt_t*)l_pkt->data;
+    size_t l_vpn_pkt_size = l_pkt->hdr.data_size;
+    if (l_vpn_pkt_size < sizeof(l_vpn_pkt->header))
+        return false;
+
     dap_chain_net_srv_stream_session_t * l_srv_session = DAP_CHAIN_NET_SRV_STREAM_SESSION (a_ch->stream->session );
     dap_chain_net_srv_ch_vpn_t *l_ch_vpn = CH_VPN(a_ch);
     dap_chain_net_srv_usage_t * l_usage = l_srv_session->usage_active;// dap_chain_net_srv_usage_find_unsafe(l_srv_session,  l_ch_vpn->usage_id);
@@ -1725,12 +1730,8 @@ static bool s_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg)
 
     // TODO move address leasing to this structure
     //dap_chain_net_srv_vpn_t * l_srv_vpn =(dap_chain_net_srv_vpn_t *) l_usage->service->_internal;
-
-    ch_vpn_pkt_t * l_vpn_pkt = (ch_vpn_pkt_t *) l_pkt->data;
-    size_t l_vpn_pkt_size = l_pkt->hdr.data_size - sizeof (l_vpn_pkt->header);
-
+    l_vpn_pkt_size -= sizeof (l_vpn_pkt->header);
     debug_if(s_debug_more, L_INFO, "Got srv_vpn packet with op_code=0x%02x", l_vpn_pkt->header.op_code);
-
     if(l_vpn_pkt->header.op_code >= 0xb0) { // Raw packets
         switch (l_vpn_pkt->header.op_code) {
             case VPN_PACKET_OP_CODE_PING:
diff --git a/modules/service/vpn/dap_chain_net_srv_vpn_cmd.c b/modules/service/vpn/dap_chain_net_srv_vpn_cmd.c
index 695fb53faab302c846a7b4e92dfdd4daaed08ae1..0cb732427a964a3559b39c63f4afc5bbaa1e4ad4 100644
--- a/modules/service/vpn/dap_chain_net_srv_vpn_cmd.c
+++ b/modules/service/vpn/dap_chain_net_srv_vpn_cmd.c
@@ -110,7 +110,7 @@ int com_vpn_client(int a_argc, char ** a_argv, void **a_str_reply)
 
     // find net
     dap_chain_net_t *l_net = NULL;
-    if(dap_chain_node_cli_cmd_values_parse_net_chain(&l_arg_index, a_argc, a_argv, a_str_reply, NULL, &l_net) < 0)
+    if(dap_chain_node_cli_cmd_values_parse_net_chain(&l_arg_index, a_argc, a_argv, a_str_reply, NULL, &l_net, CHAIN_TYPE_INVALID) < 0)
         return -2;
 
     int cmd_num = CMD_NONE;
diff --git a/modules/service/vpn/dap_chain_net_srv_vpn_common.c b/modules/service/vpn/dap_chain_net_srv_vpn_common.c
new file mode 100644
index 0000000000000000000000000000000000000000..fbfdc2962bc0283f6ea8b87d59ce98c4148543c3
--- /dev/null
+++ b/modules/service/vpn/dap_chain_net_srv_vpn_common.c
@@ -0,0 +1,44 @@
+
+#include "dap_chain_net_srv_vpn_common.h"
+#include "dap_chain_ledger.h"
+
+
+static bool s_tag_check_vpn(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx,  dap_chain_datum_tx_item_groups_t *a_items_grp, dap_chain_tx_tag_action_type_t *a_action)
+{
+    
+    //VPN  open: have SRV_PAY out with vpn uid
+    
+    if (a_items_grp->items_out_cond_srv_pay) {
+        dap_chain_tx_out_cond_t *l_cond_out = a_items_grp->items_out_cond_srv_pay->data; 
+        if (l_cond_out->header.srv_uid.uint64 == DAP_CHAIN_NET_SRV_VPN_ID)
+           if (a_action) *a_action = DAP_CHAIN_TX_TAG_ACTION_OPEN;
+        return true;
+    }
+    
+    //VPN native use: have IN_COND linked with DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY out with vpn uid
+    
+    if (a_items_grp->items_in_cond) {
+       for (dap_list_t *it = a_items_grp->items_in_cond; it; it = it->next) {
+            dap_chain_tx_in_cond_t *l_tx_in = it->data;
+            dap_chain_tx_out_cond_t *l_tx_out_cond = dap_chain_ledger_get_tx_out_cond_linked_to_tx_in_cond(a_ledger, l_tx_in);
+
+            if (l_tx_out_cond && 
+                l_tx_out_cond->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY &&
+                l_tx_out_cond->header.srv_uid.uint64 == DAP_CHAIN_NET_SRV_VPN_ID) {
+                    if (a_action) *a_action = DAP_CHAIN_TX_TAG_ACTION_USE;
+                    return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+
+
+int dap_chain_net_srv_vpn_pre_init()
+{
+    dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_VPN_ID };
+    dap_ledger_service_add(l_uid, "vpn", s_tag_check_vpn);
+    return 0;
+}
diff --git a/modules/service/vpn/include/dap_chain_net_srv_vpn.h b/modules/service/vpn/include/dap_chain_net_srv_vpn.h
index 1fb31f7cb439d11c2cbf83de6972ea6d51c626c6..93698d8b18cbac896b6bf51eb6b4aee025c2dad0 100644
--- a/modules/service/vpn/include/dap_chain_net_srv_vpn.h
+++ b/modules/service/vpn/include/dap_chain_net_srv_vpn.h
@@ -28,6 +28,7 @@
 #include "dap_config.h"
 #include "dap_chain_net_srv.h"
 #include "dap_events.h"
+#include "dap_chain_net_srv_vpn_common.h"
 
 #define DAP_CHAIN_NET_SRV_VPN_CDB_GDB_PREFIX "srv.vpn"
 
@@ -36,8 +37,6 @@
 
 #define DAP_STREAM_CH_NET_SRV_ID_VPN        'S'
 
-#define DAP_CHAIN_NET_SRV_VPN_ID            0x0000000000000001
-
 #define VPN_PACKET_OP_CODE_CONNECTED        0x000000a9
 #define VPN_PACKET_OP_CODE_CONNECT          0x000000aa
 #define VPN_PACKET_OP_CODE_DISCONNECT       0x000000ab
@@ -172,6 +171,7 @@ typedef struct dap_chain_net_srv_vpn
 
 int dap_chain_net_srv_client_vpn_init(dap_config_t * g_config);
 
+int dap_chain_net_srv_vpn_pre_init();
 int dap_chain_net_srv_vpn_init(dap_config_t * g_config);
 void dap_chain_net_srv_vpn_deinit(void);
 
diff --git a/modules/service/vpn/include/dap_chain_net_srv_vpn_common.h b/modules/service/vpn/include/dap_chain_net_srv_vpn_common.h
new file mode 100644
index 0000000000000000000000000000000000000000..abb3ad778b0fb973d578d8a8150970dc72c32ea3
--- /dev/null
+++ b/modules/service/vpn/include/dap_chain_net_srv_vpn_common.h
@@ -0,0 +1,4 @@
+
+#define DAP_CHAIN_NET_SRV_VPN_ID            0x0000000000000001
+
+int dap_chain_net_srv_vpn_pre_init();
diff --git a/modules/service/xchange/dap_chain_net_srv_xchange.c b/modules/service/xchange/dap_chain_net_srv_xchange.c
index e914b297de5edb4fb1218473cc464a06f1db0457..e366308c2ec35d55f87ff3ca7f94d495f9b46677 100644
--- a/modules/service/xchange/dap_chain_net_srv_xchange.c
+++ b/modules/service/xchange/dap_chain_net_srv_xchange.c
@@ -34,7 +34,7 @@
 #include "dap_time.h"
 #include "dap_chain_net_srv.h"
 #include "dap_chain_ledger.h"
-#include "dap_chain_node_cli.h"
+#include "dap_chain_net_srv_order.h"
 #include "dap_common.h"
 #include "dap_hash.h"
 #include "dap_math_ops.h"
@@ -42,11 +42,11 @@
 #include "dap_chain_common.h"
 #include "dap_chain_mempool.h"
 #include "dap_chain_datum_decree.h"
-#include "dap_tsd.h"
 #include "dap_chain_net_tx.h"
 #include "dap_chain_net_srv.h"
 #include "dap_chain_net_srv_xchange.h"
 #include "uthash.h"
+#include "dap_cli_server.h"
 
 #define LOG_TAG "dap_chain_net_srv_xchange"
 
@@ -56,13 +56,6 @@ typedef enum tx_opt_status {
     TX_STATUS_INACTIVE
 } tx_opt_status_t;
 
-typedef enum xchange_tx_type {
-    TX_TYPE_UNDEFINED=0,
-    TX_TYPE_ORDER,
-    TX_TYPE_EXCHANGE,
-    TX_TYPE_INVALIDATE
-} xchange_tx_type_t;
-
 static dap_chain_net_srv_fee_item_t *s_service_fees = NULL; // Governance statements for networks
 static pthread_rwlock_t s_service_fees_rwlock = PTHREAD_RWLOCK_INITIALIZER;
 
@@ -77,8 +70,6 @@ static int s_callback_requested(dap_chain_net_srv_t *a_srv, uint32_t a_usage_id,
 static int s_callback_response_success(dap_chain_net_srv_t *a_srv, uint32_t a_usage_id, dap_chain_net_srv_client_remote_t *a_srv_client, const void *a_data, size_t a_data_size);
 static int s_callback_response_error(dap_chain_net_srv_t *a_srv, uint32_t a_usage_id, dap_chain_net_srv_client_remote_t *a_srv_client, const void *a_data, size_t a_data_size);
 static int s_callback_receipt_next_success(dap_chain_net_srv_t *a_srv, uint32_t a_usage_id, dap_chain_net_srv_client_remote_t *a_srv_client, const void *a_data, size_t a_data_size);
-
-static xchange_tx_type_t s_xchange_tx_get_type (dap_chain_net_t * a_net, dap_chain_datum_tx_t * a_tx, dap_chain_tx_out_cond_t **a_out_cond_item, int *a_item_idx, dap_chain_tx_out_cond_t **a_out_prev_cond_item);
 static int s_tx_check_for_open_close(dap_chain_net_t * a_net, dap_chain_datum_tx_t * a_tx);
 static bool s_string_append_tx_cond_info( dap_string_t * a_reply_str, dap_chain_net_t * a_net, dap_chain_datum_tx_t * a_tx, tx_opt_status_t a_filter_by_status, bool a_append_prev_hash, bool a_print_status,bool a_print_ts);
 dap_chain_net_srv_xchange_price_t *s_xchange_price_from_order(dap_chain_net_t *a_net, dap_chain_datum_tx_t *a_order, uint256_t *a_fee, bool a_ret_is_invalid);
@@ -86,6 +77,66 @@ dap_chain_net_srv_xchange_price_t *s_xchange_price_from_order(dap_chain_net_t *a
 static dap_chain_net_srv_xchange_t *s_srv_xchange;
 static bool s_debug_more = true;
 
+
+static bool s_tag_check_xchange(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_datum_tx_item_groups_t *a_items_grp, dap_chain_tx_tag_action_type_t *a_action)
+{
+    //check if we have in or out for xchange
+    
+    bool have_xchange_out = false;
+    bool have_xchange_in = false;
+    if (a_items_grp->items_out_cond_srv_xchange) {
+        dap_chain_tx_out_cond_t *l_cond_out = a_items_grp->items_out_cond_srv_xchange->data; 
+        if (l_cond_out->header.srv_uid.uint64 == DAP_CHAIN_NET_SRV_XCHANGE_ID)
+            have_xchange_out = true;
+    }
+    
+    if (a_items_grp->items_in_cond) {
+       for (dap_list_t *it = a_items_grp->items_in_cond; it; it = it->next) {
+            dap_chain_tx_in_cond_t *l_tx_in = it->data;
+            dap_chain_tx_out_cond_t *l_tx_out_cond = dap_chain_ledger_get_tx_out_cond_linked_to_tx_in_cond(a_ledger, l_tx_in);
+
+            if (l_tx_out_cond && 
+                l_tx_out_cond->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE &&
+                l_tx_out_cond->header.srv_uid.uint64 == DAP_CHAIN_NET_SRV_XCHANGE_ID) {
+                    have_xchange_in = true;
+            }
+        }
+    }
+
+    if (have_xchange_in || have_xchange_out) {
+        //xchange by xchange module
+        xchange_tx_type_t type = dap_chain_net_srv_xchange_tx_get_type(a_ledger, a_tx, NULL, NULL, NULL);
+        switch(type)
+        {
+            case TX_TYPE_ORDER:
+            { 
+                if(a_action) *a_action = DAP_CHAIN_TX_TAG_ACTION_OPEN;
+                return true;
+            }
+
+            case TX_TYPE_EXCHANGE:
+            { 
+                if(a_action) *a_action = DAP_CHAIN_TX_TAG_ACTION_USE;
+                return true;
+            }
+
+            case TX_TYPE_INVALIDATE:
+            { 
+                if(a_action) *a_action = DAP_CHAIN_TX_TAG_ACTION_CLOSE;
+                return true;
+            } 
+            default:
+            {
+                if(a_action) *a_action = DAP_CHAIN_TX_TAG_ACTION_UNKNOWN;
+                return false;
+            }
+        }
+    }
+
+    return false;
+    
+}
+
 /**
  * @brief dap_chain_net_srv_xchange_init Init actions for xchanger stream channel
  * @return 0 if everything is okay, lesser then zero if errors
@@ -136,6 +187,10 @@ int dap_chain_net_srv_xchange_init()
     l_srv_callbacks.receipt_next_success = s_callback_receipt_next_success;
     l_srv_callbacks.decree = s_callback_decree;
 
+    //register service for tagging
+    dap_ledger_service_add(l_uid, "xchange", s_tag_check_xchange);
+
+
     dap_chain_net_srv_t* l_srv = dap_chain_net_srv_add(l_uid, "srv_xchange", &l_srv_callbacks);
     s_srv_xchange = DAP_NEW_Z(dap_chain_net_srv_xchange_t);
     if (!s_srv_xchange || !l_srv) {
@@ -210,7 +265,7 @@ static bool s_xchange_verificator_callback(dap_ledger_t *a_ledger, dap_chain_tx_
     byte_t * l_tx_item;
 
     dap_chain_addr_t l_service_fee_addr, *l_seller_addr = &a_tx_out_cond->subtype.srv_xchange.seller_addr;
-    uint16_t l_service_fee_type;
+    uint16_t l_service_fee_type = 0;
     dap_chain_net_t *l_net = a_ledger->net;
     bool l_service_fee_used = dap_chain_net_srv_xchange_get_fee(l_net->pub.id, &l_service_fee_val, &l_service_fee_addr, &l_service_fee_type);
     const char *l_native_ticker = l_net->pub.native_ticker;
@@ -647,7 +702,7 @@ static dap_chain_datum_tx_t *s_xchange_tx_create_exchange(dap_chain_net_srv_xcha
             l_datoshi_buy = a_datoshi_buy;
         
         if (s_debug_more) {
-            char *l_datoshi_sell_str; dap_uint256_to_char(l_datoshi_sell, &l_datoshi_sell_str);
+            const char *l_datoshi_sell_str; dap_uint256_to_char(l_datoshi_sell, &l_datoshi_sell_str);
             log_it(L_NOTICE, "l_value_sell = %s %s", l_datoshi_sell_str, a_price->token_sell);
         }
         
@@ -671,14 +726,14 @@ static dap_chain_datum_tx_t *s_xchange_tx_create_exchange(dap_chain_net_srv_xcha
     }
     // transfer unselling coins (partial exchange)
     if (s_debug_more) {
-        char *l_value_str; dap_uint256_to_char(l_tx_out_cond->header.value, &l_value_str);
+        const char *l_value_str; dap_uint256_to_char(l_tx_out_cond->header.value, &l_value_str);
         log_it(L_NOTICE, "l_value_cond = %s", l_value_str);
     }
     
     if (compare256(l_tx_out_cond->header.value, l_datoshi_sell) == 1) {
         SUBTRACT_256_256(l_tx_out_cond->header.value, l_datoshi_sell, &l_value_back);
         if (s_debug_more) {
-            char *l_value_back_str; dap_uint256_to_char(l_value_back, &l_value_back_str);
+            const char *l_value_back_str; dap_uint256_to_char(l_value_back, &l_value_back_str);
             log_it(L_NOTICE, "l_value_unselled = %s", l_value_back_str);
         }
         
@@ -703,7 +758,7 @@ static dap_chain_datum_tx_t *s_xchange_tx_create_exchange(dap_chain_net_srv_xcha
         return NULL;
     }
     if (s_debug_more) {
-        char *l_buy_str; dap_uint256_to_char(l_datoshi_buy, &l_buy_str);
+        const char *l_buy_str; dap_uint256_to_char(l_datoshi_buy, &l_buy_str);
         log_it(L_NOTICE, "l_value_buy = %s %s", l_buy_str, a_price->token_buy);
     }
     
@@ -715,7 +770,7 @@ static dap_chain_datum_tx_t *s_xchange_tx_create_exchange(dap_chain_net_srv_xcha
             return NULL;
         }
         if (s_debug_more) {
-            char *l_fee_str; dap_uint256_to_char(a_datoshi_fee, &l_fee_str);
+            const char *l_fee_str; dap_uint256_to_char(a_datoshi_fee, &l_fee_str);
             log_it (L_NOTICE, "l_validator_fee = %s", l_fee_str);
         }
     }
@@ -727,7 +782,7 @@ static dap_chain_datum_tx_t *s_xchange_tx_create_exchange(dap_chain_net_srv_xcha
             return NULL;
         }
         if (s_debug_more) {
-            char *l_net_fee_str; dap_uint256_to_char(l_net_fee, &l_net_fee_str);
+            const char *l_net_fee_str; dap_uint256_to_char(l_net_fee, &l_net_fee_str);
             log_it(L_NOTICE, "l_net_fee = %s", l_net_fee_str);
         }
     }
@@ -739,7 +794,7 @@ static dap_chain_datum_tx_t *s_xchange_tx_create_exchange(dap_chain_net_srv_xcha
             return NULL;
         }
         if (s_debug_more) {
-            char *l_srv_fee_str; dap_uint256_to_char(l_service_fee, &l_srv_fee_str);
+            const char *l_srv_fee_str; dap_uint256_to_char(l_service_fee, &l_srv_fee_str);
             log_it(L_NOTICE, "l_service_fee = %s %s", 
                              l_srv_fee_str, l_service_ticker ? l_service_ticker : "<undefined>");
         }
@@ -754,9 +809,9 @@ static dap_chain_datum_tx_t *s_xchange_tx_create_exchange(dap_chain_net_srv_xcha
         }
     }
     if (s_debug_more) {
-        char *l_value_transfer_str; dap_uint256_to_char(l_value_transfer, &l_value_transfer_str);
+        const char *l_value_transfer_str; dap_uint256_to_char(l_value_transfer, &l_value_transfer_str);
         log_it(L_NOTICE, "l_value_transfer = %s", l_value_transfer_str);
-        char *l_value_back_str; dap_uint256_to_char(l_value_back, &l_value_back_str);
+        const char *l_value_back_str; dap_uint256_to_char(l_value_back, &l_value_back_str);
         log_it(L_NOTICE, "l_value_back = %s", l_value_back_str);
     }
     // fee back
@@ -770,9 +825,9 @@ static dap_chain_datum_tx_t *s_xchange_tx_create_exchange(dap_chain_net_srv_xcha
             }
         }
         if (s_debug_more) {
-            char *l_fee_transfer_str; dap_uint256_to_char(l_fee_transfer, &l_fee_transfer_str);
+            const char *l_fee_transfer_str; dap_uint256_to_char(l_fee_transfer, &l_fee_transfer_str);
             log_it(L_NOTICE, "l_fee_transfer = %s", l_fee_transfer_str);
-            char *l_val_back_str; dap_uint256_to_char(l_value_back, &l_val_back_str);
+            const char *l_val_back_str; dap_uint256_to_char(l_value_back, &l_val_back_str);
             log_it(L_NOTICE, "l_cashback = %s", l_val_back_str);
         }
     }
@@ -834,7 +889,7 @@ uint64_t dap_chain_net_srv_xchange_get_order_completion_rate(dap_chain_net_t *a_
         MULT_256_COIN(l_percent_completed, dap_chain_coins_to_balance("100.0"), &l_percent_completed);
     } else {
         dap_chain_tx_out_cond_t *l_out_prev_cond_item = NULL;
-        xchange_tx_type_t tx_type = s_xchange_tx_get_type(a_net, l_last_tx, NULL, NULL, &l_out_prev_cond_item);
+        xchange_tx_type_t tx_type = dap_chain_net_srv_xchange_tx_get_type(a_net->pub.ledger, l_last_tx, NULL, NULL, &l_out_prev_cond_item);
         if (tx_type == TX_TYPE_EXCHANGE){
             SUBTRACT_256_256(l_out_cond->header.value, uint256_0, &l_percent_completed);
             DIV_256_COIN(l_percent_completed, l_out_cond->header.value, &l_percent_completed);
@@ -1328,7 +1383,7 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, v
                 dap_chain_datum_tx_t * l_tx = dap_chain_net_get_tx_by_hash(l_net, &l_order_tx_hash, TX_SEARCH_TYPE_NET);
                 
                 if( l_tx){
-                    xchange_tx_type_t l_tx_type = s_xchange_tx_get_type(l_net, l_tx, NULL, NULL, NULL);
+                    xchange_tx_type_t l_tx_type = dap_chain_net_srv_xchange_tx_get_type(l_net->pub.ledger, l_tx, NULL, NULL, NULL);
                     char *l_tx_hash = dap_chain_hash_fast_to_str_new(&l_order_tx_hash);
                     if(l_tx_type != TX_TYPE_ORDER){
                         dap_cli_server_cmd_set_reply_text(a_str_reply, "Datum with hash %s is not order. Check hash.", l_tx_hash);
@@ -1507,7 +1562,7 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, v
             dap_hash_fast_t l_tx_hash = {};
             dap_hash_fast(l_tx, dap_chain_datum_tx_get_size(l_tx), &l_tx_hash);
 
-            char *l_amount_coins_str = "0.0", *l_amount_datoshi_str = "0";
+            const char *l_amount_coins_str = NULL, *l_amount_datoshi_str = NULL;
 
             uint64_t l_percent_completed = dap_chain_net_srv_xchange_get_order_completion_rate(l_net, l_order_tx_hash);
 
@@ -1518,10 +1573,8 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, v
             dap_time_to_str_rfc822(l_tmp_buf, DAP_TIME_STR_SIZE, l_ts_create);
             l_tmp_buf[strlen(l_tmp_buf) - 1] = '\0';
 
-            if (l_out_cond_last_tx) {
+            if (l_out_cond_last_tx)
                 l_amount_datoshi_str = dap_uint256_to_char(l_out_cond_last_tx->header.value, &l_amount_coins_str);
-            }
-
 
             dap_cli_server_cmd_set_reply_text(a_str_reply, "orderHash: %s\n ts_created: %s (%"DAP_UINT64_FORMAT_U")\n Status: %s, amount: %s (%s) %s, filled: %lu%%, rate (%s/%s): %s, net: %s\n\n",
                                      dap_chain_hash_fast_to_str_static(&l_tx_hash),
@@ -1533,6 +1586,9 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, v
                                      l_cp_rate,
                                      l_price->net->pub.name);
 
+
+            DAP_DEL_Z(l_amount_coins_str);
+            DAP_DEL_Z(l_amount_datoshi_str);
             DAP_DEL_Z(l_cp_rate);
             DAP_DEL_Z(l_price);
         } break;
@@ -1584,7 +1640,7 @@ static bool s_filter_tx_list(dap_chain_datum_t *a_datum, dap_chain_t *a_chain, v
     return false;
 }
 
-static xchange_tx_type_t s_xchange_tx_get_type (dap_chain_net_t * a_net, dap_chain_datum_tx_t * a_tx, dap_chain_tx_out_cond_t **a_out_cond_item, int *a_item_idx, dap_chain_tx_out_cond_t **a_out_prev_cond_item)
+xchange_tx_type_t dap_chain_net_srv_xchange_tx_get_type (dap_ledger_t * a_ledger, dap_chain_datum_tx_t * a_tx, dap_chain_tx_out_cond_t **a_out_cond_item, int *a_item_idx, dap_chain_tx_out_cond_t **a_out_prev_cond_item)
 {
     int l_tx_type = TX_TYPE_UNDEFINED;
 
@@ -1597,29 +1653,43 @@ static xchange_tx_type_t s_xchange_tx_get_type (dap_chain_net_t * a_net, dap_cha
     byte_t *l_tx_item = dap_chain_datum_tx_item_get(a_tx, &l_item_idx, TX_ITEM_TYPE_IN_COND , NULL);
     dap_chain_tx_in_cond_t * l_in_cond = l_tx_item ? (dap_chain_tx_in_cond_t *) l_tx_item : NULL;
     int l_prev_cond_idx = 0;
-    dap_chain_datum_tx_t * l_prev_tx = l_in_cond ? dap_ledger_tx_find_by_hash(a_net->pub.ledger, &l_in_cond->header.tx_prev_hash) : NULL;
+    dap_chain_datum_tx_t * l_prev_tx = l_in_cond ? dap_ledger_tx_find_by_hash(a_ledger, &l_in_cond->header.tx_prev_hash) : NULL;
     dap_chain_tx_out_cond_t *l_out_prev_cond_item = l_prev_tx ? dap_chain_datum_tx_out_cond_get(l_prev_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE,
                                                                                                 &l_prev_cond_idx) : NULL;
 
     if(l_out_prev_cond_item && l_out_prev_cond_item->header.subtype != DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE)
         return l_tx_type;
-
+    
+    if (l_in_cond && l_prev_cond_idx >= 0 && (uint32_t)l_prev_cond_idx != l_in_cond->header.tx_out_prev_idx)
+        return l_tx_type;
+    
     if (l_out_cond_item && !l_out_prev_cond_item)
         l_tx_type = TX_TYPE_ORDER;
     else if (l_out_cond_item && l_out_prev_cond_item)
+    {
         l_tx_type = TX_TYPE_EXCHANGE;
-    else if (!l_out_cond_item && l_out_prev_cond_item){
+    }
+    else if (!l_out_cond_item && l_out_prev_cond_item)
+    {
         dap_chain_datum_tx_t * l_prev_tx_temp = a_tx;
         byte_t *l_tx_item_temp = NULL;
-        while((l_tx_item_temp = dap_chain_datum_tx_item_get(l_prev_tx_temp, &l_item_idx, TX_ITEM_TYPE_IN_COND , NULL)) != NULL){
+        while((l_tx_item_temp = dap_chain_datum_tx_item_get(l_prev_tx_temp, &l_item_idx, TX_ITEM_TYPE_IN_COND , NULL)) != NULL)
+        {
                 dap_chain_tx_in_cond_t * l_in_cond_temp = (dap_chain_tx_in_cond_t *) l_tx_item_temp;
-                l_prev_tx_temp = dap_ledger_tx_find_by_hash(a_net->pub.ledger, &l_in_cond_temp->header.tx_prev_hash);
+                l_prev_tx_temp = dap_ledger_tx_find_by_hash(a_ledger, &l_in_cond_temp->header.tx_prev_hash);
         }
 
-        dap_chain_tx_sig_t *l_tx_prev_sig = (dap_chain_tx_sig_t *)dap_chain_datum_tx_item_get(l_prev_tx_temp, NULL, TX_ITEM_TYPE_SIG, NULL);
-        dap_sign_t *l_prev_sign = dap_chain_datum_tx_item_sign_get_sig((dap_chain_tx_sig_t *)l_tx_prev_sig);
-        dap_chain_tx_sig_t *l_tx_sig = (dap_chain_tx_sig_t *)dap_chain_datum_tx_item_get(a_tx, NULL, TX_ITEM_TYPE_SIG, NULL);
-        dap_sign_t *l_sign = dap_chain_datum_tx_item_sign_get_sig((dap_chain_tx_sig_t *)l_tx_sig);
+        //have to find EXCHANGE tx_out_cond!
+        l_out_cond_item = NULL;
+        l_out_cond_item = dap_chain_datum_tx_out_cond_get(l_prev_tx_temp, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE,
+                                                                               &l_cond_idx);
+        if (!l_out_cond_item) {
+            l_tx_type = TX_TYPE_UNDEFINED;
+        } else {
+            dap_chain_tx_sig_t *l_tx_prev_sig = (dap_chain_tx_sig_t *)dap_chain_datum_tx_item_get(l_prev_tx_temp, NULL, TX_ITEM_TYPE_SIG, NULL);
+            dap_sign_t *l_prev_sign = dap_chain_datum_tx_item_sign_get_sig((dap_chain_tx_sig_t *)l_tx_prev_sig);
+            dap_chain_tx_sig_t *l_tx_sig = (dap_chain_tx_sig_t *)dap_chain_datum_tx_item_get(a_tx, NULL, TX_ITEM_TYPE_SIG, NULL);
+            dap_sign_t *l_sign = dap_chain_datum_tx_item_sign_get_sig((dap_chain_tx_sig_t *)l_tx_sig);
 
         bool l_owner = false;
         l_owner = dap_sign_compare_pkeys(l_prev_sign,l_sign);
@@ -1627,14 +1697,16 @@ static xchange_tx_type_t s_xchange_tx_get_type (dap_chain_net_t * a_net, dap_cha
                 l_tx_type = TX_TYPE_INVALIDATE;
         else
                 l_tx_type = TX_TYPE_EXCHANGE;
-    }
+        }
 
-    if(a_out_cond_item)
-        *a_out_cond_item = l_out_cond_item;
-    if(a_out_prev_cond_item)
-        *a_out_prev_cond_item = l_out_prev_cond_item;
-    if (a_item_idx)
-        *a_item_idx = l_cond_idx;
+        if(a_out_cond_item)
+            *a_out_cond_item = l_out_cond_item;
+        if(a_out_prev_cond_item)
+            *a_out_prev_cond_item = l_out_prev_cond_item;
+        if (a_item_idx)
+            *a_item_idx = l_cond_idx;
+        return l_tx_type;
+    }
     return l_tx_type;
 }
 
@@ -1702,7 +1774,7 @@ static bool s_string_append_tx_cond_info( dap_string_t * a_reply_str,
     dap_chain_tx_out_cond_t *l_out_cond_item = NULL;
     int l_cond_idx = 0;
 
-    xchange_tx_type_t l_tx_type = s_xchange_tx_get_type(a_net, a_tx, &l_out_cond_item, &l_cond_idx, &l_out_prev_cond_item);
+    xchange_tx_type_t l_tx_type = dap_chain_net_srv_xchange_tx_get_type(a_net->pub.ledger, a_tx, &l_out_cond_item, &l_cond_idx, &l_out_prev_cond_item);
 
     bool l_is_closed = dap_ledger_tx_hash_is_used_out_item(a_net->pub.ledger, &l_tx_hash, l_cond_idx, NULL);
     if ((a_filter_by_status == TX_STATUS_ACTIVE && l_is_closed) || (a_filter_by_status == TX_STATUS_INACTIVE && !l_is_closed))
@@ -1713,9 +1785,8 @@ static bool s_string_append_tx_cond_info( dap_string_t * a_reply_str,
 
     switch(l_tx_type){
         case TX_TYPE_ORDER:{
-            char *l_rate_str = dap_chain_balance_to_coins(l_out_cond_item->subtype.srv_xchange.rate),
-                 *l_amount_str, 
-                 *l_amount_datoshi_str = dap_uint256_to_char(l_out_cond_item->header.value, &l_amount_str);
+            char *l_rate_str = dap_chain_balance_to_coins(l_out_cond_item->subtype.srv_xchange.rate);
+            const char *l_amount_str, *l_amount_datoshi_str = dap_uint256_to_char(l_out_cond_item->header.value, &l_amount_str);
 
             dap_string_append_printf(a_reply_str, "Hash: %s\n", l_tx_hash_str);
             if(a_print_ts){
@@ -1760,19 +1831,20 @@ static bool s_string_append_tx_cond_info( dap_string_t * a_reply_str,
             if(a_print_status)
                 dap_string_append_printf(a_reply_str, "  Status: %s,", l_is_closed ? "inactive" : "active");
             
-            char *l_value_from_str, *l_value_from_datoshi_str = dap_uint256_to_char(l_value_from, &l_value_from_str);
+            const char *l_value_from_str, *l_value_from_datoshi_str = dap_uint256_to_char(l_value_from, &l_value_from_str);
             dap_string_append_printf(a_reply_str, "  changed %s (%s) %s", l_value_from_str, l_value_from_datoshi_str, l_tx_input_ticker);
 
-            char *l_value_to_str, *l_value_to_datoshi_str = dap_uint256_to_char(l_value_to, &l_value_to_str);
+            const char *l_value_to_str, *l_value_to_datoshi_str = dap_uint256_to_char(l_value_to, &l_value_to_str);
             dap_string_append_printf(a_reply_str, " for %s (%s) %s,", l_value_to_str, l_value_to_datoshi_str, l_buy_ticker);
 
-            char *l_rate_str; dap_uint256_to_char(l_rate, &l_rate_str);
+            const char *l_rate_str; dap_uint256_to_char(l_rate, &l_rate_str);
             dap_string_append_printf(a_reply_str, "  rate (%s/%s): %s,", l_buy_ticker, l_tx_input_ticker, l_rate_str);
 
-            char *l_amount_str = "0.0",
+            const char *l_amount_str = NULL,
                  *l_amount_datoshi_str = l_out_cond_item ? dap_uint256_to_char(l_out_cond_item->header.value, &l_amount_str) : "0";
-            dap_string_append_printf(a_reply_str, "  remain amount %s (%s) %s, net: %s", l_amount_str, l_amount_datoshi_str, l_tx_input_ticker, a_net->pub.name);
-            if(a_print_prev_hash)
+            dap_string_append_printf(a_reply_str, "  remain amount %s (%s) %s, net: %s", l_amount_str ? l_amount_str : "0.0",
+                                                                        l_amount_datoshi_str, l_tx_input_ticker, a_net->pub.name);
+            if (a_print_prev_hash)
                 dap_string_append_printf(a_reply_str, "\n  Prev cond: %s", l_tx_prev_cond_hash_str);
         } break;
         case TX_TYPE_INVALIDATE:{
@@ -1810,6 +1882,9 @@ static bool s_string_append_tx_cond_info( dap_string_t * a_reply_str,
             dap_string_append_printf(a_reply_str, "  returned %s(%s) %s to owner from order %s", l_value_from_str, l_value_from_datoshi_str, l_tx_input_ticker, l_order_hash_str);
             if(a_print_prev_hash)
                 dap_string_append_printf(a_reply_str, "\n  Prev cond: %s", l_tx_prev_cond_hash_str);
+
+            DAP_DELETE(l_value_from_str);
+            DAP_DELETE(l_value_from_datoshi_str);
         } break;
         default: return false;
     }
@@ -1958,27 +2033,25 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **a_str_reply)
             const char *l_offset_str = NULL;
             dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-limit", &l_limit_str);
             dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-offset", &l_offset_str);
-            size_t l_limit = l_limit_str ? strtoul(l_limit_str, NULL, 10) : 0;
+            size_t l_limit = l_limit_str ? strtoul(l_limit_str, NULL, 10) : 1000;
             size_t l_offset = l_offset_str ? strtoul(l_offset_str, NULL, 10) : 0;
-            size_t l_arr_start = 0;
-            if (l_limit > 1) {
-                l_arr_start = l_limit * l_offset;
-            }
+            size_t l_arr_start = 0;            
             size_t l_arr_end = dap_list_length(l_tx_list);
-            if (l_offset) {
+            if (l_offset > 0) {
+                l_arr_start = l_offset;
+                dap_string_append_printf(l_reply_str, "offset: %lu\n", l_arr_start);                
+            }
+            if (l_limit) {
+                dap_string_append_printf(l_reply_str, "limit: %lu\n", l_limit);
                 l_arr_end = l_arr_start + l_limit;
                 if (l_arr_end > dap_list_length(l_tx_list)) {
                     l_arr_end = dap_list_length(l_tx_list);
                 }
-            }
+            }            
             size_t i_tmp = 0;
             // Print all txs
             for (dap_list_t *it = l_tx_list; it; it = it->next) {
-                if (i_tmp < l_arr_start || i_tmp > l_arr_end) {
-                    i_tmp++;
-                    continue;
-                }
-                i_tmp++;
+                
                 dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t *)it->data;
                 dap_chain_tx_out_cond_t *l_out_cond = dap_chain_datum_tx_out_cond_get(l_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE , NULL);
                 if (!l_out_cond || l_out_cond->header.srv_uid.uint64 != DAP_CHAIN_NET_SRV_XCHANGE_ID)
@@ -2023,6 +2096,11 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **a_str_reply)
                     l_status_order = "OPENED";
                 }
 
+                if (i_tmp < l_arr_start || i_tmp >= l_arr_end) {
+                    i_tmp++;
+                    continue;
+                }
+                i_tmp++;
                 dap_hash_fast_t l_tx_hash = {};
                 dap_hash_fast(l_tx, dap_chain_datum_tx_get_size(l_tx), &l_tx_hash);
                 const char *l_tx_hash_str = dap_chain_hash_fast_to_str_static(&l_tx_hash);
@@ -2036,8 +2114,8 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **a_str_reply)
 
                 l_cp_rate = dap_chain_balance_to_coins(l_price->rate);
 
-                char *l_amount_coins_str = "0.0",
-                     *l_amount_datoshi_str = l_out_cond_last_tx ? dap_uint256_to_char(l_out_cond_last_tx->header.value, &l_amount_coins_str) : "0";
+                const char *l_amount_coins_str = NULL,
+                     *l_amount_datoshi_str = l_out_cond_last_tx ? dap_uint256_to_char(l_out_cond_last_tx->header.value, &l_amount_coins_str) : NULL;
                 dap_string_append_printf(l_reply_str, "orderHash: %s\n ts_created: %s (%"DAP_UINT64_FORMAT_U")\n Status: %s, amount: %s (%s) %s, filled: %lu%%, rate (%s/%s): %s, net: %s\n\n", l_tx_hash_str,
                                          l_tmp_buf, l_ts_create, l_status_order,
                                          l_amount_coins_str ? l_amount_coins_str : "0.0",
@@ -2298,7 +2376,7 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **a_str_reply)
                             int l_cond_idx = 0;
                             dap_chain_tx_out_cond_t *l_out_cond_item = NULL;
 
-                            if (s_xchange_tx_get_type(l_net, l_tx, &l_out_cond_item, &l_cond_idx, NULL) != TX_TYPE_ORDER){
+                            if (dap_chain_net_srv_xchange_tx_get_type(l_net->pub.ledger, l_tx, &l_out_cond_item, &l_cond_idx, NULL) != TX_TYPE_ORDER){
                                 l_cur = dap_list_next(l_cur);
                                 continue;
                             }
@@ -2341,9 +2419,9 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **a_str_reply)
                     char l_tmp_buf[DAP_TIME_STR_SIZE];
                     dap_time_to_str_rfc822(l_tmp_buf, DAP_TIME_STR_SIZE, l_last_rate_time);
                     l_tmp_buf[strlen(l_tmp_buf) - 1] = '\0';
-                    char *l_rate_average_str; dap_uint256_to_char(l_rate_average, &l_rate_average_str);
+                    const char *l_rate_average_str; dap_uint256_to_char(l_rate_average, &l_rate_average_str);
                     dap_string_append_printf(l_reply_str,"Average rate: %s   \r\n", l_rate_average_str);
-                    char *l_last_rate_str; dap_uint256_to_char(l_rate, &l_last_rate_str);
+                    const char *l_last_rate_str; dap_uint256_to_char(l_rate, &l_last_rate_str);
                     dap_string_append_printf(l_reply_str, "Last rate: %s Last rate time: %s (%"DAP_UINT64_FORMAT_U")",
                                              l_last_rate_str, l_tmp_buf, l_last_rate_time);
                     *a_str_reply = dap_string_free(l_reply_str, false);
@@ -2352,7 +2430,7 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **a_str_reply)
                     const char *l_limit_str = NULL, *l_offset_str = NULL;
                     dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-limit", &l_limit_str);
                     dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-offset", &l_offset_str);
-                    size_t l_limit = l_limit_str ? strtoul(l_limit_str, NULL, 10) : 0;
+                    size_t l_limit = l_limit_str ? strtoul(l_limit_str, NULL, 10) : 1000;
                     size_t l_offset = l_offset_str ? strtoul(l_offset_str, NULL, 10) : 0;
 
                     dap_string_t *l_reply_str = dap_string_new("");
@@ -2370,22 +2448,19 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **a_str_reply)
                     }
                     size_t l_arr_start = 0;
                     size_t l_arr_end  = l_datum_num;
-                    if (l_offset > 1) {
-                        l_arr_start = l_limit * l_offset;
+                    if (l_offset > 0) {
+                        l_arr_start = l_offset;
+                        dap_string_append_printf(l_reply_str, "offset: %lu\n", l_arr_start);
                     }
                     if (l_limit) {
                         l_arr_end = l_arr_start + l_limit;
+                        dap_string_append_printf(l_reply_str, "limit: %lu\n", l_limit);
                     }
                     size_t i_tmp = 0;
 
                     dap_list_t * l_cur = l_datum_list0;
                     while(l_cur){
-                        if (i_tmp < l_arr_start || i_tmp > l_arr_end) {
-                            i_tmp++;
-                            l_cur = dap_list_next(l_cur);
-                            continue;
-                        }
-                        i_tmp++;
+                        
                         dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t*) ((dap_chain_datum_t*) l_cur->data)->data;
                         if(l_tx){
                             dap_hash_fast_t l_tx_hash = {};
@@ -2417,6 +2492,12 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **a_str_reply)
                                 l_cur = dap_list_next(l_cur);
                                 continue;
                             }
+                            if (i_tmp < l_arr_start || i_tmp >= l_arr_end) {
+                                i_tmp++;
+                                l_cur = dap_list_next(l_cur);
+                                continue;
+                            }
+                            i_tmp++;
 
                             s_string_append_tx_cond_info(l_reply_str, l_net, l_tx, TX_STATUS_ALL, false, false, true);
                         }
@@ -2525,7 +2606,7 @@ json_object *dap_chain_net_srv_xchange_print_fee_json(dap_chain_net_t *a_net) {
     dap_chain_addr_t l_addr = {0};
     uint16_t l_type = 0;
     if (dap_chain_net_srv_xchange_get_fee(a_net->pub.id, &l_fee, &l_addr, &l_type)) {
-        char *l_fee_coins, *l_fee_balance = dap_uint256_to_char(l_fee, &l_fee_coins);
+        const char *l_fee_coins, *l_fee_balance = dap_uint256_to_char(l_fee, &l_fee_coins);
         json_object *l_jobj_xchange = json_object_new_object();
         json_object_object_add(l_jobj_xchange, "coin",      json_object_new_string(l_fee_coins));
         json_object_object_add(l_jobj_xchange, "balance",   json_object_new_string(l_fee_balance));
@@ -2544,7 +2625,7 @@ void dap_chain_net_srv_xchange_print_fee(dap_chain_net_t *a_net, dap_string_t *a
     dap_chain_addr_t l_addr = {0};
     uint16_t l_type = 0;
     if (dap_chain_net_srv_xchange_get_fee(a_net->pub.id, &l_fee, &l_addr, &l_type)) {
-        char *l_fee_coins, *l_fee_balance = dap_uint256_to_char(l_fee, &l_fee_coins);
+        const char *l_fee_coins, *l_fee_balance = dap_uint256_to_char(l_fee, &l_fee_coins);
         dap_string_append_printf(a_string_ret, "\txchange:\n"
                                                "\t\tFee: %s (%s)\n"
                                                "\t\tAddr: %s\n"
diff --git a/modules/service/xchange/include/dap_chain_net_srv_xchange.h b/modules/service/xchange/include/dap_chain_net_srv_xchange.h
index d6eae10743f4e60d17fcfd12a64121568f79ae1e..9cff53d974fe3c6f960c663dc272c196e81d07c2 100644
--- a/modules/service/xchange/include/dap_chain_net_srv_xchange.h
+++ b/modules/service/xchange/include/dap_chain_net_srv_xchange.h
@@ -25,7 +25,8 @@
 #pragma once
 
 #include "dap_chain_net_srv.h"
-#include "dap_chain_net_srv_order.h"
+#include "dap_chain_wallet.h"
+#include "dap_chain_datum_tx_out_cond.h"
 
 #define DAP_CHAIN_NET_SRV_XCHANGE_ID 0x2
 #define GROUP_LOCAL_XCHANGE "local.xchange"
@@ -77,7 +78,7 @@ typedef enum dap_chain_net_srv_xchange_create_error_list{
     XCHANGE_CREATE_ERROR_MEMORY_ALLOCATED,
     XCHANGE_CREATE_ERROR_CAN_NOT_COMPOSE_THE_CONDITIONAL_TRANSACTION,
     XCHANGE_CREATE_ERROR_CAN_NOT_PUT_TRANSACTION_TO_MEMPOOL,
-}dap_chain_net_srv_xchange_create_error_t;
+} dap_chain_net_srv_xchange_create_error_t;
 dap_chain_net_srv_xchange_create_error_t dap_chain_net_srv_xchange_create(dap_chain_net_t *a_net, const char *a_token_buy,
                                      const char *a_token_sell, uint256_t a_datoshi_sell,
                                      uint256_t a_rate, uint256_t a_fee, dap_chain_wallet_t *a_wallet,
@@ -90,7 +91,7 @@ typedef enum dap_chain_net_srv_xchange_remove_error_list{
     XCHANGE_REMOVE_ERROR_CAN_NOT_FIND_TX,
     XCHANGE_REMOVE_ERROR_CAN_NOT_CREATE_PRICE,
     XCHANGE_REMOVE_ERROR_CAN_NOT_INVALIDATE_TX
-}dap_chain_net_srv_xchange_remove_error_t;
+} dap_chain_net_srv_xchange_remove_error_t;
 dap_chain_net_srv_xchange_remove_error_t dap_chain_net_srv_xchange_remove(dap_chain_net_t *a_net, dap_hash_fast_t *a_hash_tx, uint256_t a_fee,
                                      dap_chain_wallet_t *a_wallet, char **a_out_hash_tx);
 
@@ -103,7 +104,7 @@ typedef enum dap_chain_net_srv_xchange_purchase_error_list{
     XCHANGE_PURCHASE_ERROR_SPECIFIED_ORDER_NOT_FOUND,
     XCHANGE_PURCHASE_ERROR_CAN_NOT_CREATE_PRICE,
     XCHANGE_PURCHASE_ERROR_CAN_NOT_CREATE_EXCHANGE_TX,
-}dap_chain_net_srv_xchange_purchase_error_t;
+} dap_chain_net_srv_xchange_purchase_error_t;
 dap_chain_net_srv_xchange_purchase_error_t dap_chain_net_srv_xchange_purchase(dap_chain_net_t *a_net, dap_hash_fast_t *a_order_hash, uint256_t a_value,
                                        uint256_t a_fee, dap_chain_wallet_t *a_wallet, char **a_hash_out);
 
@@ -113,6 +114,15 @@ typedef enum dap_chain_net_srv_xchange_order_status{
     XCHANGE_ORDER_STATUS_OPENED = 0,
     XCHANGE_ORDER_STATUS_CLOSED,
     XCHANGE_ORDER_STATUS_UNKNOWN,
-}dap_chain_net_srv_xchange_order_status_t;
+} dap_chain_net_srv_xchange_order_status_t;
+
+typedef enum xchange_tx_type{
+    TX_TYPE_UNDEFINED=0,
+    TX_TYPE_ORDER,
+    TX_TYPE_EXCHANGE,
+    TX_TYPE_INVALIDATE
+}   xchange_tx_type_t;
+
 dap_chain_net_srv_xchange_order_status_t dap_chain_net_srv_xchange_get_order_status(dap_chain_net_t *a_net, dap_hash_fast_t a_order_tx_hash);
 bool dap_chain_net_srv_xchange_get_fee(dap_chain_net_id_t a_net_id, uint256_t *a_fee, dap_chain_addr_t *a_addr, uint16_t *a_type);
+xchange_tx_type_t dap_chain_net_srv_xchange_tx_get_type (dap_ledger_t * a_ledger, dap_chain_datum_tx_t * a_tx, dap_chain_tx_out_cond_t **a_out_cond_item, int *a_item_idx, dap_chain_tx_out_cond_t **a_out_prev_cond_item);
diff --git a/modules/type/blocks/dap_chain_block.c b/modules/type/blocks/dap_chain_block.c
index 244f990165fcee593e212f771d3ffb4caf3c0303..42139e022a670e7c3bdbf3e381f9b7c91cc503b7 100644
--- a/modules/type/blocks/dap_chain_block.c
+++ b/modules/type/blocks/dap_chain_block.c
@@ -21,13 +21,11 @@
     along with any DAP SDK based project.  If not, see <http://www.gnu.org/licenses/>.
 */
 #include <stddef.h>
-#include "string.h"
 #include "dap_common.h"
 #include "dap_config.h"
 #include "dap_hash.h"
 #include "dap_uuid.h"
 #include "dap_chain_block.h"
-#include "dap_chain_block_cache.h"
 
 #define LOG_TAG "dap_chain_block"
 
@@ -484,49 +482,65 @@ size_t dap_chain_block_meta_add(dap_chain_block_t ** a_block_ptr, size_t a_block
     return a_block_size + l_add_size;
 }
 
+static const char *s_meta_type_to_string(uint8_t a_meta_type)
+{
+    switch (a_meta_type) {
+    case DAP_CHAIN_BLOCK_META_GENESIS: return "GENESIS";
+    case DAP_CHAIN_BLOCK_META_PREV: return "PREV";
+    case DAP_CHAIN_BLOCK_META_ANCHOR: return "ANCHOR";
+    case DAP_CHAIN_BLOCK_META_LINK: return "LINK";
+    case DAP_CHAIN_BLOCK_META_NONCE: return "NONCE";
+    case DAP_CHAIN_BLOCK_META_NONCE2: return "NONCE2";
+    case DAP_CHAIN_BLOCK_META_MERKLE: return "MERKLE_ROOT";
+    case DAP_CHAIN_BLOCK_META_EMERGENCY: return "EMERGENCY";
+    case DAP_CHAIN_BLOCK_META_SYNC_ATTEMPT: return "SYNC_ATTEMPT";
+    case DAP_CHAIN_BLOCK_META_ROUND_ATTEMPT: return "ROUND_ATTEMPT";
+    case DAP_CHAIN_BLOCK_META_EXCLUDED_KEYS: return "EXCLUDED_KEYS";
+    default: return "UNNOWN";
+    }
+}
+
 static uint8_t *s_meta_extract(dap_chain_block_meta_t *a_meta)
 {
     switch (a_meta->hdr.type) {
     case DAP_CHAIN_BLOCK_META_GENESIS:
+    case DAP_CHAIN_BLOCK_META_EMERGENCY:
         if (a_meta->hdr.data_size == 0)
             return DAP_INT_TO_POINTER(1);
+        log_it(L_WARNING, "Meta %s has wrong size %hu when expecting zero size",
+               s_meta_type_to_string(a_meta->hdr.type), a_meta->hdr.data_size);
     break;
     case DAP_CHAIN_BLOCK_META_PREV:
-        if (a_meta->hdr.data_size == sizeof(dap_hash_t))
-            return a_meta->data;
-        else
-            log_it(L_WARNING, "Meta PREV has wrong size %hu when expecting %zu", a_meta->hdr.data_size, sizeof(dap_hash_t));
-    break;
     case DAP_CHAIN_BLOCK_META_ANCHOR:
-        if (a_meta->hdr.data_size == sizeof(dap_hash_t))
-            return a_meta->data;
-        else
-            log_it(L_WARNING, "Anchor meta has wrong size %hu when expecting %zu", a_meta->hdr.data_size, sizeof(dap_hash_t));
-    break;
     case DAP_CHAIN_BLOCK_META_LINK:
+    case DAP_CHAIN_BLOCK_META_MERKLE:
         if (a_meta->hdr.data_size == sizeof(dap_hash_t))
             return a_meta->data;
-        else
-            log_it(L_WARNING, "Link meta has wrong size %hu when expecting %zu", a_meta->hdr.data_size, sizeof(dap_hash_t));
+        log_it(L_WARNING, "Meta %s has wrong size %hu when expecting %zu",
+               s_meta_type_to_string(a_meta->hdr.type), a_meta->hdr.data_size, sizeof(dap_hash_t));
     break;
     case DAP_CHAIN_BLOCK_META_NONCE:
-        if (a_meta->hdr.data_size == sizeof(uint64_t))
-            return a_meta->data;
-        else
-            log_it(L_WARNING, "NONCE meta has wrong size %hu when expecting %zu", a_meta->hdr.data_size, sizeof(uint64_t));
-    break;
     case DAP_CHAIN_BLOCK_META_NONCE2:
+    case DAP_CHAIN_BLOCK_META_SYNC_ATTEMPT:
         if (a_meta->hdr.data_size == sizeof(uint64_t))
             return a_meta->data;
-        else
-            log_it(L_WARNING, "NONCE2 meta has wrong size %hu when expecting %zu", a_meta->hdr.data_size, sizeof(uint64_t));
+        log_it(L_WARNING, "Meta %s has wrong size %hu when expecting %zu",
+               s_meta_type_to_string(a_meta->hdr.type), a_meta->hdr.data_size, sizeof(uint64_t));
     break;
-    case DAP_CHAIN_BLOCK_META_MERKLE:
-        if (a_meta->hdr.data_size == sizeof(dap_hash_t))
+    case DAP_CHAIN_BLOCK_META_ROUND_ATTEMPT:
+        if (a_meta->hdr.data_size == sizeof(uint8_t))
             return a_meta->data;
-        else
-            log_it(L_WARNING, "Merkle root meta has wrong size %hu when expecting %zu", a_meta->hdr.data_size, sizeof (dap_hash_t));
+        log_it(L_WARNING, "Meta %s has wrong size %hu when expecting %zu",
+               s_meta_type_to_string(a_meta->hdr.type), a_meta->hdr.data_size, sizeof(uint8_t));
     break;
+    case DAP_CHAIN_BLOCK_META_EXCLUDED_KEYS:
+        if (a_meta->hdr.data_size > sizeof(uint16_t)) {
+            uint16_t l_expected_size = *(uint16_t *)a_meta->data + sizeof(uint16_t);
+            if (!(l_expected_size % sizeof(uint16_t)) &&
+                    l_expected_size == a_meta->hdr.data_size)
+                return a_meta->data;
+        }
+        log_it(L_WARNING, "Meta %s has wrong size %hu", s_meta_type_to_string(a_meta->hdr.type), a_meta->hdr.data_size);
     default:
         log_it(L_WARNING, "Unknown meta type 0x%02x (size %u), possible corrupted block or you need to upgrade your software",
                           a_meta->hdr.type, a_meta->hdr.type);
@@ -574,10 +588,10 @@ uint8_t *dap_chain_block_meta_get(const dap_chain_block_t *a_block, size_t a_blo
  * @param a_reward
  */
 int dap_chain_block_meta_extract(dap_chain_block_t *a_block, size_t a_block_size,
-                                    dap_chain_hash_fast_t * a_block_prev_hash,
-                                    dap_chain_hash_fast_t * a_block_anchor_hash,
+                                    dap_chain_hash_fast_t *a_block_prev_hash,
+                                    dap_chain_hash_fast_t *a_block_anchor_hash,
                                     dap_chain_hash_fast_t *a_merkle,
-                                    dap_chain_hash_fast_t ** a_block_links,
+                                    dap_chain_hash_fast_t **a_block_links,
                                     size_t *a_block_links_count,
                                     bool *a_is_genesis,
                                     uint64_t *a_nonce,
diff --git a/modules/type/blocks/dap_chain_block_cache.c b/modules/type/blocks/dap_chain_block_cache.c
index dc1b11c3be82a2339456c17e6aa5a4900bf933c3..0a9926d4d25ca8858c1bf2214e632a2b8f4cddbb 100644
--- a/modules/type/blocks/dap_chain_block_cache.c
+++ b/modules/type/blocks/dap_chain_block_cache.c
@@ -26,7 +26,6 @@
 #include "dap_chain_block_cache.h"
 #include "dap_chain_datum_tx.h"
 #include "dap_chain_datum_tx_in.h"
-#include "dap_chain_datum_tx_out.h"
 
 #define LOG_TAG "dap_chain_block_cache"
 
diff --git a/modules/type/blocks/dap_chain_cs_blocks.c b/modules/type/blocks/dap_chain_cs_blocks.c
index 6d630a5d51bd3d10abdbf4b895ccaecc18a09db8..9485ea8ee2e41fbd2b3d9890155ab788951b2703 100644
--- a/modules/type/blocks/dap_chain_cs_blocks.c
+++ b/modules/type/blocks/dap_chain_cs_blocks.c
@@ -22,7 +22,6 @@
 */
 #include <pthread.h>
 #include "dap_common.h"
-#include "dap_enc_base58.h"
 #include "dap_chain.h"
 #include "dap_chain_cell.h"
 #include "dap_chain_cs.h"
@@ -86,7 +85,7 @@ typedef struct dap_chain_cs_blocks_pvt
 #define PVT(a) ((dap_chain_cs_blocks_pvt_t *)(a)->_pvt )
 
 static int s_cli_parse_cmd_hash(char ** a_argv, int a_arg_index, int a_argc, void **a_str_reply,const char * a_param, dap_chain_hash_fast_t * a_datum_hash);
-static void s_cli_meta_hash_print(  dap_string_t * a_str_tmp, const char * a_meta_title, dap_chain_block_meta_t * a_meta);
+static void s_cli_meta_hash_print(  json_object* json_obj_a, const char * a_meta_title, dap_chain_block_meta_t * a_meta);
 static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply);
 
 // Setup BFT consensus and select the longest chunk
@@ -232,7 +231,7 @@ void dap_chain_cs_blocks_deinit()
     dap_chain_block_cache_deinit();
 }
 
-static int s_chain_cs_blocks_new(dap_chain_t * a_chain, dap_config_t * a_chain_config)
+static int s_chain_cs_blocks_new(dap_chain_t *a_chain, dap_config_t *a_chain_config)
 {
     dap_chain_cs_blocks_t * l_cs_blocks = DAP_NEW_Z(dap_chain_cs_blocks_t);
     if (!l_cs_blocks) {
@@ -432,14 +431,14 @@ static int s_cli_parse_cmd_hash(char ** a_argv, int a_arg_index, int a_argc, voi
  * @param a_meta_title
  * @param a_meta
  */
-static void s_cli_meta_hash_print(dap_string_t *a_str_tmp, const char *a_meta_title, dap_chain_block_meta_t *a_meta)
+static void s_cli_meta_hash_print(json_object* json_obj_a, const char *a_meta_title, dap_chain_block_meta_t *a_meta)
 {
     if (a_meta->hdr.data_size == sizeof (dap_chain_hash_fast_t)) {
         char l_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE];
         dap_chain_hash_fast_to_str((dap_chain_hash_fast_t *)a_meta->data, l_hash_str, sizeof(l_hash_str));
-        dap_string_append_printf(a_str_tmp, "\t\t%s: %s\n", a_meta_title, l_hash_str);
+        json_object_object_add(json_obj_a, a_meta_title, json_object_new_string(l_hash_str));
     } else
-        dap_string_append_printf(a_str_tmp,"\t\t\%s: Error, hash size is incorrect\n", a_meta_title);
+        json_object_object_add(json_obj_a, a_meta_title, json_object_new_string("Error, hash size is incorrect"));
 }
 
 /**
@@ -448,36 +447,45 @@ static void s_cli_meta_hash_print(dap_string_t *a_str_tmp, const char *a_meta_ti
  * @param a_meta_title
  * @param a_meta
  */
-static void s_cli_meta_hex_print(  dap_string_t * a_str_tmp, const char * a_meta_title, dap_chain_block_meta_t * a_meta)
+static void s_cli_meta_hex_print(json_object* json_obj_a, const char * a_meta_title, dap_chain_block_meta_t * a_meta)
 {
     char *l_data_hex = DAP_NEW_Z_SIZE(char, a_meta->hdr.data_size * 2 + 3);
     dap_bin2hex(l_data_hex, a_meta->data, a_meta->hdr.data_size);
-    dap_string_append_printf(a_str_tmp,"\t\t\%s: 0x%s\n", a_meta_title, l_data_hex);
+    char l_tmp_buff[70]={0};
+    sprintf(l_tmp_buff,"0x%s\n", l_data_hex);
+    json_object_object_add(json_obj_a, a_meta_title, json_object_new_string(l_tmp_buff));
     DAP_DELETE(l_data_hex);
 }
 
-static void s_print_autocollect_table(dap_chain_net_t *a_net, dap_string_t *a_reply_str, const char *a_table_name)
+static void s_print_autocollect_table(dap_chain_net_t *a_net, json_object* json_obj_a, const char *a_table_name)
 {
     bool l_status = dap_chain_esbocs_get_autocollect_status(a_net->pub.id);
-    dap_string_append_printf(a_reply_str, "\nAutocollect status for %s in network %s is %s\n",
-                                         dap_strdown(a_table_name, -1), a_net->pub.name,
-                                         l_status ? "active" : "inactive, cause the network config or consensus starting problems");
+    char l_tmp_buff[150]={0};
+    sprintf(l_tmp_buff,"for %s in network %s is %s\n", a_table_name, a_net->pub.name,
+                                        l_status ? "active" : "inactive, cause the network config or consensus starting problems");
+    json_object_object_add(json_obj_a, "Autocollect status", json_object_new_string(l_tmp_buff));
     if (!l_status)
         return;
-    dap_string_append_printf(a_reply_str, "\nAutocollect tables content for:\n=== %s ===\n", a_table_name);
+    sprintf(l_tmp_buff,"\nAutocollect tables content for:\n=== %s ===\n", a_table_name);
+    json_object_object_add(json_obj_a, "Autocollect status", json_object_new_string(l_tmp_buff));
     size_t l_objs_count = 0;
     char *l_group = dap_strcmp(a_table_name, "Fees") ? dap_chain_cs_blocks_get_reward_group(a_net->pub.name)
                                                      : dap_chain_cs_blocks_get_fee_group(a_net->pub.name);
     dap_global_db_obj_t *l_objs = dap_global_db_get_all_sync(l_group, &l_objs_count);
     DAP_DELETE(l_group);
     uint256_t l_total_value = uint256_0;
+    json_object* json_arr_out = json_object_new_array();
     for (size_t i = 0; i < l_objs_count; i++) {
+        json_object* json_obj_t = json_object_new_object();
         dap_global_db_obj_t *l_obj_cur = l_objs + i;
         uint256_t l_cur_value = *(uint256_t*)l_obj_cur->value;
-        char *l_value_str; dap_uint256_to_char(l_cur_value, &l_value_str);
-        dap_string_append_printf(a_reply_str, "%s\t%s\n", l_obj_cur->key, l_value_str);
+        const char *l_value_str; dap_uint256_to_char(l_cur_value, &l_value_str);
+        json_object_object_add(json_obj_t, "obj_key",json_object_new_string(l_obj_cur->key));
+        json_object_object_add(json_obj_t, "obj_val",json_object_new_string(l_value_str));
+        json_object_array_add(json_arr_out, json_obj_t);
         SUM_256_256(l_total_value, l_cur_value, &l_total_value);
     }
+    json_object_object_add(json_obj_a,"Autocollect tables",json_arr_out);
     if (l_objs_count) {
         dap_global_db_objs_delete(l_objs, l_objs_count);
         uint256_t l_collect_fee = dap_chain_esbocs_get_fee(a_net->pub.id);
@@ -488,7 +496,7 @@ static void s_print_autocollect_table(dap_chain_net_t *a_net, dap_string_t *a_re
             dap_pkey_t *l_my_sign_pkey = dap_chain_esbocs_get_sign_pkey(a_net->pub.id);
             dap_hash_t l_my_sign_pkey_hash;
             dap_hash_fast(l_my_sign_pkey->pkey, l_my_sign_pkey->header.size, &l_my_sign_pkey_hash);
-            dap_chain_net_srv_stake_item_t *l_key_item = dap_chain_net_srv_stake_check_pkey_hash(&l_my_sign_pkey_hash);
+            dap_chain_net_srv_stake_item_t *l_key_item = dap_chain_net_srv_stake_check_pkey_hash(a_net->pub.id, &l_my_sign_pkey_hash);
             if (l_key_item && !IS_ZERO_256(l_key_item->sovereign_tax) &&
                     !dap_chain_addr_is_blank(&l_key_item->sovereign_addr)) {
                 MULT_256_COIN(l_collect_value, l_key_item->sovereign_tax, &l_collect_tax);
@@ -499,11 +507,12 @@ static void s_print_autocollect_table(dap_chain_net_t *a_net, dap_string_t *a_re
         char *l_profit_str = dap_chain_balance_to_coins(l_collect_value);
         char *l_tax_str = dap_chain_balance_to_coins(l_collect_tax);
         char *l_fee_str = dap_chain_balance_to_coins(l_collect_fee);
-        dap_string_append_printf(a_reply_str, "\nTotal prepared value: %s %s, where\n\tprofit is %s, tax is %s, fee is %s\n",
+        sprintf(l_tmp_buff,"\nTotal prepared value: %s %s, where\n\tprofit is %s, tax is %s, fee is %s\n",
                                  l_total_str, a_net->pub.native_ticker, l_profit_str, l_tax_str, l_fee_str);
+        json_object_object_add(json_obj_a, "status",json_object_new_string(l_tmp_buff));
         DAP_DEL_MULTY(l_total_str, l_profit_str, l_tax_str, l_fee_str);
     } else
-        dap_string_append(a_reply_str, "Empty\n");
+        json_object_object_add(json_obj_a, "status",json_object_new_string("Empty\n"));
 }
 
 /**
@@ -516,6 +525,9 @@ static void s_print_autocollect_table(dap_chain_net_t *a_net, dap_string_t *a_re
  */
 static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply)
 {
+    json_object **json_arr_reply = (json_object **)a_str_reply;
+    //char ** a_str_reply = (char **) reply;
+    const char *l_hash_out_type = NULL;
     enum {
         SUBCMD_UNDEFINED =0,
         SUBCMD_NEW_FLUSH,
@@ -561,16 +573,15 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply)
     dap_chain_net_t * l_net = NULL;
 
     // Parse default values
-    if(dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index, a_argc, a_argv, a_str_reply, &l_chain, &l_net) < 0)
-        return -11;
+    if (dap_chain_node_cli_cmd_values_parse_net_chain_for_json(&arg_index, a_argc, a_argv, &l_chain, &l_net, CHAIN_TYPE_TX))
+        return -DAP_CHAIN_NODE_CLI_COM_BLOCK_PARAM_ERR;
 
-    const char *l_chain_type = dap_chain_net_get_type(l_chain);
+    const char *l_chain_type = dap_chain_get_cs_type(l_chain);
 
     if (!strstr(l_chain_type, "block_") && strcmp(l_chain_type, "esbocs")){
-            dap_cli_server_cmd_set_reply_text(a_str_reply,
-                        "Type of chain %s is not block. This chain with type %s is not supported by this command",
+        dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_CHAIN_TYPE_ERR, "Type of chain %s is not block. This chain with type %s is not supported by this command",
                         l_chain->name, l_chain_type);
-            return -42;
+        return DAP_CHAIN_NODE_CLI_COM_BLOCK_CHAIN_TYPE_ERR;
     }
 
     l_blocks = DAP_CHAIN_CS_BLOCKS(l_chain);
@@ -612,9 +623,8 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply)
                 s_cli_parse_cmd_hash(a_argv,arg_index,a_argc,a_str_reply,"-datum", &l_datum_hash );
                 l_blocks->block_new_size=dap_chain_block_datum_del_by_hash( &l_blocks->block_new, l_blocks->block_new_size, &l_datum_hash );
             }else {
-                dap_cli_server_cmd_set_reply_text(a_str_reply,
-                          "Error! Can't delete datum from hash because no forming new block! Check pls you role, it must be MASTER NODE or greater");
-                ret = -12;
+                dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_DATUM_DEL_ERR, "Error! Can't delete datum from hash because no forming new block! Check pls you role, it must be MASTER NODE or greater");
+                ret = DAP_CHAIN_NODE_CLI_COM_BLOCK_DATUM_DEL_ERR;
             }
             pthread_rwlock_unlock( &PVT(l_blocks)->rwlock );
         }break;
@@ -624,9 +634,9 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply)
             dap_chain_datum_t ** l_datums = DAP_NEW_Z_SIZE(dap_chain_datum_t*,
                                                            sizeof(dap_chain_datum_t*)*l_datums_count);
             if (!l_datums) {
-        log_it(L_CRITICAL, "%s", g_error_memory_alloc);
-                dap_cli_server_cmd_set_reply_text(a_str_reply,"Out of memory in s_cli_blocks");
-                return -1;
+                log_it(L_CRITICAL, "%s", g_error_memory_alloc);
+                dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_MEMORY_ERR, "Out of memory in s_cli_blocks");
+                return DAP_CHAIN_NODE_CLI_COM_BLOCK_MEMORY_ERR;
             }
             size_t l_datum_size = 0;
 
@@ -636,16 +646,16 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply)
             for (size_t i = 0; i < l_datums_count; i++) {
                 bool l_err = dap_chain_node_mempool_process(l_chain, l_datums[i], l_subcmd_str_arg);
                 if (l_err) {
-                    dap_cli_server_cmd_set_reply_text(a_str_reply, "Error! Datum %s doesn't pass verifications, examine node log files",
+                    dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_VERIF_ERR, "Error! Datum %s doesn't pass verifications, examine node log files",
                                                       l_subcmd_str_arg);
-                    ret = -9;
+                    ret = DAP_CHAIN_NODE_CLI_COM_BLOCK_VERIF_ERR;
                 } else
                    log_it(L_INFO, "Pass datum %s from mempool to block in the new forming round ",
                                                      l_subcmd_str_arg);
                 if (l_err)
                     break;
             }
-            dap_cli_server_cmd_set_reply_text(a_str_reply, "All datums processed");
+            dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_OK, "All datums processed");
             DAP_DELETE(l_gdb_group_mempool);
         } break;
 
@@ -660,104 +670,131 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply)
         case SUBCMD_DUMP:{
             dap_chain_hash_fast_t l_block_hash={0};
             if (!l_subcmd_str_arg) {
-                dap_cli_server_cmd_set_reply_text(a_str_reply, "Enter block hash ");
-                return -13;
+                dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_HASH_ERR, "Enter block hash ");
+                return DAP_CHAIN_NODE_CLI_COM_BLOCK_HASH_ERR;
             }
             dap_chain_hash_fast_from_str(l_subcmd_str_arg, &l_block_hash); // Convert argument to hash
             dap_chain_block_cache_t *l_block_cache = dap_chain_block_cache_get_by_hash(l_blocks, &l_block_hash);
             if (!l_block_cache) {
-                dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't find block %s ", l_subcmd_str_arg);
-                return 10;
+                dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_FIND_ERR, "Can't find block %s ", l_subcmd_str_arg);
+                return DAP_CHAIN_NODE_CLI_COM_BLOCK_FIND_ERR;
             }
             dap_chain_block_t *l_block = l_block_cache->block;
-            dap_string_t *l_str_tmp = dap_string_new(NULL);
+            char l_tmp_buff[70]={0};
+
+            char l_time_buf[DAP_TIME_STR_SIZE];    
+            dap_time_to_str_rfc822(l_time_buf, DAP_TIME_STR_SIZE, l_block->hdr.ts_created);
             // Header
-            dap_string_append_printf(l_str_tmp, "Block number %"DAP_UINT64_FORMAT_U" hash %s:\n", l_block_cache->block_number, l_subcmd_str_arg);
-            dap_string_append_printf(l_str_tmp, "\t\t\tversion: 0x%04X\n", l_block->hdr.version);
-            dap_string_append_printf(l_str_tmp, "\t\t\tcell_id: 0x%016"DAP_UINT64_FORMAT_X"\n", l_block->hdr.cell_id.uint64);
-            dap_string_append_printf(l_str_tmp, "\t\t\tchain_id: 0x%016"DAP_UINT64_FORMAT_X"\n", l_block->hdr.chain_id.uint64);
-            char buf[DAP_TIME_STR_SIZE];
-            dap_time_to_str_rfc822(buf, DAP_TIME_STR_SIZE, l_block->hdr.ts_created);
-            dap_string_append_printf(l_str_tmp, "\t\t\tts_created: %s\n", buf);
+            json_object* json_obj_inf = json_object_new_object();
+            json_object_object_add(json_obj_inf, "Block number", json_object_new_uint64(l_block_cache->block_number));
+            json_object_object_add(json_obj_inf, "hash", json_object_new_string(l_subcmd_str_arg));
+            sprintf(l_tmp_buff,"0x%04X",l_block->hdr.version);
+            json_object_object_add(json_obj_inf, "version", json_object_new_string(l_tmp_buff));
+            sprintf(l_tmp_buff,"0x%016"DAP_UINT64_FORMAT_X"",l_block->hdr.cell_id.uint64);
+            json_object_object_add(json_obj_inf, "cell_id", json_object_new_string(l_tmp_buff));
+            sprintf(l_tmp_buff,"0x%016"DAP_UINT64_FORMAT_X"",l_block->hdr.chain_id.uint64);
+            json_object_object_add(json_obj_inf, "chain_id", json_object_new_string(l_tmp_buff));
+            json_object_object_add(json_obj_inf, "ts_created", json_object_new_string(l_time_buf));
 
             // Dump Metadata
             size_t l_offset = 0;
-            dap_string_append_printf(l_str_tmp,"\tMetadata. Count: %us\n",l_block->hdr.meta_count );
+            json_object_object_add(json_obj_inf, "Metadata: count", json_object_new_int(l_block->hdr.meta_count));
+            json_object* json_arr_meta_out = json_object_new_array();
+            json_object_array_add(*json_arr_reply, json_obj_inf);
             for (uint32_t i=0; i < l_block->hdr.meta_count; i++) {
+                json_object* json_obj_meta = json_object_new_object();
                 dap_chain_block_meta_t *l_meta = (dap_chain_block_meta_t *)(l_block->meta_n_datum_n_sign + l_offset);
                 switch (l_meta->hdr.type) {
                 case DAP_CHAIN_BLOCK_META_GENESIS:
-                    dap_string_append_printf(l_str_tmp, "\t\tGENESIS\n");
+                    json_object_object_add(json_obj_meta, "GENESIS", json_object_new_string("GENESIS"));
                     break;
                 case DAP_CHAIN_BLOCK_META_PREV:
-                    s_cli_meta_hash_print(l_str_tmp, "PREV", l_meta);
+                    s_cli_meta_hash_print(json_obj_meta,"PREV", l_meta);
                     break;
                 case DAP_CHAIN_BLOCK_META_ANCHOR:
-                    s_cli_meta_hash_print(l_str_tmp, "ANCHOR", l_meta);
+                    s_cli_meta_hash_print(json_obj_meta, "ANCHOR", l_meta);
                     break;
                 case DAP_CHAIN_BLOCK_META_LINK:
-                    s_cli_meta_hash_print(l_str_tmp, "LINK", l_meta);
+                    s_cli_meta_hash_print(json_obj_meta, "LINK", l_meta);
                     break;
                 case DAP_CHAIN_BLOCK_META_NONCE:
-                    s_cli_meta_hex_print(l_str_tmp, "NONCE", l_meta);
+                    s_cli_meta_hex_print(json_obj_meta, "NONCE", l_meta);
                     break;
                 case DAP_CHAIN_BLOCK_META_NONCE2:
-                    s_cli_meta_hex_print(l_str_tmp, "NONCE2", l_meta);
+                    s_cli_meta_hex_print(json_obj_meta, "NONCE2", l_meta);
                     break;
                 default: {
                         char * l_data_hex = DAP_NEW_Z_SIZE(char,l_meta->hdr.data_size*2+3);
                         dap_bin2hex(l_data_hex, l_meta->data, l_meta->hdr.data_size);
-                        dap_string_append_printf(l_str_tmp, "\t\t 0x%0X: 0x%s\n", i, l_data_hex );
+                        sprintf(l_tmp_buff,"0x%0X",i);
+                        json_object_object_add(json_obj_meta, "# -", json_object_new_string(l_tmp_buff));
+                        sprintf(l_tmp_buff,"0x%s",l_data_hex);
+                        json_object_object_add(json_obj_meta, "Data hex - ", json_object_new_string(l_tmp_buff));
                         DAP_DELETE(l_data_hex);
                     }
                 }
+                json_object_array_add(json_arr_meta_out, json_obj_meta);
                 l_offset += sizeof(l_meta->hdr) + l_meta->hdr.data_size;
             }
-            dap_string_append_printf(l_str_tmp,"\t\tdatums:\tcount: %zu\n",l_block_cache->datum_count);
+            json_object_array_add(*json_arr_reply, json_arr_meta_out);
+            json_object* json_obj_datum = json_object_new_object();
+            json_object_object_add(json_obj_datum, "Datums: count", json_object_new_uint64(l_block_cache->datum_count));
+            json_object_array_add(*json_arr_reply, json_obj_datum);
+            json_object* json_arr_datum_out = json_object_new_array();
             for (uint32_t i=0; i < l_block_cache->datum_count ; i++){
+                char buf[70];
+                json_object* json_obj_tx = json_object_new_object();
                 dap_chain_datum_t * l_datum = l_block_cache->datum[i];
                 size_t l_datum_size =  dap_chain_datum_size(l_datum);
-                dap_string_append_printf(l_str_tmp,"\t\t\tdatum:\tdatum_size: %zu\n",l_datum_size);
+                json_object_object_add(json_obj_tx, "datum size ",json_object_new_uint64(l_datum_size));
                 if (l_datum_size < sizeof (l_datum->header) ){
-                    dap_string_append_printf(l_str_tmp,"\t\t\tERROR: datum size %zu is smaller than header size %zu \n",l_datum_size,
+                    dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_DATUM_SIZE_ERR, "ERROR: datum size %zu is smaller than header size %zu \n",l_datum_size,
                                             sizeof (l_datum->header));
                     break;
                 }
                 // Nested datums
-                dap_string_append_printf(l_str_tmp,"\t\t\t\tversion:=0x%02X\n", l_datum->header.version_id);
+                sprintf(l_tmp_buff,"0x%02X",l_datum->header.version_id);
+                json_object_object_add(json_obj_tx, "version",json_object_new_string(l_tmp_buff));
                 const char * l_datum_type_str="UNKNOWN";
                 DAP_DATUM_TYPE_STR(l_datum->header.type_id, l_datum_type_str);
-                dap_string_append_printf(l_str_tmp,"\t\t\t\ttype_id:=%s\n", l_datum_type_str);
+                json_object_object_add(json_obj_tx, "type_id",json_object_new_string(l_datum_type_str));
                 dap_time_to_str_rfc822(buf, DAP_TIME_STR_SIZE, l_datum->header.ts_create);
-                dap_string_append_printf(l_str_tmp,"\t\t\t\tts_create=%s\n", buf);
-                dap_string_append_printf(l_str_tmp,"\t\t\t\tdata_size=%u\n", l_datum->header.data_size);
-                dap_chain_datum_dump(l_str_tmp, l_datum, "hex", l_net->pub.id);
+                json_object_object_add(json_obj_tx, "ts_create",json_object_new_string(buf));
+                json_object_object_add(json_obj_tx, "data_size",json_object_new_int(l_datum->header.data_size));
+                dap_chain_datum_dump_json(json_obj_tx,l_datum,l_hash_out_type,l_net->pub.id);
+                json_object_array_add(json_arr_datum_out, json_obj_tx);
             }
             // Signatures
-            dap_string_append_printf(l_str_tmp,"\t\tsignatures:\tcount: %zu\n", l_block_cache->sign_count );
+            json_object_array_add(*json_arr_reply, json_arr_datum_out);
+            // Signatures
+            json_object* json_obj_sig = json_object_new_object();
+            json_object_object_add(json_obj_sig, "signatures count", json_object_new_uint64(l_block_cache->sign_count));
+            json_object_array_add(*json_arr_reply, json_obj_sig);
+            json_object* json_arr_sign_out = json_object_new_array();
             for (uint32_t i=0; i < l_block_cache->sign_count ; i++) {
+                json_object* json_obj_sign = json_object_new_object();
                 dap_sign_t * l_sign = dap_chain_block_sign_get(l_block_cache->block, l_block_cache->block_size, i);
                 size_t l_sign_size = dap_sign_get_size(l_sign);
                 dap_chain_hash_fast_t l_pkey_hash;
                 dap_sign_get_pkey_hash(l_sign, &l_pkey_hash);
                 char l_pkey_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE];
                 dap_chain_hash_fast_to_str(&l_pkey_hash, l_pkey_hash_str, sizeof(l_pkey_hash_str));
-                dap_string_append_printf(l_str_tmp,"\t\t\ttype:%s size: %zd pkey_hash: %s \n"
-                                                "\t\t\t\n", dap_sign_type_to_str( l_sign->header.type ),
-                                                        l_sign_size, l_pkey_hash_str );
+                json_object_object_add(json_obj_sign, "type",json_object_new_string(dap_sign_type_to_str( l_sign->header.type )));
+                json_object_object_add(json_obj_sign, "size",json_object_new_uint64(l_sign_size));
+                json_object_object_add(json_obj_sign, "pkey_hash",json_object_new_string(l_pkey_hash_str));
+                json_object_array_add(json_arr_sign_out, json_obj_sign);
             }
-            dap_cli_server_cmd_set_reply_text(a_str_reply, "%s", l_str_tmp->str);
-            dap_string_free(l_str_tmp, true);
+            json_object_array_add(*json_arr_reply, json_arr_sign_out);
         } break;
 
         case SUBCMD_LIST:{
             const char *l_cert_name = NULL, *l_from_hash_str = NULL, *l_to_hash_str = NULL,
                         *l_from_date_str = NULL, *l_to_date_str = NULL, *l_pkey_hash_str = NULL, *l_limit_str = NULL, *l_offset_str = NULL;
             bool l_unspent_flag = false, l_first_signed_flag = false, l_signed_flag = false, l_hash_flag = false;
-            size_t l_block_count = 0;
             dap_pkey_t * l_pub_key = NULL;
             dap_hash_fast_t l_from_hash = {}, l_to_hash = {}, l_pkey_hash = {};
             dap_time_t l_from_time = 0, l_to_time = 0;
+            char l_tmp_buff[150]={0};
 
             l_signed_flag = dap_cli_server_cmd_check_option(a_argv, 1, a_argc, "signed") > 0;
             l_first_signed_flag = dap_cli_server_cmd_check_option(a_argv, 1, a_argc, "first_signed") > 0;
@@ -771,33 +808,32 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply)
             dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-limit", &l_limit_str);
             dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-offset", &l_offset_str);
             size_t l_offset = l_offset_str ? strtoul(l_offset_str, NULL, 10) : 0;
-            size_t l_limit = l_limit_str ? strtoul(l_limit_str, NULL, 10) : 0;
+            size_t l_limit = l_limit_str ? strtoul(l_limit_str, NULL, 10) : 1000;
 
             if (l_signed_flag && l_first_signed_flag) {
-                dap_cli_server_cmd_set_reply_text(a_str_reply, "Choose only one option from 'singed' and 'first_signed'");
-                return -10;
+                dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_PARAM_ERR, "Choose only one option from 'singed' and 'first_signed'");
+                return DAP_CHAIN_NODE_CLI_COM_BLOCK_PARAM_ERR;
             }
             if ((l_signed_flag || l_first_signed_flag) && !l_cert_name && !l_pkey_hash_str) {
-                dap_cli_server_cmd_set_reply_text(a_str_reply, "Option from '%s' requires parameter '-cert' or 'pkey_hash'",
+                dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_PARAM_ERR, "Option from '%s' requires parameter '-cert' or 'pkey_hash'",
                                                                 l_first_signed_flag ? "first_signed" : "signed");
-                return -11;
+                return DAP_CHAIN_NODE_CLI_COM_BLOCK_PARAM_ERR;
             }
             if (l_cert_name) {
                 dap_cert_t *l_cert = dap_cert_find_by_name(l_cert_name);
                 if (!l_cert) {
-                    dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't find \"%s\" certificate", l_cert_name);
-                    return -18;
+                    dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_CERT_ERR, "Can't find \"%s\" certificate", l_cert_name);
+                    return DAP_CHAIN_NODE_CLI_COM_BLOCK_CERT_ERR;
                 }
                 l_pub_key = dap_pkey_from_enc_key(l_cert->enc_key);
                 if (!l_pub_key) {
-                    dap_cli_server_cmd_set_reply_text(a_str_reply,
-                            "Corrupted certificate \"%s\" have no public key data", l_cert_name);
-                    return -20;
+                    dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_PUB_KEY_ERR, "Corrupted certificate \"%s\" have no public key data", l_cert_name);
+                    return DAP_CHAIN_NODE_CLI_COM_BLOCK_PUB_KEY_ERR;
                 }
             } else if (l_pkey_hash_str) {
                 if (dap_chain_hash_fast_from_str(l_pkey_hash_str, &l_pkey_hash)) {
-                    dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't convert \"%s\" to hash", l_pkey_hash_str);
-                    return -12;
+                    dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_CONVERT_ERR, "Can't convert \"%s\" to hash", l_pkey_hash_str);
+                    return DAP_CHAIN_NODE_CLI_COM_BLOCK_CONVERT_ERR;
                 }
             }
             if (l_unspent_flag && l_signed_flag && !l_pkey_hash_str)
@@ -807,29 +843,29 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply)
 
             if (l_from_hash_str) {
                 if (dap_chain_hash_fast_from_str(l_from_hash_str, &l_from_hash)) {
-                    dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't convert \"%s\" to hash", l_from_hash_str);
-                    return -13;
+                    dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_CONVERT_ERR, "Can't convert \"%s\" to hash", l_from_hash_str);
+                    return DAP_CHAIN_NODE_CLI_COM_BLOCK_CONVERT_ERR;
                 }
             }
             if (l_to_hash_str) {
                 if (dap_chain_hash_fast_from_str(l_to_hash_str, &l_to_hash)) {
-                    dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't convert \"%s\" to hash", l_to_hash_str);
-                    return -14;
+                    dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_CONVERT_ERR, "Can't convert \"%s\" to hash", l_to_hash_str);
+                    return DAP_CHAIN_NODE_CLI_COM_BLOCK_CONVERT_ERR;
                 }
             }
 
             if (l_from_date_str) {
                 l_from_time = dap_time_from_str_simplified(l_from_date_str);
                 if (!l_from_time) {
-                    dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't convert \"%s\" to date", l_from_date_str);
-                    return -21;
+                    dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_CONVERT_ERR, "Can't convert \"%s\" to date", l_from_date_str);
+                    return DAP_CHAIN_NODE_CLI_COM_BLOCK_CONVERT_ERR;
                 }
             }
             if (l_to_date_str) {
                 l_to_time = dap_time_from_str_simplified(l_to_date_str);
                 if (!l_to_time) {
-                    dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't convert \"%s\" to date", l_to_date_str);
-                    return -21;
+                    dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_CONVERT_ERR, "Can't convert \"%s\" to date", l_to_date_str);
+                    return DAP_CHAIN_NODE_CLI_COM_BLOCK_CONVERT_ERR;
                 }
                 struct tm *l_localtime = localtime((time_t *)&l_to_time);
                 l_localtime->tm_mday += 1;  // + 1 day to end date, got it inclusive
@@ -837,19 +873,23 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply)
             }
 
             pthread_rwlock_rdlock(&PVT(l_blocks)->rwlock);
-            dap_string_t *l_str_tmp = dap_string_new(NULL);
+            json_object* json_arr_bl_cache_out = json_object_new_array();
+            json_object* json_obj_lim = json_object_new_object();
             size_t l_start_arr = 0;
-            if(l_offset > 1) {
-                l_start_arr = l_offset * l_limit;
+            if(l_offset > 0) {
+                l_start_arr = l_offset;
+                json_object_object_add(json_obj_lim, "offset",json_object_new_uint64(l_start_arr));
             }
             size_t l_arr_end = PVT(l_blocks)->blocks_count;
             if (l_limit) {
+                json_object_object_add(json_obj_lim, "limit",json_object_new_uint64(l_limit));
                 l_arr_end = l_start_arr + l_limit;
                 if (l_arr_end > PVT(l_blocks)->blocks_count)
                     l_arr_end = PVT(l_blocks)->blocks_count;
             }
+            json_object_array_add(json_arr_bl_cache_out, json_obj_lim);
             size_t i_tmp = 0;
-            for (dap_chain_block_cache_t *l_block_cache = PVT(l_blocks)->blocks; l_block_cache; l_block_cache = l_block_cache->hh.next) {
+            for (dap_chain_block_cache_t *l_block_cache = PVT(l_blocks)->blocks; l_block_cache; l_block_cache = l_block_cache->hh.next) {                
                 if (i_tmp < l_start_arr || i_tmp >= l_arr_end) {
                     i_tmp++;
                     continue;
@@ -916,26 +956,34 @@ 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);
-                dap_string_append_printf(l_str_tmp, "\t%s: ts_create=%s\n", l_block_cache->block_hash_str, l_buf);
-                l_block_count++;
+                json_object_object_add(json_obj_bl_cache, "block",json_object_new_uint64(i_tmp));
+                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, "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(*json_arr_reply, json_arr_bl_cache_out);
 
-            char *l_filtered_criteria = "";
+            char *l_filtered_criteria = "none";
+            json_object* json_obj_out = json_object_new_object();
             if (l_cert_name || l_pkey_hash_str || l_from_hash_str || l_to_hash_str || l_from_date_str || l_to_date_str)
                 l_filtered_criteria = " filtered according to the specified criteria";
-            dap_string_append_printf(l_str_tmp, "%s.%s: Have %"DAP_UINT64_FORMAT_U" blocks%s\n",
-                                     l_net->pub.name, l_chain->name, l_block_count, l_filtered_criteria);
-            dap_cli_server_cmd_set_reply_text(a_str_reply, "%s", l_str_tmp->str);
-            dap_string_free(l_str_tmp, true);
+            sprintf(l_tmp_buff,"%s.%s with filter - %s, have blocks",l_net->pub.name,l_chain->name,l_filtered_criteria);
+            json_object_object_add(json_obj_out, l_tmp_buff, json_object_new_uint64(i_tmp));
+            json_object_array_add(*json_arr_reply,json_obj_out);
         } break;
 
         case SUBCMD_COUNT: {
-            dap_cli_server_cmd_set_reply_text(a_str_reply, "%zu blocks in %s.%s", PVT(l_blocks)->blocks_count,
-                                              l_net->pub.name, l_chain->name);
+            char l_tmp_buff[70]={0};
+            json_object* json_obj_out = json_object_new_object();
+            sprintf(l_tmp_buff,"%s.%s has blocks - ",l_net->pub.name,l_chain->name);
+            json_object_object_add(json_obj_out, l_tmp_buff, json_object_new_uint64(PVT(l_blocks)->blocks_count));
+            json_object_array_add(*json_arr_reply, json_obj_out);
+
         } break;
 
         case SUBCMD_FEE:
@@ -945,6 +993,7 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply)
             const char * l_addr_str = NULL;
             const char * l_hash_out_type = NULL;
             const char * l_hash_str = NULL;
+            char l_tmp_buff[70]={0};
 
             uint256_t               l_fee_value = {};
             size_t                  l_hashes_count = 0;
@@ -953,52 +1002,54 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply)
 
             if (l_subcmd == SUBCMD_FEE) {
                 if (dap_cli_server_cmd_check_option(a_argv, arg_index, a_argc, "collect") == -1) {
-                    dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'block fee' requires subcommand 'collect'");
-                    return -14;
+                    dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_PARAM_ERR, "Command 'block fee' requires subcommand 'collect'");
+                    return DAP_CHAIN_NODE_CLI_COM_BLOCK_PARAM_ERR;
                 }
             } else { // l_sumcmd == SUBCMD_REWARD
                 if (dap_cli_server_cmd_check_option(a_argv, arg_index, a_argc, "set") >= 0) {
                     const char *l_value_str = NULL;
                     dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-poa_cert", &l_cert_name);
                     if(!l_cert_name) {
-                        dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'block reward set' requires parameter '-poa_cert'");
-                        return -17;
+                        dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_PARAM_ERR, "Command 'block reward set' requires parameter '-poa_cert'");
+                        return DAP_CHAIN_NODE_CLI_COM_BLOCK_PARAM_ERR;
                     }
                     dap_cert_t *l_cert = dap_cert_find_by_name(l_cert_name);
                     if (!l_cert) {
-                        dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't find \"%s\" certificate", l_cert_name);
-                        return -18;
+                        dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_CERT_ERR, "Can't find \"%s\" certificate", l_cert_name);
+                        return DAP_CHAIN_NODE_CLI_COM_BLOCK_CERT_ERR;
                     }
                     if (!l_cert->enc_key || !l_cert->enc_key->priv_key_data || !l_cert->enc_key->priv_key_data_size) {
-                        dap_cli_server_cmd_set_reply_text(a_str_reply,
-                                "Certificate \"%s\" doesn't contains private key", l_cert_name);
-                        return -19;
+                        dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_PVT_KEY_ERR, "Certificate \"%s\" doesn't contains private key", l_cert_name);
+                        return DAP_CHAIN_NODE_CLI_COM_BLOCK_PVT_KEY_ERR;
                     }
 
                     dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-value", &l_value_str);
                     uint256_t l_value = dap_chain_balance_scan(l_value_str);
                     if (!l_value_str || IS_ZERO_256(l_value)) {
-                        dap_cli_server_cmd_set_reply_text(a_str_reply,
-                                "Command 'block reward set' requires parameter '-value' to be valid 256-bit unsigned integer");
-                        return -20;
+                        dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_PARAM_ERR, "Command 'block reward set' requires parameter '-value' to be valid 256-bit unsigned integer");
+                        return DAP_CHAIN_NODE_CLI_COM_BLOCK_PARAM_ERR;
                     }
                     char *l_decree_hash_str = s_blocks_decree_set_reward(l_net, l_chain, l_value, l_cert);
                     if (l_decree_hash_str) {
-                        dap_cli_server_cmd_set_reply_text(a_str_reply, "Decree with hash %s created to set basic block sign reward", l_decree_hash_str);
+                        //добавить вывод
+                        dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_OK, "Decree with hash %s created to set basic block sign reward", l_decree_hash_str);
                         DAP_DELETE(l_decree_hash_str);
                     } else {
-                        dap_cli_server_cmd_set_reply_text(a_str_reply, "Basic block sign reward setting failed. Examine log file for details");
-                        return -21;
+                        dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_SIGN_ERR, "Basic block sign reward setting failed. Examine log file for details");
+                        return DAP_CHAIN_NODE_CLI_COM_BLOCK_SIGN_ERR;
                     }
                     break;
                 } else if (dap_cli_server_cmd_check_option(a_argv, arg_index, a_argc, "show") >= 0) {
                     uint256_t l_cur_reward = dap_chain_net_get_reward(l_net, UINT64_MAX);
-                    char *l_reward_str; dap_uint256_to_char(l_cur_reward, &l_reward_str);
-                    dap_cli_server_cmd_set_reply_text(a_str_reply, "Current base block reward is %s\n", l_reward_str);
+                    const char *l_reward_str; dap_uint256_to_char(l_cur_reward, &l_reward_str);
+                    json_object* json_obj_out = json_object_new_object();
+                    sprintf(l_tmp_buff,"Current base block reward is %s\n", l_reward_str);
+                    json_object_object_add(json_obj_out, "status", json_object_new_string(l_tmp_buff));
+                    json_object_array_add(*json_arr_reply, json_obj_out);
                     break;
                 } else if (dap_cli_server_cmd_check_option(a_argv, arg_index, a_argc, "collect") == -1) {
-                    dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'block reward' requires subcommands 'set' or 'show' or 'collect'");
-                    return -14;
+                    dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_PARAM_ERR, "Command 'block reward' requires subcommands 'set' or 'show' or 'collect'");
+                    return DAP_CHAIN_NODE_CLI_COM_BLOCK_PARAM_ERR;
                 }
             }
 
@@ -1007,8 +1058,8 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply)
             if(!l_hash_out_type)
                 l_hash_out_type = "hex";
             if(dap_strcmp(l_hash_out_type,"hex") && dap_strcmp(l_hash_out_type,"base58")) {
-                dap_cli_server_cmd_set_reply_text(a_str_reply, "invalid parameter -H, valid values: -H <hex | base58>");
-                return -15;
+                dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_PARAM_ERR, "invalid parameter -H, valid values: -H <hex | base58>");
+                return DAP_CHAIN_NODE_CLI_COM_BLOCK_PARAM_ERR;
             }
 
             // Private certificate
@@ -1019,42 +1070,41 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply)
             dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-fee", &l_fee_value_str);
 
             if (!l_addr_str) {
-                dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'block %s collect' requires parameter '-addr'", l_subcmd_str);
-                return -16;
+                dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_PARAM_ERR, "Command 'block %s collect' requires parameter '-addr'", l_subcmd_str);
+                return DAP_CHAIN_NODE_CLI_COM_BLOCK_PARAM_ERR;
             }
             l_addr = dap_chain_addr_from_str(l_addr_str);
             if(!l_cert_name) {
-                dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'block %s collect' requires parameter '-cert'", l_subcmd_str);
-                return -17;
+                dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_PARAM_ERR, "Command 'block %s collect' requires parameter '-cert'", l_subcmd_str);
+                return DAP_CHAIN_NODE_CLI_COM_BLOCK_PARAM_ERR;
             }
             dap_cert_t *l_cert = dap_cert_find_by_name(l_cert_name);
             if (!l_cert) {
-                dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't find \"%s\" certificate", l_cert_name);
-                return -18;
+                dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_CERT_ERR, "Can't find \"%s\" certificate", l_cert_name);
+                return DAP_CHAIN_NODE_CLI_COM_BLOCK_CERT_ERR;
             }
             if (!l_cert->enc_key || !l_cert->enc_key->priv_key_data || !l_cert->enc_key->priv_key_data_size) {
-                dap_cli_server_cmd_set_reply_text(a_str_reply,
-                        "Certificate \"%s\" doesn't contains private key", l_cert_name);
-                return -19;
+                dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_CERT_ERR,
+                                        "Certificate \"%s\" doesn't contains private key", l_cert_name);
+                return DAP_CHAIN_NODE_CLI_COM_BLOCK_CERT_ERR;
             }
 
             l_fee_value = dap_chain_balance_scan(l_fee_value_str);
             if (!l_fee_value_str || IS_ZERO_256(l_fee_value)) {
-                dap_cli_server_cmd_set_reply_text(a_str_reply,
-                                                  "Command 'block %s collect' requires parameter '-fee' to be valid uint256", l_subcmd_str);
-                return -20;
+                dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_PARAM_ERR, "Command 'block %s collect' requires parameter '-fee' to be valid uint256", l_subcmd_str);
+                return DAP_CHAIN_NODE_CLI_COM_BLOCK_PARAM_ERR;
             }
 
             if (!l_hash_str) {
-                dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'block fee collect' requires parameter '-hashes'");
-                return -21;
+                dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_PARAM_ERR, "Command 'block fee collect' requires parameter '-hashes'");
+                return DAP_CHAIN_NODE_CLI_COM_BLOCK_PARAM_ERR;
             }
             // NOTE: This call will modify source string
             l_block_list = s_block_parse_str_list((char *)l_hash_str, &l_hashes_count, l_chain);            
             if (!l_block_list || !l_hashes_count) {
-                dap_cli_server_cmd_set_reply_text(a_str_reply,
-                        "Block fee collection requires at least one hash to create a transaction");
-                return -22;
+                dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_HASH_ERR,
+                                            "Block fee collection requires at least one hash to create a transaction");
+                return DAP_CHAIN_NODE_CLI_COM_BLOCK_HASH_ERR;
             }
 
             char *l_hash_tx = NULL;
@@ -1063,11 +1113,15 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply)
             else
                 l_hash_tx = 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) {
-                dap_cli_server_cmd_set_reply_text(a_str_reply, "TX for %s collection created succefully, hash=%s\n", l_subcmd_str, l_hash_tx);
+                json_object* json_obj_out = json_object_new_object();
+                sprintf(l_tmp_buff, "TX for %s collection created succefully, hash = %s\n", l_subcmd_str, l_hash_tx);
+                json_object_object_add(json_obj_out, "status", json_object_new_string(l_tmp_buff));
+                json_object_array_add(*json_arr_reply, json_obj_out);
                 DAP_DELETE(l_hash_tx);
             } else {
-                dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't create %s collect TX\n", l_subcmd_str);
-                ret = -24;
+                dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_HASH_ERR,
+                                            "Can't create %s collect TX\n", l_subcmd_str);
+                return DAP_CHAIN_NODE_CLI_COM_BLOCK_HASH_ERR;
             }
             dap_list_free_full(l_block_list, NULL);
         }break;
@@ -1078,6 +1132,7 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply)
             dap_hash_fast_t l_pkey_hash = {};
             dap_chain_addr_t *l_addr = NULL;
             size_t l_block_count = 0;
+            char l_tmp_buff[128]={0};
             int fl_renew = dap_cli_server_cmd_check_option(a_argv, arg_index,a_argc, "renew");
             if(fl_renew != -1)
             {
@@ -1085,27 +1140,30 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply)
                 dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-addr", &l_addr_str);
                 l_addr = dap_chain_addr_from_str(l_addr_str);
                 if(!l_cert_name) {
-                    dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'block autocollect renew' requires parameter '-cert'");
-                    return -20;
+                    dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_PARAM_ERR,
+                                            "Command 'block autocollect renew' requires parameter '-cert'", l_subcmd_str);
+                    return DAP_CHAIN_NODE_CLI_COM_BLOCK_PARAM_ERR;
                 }
                 if (!l_addr_str) {
-                    dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'block autocollect renew' requires parameter '-addr'");
-                    return -20;
+                    dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_PARAM_ERR,
+                                            "Command 'block autocollect renew' requires parameter '-addr'", l_subcmd_str);
+                    return DAP_CHAIN_NODE_CLI_COM_BLOCK_PARAM_ERR;
                 }
                 dap_cert_t *l_cert = dap_cert_find_by_name(l_cert_name);
                 if (!l_cert) {
-                    dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't find \"%s\" certificate", l_cert_name);
-                    return -20;
+                    dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_CERT_ERR,
+                                            "Can't find \"%s\" certificate", l_cert_name);
+                    return DAP_CHAIN_NODE_CLI_COM_BLOCK_CERT_ERR;
                 }
                 l_pub_key = dap_pkey_from_enc_key(l_cert->enc_key);
                 if (!l_pub_key) {
-                    dap_cli_server_cmd_set_reply_text(a_str_reply,
-                            "Corrupted certificate \"%s\" have no public key data", l_cert_name);
-                    return -20;
+                    dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_PUB_KEY_ERR,
+                                            "Corrupted certificate \"%s\" have no public key data", l_cert_name);
+                    return DAP_CHAIN_NODE_CLI_COM_BLOCK_PUB_KEY_ERR;
                 }
                 dap_chain_esbocs_block_collect_t l_block_collect_params = (dap_chain_esbocs_block_collect_t){
-                        .collecting_level = l_chain->callback_get_collectiong_level(l_chain),
-                        .minimum_fee = l_chain->callback_get_minimum_fee(l_chain),
+                        .collecting_level = dap_chain_esbocs_get_collecting_level(l_chain),
+                        .minimum_fee = dap_chain_esbocs_get_fee(l_chain->net_id),
                         .chain = l_chain,
                         .blocks_sign_key = l_cert->enc_key,
                         .block_sign_pkey = l_pub_key,
@@ -1122,7 +1180,7 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply)
                 if(l_objs_rew_count)dap_global_db_objs_delete(l_objs_rew,l_objs_rew_count);
                 DAP_DELETE(l_group_fee);
                 DAP_DELETE(l_group_rew);
-                dap_string_t *l_str_tmp = dap_string_new(NULL);
+                json_object* json_arr_bl_out = json_object_new_array();
 
                 for (dap_chain_block_cache_t *l_block_cache = PVT(l_blocks)->blocks; l_block_cache; l_block_cache = l_block_cache->hh.next) {
                     dap_time_t l_ts = l_block_cache->block->hdr.ts_created;
@@ -1142,10 +1200,13 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply)
                         if (NULL == dap_chain_datum_tx_out_cond_get(l_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE, &l_out_idx_tmp))
                             continue;
                         if (!dap_ledger_tx_hash_is_used_out_item(l_net->pub.ledger, l_block_cache->datum_hash + i, l_out_idx_tmp, NULL)) {
-                            dap_chain_esbocs_add_block_collect(l_block_cache->block, l_block_cache->block_size, &l_block_collect_params,1);
-                            char l_buf[50];
-                            dap_time_to_str_rfc822(l_buf, 50, l_ts);
-                            dap_string_append_printf(l_str_tmp, "fee - \t%s: ts_create=%s\n", l_block_cache->block_hash_str, l_buf);
+                            dap_chain_esbocs_add_block_collect(l_block_cache, &l_block_collect_params, DAP_CHAIN_BLOCK_COLLECT_FEES);
+                            char l_buf[DAP_TIME_STR_SIZE];
+                            json_object* json_obj_bl = json_object_new_object();
+                            dap_time_to_str_rfc822(l_buf, DAP_TIME_STR_SIZE, l_ts);
+                            sprintf(l_tmp_buff, "fee - \t%s: ts_create=%s\n", l_block_cache->block_hash_str, l_buf);
+                            json_object_object_add(json_obj_bl, "block", json_object_new_string(l_tmp_buff));
+                            json_object_array_add(json_arr_bl_out, json_obj_bl);
                             l_block_count++;
                             break;
                         }
@@ -1170,37 +1231,44 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply)
                         continue;
                     if (dap_ledger_is_used_reward(l_net->pub.ledger, &l_block_cache->block_hash, &l_pkey_hash))
                         continue;
-                    dap_chain_esbocs_add_block_collect(l_block_cache->block, l_block_cache->block_size, &l_block_collect_params,2);
-                    {   
-                        char l_buf[50];
-                        dap_time_to_str_rfc822(l_buf, 50, l_ts);
-                        dap_string_append_printf(l_str_tmp, "rewards - \t%s: ts_create=%s\n", l_block_cache->block_hash_str, l_buf);
-                        l_block_count++; 
-                    }                   
+                    dap_chain_esbocs_add_block_collect(l_block_cache, &l_block_collect_params, DAP_CHAIN_BLOCK_COLLECT_REWARDS);
+                    char l_buf[DAP_TIME_STR_SIZE];
+                    json_object* json_obj_bl = json_object_new_object();
+                    dap_time_to_str_rfc822(l_buf, DAP_TIME_STR_SIZE, l_ts);
+                    sprintf(l_tmp_buff, "rewards - \t%s: ts_create=%s\n", l_block_cache->block_hash_str, l_buf);
+                    json_object_object_add(json_obj_bl, "block", json_object_new_string(l_tmp_buff));
+                    json_object_array_add(json_arr_bl_out, json_obj_bl);
+                    l_block_count++;
                 }
-                dap_string_append_printf(l_str_tmp, "%s.%s: Have %"DAP_UINT64_FORMAT_U" blocks\n",
+                json_object_array_add(*json_arr_reply, json_arr_bl_out);
+                json_object* json_obj_out = json_object_new_object();
+                sprintf(l_tmp_buff, "%s.%s: Have %"DAP_UINT64_FORMAT_U" blocks\n",
                                      l_net->pub.name, l_chain->name, l_block_count);
-                dap_cli_server_cmd_set_reply_text(a_str_reply, "%s", l_str_tmp->str);
-                dap_string_free(l_str_tmp, true);
+                json_object_object_add(json_obj_out, "status", json_object_new_string(l_tmp_buff));
+                json_object_array_add(*json_arr_reply, json_obj_out);
             }else{
                 if (dap_cli_server_cmd_check_option(a_argv, arg_index, a_argc, "status") == -1) {
-                    dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'block autocollect' requires subcommand 'status'");
-                    return -14;
+                    dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_PARAM_ERR,
+                                            "Command 'block autocollect' requires subcommand 'status'");
+                    return DAP_CHAIN_NODE_CLI_COM_BLOCK_PARAM_ERR;
                 }
-                dap_string_t *l_reply_str = dap_string_new("");
-                s_print_autocollect_table(l_net, l_reply_str, "Fees");
-                s_print_autocollect_table(l_net, l_reply_str, "Rewards");                
-                dap_cli_server_cmd_set_reply_text(a_str_reply, "%s", l_reply_str->str);
-                dap_string_free(l_reply_str, true);
+                json_object* json_obj_out = json_object_new_object();
+                s_print_autocollect_table(l_net, json_obj_out, "Fees");
+                s_print_autocollect_table(l_net, json_obj_out, "Rewards");
+                json_object_array_add(*json_arr_reply, json_obj_out);
             }            
         } break;
 
         case SUBCMD_UNDEFINED:
         default: {
-            dap_cli_server_cmd_set_reply_text(a_str_reply,
-                                              "Undefined block subcommand \"%s\" ",
+            char l_tmp_buff[70]={0};
+            json_object* json_obj_out = json_object_new_object();
+            snprintf(l_tmp_buff, sizeof(l_tmp_buff), "Undefined block subcommand \"%s\" ",
                                               l_subcmd_str);
-            ret=-11;
+            json_object_object_add(json_obj_out, "status", json_object_new_string(l_tmp_buff));
+            json_object_array_add(*json_arr_reply, json_obj_out);
+            ret=DAP_CHAIN_NODE_CLI_COM_BLOCK_UNKNOWN;
+
         } break;
     }
     return ret;
diff --git a/modules/type/blocks/include/dap_chain_block.h b/modules/type/blocks/include/dap_chain_block.h
index 3c986857fc699b2d0258f6be811c81c5b06d6795..519b655c85ed90f61657cc85543473fcece94e8b 100644
--- a/modules/type/blocks/include/dap_chain_block.h
+++ b/modules/type/blocks/include/dap_chain_block.h
@@ -23,12 +23,9 @@
 #pragma once
 #include "dap_common.h"
 #include "dap_time.h"
-#include "dap_math_ops.h"
 #include "dap_hash.h"
-#include "dap_cert.h"
 #include "dap_chain_common.h"
 #include "dap_chain_datum.h"
-#include "dap_chain_datum_hashtree_roots.h"
 
 #define DAP_CHAIN_BLOCK_SIGNATURE 0xDA05BF8E
 #define DAP_CHAIN_BLOCK_ID_SIZE 4
@@ -65,13 +62,17 @@ typedef struct dap_chain_block_meta{
 
 // Block metadata types
 
-#define DAP_CHAIN_BLOCK_META_GENESIS           0x01
-#define DAP_CHAIN_BLOCK_META_PREV              0x10
-#define DAP_CHAIN_BLOCK_META_ANCHOR            0x11
-#define DAP_CHAIN_BLOCK_META_LINK              0x12
-#define DAP_CHAIN_BLOCK_META_NONCE             0x20
-#define DAP_CHAIN_BLOCK_META_NONCE2            0x21
-#define DAP_CHAIN_BLOCK_META_MERKLE            0x30
+#define DAP_CHAIN_BLOCK_META_GENESIS            0x01
+#define DAP_CHAIN_BLOCK_META_PREV               0x10
+#define DAP_CHAIN_BLOCK_META_ANCHOR             0x11
+#define DAP_CHAIN_BLOCK_META_LINK               0x12
+#define DAP_CHAIN_BLOCK_META_NONCE              0x20
+#define DAP_CHAIN_BLOCK_META_NONCE2             0x21
+#define DAP_CHAIN_BLOCK_META_MERKLE             0x30
+#define DAP_CHAIN_BLOCK_META_EMERGENCY          0x80
+#define DAP_CHAIN_BLOCK_META_SYNC_ATTEMPT       0x81
+#define DAP_CHAIN_BLOCK_META_ROUND_ATTEMPT      0x82
+#define DAP_CHAIN_BLOCK_META_EXCLUDED_KEYS      0x83
 
 /**
  * @struct dap_chain_block
diff --git a/modules/type/blocks/include/dap_chain_block_cache.h b/modules/type/blocks/include/dap_chain_block_cache.h
index 4ba9fffaba05aea576dc3db8342a19f482fc2aa7..b7cdf1e38098fd3d6f03f04d3e674f432acaa033 100644
--- a/modules/type/blocks/include/dap_chain_block_cache.h
+++ b/modules/type/blocks/include/dap_chain_block_cache.h
@@ -22,8 +22,6 @@
 */
 #pragma once
 #include "dap_chain_block.h"
-#include "dap_chain_datum_tx.h"
-#include "dap_sign.h"
 #include "dap_hash.h"
 #include "uthash.h"
 #include "dap_chain_ledger.h"
diff --git a/modules/type/blocks/include/dap_chain_cs_blocks.h b/modules/type/blocks/include/dap_chain_cs_blocks.h
index 985ead94e7d4497a26522bc7a174bd083658e84a..bb40da5a247e6a4fbb0adf662dd5650a6deaf976 100644
--- a/modules/type/blocks/include/dap_chain_cs_blocks.h
+++ b/modules/type/blocks/include/dap_chain_cs_blocks.h
@@ -34,8 +34,7 @@
 
 #define DAP_FORK_MAX_DEPTH 100
 
-
-#define DAP_REWARD_INIT_TIMESTAMP 1700870400UL // 25 Nov 00:00:00 GMT
+#define DAP_REWARD_INIT_TIMESTAMP 1700870400UL // 25 Nov 2023 00:00:00 GMT
 
 typedef struct dap_chain_cs_blocks dap_chain_cs_blocks_t;
 
@@ -65,6 +64,27 @@ typedef struct dap_chain_cs_blocks
    void * _inheritor;
 } dap_chain_cs_blocks_t;
 
+typedef enum s_com_blocks_err{
+    DAP_CHAIN_NODE_CLI_COM_BLOCK_OK = 0,
+    DAP_CHAIN_NODE_CLI_COM_BLOCK_PARAM_ERR,
+    DAP_CHAIN_NODE_CLI_COM_BLOCK_CHAIN_TYPE_ERR,
+    DAP_CHAIN_NODE_CLI_COM_BLOCK_DATUM_DEL_ERR,
+    DAP_CHAIN_NODE_CLI_COM_BLOCK_MEMORY_ERR,
+    DAP_CHAIN_NODE_CLI_COM_BLOCK_VERIF_ERR,
+    DAP_CHAIN_NODE_CLI_COM_BLOCK_HASH_ERR,
+    DAP_CHAIN_NODE_CLI_COM_BLOCK_FIND_ERR,
+    DAP_CHAIN_NODE_CLI_COM_BLOCK_DATUM_SIZE_ERR,
+    DAP_CHAIN_NODE_CLI_COM_BLOCK_CERT_ERR,
+    DAP_CHAIN_NODE_CLI_COM_BLOCK_PUB_KEY_ERR,
+    DAP_CHAIN_NODE_CLI_COM_BLOCK_CONVERT_ERR,
+    DAP_CHAIN_NODE_CLI_COM_BLOCK_PVT_KEY_ERR,
+    DAP_CHAIN_NODE_CLI_COM_BLOCK_SIGN_ERR,
+
+    /* add custom codes here */
+
+    DAP_CHAIN_NODE_CLI_COM_BLOCK_UNKNOWN /* MAX */
+} s_com_blocks_err_t;
+
 #define DAP_CHAIN_CS_BLOCKS(a) ((dap_chain_cs_blocks_t *)(a)->_inheritor)
 typedef int (*dap_chain_blocks_block_callback_ptr_t)(dap_chain_cs_blocks_t *, dap_chain_block_t *);
 
diff --git a/modules/type/dag/dap_chain_cs_dag.c b/modules/type/dag/dap_chain_cs_dag.c
index b324de02644a4ec4eb46903483e81cdf75c1f04f..7b87103bd1fb1b01571cf7a348893d972fe9b8d2 100644
--- a/modules/type/dag/dap_chain_cs_dag.c
+++ b/modules/type/dag/dap_chain_cs_dag.c
@@ -83,7 +83,7 @@ typedef struct dap_chain_cs_dag_pvt {
     dap_chain_cs_dag_event_item_t * events_lasts_unlinked;
     dap_chain_cs_dag_blocked_t *removed_events_from_treshold;
     dap_interval_timer_t treshold_fee_timer;
-    size_t tx_count;
+    uint64_t tx_count;
 } dap_chain_cs_dag_pvt_t;
 
 #define PVT(a) ((dap_chain_cs_dag_pvt_t *) a->_pvt )
@@ -129,10 +129,10 @@ static dap_chain_datum_t *s_chain_callback_datum_iter_get_next(dap_chain_datum_i
 static int s_cli_dag(int argc, char ** argv, void **a_str_reply);
 void s_dag_events_lasts_process_new_last_event(dap_chain_cs_dag_t * a_dag, dap_chain_cs_dag_event_item_t * a_event_item);
 
-static size_t s_dap_chain_callback_get_count_tx(dap_chain_t *a_chain);
+static uint64_t s_dap_chain_callback_get_count_tx(dap_chain_t *a_chain);
 static dap_list_t *s_dap_chain_callback_get_txs(dap_chain_t *a_chain, size_t a_count, size_t a_page, bool a_reverse);
 
-static size_t s_dap_chain_callback_get_count_atom(dap_chain_t *a_chain);
+static uint64_t s_dap_chain_callback_get_count_atom(dap_chain_t *a_chain);
 static dap_list_t *s_callback_get_atoms(dap_chain_t *a_chain, size_t a_count, size_t a_page, bool a_reverse);
 
 static bool s_seed_mode = false, s_debug_more = false, s_threshold_enabled = false;
@@ -705,8 +705,6 @@ static bool s_chain_callback_datums_pool_proc(dap_chain_t *a_chain, dap_chain_da
     return l_res;
 }
 
-
-
 /**
  * @brief dap_chain_cs_dag_find_event_by_hash
  * @param a_dag
@@ -747,8 +745,6 @@ static bool s_event_verify_size(dap_chain_cs_dag_event_t *a_event, size_t a_even
     return l_sign_offset == a_event_size;
 }
 
-
-
 /**
  * @brief s_chain_callback_atom_verify Verify atomic element
  * @param a_chain
@@ -1055,9 +1051,9 @@ static dap_chain_atom_ptr_t* s_chain_callback_atom_iter_get_links( dap_chain_ato
                     (*a_links_size_array)[i] = l_link_item->event_size;
                 }else {
                     char l_err_str[256];
-                    unsigned l_off = dap_snprintf(l_err_str, sizeof(l_err_str), "Can't find %s -> ",
+                    unsigned l_off = snprintf(l_err_str, sizeof(l_err_str), "Can't find %s -> ",
                         dap_chain_hash_fast_to_str_static(l_link_hash));
-                    dap_snprintf(l_err_str + l_off, sizeof(l_err_str) - l_off, "%s links",
+                    snprintf(l_err_str + l_off, sizeof(l_err_str) - l_off, "%s links",
                         l_event_item ? dap_chain_hash_fast_to_str_static(&l_event_item->hash) : "<null>");
                     log_it(L_ERROR, "%s", l_err_str);
                     (*a_links_size_array)--;
@@ -1329,7 +1325,8 @@ static int s_cli_dag(int argc, char ** argv, void **a_str_reply)
         return -1;
     }
 
-    dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index, argc, argv, a_str_reply, &l_chain, &l_net);
+    dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index, argc, argv, a_str_reply, &l_chain, &l_net,
+                                                  CHAIN_TYPE_INVALID);
     if ((l_net == NULL) || (l_chain == NULL)){
         return -1;
     } else if (a_str_reply && *a_str_reply) {
@@ -1338,7 +1335,7 @@ static int s_cli_dag(int argc, char ** argv, void **a_str_reply)
     }
     l_dag = DAP_CHAIN_CS_DAG(l_chain);
 
-    const char *l_chain_type = dap_chain_net_get_type(l_chain);
+    const char *l_chain_type = dap_chain_get_cs_type(l_chain);
 
     if (!strstr(l_chain_type, "dag_")){
             dap_cli_server_cmd_set_reply_text(a_str_reply,
@@ -1420,7 +1417,7 @@ static int s_cli_dag(int argc, char ** argv, void **a_str_reply)
             // dap_chain_net_sync_all(l_net);
         }
         if (strcmp(l_round_cmd_str, "find") == 0) {
-            dap_cli_server_cmd_find_option_val(argv, arg_index, arg_index + 2, "-datum", &l_datum_hash_str);
+            dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-datum", &l_datum_hash_str);
             char *l_datum_in_hash = NULL;
             if (l_datum_hash_str) {
                 if(!dap_strncmp(l_datum_hash_str, "0x", 2) || !dap_strncmp(l_datum_hash_str, "0X", 2)) {
@@ -1685,7 +1682,7 @@ static int s_cli_dag(int argc, char ** argv, void **a_str_reply)
                         dap_string_append_printf(l_str_tmp,
                             "\tRound info:\n\t\tsigns reject: %d\n",
                             l_round_item->round_info.reject_count);
-                        dap_time_to_str_rfc822(buf, DAP_TIME_STR_SIZE, l_round_item->round_info.ts_update);
+                        dap_nanotime_to_str_rfc822(buf, DAP_TIME_STR_SIZE, l_round_item->round_info.ts_update);
                         dap_string_append_printf(l_str_tmp, "\t\tdatum_hash: %s\n\t\tts_update: %s\n",
                             dap_chain_hash_fast_to_str_static(&l_round_item->round_info.datum_hash), buf);
                     }
@@ -1768,15 +1765,16 @@ static int s_cli_dag(int argc, char ** argv, void **a_str_reply)
                         size_t l_objs_count = 0;
                         l_objs = dap_global_db_get_all_sync(l_gdb_group_events,&l_objs_count);
                         char *ptr;
-                        size_t l_limit = l_limit_str ? strtoull(l_limit_str, &ptr, 10) : 0;
+                        size_t l_limit = l_limit_str ? strtoull(l_limit_str, &ptr, 10) : 1000;
                         size_t l_offset = l_offset_str ? strtoull(l_offset_str, &ptr, 10) : 0;
                         size_t l_arr_start = 0;
                         if (l_offset) {
-                            l_arr_start = l_offset * l_limit;
-                            dap_string_append_printf(l_str_tmp, "limit: %lu", l_arr_start);
+                            l_arr_start = l_offset;
+                            dap_string_append_printf(l_str_tmp, "offset: %lu\n", l_arr_start);
                         }
                         size_t l_arr_end = l_objs_count;
                         if (l_limit) {
+                            dap_string_append_printf(l_str_tmp, "limit: %lu\n", l_limit);
                             l_arr_end = l_arr_start + l_limit;
                             if (l_arr_end > l_objs_count)
                                 l_arr_end = l_objs_count;
@@ -1793,14 +1791,14 @@ static int s_cli_dag(int argc, char ** argv, void **a_str_reply)
                                             ((dap_chain_cs_dag_event_round_item_t *)l_objs[i].value)->event_n_signs;
                             char buf[DAP_TIME_STR_SIZE];
                             dap_time_to_str_rfc822(buf, DAP_TIME_STR_SIZE, l_event->header.ts_created);
-                            dap_string_append_printf(l_str_tmp, "\t%s: ts_create=%s\n", l_objs[i].key, buf);
+                            dap_string_append_printf(l_str_tmp, "\t%zu\t - %s: ts_create=%s\n", i - 1, l_objs[i].key, buf);
 
                         }
                         if (l_objs && l_objs_count )
                             dap_global_db_objs_delete(l_objs, l_objs_count);
                         ret = 0;
                     } else {
-                        dap_string_append_printf(l_str_tmp,"%s.%s: Error! No GlobalDB group!\n",l_net->pub.name,l_chain->name);
+                        dap_string_append_printf(l_str_tmp, "%s.%s: Error! No GlobalDB group!\n", l_net->pub.name, l_chain->name);
                         ret = -2;
 
                     }
@@ -1809,15 +1807,16 @@ static int s_cli_dag(int argc, char ** argv, void **a_str_reply)
                 } else if (!l_from_events_str || (strcmp(l_from_events_str,"events") == 0)) {
                     dap_string_t * l_str_tmp = dap_string_new(NULL);
                     pthread_mutex_lock(&PVT(l_dag)->events_mutex);
-                    size_t l_limit = l_limit_str ? strtoul(l_limit_str, NULL, 10) : 0;
+                    size_t l_limit = l_limit_str ? strtoul(l_limit_str, NULL, 10) : 1000;
                     size_t l_offset = l_offset_str ? strtoul(l_offset_str, NULL, 10) : 0;
                     size_t l_arr_start = 0;
-                    if (l_offset > 1) {
-                        l_arr_start = l_offset * l_limit;
-                        dap_string_append_printf(l_str_tmp, "limit: %lu\n", l_arr_start);
+                    if (l_offset > 0) {
+                        l_arr_start = l_offset;
+                        dap_string_append_printf(l_str_tmp, "offset: %lu\n", l_arr_start);                        
                     }
                     size_t l_arr_end = HASH_COUNT(PVT(l_dag)->events);
                     if (l_limit) {
+                        dap_string_append_printf(l_str_tmp, "limit: %lu\n", l_limit);
                         l_arr_end = l_arr_start + l_limit;
                         if (l_arr_end > HASH_COUNT(PVT(l_dag)->events))
                             l_arr_end = HASH_COUNT(PVT(l_dag)->events);
@@ -1831,7 +1830,7 @@ static int s_cli_dag(int argc, char ** argv, void **a_str_reply)
                             i_tmp++;
                             char buf[DAP_TIME_STR_SIZE];
                             dap_time_to_str_rfc822(buf, DAP_TIME_STR_SIZE, l_event_item->event->header.ts_created);
-                            dap_string_append_printf(l_str_tmp, "\t%s: ts_create=%s\n",
+                            dap_string_append_printf(l_str_tmp, "\t%zu\t- %s: ts_create=%s\n", i_tmp,
                                                      dap_chain_hash_fast_to_str_static(&l_event_item->hash),
                                                      buf);
                         }
@@ -1850,11 +1849,12 @@ static int s_cli_dag(int argc, char ** argv, void **a_str_reply)
                     size_t l_offset = l_offset_str ? strtoul(l_offset_str, NULL, 10) : 0;
                     size_t l_arr_start = 0;
                     if (l_offset) {
-                        l_arr_start = l_offset * l_limit;
-                        dap_string_append_printf(l_str_tmp, "limit: %lu", l_arr_start);
+                        l_arr_start = l_offset;
+                        dap_string_append_printf(l_str_tmp, "offset: %lu\n", l_arr_start);
                     }
                     size_t l_arr_end = HASH_COUNT(PVT(l_dag)->events_treshold);
                     if (l_limit) {
+                        dap_string_append_printf(l_str_tmp, "limit: %lu\n", l_limit);
                         l_arr_end = l_arr_start + l_limit;
                         if (l_arr_end > HASH_COUNT(PVT(l_dag)->events_treshold))
                             l_arr_end = HASH_COUNT(PVT(l_dag)->events_treshold);
@@ -1869,7 +1869,7 @@ static int s_cli_dag(int argc, char ** argv, void **a_str_reply)
                         i_tmp++;
                         char buf[DAP_TIME_STR_SIZE];
                         dap_time_to_str_rfc822(buf, DAP_TIME_STR_SIZE, l_event_item->event->header.ts_created);
-                        dap_string_append_printf(l_str_tmp,"\t%s: ts_create=%s\n",
+                        dap_string_append_printf(l_str_tmp, "\t%zu\t- %s: ts_create=%s\n", i_tmp,
                                                  dap_chain_hash_fast_to_str_static( &l_event_item->hash),
                                                  buf);
                     }
@@ -1898,7 +1898,7 @@ static int s_cli_dag(int argc, char ** argv, void **a_str_reply)
                 }
                 size_t l_event_count = HASH_COUNT(PVT(l_dag)->events);
                 size_t l_event_treshold_count = HASH_COUNT(PVT(l_dag)->events_treshold);
-                dap_string_append_printf(l_ret_str, "%zu atoms(s) in events\n%zu atom(s) in threshold", l_event_count, l_event_treshold_count);
+                dap_string_append_printf(l_ret_str, "%zu atom(s) in events\n%zu atom(s) in threshold", l_event_count, l_event_treshold_count);
                 dap_cli_server_cmd_set_reply_text(a_str_reply, "%s", l_ret_str->str);
                 dap_string_free(l_ret_str, true);
             } break;
@@ -1975,7 +1975,7 @@ static int s_cli_dag(int argc, char ** argv, void **a_str_reply)
     return ret;
 }
 
-static size_t s_dap_chain_callback_get_count_tx(dap_chain_t *a_chain)
+static uint64_t s_dap_chain_callback_get_count_tx(dap_chain_t *a_chain)
 {
     return PVT(DAP_CHAIN_CS_DAG(a_chain))->tx_count;
 }
@@ -2005,10 +2005,11 @@ static dap_list_t *s_dap_chain_callback_get_txs(dap_chain_t *a_chain, size_t a_c
     return l_list;
 }
 
-static size_t s_dap_chain_callback_get_count_atom(dap_chain_t *a_chain){
+static uint64_t s_dap_chain_callback_get_count_atom(dap_chain_t *a_chain)
+{
     dap_chain_cs_dag_t  *l_dag = DAP_CHAIN_CS_DAG(a_chain);
     pthread_mutex_lock(&PVT(l_dag)->events_mutex);
-    size_t l_count = HASH_COUNT(PVT(l_dag)->events);
+    uint64_t l_count = HASH_COUNT(PVT(l_dag)->events);
     pthread_mutex_unlock(&PVT(l_dag)->events_mutex);
     return l_count;
 }
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 bbe4f5b064044e7bc25f1b59e601f50fbaebab05..e4ac5b7a66382a90676db4ee389aab97f936c0c1 100644
--- a/modules/type/dag/include/dap_chain_cs_dag_event.h
+++ b/modules/type/dag/include/dap_chain_cs_dag_event.h
@@ -35,7 +35,7 @@ typedef struct dap_chain_cs_dag dap_chain_cs_dag_t;
 typedef struct dap_chain_class_dag_event_hdr {
         uint16_t version;
         uint64_t round_id;
-        dap_nanotime_t ts_created;
+        dap_time_t ts_created;
         dap_chain_id_t chain_id;
         dap_chain_cell_id_t cell_id; // Cell id if celled dag
         uint16_t hash_count; // Number of hashes
diff --git a/modules/type/none/dap_chain_cs_none.c b/modules/type/none/dap_chain_cs_none.c
index 45f1dee54dfb41ec918bd939bd895dfe9554b7bf..7cc90543c2872bd26ca91e80d8d4732f0cb98ce1 100644
--- a/modules/type/none/dap_chain_cs_none.c
+++ b/modules/type/none/dap_chain_cs_none.c
@@ -54,8 +54,6 @@ typedef struct dap_nonconsensus_private {
     bool is_load_mode; // If load mode - not save when new atom adds
     char *group_datums;
     dap_chain_t *chain;
-    pthread_cond_t load_cond;
-    pthread_mutex_t load_mutex;
     dap_nonconsensus_datum_hash_item_t * hash_items;
 } dap_nonconsensus_private_t;
 
@@ -134,6 +132,12 @@ static void s_changes_callback_notify(dap_store_obj_t *a_obj, void *a_arg)
     s_nonconsensus_callback_atom_add(l_chain, (dap_chain_datum_t *)a_obj->value, a_obj->value_len, &l_hash);
 }
 
+int s_nonconsensus_callback_created(dap_chain_t *a_chain, dap_config_t UNUSED_ARG *a_chain_cfg)
+{
+    dap_chain_add_mempool_notify_callback(a_chain, s_nonconsensus_callback_mempool_notify, a_chain);
+    return 0;
+}
+
 /**
  * @brief configure chain gdb
  * Set atom element callbacks
@@ -167,16 +171,12 @@ static int s_cs_callback_new(dap_chain_t *a_chain, dap_config_t UNUSED_ARG *a_ch
             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_nochain_priv->group_datums, 0,
-                                      true, DAP_GDB_MEMBER_ROLE_USER, DAP_CLUSTER_ROLE_EMBEDDED);
+                                      true, DAP_GDB_MEMBER_ROLE_USER, DAP_CLUSTER_TYPE_EMBEDDED);
     if (!l_nonconsensus_cluster) {
         log_it(L_ERROR, "Can't create global DB cluster for synchronization");
         return -3;
     }
     dap_global_db_cluster_add_notify_callback(l_nonconsensus_cluster, s_changes_callback_notify, a_chain);
-    dap_chain_add_mempool_notify_callback(a_chain, s_nonconsensus_callback_mempool_notify, a_chain);
-
-    pthread_cond_init(&l_nochain_priv->load_cond, NULL);
-    pthread_mutex_init(&l_nochain_priv->load_mutex, NULL);
 
     a_chain->callback_delete = s_nonconsensus_delete;
     a_chain->callback_purge = s_nonconsensus_callback_purge;
@@ -207,6 +207,7 @@ static int s_cs_callback_new(dap_chain_t *a_chain, dap_config_t UNUSED_ARG *a_ch
     a_chain->callback_add_datums = s_nonconsensus_callback_datums_pool_proc;
 
     a_chain->callback_load_from_gdb = s_nonconsensus_ledger_load;
+    a_chain->callback_created = s_nonconsensus_callback_created;
 
     return 0;
 }
@@ -244,46 +245,6 @@ const char* dap_nonconsensus_get_group(dap_chain_t * a_chain)
 }
 
 
-/**
- * @brief s_ledger_load_callback
- * @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_ledger_load_callback(UNUSED_ARG dap_global_db_instance_t *a_dbi,
-                                   UNUSED_ARG int a_rc, UNUSED_ARG const char *a_group,
-                                   UNUSED_ARG const size_t a_values_total, const size_t a_values_count,
-                                   dap_global_db_obj_t *a_values, void *a_arg)
-{
-    assert(a_arg);
-    dap_chain_t * l_chain = (dap_chain_t *) a_arg;
-    assert(l_chain);
-    dap_nonconsensus_t * l_nochain = DAP_NONCONSENSUS(l_chain);
-    assert(l_nochain);
-    dap_nonconsensus_private_t * l_nochain_pvt = PVT(l_nochain);
-    assert(l_nochain_pvt);
-    // make list of datums
-    for(size_t i = 0; i < a_values_count; i++) {
-        dap_global_db_obj_t *it = a_values + i;
-        dap_hash_fast_t l_hash = {};
-        dap_hash_fast(it->value, it->value_len, &l_hash);
-        s_nonconsensus_callback_atom_add(l_chain, it->value, it->value_len, &l_hash);
-        log_it(L_DEBUG,"Load mode, doesn't save item %s:%s", it->key, l_nochain_pvt->group_datums);
-    }
-
-    pthread_mutex_lock(&l_nochain_pvt->load_mutex);
-    l_nochain_pvt->is_load_mode = false;
-    pthread_cond_broadcast(&l_nochain_pvt->load_cond);
-    pthread_mutex_unlock(&l_nochain_pvt->load_mutex);
-    return true;
-}
-
 /**
  * @brief Load ledger from mempool
  *
@@ -293,16 +254,20 @@ static bool s_ledger_load_callback(UNUSED_ARG dap_global_db_instance_t *a_dbi,
  */
 static void s_nonconsensus_ledger_load(dap_chain_t *a_chain)
 {
-    dap_nonconsensus_t * l_nochain = DAP_NONCONSENSUS(a_chain);
-    dap_nonconsensus_private_t * l_nochain_pvt = PVT(l_nochain);
-    // load ledger
-    l_nochain_pvt->is_load_mode = true;
+    dap_nonconsensus_t *l_nochain = DAP_NONCONSENSUS(a_chain);
+    dap_nonconsensus_private_t *l_nochain_pvt = PVT(l_nochain);
+    size_t l_values_count = 0;
     //  Read the entire database into an array of size bytes
-    pthread_mutex_lock(&l_nochain_pvt->load_mutex);
-    dap_global_db_get_all(l_nochain_pvt->group_datums, 0, s_ledger_load_callback, a_chain);
-    while (l_nochain_pvt->is_load_mode)
-        pthread_cond_wait(&l_nochain_pvt->load_cond, &l_nochain_pvt->load_mutex);
-    pthread_mutex_unlock(&l_nochain_pvt->load_mutex);
+    dap_global_db_obj_t *l_values = dap_global_db_get_all_sync(l_nochain_pvt->group_datums, &l_values_count);
+    // make list of datums
+    for (size_t i = 0; l_values && i < l_values_count; i++) {
+        dap_global_db_obj_t *it = l_values + i;
+        // load ledger
+        s_nonconsensus_callback_atom_add(a_chain, it->value, it->value_len);
+        log_it(L_DEBUG,"Load mode, doesn't save item %s:%s", it->key, l_nochain_pvt->group_datums);
+    }
+    dap_global_db_objs_delete(l_values, l_values_count);
+    l_nochain_pvt->is_load_mode = false;
 }
 
 /**
@@ -453,7 +418,8 @@ static dap_chain_atom_ptr_t s_nonconsensus_callback_atom_iter_find_by_hash(dap_c
     dap_nonconsensus_t *l_nochain = DAP_NONCONSENSUS(a_atom_iter->chain);
     if (l_nochain) {
         l_ret = dap_global_db_get_sync(PVT(l_nochain)->group_datums, l_key, &l_ret_size, NULL, NULL);
-        *a_atom_size = l_ret_size;
+        if (a_atom_size)
+            *a_atom_size = l_ret_size;
     }
     //TODO set a_atom_iter item field
     return l_ret;