diff --git a/dap-sdk b/dap-sdk
index 1587a436ec9231ac3bb485e74cc5ec2a7534efd5..9e7565c9417bad979e90b83ccd537aecfe7c07f9 160000
--- a/dap-sdk
+++ b/dap-sdk
@@ -1 +1 @@
-Subproject commit 1587a436ec9231ac3bb485e74cc5ec2a7534efd5
+Subproject commit 9e7565c9417bad979e90b83ccd537aecfe7c07f9
diff --git a/modules/chain/include/dap_chain.h b/modules/chain/include/dap_chain.h
index 63a772b325f40357bc4060cdf6ec4414b419bb81..7082039bcce764c727207eabe32cc5e78171a0c7 100644
--- a/modules/chain/include/dap_chain.h
+++ b/modules/chain/include/dap_chain.h
@@ -142,6 +142,14 @@ typedef enum dap_chain_type {
     CHAIN_TYPE_ANCHOR = 8
 } dap_chain_type_t;
 
+// not rotate, use in state machine
+typedef enum dap_chain_sync_state {
+    CHAIN_SYNC_STATE_SYNCED = -1,  // chain was synced
+    CHAIN_SYNC_STATE_IDLE = 0,  // do nothink
+    CHAIN_SYNC_STATE_WAITING = 1,  // wait packet in
+    CHAIN_SYNC_STATE_ERROR = 2 // have a error
+} dap_chain_sync_state_t;
+
 typedef struct dap_chain {
     pthread_rwlock_t rwlock; // Common rwlock for the whole structure
 
@@ -166,6 +174,8 @@ typedef struct dap_chain {
     uint16_t *autoproc_datum_types;
     uint64_t atom_num_last;
 
+    dap_chain_sync_state_t  state;
+
     // To hold it in double-linked lists
     struct dap_chain * next;
     struct dap_chain * prev;
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 0ac4c23414c1f025661d4d3d28db0c8051380c07..b708d9d05db22af9ce2f1acdcaaae2d72cd6f7dc 100644
--- a/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c
+++ b/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c
@@ -751,7 +751,7 @@ static int s_callback_created(dap_chain_t * a_chain, dap_config_t *a_chain_net_c
     assert(l_net);
     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,
+                                                                       l_dag->gdb_group_events_round_new, 1, true,
                                                                        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);
diff --git a/modules/consensus/esbocs/dap_chain_cs_esbocs.c b/modules/consensus/esbocs/dap_chain_cs_esbocs.c
index 9b1e629107767a4294f513b3998a33875343a9ec..eaa405cd7fff060fb691a9ac78e475bdc861a140 100644
--- a/modules/consensus/esbocs/dap_chain_cs_esbocs.c
+++ b/modules/consensus/esbocs/dap_chain_cs_esbocs.c
@@ -539,7 +539,7 @@ static int s_callback_created(dap_chain_t *a_chain, dap_config_t *a_chain_net_cf
     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,
+                                                      l_sync_group, 72, true,
                                                       DAP_GDB_MEMBER_ROLE_NOBODY, DAP_CLUSTER_TYPE_AUTONOMIC);
     dap_link_manager_add_net_associate(l_net->pub.id.uint64, l_session->db_cluster->links_cluster);
     dap_global_db_erase_table_sync(l_sync_group);     // Drop table on stratup
@@ -729,6 +729,15 @@ int dap_chain_esbocs_set_min_validators_count(dap_chain_t *a_chain, uint16_t a_n
     return 0;
 }
 
+int dap_chain_esbocs_get_min_validators_count(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)
+            return PVT(l_session->esbocs)->min_validators_count;
+    return -1;
+}
+
 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), DAP_CHAIN_ESBOCS_CS_TYPE_STR), -1);
@@ -873,7 +882,8 @@ static dap_list_t *s_get_validators_list(dap_chain_esbocs_t *a_esbocs, dap_hash_
         for (size_t l_current_vld_cnt = 0; l_current_vld_cnt < l_need_vld_cnt; l_current_vld_cnt++) {
             uint256_t l_raw_result;
             uint256_t l_chosen_weight = dap_pseudo_random_get(l_total_weight, &l_raw_result);
-            if (false) { //PVT(a_session->esbocs)->debug) {
+#if DAP_ESBOCS_PRNG_DEBUG
+            if (l_esbocs_pvt->debug) {
                 unsigned l_strlen = 1024, l_off = 0;
                 const char *l_chosen_weight_str, *l_total_weight_str, *l_raw_result_str;
                 char l_str[l_strlen];
@@ -888,6 +898,7 @@ static dap_list_t *s_get_validators_list(dap_chain_esbocs_t *a_esbocs, dap_hash_
                 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);
             }
+#endif
             dap_list_t *l_chosen = NULL;
             uint256_t l_cur_weight = uint256_0;
             for (dap_list_t *it = l_validators; it; it = it->next) {
@@ -950,6 +961,9 @@ static dap_list_t *s_validator_check_synced(dap_chain_addr_t *a_addr, dap_list_t
 
 static void s_db_calc_sync_hash(dap_chain_esbocs_session_t *a_session)
 {
+    dap_chain_addr_t l_addr_blank = c_dap_chain_addr_blank;
+    l_addr_blank.net_id = a_session->chain->net_id;
+    dap_chain_net_srv_stake_mark_validator_active(&l_addr_blank, true);  // Mark all validators active for now
     char *l_penalty_group = s_get_penalty_group(a_session->chain->net_id);
     size_t l_penalties_count = 0;
     dap_global_db_obj_t *l_objs = dap_global_db_get_all_sync(l_penalty_group, &l_penalties_count);
diff --git a/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h b/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h
index bd009e34b125c2eac26c81315a10a16800def6d7..5a99570e8ba8fcc13714422ddb36179ac177e934 100644
--- a/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h
+++ b/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h
@@ -268,5 +268,6 @@ bool dap_chain_esbocs_remove_validator_from_clusters(dap_chain_net_id_t a_net_id
 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_get_min_validators_count(dap_chain_net_id_t a_net_id);
 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/net/dap_chain_ledger.c b/modules/net/dap_chain_ledger.c
index c24fe2c8ad288fddbea24f873bc7f4153f757d97..7c449e82744c8dbb0ccbd82c75f56f208253006e 100644
--- a/modules/net/dap_chain_ledger.c
+++ b/modules/net/dap_chain_ledger.c
@@ -3379,18 +3379,21 @@ static int s_tx_cache_check(dap_ledger_t *a_ledger,
                             bool a_check_for_removing)
 {
     dap_return_val_if_fail(a_ledger && a_tx && a_tx_hash, DAP_LEDGER_CHECK_INVALID_ARGS);
-    if (!dap_chain_net_get_load_mode(a_ledger->net) && !a_from_threshold && !a_check_for_removing) {
+    if (!a_from_threshold) {
         dap_ledger_tx_item_t *l_ledger_item = NULL;
         pthread_rwlock_rdlock(&PVT(a_ledger)->ledger_rwlock);
         HASH_FIND(hh, PVT(a_ledger)->ledger_items, a_tx_hash, sizeof(dap_chain_hash_fast_t), l_ledger_item);
         pthread_rwlock_unlock(&PVT(a_ledger)->ledger_rwlock);
-        if (l_ledger_item) {     // transaction already present in the cache list
+        if (l_ledger_item && !a_check_for_removing ) {     // transaction already present in the cache list
             if (s_debug_more) {
                 log_it(L_WARNING, "Transaction %s already present in the cache", dap_chain_hash_fast_to_str_static(a_tx_hash));
                 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_CHECK_ALREADY_CACHED;
+        } else if (!l_ledger_item && a_check_for_removing) {     // transaction already present in the cache list
+            debug_if(s_debug_more, L_WARNING, "Transaction %s not present in the cache. Can not delete it. Skip.", dap_chain_hash_fast_to_str_static(a_tx_hash));
+            return DAP_LEDGER_TX_CHECK_FOR_REMOVING_CANT_FIND_TX;
         }
     }
 /*
diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c
index 7872b7ee40adf8c59700386e991a970df5fb22de..3df4dc5b0153a41fa91d1f8b924321195e279d06 100644
--- a/modules/net/dap_chain_net.c
+++ b/modules/net/dap_chain_net.c
@@ -117,6 +117,7 @@
 #define F_DAP_CHAIN_NET_SYNC_FROM_ZERO   ( 1 << 8 )
 
 static bool s_debug_more = false;
+static const int c_sync_timer_period = 5000;  // msec
 
 struct request_link_info {
     char addr[DAP_HOSTADDR_STRLEN + 1];
@@ -129,23 +130,16 @@ struct block_reward {
     struct block_reward *prev, *next;
 };
 
-enum sync_state {
-    SYNC_STATE_IDLE,
-    SYNC_STATE_WAITING,
-    SYNC_STATE_SYNCED,
-    SYNC_STATE_ERROR
-};
 
 struct chain_sync_context {
-    enum sync_state state,
-                    last_state;
-    dap_time_t      stage_last_activity,
-                    sync_idle_time;
-    dap_stream_node_addr_t current_link;
-    dap_chain_t *cur_chain;
-    dap_chain_cell_t *cur_cell;
-    dap_hash_fast_t requested_atom_hash;
-    uint64_t requested_atom_num;
+    dap_chain_sync_state_t  state;
+    dap_time_t              stage_last_activity,
+                            sync_idle_time;
+    dap_stream_node_addr_t  current_link;
+    dap_chain_t             *cur_chain;
+    dap_chain_cell_t        *cur_cell;
+    dap_hash_fast_t         requested_atom_hash;
+    uint64_t                requested_atom_num;
 };
 
 /**
@@ -156,7 +150,6 @@ typedef struct dap_chain_net_pvt{
     pthread_t proc_tid;
     dap_chain_node_role_t node_role;
     uint32_t  flags;
-    time_t    last_sync;
 
     dap_chain_node_info_t *node_info;  // Current node's info
 
@@ -348,63 +341,10 @@ char *dap_chain_net_get_gdb_group_acl(dap_chain_net_t *a_net)
     return NULL;
 }
 
-/**
- * @brief set current network state to F_DAP_CHAIN_NET_GO_SYNC
- *
- * @param a_net dap_chain_net_t network object
- * @param a_new_state dap_chain_net_state_t new network state
- * @return int
- */
-int dap_chain_net_state_go_to(dap_chain_net_t *a_net, dap_chain_net_state_t a_new_state)
-{
-    if (PVT(a_net)->load_mode) {
-        log_it(L_ERROR, "Can't change state of loading network '%s'", a_net->pub.name);
-        return -1;
-    }
-    if (PVT(a_net)->state_target == a_new_state) {
-        log_it(L_NOTICE, "Network %s already %s state %s", a_net->pub.name,
-                                PVT(a_net)->state == a_new_state ? "have" : "going to", dap_chain_net_state_to_str(a_new_state));
-        return 0;
-    }
-    //PVT(a_net)->flags |= F_DAP_CHAIN_NET_SYNC_FROM_ZERO;  // TODO set this flag according to -mode argument from command line
-    PVT(a_net)->state_target = a_new_state;
-    if (a_new_state == NET_STATE_OFFLINE) {
-        char l_err_str[] = "ERROR_NET_IS_OFFLINE";
-        size_t l_error_size = sizeof(dap_stream_ch_chain_net_pkt_t) + sizeof(l_err_str);
-        dap_stream_ch_chain_net_pkt_t *l_error = DAP_NEW_STACK_SIZE(dap_stream_ch_chain_net_pkt_t, l_error_size);
-        l_error->hdr.version = DAP_STREAM_CH_CHAIN_NET_PKT_VERSION;
-        l_error->hdr.net_id = a_net->pub.id;
-        l_error->hdr.data_size = sizeof(l_err_str);
-        memcpy(l_error->data, l_err_str, sizeof(l_err_str));
-        dap_cluster_broadcast(PVT(a_net)->nodes_cluster->links_cluster, DAP_STREAM_CH_CHAIN_NET_ID,
-                              DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_ERROR, l_error, l_error_size, NULL, 0);
-        dap_link_manager_set_net_condition(a_net->pub.id.uint64, false);
-        dap_chain_esbocs_stop_timer(a_net->pub.id);
-    } else if (PVT(a_net)->state == NET_STATE_OFFLINE) {
-        dap_link_manager_set_net_condition(a_net->pub.id.uint64, true);
-        for (uint16_t i = 0; i < PVT(a_net)->permanent_links_count; ++i) {
-            dap_link_info_t *l_permalink_info = PVT(a_net)->permanent_links[i];
-            if (dap_chain_net_link_add(a_net, &l_permalink_info->node_addr, l_permalink_info->uplink_addr, l_permalink_info->uplink_port)) {
-                log_it(L_ERROR, "Can't create permanent link to addr " NODE_ADDR_FP_STR, NODE_ADDR_FP_ARGS_S(l_permalink_info->node_addr));
-                continue;
-            }
-            PVT(a_net)->state = NET_STATE_LINKS_CONNECTING;
-        }
-        if (a_new_state == NET_STATE_ONLINE)
-            dap_chain_esbocs_start_timer(a_net->pub.id);
-    }
-    return dap_proc_thread_callback_add(NULL, s_net_states_proc, a_net);
-}
-
-DAP_INLINE dap_chain_net_state_t dap_chain_net_get_target_state(dap_chain_net_t *a_net)
-{
-    return PVT(a_net)->state_target;
-}
-
 static struct request_link_info *s_balancer_link_from_cfg(dap_chain_net_t *a_net)
 {
     switch (PVT(a_net)->seed_nodes_count) {
-    case 0: return log_it(L_ERROR, "No available links! Add them in net config"), NULL;
+    case 0: return log_it(L_ERROR, "No available links in net %s! Add them in net config", a_net->pub.name), NULL;
     case 1: return PVT(a_net)->seed_nodes_info[0];
     default: return PVT(a_net)->seed_nodes_info[dap_random_uint16() % PVT(a_net)->seed_nodes_count];
     }
@@ -556,7 +496,7 @@ int s_link_manager_link_request(uint64_t a_net_id)
         l_net_pvt->state = NET_STATE_LINKS_CONNECTING;
     struct request_link_info *l_balancer_link = s_balancer_link_from_cfg(l_net);
     if (!l_balancer_link) {
-        log_it(L_ERROR, "Can't process balancer link %s request", dap_chain_net_balancer_type_to_str(PVT(l_net)->balancer_type));
+        log_it(L_ERROR, "Can't process balancer link %s request in nte %s", dap_chain_net_balancer_type_to_str(PVT(l_net)->balancer_type), l_net->pub.name);
         return -5;
     }
     return dap_chain_net_balancer_request(l_net, l_balancer_link->addr,  l_balancer_link->port, PVT(l_net)->balancer_type);
@@ -592,40 +532,32 @@ json_object *s_net_sync_status(dap_chain_net_t *a_net)
         json_object *l_jobj_chain = json_object_new_object();
         json_object *l_jobj_chain_status = NULL;
         json_object *l_jobj_percent = NULL;
-        double l_percent = l_chain->callback_count_atom(l_chain) ?
-                                   (double) (l_chain->callback_count_atom(l_chain) * 100) / l_chain->atom_num_last : 0;
-        if (l_percent > 100)
-            l_percent = 100;
-        char *l_percent_str = dap_strdup_printf("%.3f", l_percent);
-        dap_chain_net_state_t l_state = PVT(a_net)->state;
-        switch (l_state) {
-            case NET_STATE_OFFLINE:
-            case NET_STATE_LINKS_PREPARE:
-            case NET_STATE_LINKS_ESTABLISHED:
-            case NET_STATE_LINKS_CONNECTING:
-                l_jobj_chain_status = json_object_new_string("not synced");
-                l_jobj_percent = json_object_new_string(" - %");
+        
+        switch (l_chain->state) {
+            case CHAIN_SYNC_STATE_ERROR:
+                l_jobj_chain_status = json_object_new_string("error");
+                break;
+            case CHAIN_SYNC_STATE_IDLE:
+                l_jobj_chain_status = json_object_new_string("idle");
                 break;
-            case NET_STATE_ONLINE:
+            case CHAIN_SYNC_STATE_WAITING:
+                l_jobj_chain_status = json_object_new_string("sync in process");
+                break;
+            case CHAIN_SYNC_STATE_SYNCED:
                 l_jobj_chain_status = json_object_new_string("synced");
-                l_jobj_percent = json_object_new_string(l_percent_str);
                 break;
-            case NET_STATE_SYNC_CHAINS:
-                if (PVT(a_net)->sync_context.cur_chain && PVT(a_net)->sync_context.cur_chain->id.uint64 == l_chain->id.uint64) {
-                    l_jobj_chain_status = json_object_new_string("sync in process");
-                    l_jobj_percent = json_object_new_string(l_percent_str);
-                } else {
-                    if (l_chain->atom_num_last == l_chain->callback_count_atom(l_chain)) {
-                        l_jobj_chain_status = json_object_new_string("synced");
-                        l_jobj_percent = json_object_new_string(l_percent_str);
-                    } else {
-                        l_jobj_chain_status = json_object_new_string("not synced");
-                        l_jobj_percent = json_object_new_string(" - %");
-                    }
-                }
+            default:
+                l_jobj_chain_status = json_object_new_string("unknown");
                 break;
         }
-        DAP_DELETE(l_percent_str);
+        if (l_chain->state == CHAIN_SYNC_STATE_IDLE) {
+            l_jobj_percent = json_object_new_string(" - %");
+        } else {
+            double l_percent = dap_min((double)l_chain->callback_count_atom(l_chain) * 100 / l_chain->atom_num_last, 100.0);
+            char *l_percent_str = dap_strdup_printf("%.3f %c", l_percent, '%');
+            l_jobj_percent = json_object_new_string(l_percent_str);
+            DAP_DELETE(l_percent_str);
+        }
         json_object *l_jobj_current = json_object_new_uint64(l_chain->callback_count_atom(l_chain));
         json_object *l_jobj_total = json_object_new_uint64(l_chain->atom_num_last);
         json_object_object_add(l_jobj_chain, "status", l_jobj_chain_status);
@@ -668,68 +600,6 @@ static void s_net_states_notify(dap_chain_net_t *a_net)
     json_object_put(l_json);
 }
 
-/**
- * @brief s_net_states_proc
- * @param l_net
- */
-static bool s_net_states_proc(void *a_arg)
-{
-    bool l_repeat_after_exit = false; // If true - repeat on next iteration of proc thread loop
-    dap_chain_net_t *l_net = (dap_chain_net_t *) a_arg;
-    assert(l_net);
-    dap_chain_net_pvt_t *l_net_pvt = PVT(l_net);
-    assert(l_net_pvt);
-    if (l_net_pvt->state_target == NET_STATE_OFFLINE) {
-        if(l_net_pvt->state == NET_STATE_SYNC_CHAINS)
-            dap_leger_load_end(l_net->pub.ledger);
-        l_net_pvt->state = NET_STATE_OFFLINE;
-    }
-
-    switch ((dap_chain_net_state_t)l_net_pvt->state) {
-        // State OFFLINE where we don't do anything
-        case NET_STATE_OFFLINE: {
-            log_it(L_NOTICE,"%s.state: NET_STATE_OFFLINE", l_net->pub.name);
-            // delete all links
-            if ( l_net_pvt->state_target != NET_STATE_OFFLINE ){
-                dap_chain_net_state_t l_prev_state = l_net_pvt->state;
-                l_net_pvt->state = NET_STATE_LINKS_PREPARE;
-                l_repeat_after_exit = true;
-                if(l_prev_state == NET_STATE_SYNC_CHAINS)
-                    dap_leger_load_end(l_net->pub.ledger);
-            }
-            l_net_pvt->last_sync = 0;
-        } break;
-
-        // Prepare links
-        case NET_STATE_LINKS_PREPARE: {
-            log_it(L_NOTICE,"%s.state: NET_STATE_LINKS_PREPARE", l_net->pub.name);
-        } break;
-
-        case NET_STATE_LINKS_CONNECTING: {
-            log_it(L_INFO, "%s.state: NET_STATE_LINKS_CONNECTING",l_net->pub.name);
-            size_t l_used_links = 0;
-        } break;
-
-        case NET_STATE_LINKS_ESTABLISHED:
-            log_it(L_INFO,"%s.state: NET_STATE_LINKS_ESTABLISHED", l_net->pub.name);
-            break;
-
-        case NET_STATE_SYNC_CHAINS:
-            log_it(L_INFO,"%s.state: NET_STATE_SYNC_CHAINS", l_net->pub.name);
-            break;
-
-        case NET_STATE_ONLINE:
-            log_it(L_NOTICE,"%s.state: NET_STATE_ONLINE", l_net->pub.name);
-            l_net_pvt->last_sync = dap_time_now();
-            break;
-
-        default:
-            log_it(L_DEBUG, "Unprocessed state");
-    }
-    s_net_states_notify(l_net);
-    return l_repeat_after_exit;
-}
-
 /**
  * @brief dap_chain_net_get_role
  * @param a_net
@@ -2326,7 +2196,7 @@ bool s_net_load(void *a_arg)
     l_gdb_groups_mask = dap_strdup_printf("%s.orders", l_net->pub.gdb_groups_prefix);
     l_net_pvt->common_orders = 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_gdb_groups_mask, 72, true,
+                                                          l_gdb_groups_mask, 336, true,
                                                           DAP_GDB_MEMBER_ROLE_USER,
                                                           DAP_CLUSTER_TYPE_EMBEDDED);
     if (!l_net_pvt->common_orders) {
@@ -2337,12 +2207,11 @@ bool s_net_load(void *a_arg)
     DAP_DELETE(l_gdb_groups_mask);
     // Node states cluster
     l_gdb_groups_mask = dap_strdup_printf("%s.nodes.states", l_net->pub.gdb_groups_prefix);
-    l_net_pvt->nodes_states = 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_gdb_groups_mask, 0, true,
-        DAP_GDB_MEMBER_ROLE_USER,
-        DAP_CLUSTER_TYPE_EMBEDDED);
+    l_net_pvt->nodes_states = 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_gdb_groups_mask, 6, true,
+                                                        DAP_GDB_MEMBER_ROLE_USER,
+                                                        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);
@@ -2411,7 +2280,7 @@ bool s_net_load(void *a_arg)
         log_it(L_WARNING, "Unknown node address type will be defalted to 'auto'");
 
     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);
+    dap_proc_thread_timer_add(NULL, s_sync_timer_callback, l_net, c_sync_timer_period);
 
     log_it(L_INFO, "Chain network \"%s\" initialized", l_net->pub.name);
 ret:
@@ -2424,328 +2293,56 @@ ret:
     return false;
 }
 
-static const uint64_t s_fork_sync_step = 20; // TODO get it from config
-
-static void s_ch_in_pkt_callback(dap_stream_ch_t *a_ch, uint8_t a_type, const void *a_data, size_t a_data_size, void *a_arg)
+dap_global_db_cluster_t *dap_chain_net_get_mempool_cluster(dap_chain_t *a_chain)
 {
-    debug_if(s_debug_more, L_DEBUG, "Got IN sync packet type %hhu size %zu from addr " NODE_ADDR_FP_STR,
-                                                           a_type, a_data_size, NODE_ADDR_FP_ARGS_S(a_ch->stream->node));
-    dap_chain_net_t *l_net = a_arg;
-    dap_chain_net_pvt_t *l_net_pvt = PVT(l_net);
-    if (l_net_pvt->state == NET_STATE_LINKS_ESTABLISHED)
-        l_net_pvt->state = NET_STATE_SYNC_CHAINS;
-
-    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;
+    dap_return_val_if_fail(a_chain, NULL);
+    dap_chain_net_t *l_net = dap_chain_net_by_id(a_chain->net_id);
+    if (!l_net) {
+        log_it(L_ERROR, "Invalid chain specified for mempool cluster search");
+        return NULL;
+    }
+    dap_global_db_cluster_t *l_mempool = PVT(l_net)->mempool_clusters;
+    dap_chain_t *l_chain;
+    DL_FOREACH(l_net->pub.chains, l_chain) {
+        if (l_chain == a_chain)
+            return l_mempool;
+        assert(l_mempool);
+        l_mempool = l_mempool->next;
     }
+    log_it(L_ERROR, "No mempool cluster found for chain specified");
+    return NULL;
+}
 
-    switch (a_type) {
-    case DAP_CHAIN_CH_PKT_TYPE_ERROR:
-        l_net_pvt->sync_context.state = SYNC_STATE_ERROR;
-        return;
+void dap_chain_add_mempool_notify_callback(dap_chain_t *a_chain, dap_store_obj_callback_notify_t a_callback, void *a_cb_arg)
+{
+    dap_global_db_cluster_add_notify_callback(dap_chain_net_get_mempool_cluster(a_chain), a_callback, a_cb_arg);
+}
 
-    case DAP_CHAIN_CH_PKT_TYPE_SYNCED_CHAIN:
-        l_net_pvt->sync_context.state = SYNC_STATE_SYNCED;
+static void s_nodelist_change_notify(dap_store_obj_t *a_obj, void *a_arg)
+{
+    dap_chain_net_t *l_net = a_arg;
+    dap_return_if_fail(a_obj->key && !dap_strcmp(l_net->pub.gdb_nodes, a_obj->group));
+    char l_ts[DAP_TIME_STR_SIZE] = { '\0' };
+    dap_nanotime_to_str_rfc822(l_ts, sizeof(l_ts), a_obj->timestamp);
+    if (dap_store_obj_get_type(a_obj) == DAP_GLOBAL_DB_OPTYPE_DEL) {
+        log_it(L_NOTICE, "Removed node %s from network %s at %s\n",
+                                 a_obj->key, l_net->pub.name, l_ts);
         return;
-
-    case DAP_CHAIN_CH_PKT_TYPE_CHAIN_MISS: {
-        if (!l_net_pvt->sync_context.cur_chain)
-            return;
-        dap_chain_ch_miss_info_t *l_miss_info = (dap_chain_ch_miss_info_t *)(((dap_chain_ch_pkt_t *)(a_data))->data);
-        if (!dap_hash_fast_compare(&l_miss_info->missed_hash, &l_net_pvt->sync_context.requested_atom_hash)) {
-            char l_missed_hash_str[DAP_HASH_FAST_STR_SIZE];
-            dap_hash_fast_to_str(&l_miss_info->missed_hash, l_missed_hash_str, DAP_HASH_FAST_STR_SIZE);
-            log_it(L_WARNING, "Get irrelevant chain sync MISSED packet with missed hash %s, but requested hash is %s",
-                                                                        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,
-                                             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,
-                                             DAP_CHAIN_CH_ERROR_INCORRECT_SYNC_SEQUENCE);
-            return;
-        }
-        dap_chain_atom_iter_t *l_iter = l_net_pvt->sync_context.cur_chain->callback_atom_iter_create(
-                                                                            l_net_pvt->sync_context.cur_chain,
-                                                                            l_net_pvt->sync_context.cur_cell
-                                                                            ? l_net_pvt->sync_context.cur_cell->id
-                                                                            : c_dap_chain_cell_id_null,
-                                                                            NULL);
-        if (!l_iter) {
-            log_it(L_CRITICAL, "%s", c_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
-                                             : c_dap_chain_cell_id_null,
-                                             DAP_CHAIN_CH_ERROR_OUT_OF_MEMORY);
-            return;
-        }
-        dap_chain_atom_ptr_t l_atom = l_net_pvt->sync_context.cur_chain->callback_atom_find_by_hash(l_iter, &l_miss_info->last_hash, NULL);
-        if (l_atom && l_iter->cur_num == l_miss_info->last_num) {       // We already have this subchain in our chain
-            l_net_pvt->sync_context.state = SYNC_STATE_SYNCED;
-            return;
-        }
-        dap_chain_ch_sync_request_t l_request = {};
-        l_request.num_from = l_net_pvt->sync_context.requested_atom_num > s_fork_sync_step
-                            ? l_net_pvt->sync_context.requested_atom_num - s_fork_sync_step
-                            : 0;
-        if (l_request.num_from) {
-            l_atom = l_net_pvt->sync_context.cur_chain->callback_atom_get_by_num(l_iter, l_request.num_from);
-            assert(l_atom);
-            l_request.hash_from = *l_iter->cur_hash;
-        }
-        l_net_pvt->sync_context.cur_chain->callback_atom_iter_delete(l_iter);
-        debug_if(s_debug_more, L_INFO, "Send sync request to node " NODE_ADDR_FP_STR
-                                        " for net %s and chain %s, hash from %s, num from %" DAP_UINT64_FORMAT_U,
-                                                        NODE_ADDR_FP_ARGS_S(l_net_pvt->sync_context.current_link),
-                                                        l_net->pub.name, l_net_pvt->sync_context.cur_chain->name,
-                                                        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,
-                                      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);
-        l_net_pvt->sync_context.requested_atom_hash = l_request.hash_from;
-        l_net_pvt->sync_context.requested_atom_num = l_request.num_from;
-    }
-    default:
-        break;
     }
-    l_net_pvt->sync_context.stage_last_activity = dap_time_now();
+    dap_chain_node_info_t *l_node_info = (dap_chain_node_info_t *)a_obj->value;
+    assert(dap_chain_node_info_get_size(l_node_info) == a_obj->value_len);
+    log_it(L_NOTICE, "Added node "NODE_ADDR_FP_STR" [%s : %u] to network %s at %s\n",
+                             NODE_ADDR_FP_ARGS_S(l_node_info->address),
+                             l_node_info->ext_host, l_node_info->ext_port,
+                             l_net->pub.name, l_ts);
 }
 
-static void s_ch_out_pkt_callback(dap_stream_ch_t *a_ch, uint8_t a_type, const void *a_data, size_t a_data_size, void *a_arg)
+void dap_chain_net_add_nodelist_notify_callback(dap_chain_net_t *a_net, dap_store_obj_callback_notify_t a_callback, void *a_cb_arg)
 {
-    debug_if(s_debug_more, L_DEBUG, "Sent OUT sync packet type %hhu size %zu to addr " NODE_ADDR_FP_STR,
-                                                           a_type, a_data_size, NODE_ADDR_FP_ARGS_S(a_ch->stream->node));
-    dap_chain_net_t *l_net = a_arg;
-    dap_chain_net_pvt_t *l_net_pvt = PVT(l_net);
-    switch (a_type) {
-    case DAP_CHAIN_CH_PKT_TYPE_ERROR:
-        l_net_pvt->sync_context.state = SYNC_STATE_ERROR;
-        break;
-    default:
-        break;
-    }
-    l_net_pvt->sync_context.stage_last_activity = dap_time_now();
+    dap_global_db_cluster_add_notify_callback(PVT(a_net)->nodes_cluster, a_callback, a_cb_arg);
 }
 
-static void s_sync_timer_callback(void *a_arg)
-{
-    dap_chain_net_t *l_net = a_arg;
-    dap_chain_net_pvt_t *l_net_pvt = PVT(l_net);
-    if (l_net_pvt->state_target == NET_STATE_OFFLINE)
-        return;
-    if (l_net_pvt->sync_context.last_state == SYNC_STATE_SYNCED || l_net_pvt->sync_context.last_state == SYNC_STATE_ERROR ||
-            (l_net_pvt->sync_context.last_state == SYNC_STATE_IDLE && l_net_pvt->state != NET_STATE_ONLINE) ||
-            dap_time_now() - l_net_pvt->sync_context.stage_last_activity > l_net_pvt->sync_context.sync_idle_time) {
-        if (!l_net_pvt->sync_context.cur_chain || l_net_pvt->sync_context.last_state == SYNC_STATE_ERROR) {
-            // Go no next link
-            dap_cluster_t *l_cluster = dap_cluster_by_mnemonim(l_net->pub.name);
-            if (!dap_stream_node_addr_is_blank(&l_net_pvt->sync_context.current_link)) {
-                dap_stream_ch_del_notifier(&l_net_pvt->sync_context.current_link, DAP_CHAIN_CH_ID,
-                                           DAP_STREAM_PKT_DIR_IN, s_ch_in_pkt_callback, l_net);
-                dap_stream_ch_del_notifier(&l_net_pvt->sync_context.current_link, DAP_CHAIN_CH_ID,
-                                           DAP_STREAM_PKT_DIR_OUT, s_ch_out_pkt_callback, l_net);
-            }
-            l_net_pvt->sync_context.current_link = dap_cluster_get_random_link(l_cluster);
-            if (dap_stream_node_addr_is_blank(&l_net_pvt->sync_context.current_link))
-                return;     // No links in cluster
-            l_net_pvt->sync_context.cur_chain = l_net->pub.chains;
-            if (!l_net_pvt->sync_context.cur_chain) {
-                log_it(L_ERROR, "No chains in net %s", l_net->pub.name);
-                return;
-            }
-            dap_stream_ch_add_notifier(&l_net_pvt->sync_context.current_link, DAP_CHAIN_CH_ID,
-                                       DAP_STREAM_PKT_DIR_IN, s_ch_in_pkt_callback, l_net);
-            dap_stream_ch_add_notifier(&l_net_pvt->sync_context.current_link, DAP_CHAIN_CH_ID,
-                                       DAP_STREAM_PKT_DIR_OUT, s_ch_out_pkt_callback, l_net);
-            l_net_pvt->sync_context.state = l_net_pvt->sync_context.last_state = SYNC_STATE_WAITING;
-        } else {
-            l_net_pvt->sync_context.cur_chain = l_net_pvt->sync_context.cur_chain->next;
-            if (l_net_pvt->sync_context.cur_chain)
-                log_it(L_DEBUG, "[%s:%d] Go to next chain \"%s\" for net %s", __FUNCTION__, __LINE__,
-                        l_net_pvt->sync_context.cur_chain->name, l_net_pvt->sync_context.cur_chain->net_name);
-            else 
-                log_it(L_DEBUG, "[%s:%d] Go to next chain: <NULL>",  __FUNCTION__, __LINE__);
-            if (!l_net_pvt->sync_context.cur_chain) {
-                dap_chain_net_state_t l_prev_state = l_net_pvt->state;
-                if (l_net_pvt->sync_context.last_state == SYNC_STATE_SYNCED) {
-                    l_net_pvt->state = NET_STATE_ONLINE;
-                    l_net_pvt->sync_context.state = l_net_pvt->sync_context.last_state = SYNC_STATE_IDLE;
-                    s_net_states_proc(l_net);
-                    if(l_prev_state == NET_STATE_SYNC_CHAINS)
-                        dap_leger_load_end(l_net->pub.ledger);
-                } else
-                    l_net_pvt->sync_context.state = l_net_pvt->sync_context.last_state = SYNC_STATE_WAITING;
-                return;
-            }
-        }
-        // 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;
-            if (l_net_pvt->sync_context.cur_chain)
-                log_it(L_DEBUG, "[%s:%d] Go to next chain \"%s\" for net %s", __FUNCTION__, __LINE__,
-                        l_net_pvt->sync_context.cur_chain->name, l_net_pvt->sync_context.cur_chain->net_name);
-            else 
-                log_it(L_DEBUG, "[%s:%d] Go to next chain: <NULL>",  __FUNCTION__, __LINE__);
-            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 = {};
-        uint64_t l_last_num = 0;
-        if (!dap_chain_get_atom_last_hash_num(l_net_pvt->sync_context.cur_chain,
-                                              l_net_pvt->sync_context.cur_cell
-                                              ? l_net_pvt->sync_context.cur_cell->id
-                                              : c_dap_chain_cell_id_null,
-                                              &l_request.hash_from,
-                                              &l_last_num)) {
-            log_it(L_ERROR, "Can't get last atom hash and number for chain %s with net %s", l_net_pvt->sync_context.cur_chain->name,
-                                                                                            l_net->pub.name);
-            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, 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, "%s", c_error_memory_alloc);
-            return;
-        }
-        log_it(L_INFO, "Start synchronization process with " NODE_ADDR_FP_STR
-                        " for net %s and chain %s, last hash %s, last num %" DAP_UINT64_FORMAT_U,
-                                                        NODE_ADDR_FP_ARGS_S(l_net_pvt->sync_context.current_link),
-                                                        l_net->pub.name, l_net_pvt->sync_context.cur_chain->name,
-                                                        dap_hash_fast_to_str_static(&l_request.hash_from), l_last_num);
-        dap_stream_ch_pkt_send_by_addr(&l_net_pvt->sync_context.current_link, DAP_CHAIN_CH_ID,
-                                       DAP_CHAIN_CH_PKT_TYPE_CHAIN_REQ, l_chain_pkt,
-                                       dap_chain_ch_pkt_get_size(l_chain_pkt));
-        l_net_pvt->sync_context.requested_atom_hash = l_request.hash_from;
-        l_net_pvt->sync_context.requested_atom_num = l_request.num_from;
-        DAP_DELETE(l_chain_pkt);
-    }
-    if (l_net_pvt->sync_context.last_state != SYNC_STATE_IDLE &&
-            l_net_pvt->sync_context.last_state != l_net_pvt->sync_context.state)
-        l_net_pvt->sync_context.last_state = l_net_pvt->sync_context.state;
-}
-
-/**
- * @brief try net to go online
- *
- * @param a_net dap_chain_net_t *: network 
- * @return int
- *
- **/
-static int s_net_try_online(dap_chain_net_t *a_net)
-{
-    
-    dap_chain_net_t *l_net = a_net;
-    
-    dap_chain_net_pvt_t * l_net_pvt = PVT(l_net);
-    dap_chain_net_state_t l_target_state = NET_STATE_OFFLINE;
-    
-    if (dap_config_get_item_bool_default(g_config ,"general", "auto_online", false))
-    {
-        l_target_state = NET_STATE_ONLINE;
-    }
-    
-    if (l_target_state != l_net_pvt->state_target)
-    {   
-        dap_chain_net_state_go_to(l_net, l_target_state);
-        log_it(L_INFO, "Network \"%s\" goes online",l_net->pub.name);
-    }
-    
-    return 0;
-}
-
-/**
- * @brief
- * change all network states according to auto-online settings
- */
-void dap_chain_net_try_online_all() {
-    int32_t l_ret = 0;
-
-    if(!HASH_COUNT(s_net_items)){
-        log_it(L_ERROR, "Can't find any nets");
-        return;
-    }
-    dap_chain_net_item_t *l_net_items_current = NULL, *l_net_items_tmp = NULL;
-    HASH_ITER(hh, s_net_items, l_net_items_current, l_net_items_tmp) {
-        if( (l_ret = s_net_try_online(l_net_items_current->chain_net)) ) {
-            log_it(L_ERROR, "Can't try online state for net %s.  Finished with (%d) error code.", l_net_items_current->name, l_ret);
-        }
-    }
-}
-
-
-dap_global_db_cluster_t *dap_chain_net_get_mempool_cluster(dap_chain_t *a_chain)
-{
-    dap_return_val_if_fail(a_chain, NULL);
-    dap_chain_net_t *l_net = dap_chain_net_by_id(a_chain->net_id);
-    if (!l_net) {
-        log_it(L_ERROR, "Invalid chain specified for mempool cluster search");
-        return NULL;
-    }
-    dap_global_db_cluster_t *l_mempool = PVT(l_net)->mempool_clusters;
-    dap_chain_t *l_chain;
-    DL_FOREACH(l_net->pub.chains, l_chain) {
-        if (l_chain == a_chain)
-            return l_mempool;
-        assert(l_mempool);
-        l_mempool = l_mempool->next;
-    }
-    log_it(L_ERROR, "No mempool cluster found for chain specified");
-    return NULL;
-}
-
-void dap_chain_add_mempool_notify_callback(dap_chain_t *a_chain, dap_store_obj_callback_notify_t a_callback, void *a_cb_arg)
-{
-    dap_global_db_cluster_add_notify_callback(dap_chain_net_get_mempool_cluster(a_chain), a_callback, a_cb_arg);
-}
-
-static void s_nodelist_change_notify(dap_store_obj_t *a_obj, void *a_arg)
-{
-    dap_chain_net_t *l_net = a_arg;
-    dap_return_if_fail(a_obj->key && !dap_strcmp(l_net->pub.gdb_nodes, a_obj->group));
-    char l_ts[DAP_TIME_STR_SIZE] = { '\0' };
-    dap_nanotime_to_str_rfc822(l_ts, sizeof(l_ts), a_obj->timestamp);
-    if (dap_store_obj_get_type(a_obj) == DAP_GLOBAL_DB_OPTYPE_DEL) {
-        log_it(L_NOTICE, "Removed node %s from network %s at %s\n",
-                                 a_obj->key, l_net->pub.name, l_ts);
-        return;
-    }
-    dap_chain_node_info_t *l_node_info = (dap_chain_node_info_t *)a_obj->value;
-    assert(dap_chain_node_info_get_size(l_node_info) == a_obj->value_len);
-    log_it(L_NOTICE, "Added node "NODE_ADDR_FP_STR" [%s : %u] to network %s at %s\n",
-                             NODE_ADDR_FP_ARGS_S(l_node_info->address),
-                             l_node_info->ext_host, l_node_info->ext_port,
-                             l_net->pub.name, l_ts);
-}
-
-void dap_chain_net_add_nodelist_notify_callback(dap_chain_net_t *a_net, dap_store_obj_callback_notify_t a_callback, void *a_cb_arg)
-{
-    dap_global_db_cluster_add_notify_callback(PVT(a_net)->nodes_cluster, a_callback, a_cb_arg);
-}
-
-void dap_chain_net_srv_order_add_notify_callback(dap_chain_net_t *a_net, dap_store_obj_callback_notify_t a_callback, void *a_cb_arg)
+void dap_chain_net_srv_order_add_notify_callback(dap_chain_net_t *a_net, dap_store_obj_callback_notify_t a_callback, void *a_cb_arg)
 {
     dap_global_db_cluster_add_notify_callback(PVT(a_net)->orders_cluster, a_callback, a_cb_arg);
 }
@@ -2958,24 +2555,6 @@ dap_chain_net_state_t dap_chain_net_get_state (dap_chain_net_t * l_net)
     return PVT(l_net)->state;
 }
 
-/**
- * @brief dap_chain_net_set_state
- * @param l_net
- * @param a_state
- */
-void dap_chain_net_set_state(dap_chain_net_t *l_net, dap_chain_net_state_t a_state)
-{
-    assert(l_net);
-    log_it(L_DEBUG,"%s set state %s", l_net->pub.name, dap_chain_net_state_to_str(a_state));
-    if(a_state == PVT(l_net)->state){
-        return;
-    }
-    if(PVT(l_net)->state == NET_STATE_SYNC_CHAINS)
-        dap_leger_load_end(l_net->pub.ledger);
-    PVT(l_net)->state = a_state;
-    dap_proc_thread_callback_add(NULL, s_net_states_proc, l_net);
-}
-
 dap_chain_cell_id_t * dap_chain_net_get_cur_cell( dap_chain_net_t * l_net)
 {
     return  PVT(l_net)->node_info ? &PVT(l_net)->node_info->cell_id: 0;
@@ -3407,3 +2986,419 @@ decree_table_t **dap_chain_net_get_decrees(dap_chain_net_t *a_net) {
 anchor_table_t **dap_chain_net_get_anchors(dap_chain_net_t *a_net) {
     return a_net ? &(PVT(a_net)->anchors) : NULL;
 }
+
+/*------------------------------------State machine block------------------------------------*/
+
+/**
+ * @brief try net to go online
+ * @param a_net dap_chain_net_t *: network 
+ * @return 0 if ok
+ **/
+static int s_net_try_online(dap_chain_net_t *a_net)
+{
+// sanity check
+    dap_return_val_if_pass(!a_net || !PVT(a_net), -1);
+// func work
+    dap_chain_net_t *l_net = a_net;
+    dap_chain_net_pvt_t * l_net_pvt = PVT(l_net);
+    dap_chain_net_state_go_to(l_net, NET_STATE_ONLINE);
+    log_it(L_INFO, "Network \"%s\" goes online",l_net->pub.name);
+    return 0;
+}
+
+/**
+ * @brief
+ * change all network states according to auto-online settings
+ */
+void dap_chain_net_try_online_all() {
+    int32_t l_ret = 0;
+
+    if(!HASH_COUNT(s_net_items)){
+        log_it(L_ERROR, "Can't find any nets");
+        return;
+    }
+    if (!dap_config_get_item_bool_default(g_config ,"general", "auto_online", false)) {
+        log_it(L_DEBUG, "Auto online is off in config");
+        return;
+    }
+    dap_chain_net_item_t *l_net_items_current = NULL, *l_net_items_tmp = NULL;
+    HASH_ITER(hh, s_net_items, l_net_items_current, l_net_items_tmp) {
+        if( (l_ret = s_net_try_online(l_net_items_current->chain_net)) ) {
+            log_it(L_ERROR, "Can't try online state for net %s.  Finished with (%d) error code.", l_net_items_current->name, l_ret);
+        }
+    }
+}
+
+static const uint64_t s_fork_sync_step = 20; // TODO get it from config
+
+static void s_ch_in_pkt_callback(dap_stream_ch_t *a_ch, uint8_t a_type, const void *a_data, size_t a_data_size, void *a_arg)
+{
+    debug_if(s_debug_more, L_DEBUG, "Got IN sync packet type %hhu size %zu from addr " NODE_ADDR_FP_STR,
+                                                           a_type, a_data_size, NODE_ADDR_FP_ARGS_S(a_ch->stream->node));
+    dap_chain_net_t *l_net = a_arg;
+    dap_chain_net_pvt_t *l_net_pvt = PVT(l_net);
+    if (l_net_pvt->state == NET_STATE_LINKS_ESTABLISHED)
+        l_net_pvt->state = NET_STATE_SYNC_CHAINS;
+
+    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:
+        if (!l_net_pvt->sync_context.cur_chain) {
+            log_it(L_DEBUG, "Got ERROR paket with NO chain net %s", l_net->pub.name);
+            return;
+        }
+        log_it(L_DEBUG, "Got ERROR paket to %s chain in net %s", l_net_pvt->sync_context.cur_chain->name, l_net->pub.name);
+        l_net_pvt->sync_context.cur_chain->state = CHAIN_SYNC_STATE_ERROR;
+        return;
+
+    case DAP_CHAIN_CH_PKT_TYPE_SYNCED_CHAIN:
+        if (!l_net_pvt->sync_context.cur_chain) {
+            log_it(L_DEBUG, "Got SYNCED_CHAIN paket with NO chain net %s", l_net->pub.name);
+            return;
+        }
+        log_it(L_DEBUG, "Got SYNCED_CHAIN paket to %s chain net %s", l_net_pvt->sync_context.cur_chain->name, l_net->pub.name);
+        l_net_pvt->sync_context.cur_chain->state = CHAIN_SYNC_STATE_SYNCED;
+        l_net_pvt->sync_context.cur_chain->atom_num_last = l_net_pvt->sync_context.cur_chain->callback_count_atom(l_net_pvt->sync_context.cur_chain);
+        return;
+
+    case DAP_CHAIN_CH_PKT_TYPE_CHAIN_MISS: {
+        if (!l_net_pvt->sync_context.cur_chain)
+            return;
+        dap_chain_ch_miss_info_t *l_miss_info = (dap_chain_ch_miss_info_t *)(((dap_chain_ch_pkt_t *)(a_data))->data);
+        if (!dap_hash_fast_compare(&l_miss_info->missed_hash, &l_net_pvt->sync_context.requested_atom_hash)) {
+            char l_missed_hash_str[DAP_HASH_FAST_STR_SIZE];
+            dap_hash_fast_to_str(&l_miss_info->missed_hash, l_missed_hash_str, DAP_HASH_FAST_STR_SIZE);
+            log_it(L_WARNING, "Get irrelevant chain sync MISSED packet with missed hash %s, but requested hash is %s",
+                                                                        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,
+                                             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,
+                                             DAP_CHAIN_CH_ERROR_INCORRECT_SYNC_SEQUENCE);
+            return;
+        }
+        dap_chain_atom_iter_t *l_iter = l_net_pvt->sync_context.cur_chain->callback_atom_iter_create(
+                                                                            l_net_pvt->sync_context.cur_chain,
+                                                                            l_net_pvt->sync_context.cur_cell
+                                                                            ? l_net_pvt->sync_context.cur_cell->id
+                                                                            : c_dap_chain_cell_id_null,
+                                                                            NULL);
+        if (!l_iter) {
+            log_it(L_CRITICAL, "%s", c_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
+                                             : c_dap_chain_cell_id_null,
+                                             DAP_CHAIN_CH_ERROR_OUT_OF_MEMORY);
+            return;
+        }
+        dap_chain_atom_ptr_t l_atom = l_net_pvt->sync_context.cur_chain->callback_atom_find_by_hash(l_iter, &l_miss_info->last_hash, NULL);
+        if (l_atom && l_iter->cur_num == l_miss_info->last_num) {       // We already have this subchain in our chain
+            l_net_pvt->sync_context.cur_chain->state = CHAIN_SYNC_STATE_SYNCED;
+            l_net_pvt->sync_context.cur_chain->atom_num_last = l_miss_info->last_num;
+            return;
+        }
+        dap_chain_ch_sync_request_t l_request = {};
+        l_request.num_from = l_net_pvt->sync_context.requested_atom_num > s_fork_sync_step
+                            ? l_net_pvt->sync_context.requested_atom_num - s_fork_sync_step
+                            : 0;
+        if (l_request.num_from) {
+            l_atom = l_net_pvt->sync_context.cur_chain->callback_atom_get_by_num(l_iter, l_request.num_from);
+            assert(l_atom);
+            l_request.hash_from = *l_iter->cur_hash;
+        }
+        l_net_pvt->sync_context.cur_chain->callback_atom_iter_delete(l_iter);
+        debug_if(s_debug_more, L_INFO, "Send sync request to node " NODE_ADDR_FP_STR
+                                        " for net %s and chain %s, hash from %s, num from %" DAP_UINT64_FORMAT_U,
+                                                        NODE_ADDR_FP_ARGS_S(l_net_pvt->sync_context.current_link),
+                                                        l_net->pub.name, l_net_pvt->sync_context.cur_chain->name,
+                                                        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,
+                                      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);
+        l_net_pvt->sync_context.requested_atom_hash = l_request.hash_from;
+        l_net_pvt->sync_context.requested_atom_num = l_request.num_from;
+    }
+    default:
+        break;
+    }
+    l_net_pvt->sync_context.stage_last_activity = dap_time_now();
+}
+
+static void s_ch_out_pkt_callback(dap_stream_ch_t *a_ch, uint8_t a_type, const void *a_data, size_t a_data_size, void *a_arg)
+{
+    debug_if(s_debug_more, L_DEBUG, "Sent OUT sync packet type %hhu size %zu to addr " NODE_ADDR_FP_STR,
+                                                           a_type, a_data_size, NODE_ADDR_FP_ARGS_S(a_ch->stream->node));
+    dap_chain_net_t *l_net = a_arg;
+    dap_chain_net_pvt_t *l_net_pvt = PVT(l_net);
+    switch (a_type) {
+    case DAP_CHAIN_CH_PKT_TYPE_ERROR:
+        l_net_pvt->sync_context.cur_chain->state = CHAIN_SYNC_STATE_ERROR;
+        break;
+    default:
+        break;
+    }
+    l_net_pvt->sync_context.stage_last_activity = dap_time_now();
+}
+
+
+static int s_restart_sync_chains(dap_chain_net_t *a_net)
+{
+    // sanity check
+    dap_return_val_if_pass(!a_net || !PVT(a_net), -1);
+    dap_chain_net_pvt_t *l_net_pvt = PVT(a_net);
+
+    dap_cluster_t *l_cluster = dap_cluster_by_mnemonim(a_net->pub.name);
+    if (!dap_stream_node_addr_is_blank(&l_net_pvt->sync_context.current_link)) {
+        dap_stream_ch_del_notifier(&l_net_pvt->sync_context.current_link, DAP_CHAIN_CH_ID,
+                                    DAP_STREAM_PKT_DIR_IN, s_ch_in_pkt_callback, a_net);
+        dap_stream_ch_del_notifier(&l_net_pvt->sync_context.current_link, DAP_CHAIN_CH_ID,
+                                    DAP_STREAM_PKT_DIR_OUT, s_ch_out_pkt_callback, a_net);
+    }
+    l_net_pvt->sync_context.current_link = dap_cluster_get_random_link(l_cluster);
+    if (dap_stream_node_addr_is_blank(&l_net_pvt->sync_context.current_link)) {
+        log_it(L_DEBUG, "No links in net %s cluster", a_net->pub.name);
+        return -2;     // No links in cluster
+    }
+    l_net_pvt->sync_context.cur_chain = a_net->pub.chains;
+    if (!l_net_pvt->sync_context.cur_chain) {
+        log_it(L_ERROR, "No chains in net %s", a_net->pub.name);
+        return -3;
+    }
+    dap_stream_ch_add_notifier(&l_net_pvt->sync_context.current_link, DAP_CHAIN_CH_ID,
+                                DAP_STREAM_PKT_DIR_IN, s_ch_in_pkt_callback, a_net);
+    dap_stream_ch_add_notifier(&l_net_pvt->sync_context.current_link, DAP_CHAIN_CH_ID,
+                                DAP_STREAM_PKT_DIR_OUT, s_ch_out_pkt_callback, a_net);
+    dap_chain_t *l_chain = NULL;
+    DL_FOREACH(a_net->pub.chains, l_chain) {
+        l_chain->state = CHAIN_SYNC_STATE_IDLE;
+    }
+    l_net_pvt->sync_context.stage_last_activity = dap_time_now();
+    return 0;
+}
+
+static dap_chain_t *s_switch_sync_chain(dap_chain_net_t *a_net)
+{
+// sanity check
+    dap_return_val_if_pass(!a_net || !PVT(a_net), NULL);
+    dap_chain_net_pvt_t *l_net_pvt = PVT(a_net);
+// func work
+    dap_chain_t *l_curr_chain = NULL;
+    for (l_curr_chain = a_net->pub.chains; l_curr_chain && l_curr_chain->state == CHAIN_SYNC_STATE_SYNCED; l_curr_chain = l_curr_chain->next) {
+        // find last not synced chain
+    }
+    l_net_pvt->sync_context.cur_chain = l_curr_chain;
+    if (l_curr_chain) {
+        log_it(L_DEBUG, "Go to chain \"%s\" for net %s", l_curr_chain->name, l_curr_chain->net_name);
+        return l_curr_chain;
+    }
+    log_it(L_DEBUG, "Go to next chain: <NULL>");
+    if (l_net_pvt->state_target != NET_STATE_ONLINE) {
+        dap_chain_net_state_go_to(a_net, NET_STATE_OFFLINE);
+        return NULL;
+    }
+    dap_chain_net_state_t l_prev_state = l_net_pvt->state;
+    l_net_pvt->state = NET_STATE_ONLINE;
+    s_net_states_proc(a_net);
+    if(l_prev_state == NET_STATE_SYNC_CHAINS)
+        dap_leger_load_end(a_net->pub.ledger);
+    return NULL;
+}
+
+static dap_chain_sync_state_t s_sync_context_state_forming(dap_chain_t *a_chains)
+{
+    dap_chain_sync_state_t l_ret = CHAIN_SYNC_STATE_SYNCED;
+    dap_chain_t *l_chain = NULL;
+    DL_FOREACH(a_chains, l_chain) {
+        l_ret = dap_max(l_ret, l_chain->state);
+    }
+    return l_ret;
+}
+
+static void s_sync_timer_callback(void *a_arg)
+{
+    dap_chain_net_t *l_net = a_arg;
+    dap_chain_net_pvt_t *l_net_pvt = PVT(l_net);
+    if (l_net_pvt->state_target == NET_STATE_OFFLINE) // if offline no need sync
+        return;
+    l_net_pvt->sync_context.state = s_sync_context_state_forming(l_net->pub.chains);
+    if ( // check if need restart sync chains
+        l_net_pvt->sync_context.state == CHAIN_SYNC_STATE_ERROR ||
+        dap_time_now() - l_net_pvt->sync_context.stage_last_activity > l_net_pvt->sync_context.sync_idle_time
+    ) {
+        if (s_restart_sync_chains(l_net)) {
+            log_it(L_INFO, "Can't start sync chains in net %s, wait seccond attempt", l_net->pub.name);
+            return;
+        }
+    } else if (l_net_pvt->state == NET_STATE_ONLINE && l_net_pvt->sync_context.state == CHAIN_SYNC_STATE_SYNCED) {
+        return;
+    }
+    if (!s_switch_sync_chain(l_net)) {  // return if all chans synced
+        log_it(L_DEBUG, "All chains in net %s synced, no need new sync request", l_net->pub.name);
+        return;
+    }
+    if (l_net_pvt->sync_context.cur_chain->state == CHAIN_SYNC_STATE_WAITING) {
+        return;
+    }
+    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
+        log_it(L_DEBUG, "Chain %s in net %s will sync from gdb", l_net_pvt->sync_context.cur_chain->name, l_net->pub.name);
+        l_net_pvt->sync_context.cur_chain->state = CHAIN_SYNC_STATE_SYNCED;
+        return;
+    }
+
+    l_net_pvt->sync_context.cur_cell = l_net_pvt->sync_context.cur_chain->cells;
+    l_net_pvt->sync_context.cur_chain->state = CHAIN_SYNC_STATE_WAITING;
+    dap_chain_ch_sync_request_t l_request = {};
+    uint64_t l_last_num = l_request.num_from;
+    if (!dap_chain_get_atom_last_hash_num(l_net_pvt->sync_context.cur_chain,
+                                            l_net_pvt->sync_context.cur_cell
+                                            ? l_net_pvt->sync_context.cur_cell->id
+                                            : c_dap_chain_cell_id_null,
+                                            &l_request.hash_from,
+                                            &l_last_num)) {
+        log_it(L_ERROR, "Can't get last atom hash and number for chain %s with net %s", l_net_pvt->sync_context.cur_chain->name,
+                                                                                        l_net->pub.name);
+        return;
+    }
+
+    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, "%s", c_error_memory_alloc);
+        return;
+    }
+    log_it(L_INFO, "Start synchronization process with " NODE_ADDR_FP_STR
+                    " for net %s and chain %s, last hash %s, last num %" DAP_UINT64_FORMAT_U,
+                                                    NODE_ADDR_FP_ARGS_S(l_net_pvt->sync_context.current_link),
+                                                    l_net->pub.name, l_net_pvt->sync_context.cur_chain->name,
+                                                    dap_hash_fast_to_str_static(&l_request.hash_from), l_last_num);
+    dap_stream_ch_pkt_send_by_addr(&l_net_pvt->sync_context.current_link, DAP_CHAIN_CH_ID,
+                                    DAP_CHAIN_CH_PKT_TYPE_CHAIN_REQ, l_chain_pkt,
+                                    dap_chain_ch_pkt_get_size(l_chain_pkt));
+    l_net_pvt->sync_context.requested_atom_hash = l_request.hash_from;
+    l_net_pvt->sync_context.requested_atom_num = l_last_num;
+    DAP_DELETE(l_chain_pkt);
+}
+
+/**
+ * @brief s_net_states_proc
+ * @param l_net
+ */
+static bool s_net_states_proc(void *a_arg)
+{
+    bool l_repeat_after_exit = false; // If true - repeat on next iteration of proc thread loop
+    dap_chain_net_t *l_net = (dap_chain_net_t *) a_arg;
+    assert(l_net);
+    dap_chain_net_pvt_t *l_net_pvt = PVT(l_net);
+    assert(l_net_pvt);
+    if (l_net_pvt->state_target == NET_STATE_OFFLINE) {
+        if(l_net_pvt->state == NET_STATE_SYNC_CHAINS)
+            dap_leger_load_end(l_net->pub.ledger);
+        l_net_pvt->state = NET_STATE_OFFLINE;
+    }
+
+    switch ((dap_chain_net_state_t)l_net_pvt->state) {
+        // State OFFLINE where we don't do anything
+        case NET_STATE_OFFLINE: {
+            log_it(L_NOTICE,"%s.state: %s", l_net->pub.name, c_net_states[l_net_pvt->state]);
+            // delete all links
+            if ( l_net_pvt->state_target != NET_STATE_OFFLINE ){
+                l_net_pvt->state = NET_STATE_LINKS_PREPARE;
+                l_repeat_after_exit = true;
+            }
+        } break;
+
+        case NET_STATE_LINKS_PREPARE:
+        case NET_STATE_LINKS_CONNECTING:
+        case NET_STATE_LINKS_ESTABLISHED:
+        case NET_STATE_SYNC_CHAINS:
+        case NET_STATE_ONLINE:
+            log_it(L_INFO,"%s.state: %s", l_net->pub.name, c_net_states[l_net_pvt->state]);
+            break;
+        default:
+            log_it(L_DEBUG, "Unprocessed state");
+    }
+    s_net_states_notify(l_net);
+    return l_repeat_after_exit;
+}
+
+/**
+ * @brief set current network state to F_DAP_CHAIN_NET_GO_SYNC
+ *
+ * @param a_net dap_chain_net_t network object
+ * @param a_new_state dap_chain_net_state_t new network state
+ * @return int
+ */
+int dap_chain_net_state_go_to(dap_chain_net_t *a_net, dap_chain_net_state_t a_new_state)
+{
+    if (PVT(a_net)->load_mode) {
+        log_it(L_ERROR, "Can't change state of loading network '%s'", a_net->pub.name);
+        return -1;
+    }
+    if (PVT(a_net)->state_target == a_new_state) {
+        log_it(L_NOTICE, "Network %s already %s state %s", a_net->pub.name,
+                                PVT(a_net)->state == a_new_state ? "have" : "going to", dap_chain_net_state_to_str(a_new_state));
+        return 0;
+    }
+    //PVT(a_net)->flags |= F_DAP_CHAIN_NET_SYNC_FROM_ZERO;  // TODO set this flag according to -mode argument from command line
+    PVT(a_net)->state_target = a_new_state;
+    if (a_new_state == NET_STATE_OFFLINE) {
+        char l_err_str[] = "ERROR_NET_IS_OFFLINE";
+        size_t l_error_size = sizeof(dap_stream_ch_chain_net_pkt_t) + sizeof(l_err_str);
+        dap_stream_ch_chain_net_pkt_t *l_error = DAP_NEW_STACK_SIZE(dap_stream_ch_chain_net_pkt_t, l_error_size);
+        l_error->hdr.version = DAP_STREAM_CH_CHAIN_NET_PKT_VERSION;
+        l_error->hdr.net_id = a_net->pub.id;
+        l_error->hdr.data_size = sizeof(l_err_str);
+        memcpy(l_error->data, l_err_str, sizeof(l_err_str));
+        dap_cluster_broadcast(PVT(a_net)->nodes_cluster->links_cluster, DAP_STREAM_CH_CHAIN_NET_ID,
+                              DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_ERROR, l_error, l_error_size, NULL, 0);
+        dap_link_manager_set_net_condition(a_net->pub.id.uint64, false);
+        dap_chain_esbocs_stop_timer(a_net->pub.id);
+    } else if (PVT(a_net)->state == NET_STATE_OFFLINE) {
+        dap_link_manager_set_net_condition(a_net->pub.id.uint64, true);
+        for (uint16_t i = 0; i < PVT(a_net)->permanent_links_count; ++i) {
+            dap_link_info_t *l_permalink_info = PVT(a_net)->permanent_links[i];
+            if (dap_chain_net_link_add(a_net, &l_permalink_info->node_addr, l_permalink_info->uplink_addr, l_permalink_info->uplink_port)) {
+                log_it(L_ERROR, "Can't create permanent link to addr " NODE_ADDR_FP_STR, NODE_ADDR_FP_ARGS_S(l_permalink_info->node_addr));
+                continue;
+            }
+            PVT(a_net)->state = NET_STATE_LINKS_CONNECTING;
+        }
+        if (a_new_state == NET_STATE_ONLINE) {
+            dap_chain_esbocs_start_timer(a_net->pub.id);
+            PVT(a_net)->sync_context.current_link.uint64 = 0;
+            PVT(a_net)->sync_context.cur_chain = NULL;
+            PVT(a_net)->sync_context.cur_cell = NULL;
+        }
+    }
+    return dap_proc_thread_callback_add(NULL, s_net_states_proc, a_net);
+}
+
+DAP_INLINE dap_chain_net_state_t dap_chain_net_get_target_state(dap_chain_net_t *a_net)
+{
+    return PVT(a_net)->state_target;
+}
+
+/*------------------------------------State machine block end---------------------------------*/
\ 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 616e9558aadd0334dd93347c079ea3752bd3c8c8..c96ccaf73e8625175509fc78fc8e77fa90a68d44 100644
--- a/modules/net/dap_chain_net_decree.c
+++ b/modules/net/dap_chain_net_decree.c
@@ -445,15 +445,23 @@ static int s_common_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain
                 break;
             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:
+        case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_INVALIDATE: {
             if (dap_chain_datum_decree_get_stake_signing_addr(a_decree, &l_addr)){
                 log_it(L_WARNING,"Can't get signing address from decree.");
                 return -105;
             }
+
+            uint16_t l_current_count = dap_chain_net_srv_stake_get_total_keys(a_net->pub.id, NULL);
+            uint16_t l_min_count = dap_chain_esbocs_get_min_validators_count(a_net->pub.id);
+            if (l_current_count == l_min_count) {
+                log_it(L_WARNING, "Can't invalidate validator cause min validators count %hu will become less than total count for net %s",
+                                                                                l_current_count, a_net->pub.name);
+                return -116;
+            }
             if (!a_apply)
                 break;
             dap_chain_net_srv_stake_key_invalidate(&l_addr);
-            break;
+        } break;
         case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_MIN_VALUE:
             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.");
@@ -463,7 +471,7 @@ static int s_common_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain
                 break;
             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:
+        case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_MIN_VALIDATORS_COUNT: {
             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;
@@ -477,10 +485,17 @@ static int s_common_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain
                 log_it(L_WARNING, "Can't apply this decree to specified chain");
                 return -115;
             }
+            uint16_t l_decree_count = (uint16_t)dap_chain_uint256_to(l_value);
+            uint16_t l_current_count = dap_chain_net_srv_stake_get_total_keys(a_net->pub.id, NULL);
+            if (l_decree_count > l_current_count) {
+                log_it(L_WARNING, "Minimum validators count by decree %hu is greater than total validators count %hu in network %s",
+                                                                            l_decree_count, l_current_count, a_net->pub.name);
+                return -116;
+            }
             if (!a_apply)
                 break;
-            dap_chain_esbocs_set_min_validators_count(l_chain, (uint16_t)dap_chain_uint256_to(l_value));
-            break;
+            dap_chain_esbocs_set_min_validators_count(l_chain, l_decree_count);
+        } 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.");
diff --git a/modules/net/include/dap_chain_ledger.h b/modules/net/include/dap_chain_ledger.h
index 2993133a1dd253fb7e99d9e1a8f1ac5959d1568b..b7e2418cf9a8f599215455b7aa07f4e667af957e 100644
--- a/modules/net/include/dap_chain_ledger.h
+++ b/modules/net/include/dap_chain_ledger.h
@@ -89,6 +89,7 @@ typedef enum dap_ledger_check_error {
     DAP_LEDGER_TX_CHECK_UNEXPECTED_TOKENIZED_OUT,
     DAP_LEDGER_TX_CHECK_NOT_ENOUGH_FEE,
     DAP_LEDGER_TX_CHECK_NOT_ENOUGH_TAX,
+    DAP_LEDGER_TX_CHECK_FOR_REMOVING_CANT_FIND_TX,
     /* Emisssion check return codes */
     DAP_LEDGER_EMISSION_CHECK_VALUE_EXCEEDS_CURRENT_SUPPLY,
     DAP_LEDGER_EMISSION_CHECK_LEGACY_FORBIDDEN,
@@ -145,6 +146,7 @@ DAP_STATIC_INLINE const char *dap_ledger_check_error_str(dap_ledger_check_error_
     case DAP_LEDGER_TX_CHECK_UNEXPECTED_TOKENIZED_OUT: return "Tokenized out is forbidden for single-channel trandactions";
     case DAP_LEDGER_TX_CHECK_NOT_ENOUGH_FEE: return "Not enough network fee for transaction processing";
     case DAP_LEDGER_TX_CHECK_NOT_ENOUGH_TAX: return "Not enough sovereign tax provided with current transaction";
+    case DAP_LEDGER_TX_CHECK_FOR_REMOVING_CANT_FIND_TX: return "Can't find tx in ledger for removing.";
     /* Emisssion check return codes */
     case DAP_LEDGER_EMISSION_CHECK_VALUE_EXCEEDS_CURRENT_SUPPLY: return "Value of emission execeeds current token supply";
     case DAP_LEDGER_EMISSION_CHECK_LEGACY_FORBIDDEN: return "Legacy type of emissions are present for old chains comliance only";
diff --git a/modules/net/include/dap_chain_net.h b/modules/net/include/dap_chain_net.h
index 720f6cb5f4c9be689c1ba86943b2fc6227b16198..904ea35a28d734a9b545c4aa082e4f6dd1292c26 100644
--- a/modules/net/include/dap_chain_net.h
+++ b/modules/net/include/dap_chain_net.h
@@ -101,7 +101,6 @@ void dap_chain_net_try_online_all();
 
 int dap_chain_net_state_go_to(dap_chain_net_t * a_net, dap_chain_net_state_t a_new_state);
 dap_chain_net_state_t dap_chain_net_get_target_state(dap_chain_net_t *a_net);
-void dap_chain_net_set_state ( dap_chain_net_t * l_net, dap_chain_net_state_t a_state);
 dap_chain_net_state_t dap_chain_net_get_state ( dap_chain_net_t * l_net);
 
 inline static int dap_chain_net_start(dap_chain_net_t * a_net){ return dap_chain_net_state_go_to(a_net,NET_STATE_ONLINE); }
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 494ae6cd9eab56720468c56ea16bdb808b801a69..2efa8490bfb650e3268f9e8e8e4595c6a79d508c 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
@@ -505,13 +505,17 @@ int dap_chain_net_srv_stake_mark_validator_active(dap_chain_addr_t *a_signing_ad
     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, 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
+    dap_chain_net_srv_stake_item_t *l_stake = NULL, *l_tmp;
+    if (!dap_hash_fast_is_blank(&a_signing_addr->data.hash_fast)) {
+        // Mark a single validator
+        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 isn't delegated for this network
+            return -2;
         l_stake->is_active = a_on_off;
-        return 0;
-    }
-    return -2;
+    } else // Mark all validators
+        HASH_ITER(hh, l_srv_stake->itemlist, l_stake, l_tmp)
+            l_stake->is_active = a_on_off;
+    return 0;
 }
 
 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)
@@ -2721,7 +2725,7 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, void **a_str_reply)
             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");
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'max_weight' requires parameter -net");
                 return -3;
             }
             dap_chain_net_t *l_net = dap_chain_net_by_name(l_net_str);
@@ -2738,7 +2742,7 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, void **a_str_reply)
             }
             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");
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'max_weight' requires parameter -poa_cert");
                 return -3;
             }
             dap_cert_t *l_poa_cert = dap_cert_find_by_name(l_cert_str);
@@ -2753,10 +2757,10 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, void **a_str_reply)
 
             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");
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'max_weight' requires parameter -percent");
                 return -9;
             }
-            uint256_t l_value = dap_chain_balance_scan(l_value_str);
+            uint256_t l_value = dap_chain_coins_to_balance(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;
@@ -2944,7 +2948,8 @@ dap_chain_net_srv_stake_item_t *dap_chain_net_srv_stake_check_pkey_hash(dap_chai
     return NULL;
 }
 
-size_t dap_chain_net_srv_stake_get_total_keys(dap_chain_net_id_t a_net_id, size_t *a_in_active_count){
+size_t dap_chain_net_srv_stake_get_total_keys(dap_chain_net_id_t a_net_id, size_t *a_in_active_count)
+{
     dap_chain_net_srv_stake_t *l_stake_rec = s_srv_stake_by_net_id(a_net_id);
     if (!l_stake_rec)
         return 0;
diff --git a/modules/service/voting/dap_chain_net_srv_voting.c b/modules/service/voting/dap_chain_net_srv_voting.c
index 84b2689868d76f591cbbc8a314f57e4d8f11ce93..7583bc2f1bd431cdeb18f5731eba9e8d42dd6b71 100644
--- a/modules/service/voting/dap_chain_net_srv_voting.c
+++ b/modules/service/voting/dap_chain_net_srv_voting.c
@@ -671,7 +671,7 @@ static int s_cli_voting(int a_argc, char **a_argv, void **a_str_reply)
         dap_time_t l_time_expire = 0;
         if (l_voting_expire_str)
             l_time_expire = dap_time_from_str_rfc822(l_voting_expire_str);
-        if(!l_time_expire){
+        if(l_voting_expire_str && !l_time_expire){
             dap_cli_server_cmd_set_reply_text(a_str_reply, "Wrong time format. -expire parameter must be in format \"Day Month Year HH:MM:SS Timezone\" e.g. \"19 August 2024 22:00:00 +00\"");
             return -104;
         }
diff --git a/modules/type/blocks/dap_chain_cs_blocks.c b/modules/type/blocks/dap_chain_cs_blocks.c
index e23d1a1e11164fa471818b7ba42bf1fe11c56a45..295b2e4b287ef4e73df3a1da72309ec2780da6e0 100644
--- a/modules/type/blocks/dap_chain_cs_blocks.c
+++ b/modules/type/blocks/dap_chain_cs_blocks.c
@@ -1758,8 +1758,7 @@ static dap_chain_atom_verify_res_t s_callback_atom_add(dap_chain_t * a_chain, da
         }
         debug_if(s_debug_more, L_DEBUG, "... new block %s", l_block_cache->block_hash_str);
         dap_chain_block_cache_t *l_prev_bcache = NULL, *l_tmp = NULL;
-        pthread_rwlock_wrlock(& PVT(l_blocks)->rwlock);
-        log_it(L_INFO, "New fork. Previous block hash %s, current block hash %s", dap_chain_hash_fast_to_str_static(&l_block_prev_hash), 
+        pthread_rwlock_wrlock(& PVT(l_blocks)->rwlock);        log_it(L_INFO, "New fork. Previous block hash %s, current block hash %s", dap_chain_hash_fast_to_str_static(&l_block_prev_hash), 
                                                                                     l_block_cache->block_hash_str);
         HASH_FIND(hh, PVT(l_blocks)->blocks, &l_block_prev_hash, sizeof(dap_hash_fast_t), l_prev_bcache);
         if (l_prev_bcache){