diff --git a/dap-sdk b/dap-sdk
index e15ca735db71aa657f357821bf0e9d19346a9ae2..e85a4e785cd64395685ecbb9df24830a1ccb4dcf 160000
--- a/dap-sdk
+++ b/dap-sdk
@@ -1 +1 @@
-Subproject commit e15ca735db71aa657f357821bf0e9d19346a9ae2
+Subproject commit e85a4e785cd64395685ecbb9df24830a1ccb4dcf
diff --git a/modules/chain/dap_chain.c b/modules/chain/dap_chain.c
index 9bde364796bc7f4b3d57c58316c7afaa8a2a62d2..20b2e15e7d3e447ace60cd902ea44626aa7be6f4 100644
--- a/modules/chain/dap_chain.c
+++ b/modules/chain/dap_chain.c
@@ -83,11 +83,11 @@ int dap_chain_init(void)
  */
 void dap_chain_deinit(void)
 {
-    dap_chain_item_t * l_item = NULL, *l_tmp = NULL;
+    /*dap_chain_item_t * l_item = NULL, *l_tmp = NULL;
     HASH_ITER(hh, s_chain_items, l_item, l_tmp) {
           dap_chain_delete(l_item->chain);
           DAP_DELETE(l_item);
-    }
+    }*/ // TODO!
     dap_chain_srv_deinit();
 }
 
@@ -144,12 +144,6 @@ void dap_chain_set_cs_type(dap_chain_t *a_chain, const char *a_cs_type)
     DAP_CHAIN_PVT(a_chain)->cs_type = dap_strdup(a_cs_type);
 }
 
-int dap_chain_purge(dap_chain_t *a_chain)
-{
-    int ret = dap_chain_cs_class_purge(a_chain);
-    return ret + dap_chain_cs_purge(a_chain);
-}
-
 /**
  * @brief
  * delete dap chain object
@@ -216,6 +210,7 @@ dap_chain_atom_ptr_t dap_chain_get_atom_by_hash(dap_chain_t * a_chain, dap_chain
  */
 dap_chain_t * dap_chain_find_by_id(dap_chain_net_id_t a_chain_net_id,dap_chain_id_t a_chain_id)
 {
+    // TODO! Reconsider lock mechanics
     dap_chain_item_id_t l_chain_item_id = {
         .id = a_chain_id,
         .net_id = a_chain_net_id,
@@ -385,10 +380,11 @@ dap_chain_t *dap_chain_load_from_cfg(const char *a_chain_net_name, dap_chain_net
         if (!dap_dir_test(DAP_CHAIN_PVT(l_chain)->file_storage_dir))
             dap_mkdir_with_parents(DAP_CHAIN_PVT(l_chain)->file_storage_dir);
     } else
-        log_it (L_INFO, "Not set file storage path, will not stored in files");
+        log_it (L_INFO, "Not set file storage path, will not be stored in files"); // TODO
 
-    if (!l_chain->cells)
-        dap_chain_cell_create_fill( l_chain, (dap_chain_cell_id_t){ .uint64 = 0 } );
+    /*if (!l_chain->cells)
+        dap_chain_cell_create_fill( l_chain, (dap_chain_cell_id_t){ .uint64 = 0 } );*/
+    
     l_chain->config = a_cfg;
     l_chain->load_priority = dap_config_get_item_uint16_default(a_cfg, "chain", "load_priority", 100);
 
@@ -490,26 +486,8 @@ const char *dap_chain_get_cs_type(dap_chain_t *l_chain)
     return (const char *)DAP_CHAIN_PVT(l_chain)->cs_name;
 }
 
-/**
- * @brief dap_chain_save_all
- * @param l_chain
- * @return
- */
-int dap_chain_save_all(dap_chain_t *l_chain)
-{
-    int l_ret = 0;
-    pthread_rwlock_rdlock(&l_chain->cell_rwlock);
-    dap_chain_cell_t *l_item = NULL, *l_item_tmp = NULL;
-    HASH_ITER(hh,l_chain->cells,l_item,l_item_tmp){
-        if(dap_chain_cell_file_update(l_item) <= 0)
-            l_ret++;
-    }
-    pthread_rwlock_unlock(&l_chain->cell_rwlock);
-    return l_ret;
-}
-
 //send chain load_progress data to notify socket
-bool download_notify_callback(dap_chain_t* a_chain) {
+static bool s_load_notify_callback(dap_chain_t* a_chain) {
     json_object* l_chain_info = json_object_new_object();
     json_object_object_add(l_chain_info, "class", json_object_new_string("chain_init"));
     json_object_object_add(l_chain_info, "net", json_object_new_string(a_chain->net_name));
@@ -529,56 +507,47 @@ bool download_notify_callback(dap_chain_t* a_chain) {
  */
 int dap_chain_load_all(dap_chain_t *a_chain)
 {
-    int l_ret = 0;
-    if (!a_chain)
-        return -2;
+    dap_return_val_if_fail(a_chain, -2);
     if (a_chain->callback_load_from_gdb) {
         a_chain->is_mapped = false;
         a_chain->callback_load_from_gdb(a_chain);
         return 0;
     }
     char *l_storage_dir = DAP_CHAIN_PVT(a_chain)->file_storage_dir;
-    if (!l_storage_dir)
-        return 0;
+    dap_return_val_if_fail_err(l_storage_dir, 0, "No path set for chains files in net %s", a_chain->net_name); // TODO: light mode?
+
     DIR *l_dir = opendir(l_storage_dir);
-    if (!l_dir) {
-        log_it(L_ERROR, "Cannot open directory %s", DAP_CHAIN_PVT(a_chain)->file_storage_dir);
-        return -3;
-    }
-    for (struct dirent *l_dir_entry = readdir(l_dir); l_dir_entry != NULL; l_dir_entry = readdir(l_dir)) {
-        const char * l_filename = l_dir_entry->d_name;
-        const char l_suffix[] = ".dchaincell";
-        size_t l_suffix_len = strlen(l_suffix);
-        if (!strncmp(l_filename + strlen(l_filename) - l_suffix_len, l_suffix, l_suffix_len)) {
-            uint64_t l_cell_id_uint64 = 0;
-            sscanf(l_filename, "%"DAP_UINT64_FORMAT_x".dchaincell", &l_cell_id_uint64);
-            dap_chain_cell_t *l_cell = dap_chain_cell_create_fill(a_chain, (dap_chain_cell_id_t){ .uint64 = l_cell_id_uint64 });
-            dap_timerfd_t* l_download_notify_timer = dap_timerfd_start(5000, (dap_timerfd_callback_t)download_notify_callback, a_chain);
-            l_ret += dap_chain_cell_load(a_chain, l_cell);
-            if ( DAP_CHAIN_PVT(a_chain)->need_reorder ) {
-#ifdef DAP_OS_WINDOWS
-                strcat(l_cell->file_storage_path, ".new");
-                if (remove(l_cell->file_storage_path) == -1) {
-                    log_it(L_ERROR, "File %s doesn't exist", l_cell->file_storage_path);
-                }
-                *(l_cell->file_storage_path + strlen(l_cell->file_storage_path) - 4) = '\0';
-#else
-                const char *l_filename_backup = dap_strdup_printf("%s.unsorted", l_cell->file_storage_path);
-                if (remove(l_filename_backup) == -1) {
-                    log_it(L_ERROR, "File %s doesn't exist", l_filename_backup);
-                }
-                if (rename(l_cell->file_storage_path, l_filename_backup)) {
-                    log_it(L_ERROR, "Couldn't rename %s to %s", l_cell->file_storage_path, l_filename_backup);
-                }
-                DAP_DELETE(l_filename_backup);
-#endif
-            }
-            dap_timerfd_delete(l_download_notify_timer->worker, l_download_notify_timer->esocket_uuid);
-            download_notify_callback(a_chain);
+    dap_return_val_if_fail_err(l_dir, -3, "Cannot open directory %s, error %d: \"%s\"",
+                                          DAP_CHAIN_PVT(a_chain)->file_storage_dir, errno, dap_strerror(errno));
+    int l_err = -1;
+    const char l_suffix[] = ".dchaincell", *l_filename;
+    struct dirent *l_dir_entry = NULL;
+    dap_time_t l_ts_start = dap_time_now();
+    while (( l_dir_entry = readdir(l_dir) ) && !l_err ) {
+        l_filename = l_dir_entry->d_name;
+        size_t l_namelen = strlen(l_filename);
+        if ( l_namelen >= sizeof(l_suffix) && !strncmp(l_filename + l_namelen - sizeof(l_suffix) - 1, l_suffix, sizeof(l_suffix) - 1) ) {
+            dap_timerfd_t* l_load_notify_timer = dap_timerfd_start(5000, (dap_timerfd_callback_t)s_load_notify_callback, a_chain);
+            l_err = dap_chain_cell_open(a_chain, l_filename, 'a');
+            dap_timerfd_delete(l_load_notify_timer->worker, l_load_notify_timer->esocket_uuid);
+            s_load_notify_callback(a_chain);
         }
     }
     closedir(l_dir);
-    return l_ret;
+    
+    switch (l_err) {
+    case 0:
+        log_it(L_INFO, "Loaded all chain \"%s : %s\" cells in %lf s",
+                        a_chain->net_name, a_chain->name, difftime((time_t)dap_time_now(), l_ts_start));
+        break;
+    case -1:
+        if (!( l_err = dap_chain_cell_open(a_chain, "0.dchaincell", 'w') ))
+            log_it(L_INFO, "Initialized chain \"%s : %s\" cell 0", a_chain->net_name, a_chain->name);
+        break;
+    default:
+        log_it(L_ERROR, "Chain \"%s : %s\" cell was not loaded, error %d", a_chain->net_name, a_chain->name, l_err);
+    }
+    return l_err;
 }
 
 /**
@@ -809,17 +778,16 @@ static bool s_notify_datum_removed_on_thread(void *a_arg)
     return false;
 }
 
-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_chain_atom_save(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id,
+                            const uint8_t *a_atom, size_t a_atom_size,
+                            dap_hash_fast_t *a_new_atom_hash, char **a_atom_map)
 {
-    dap_return_val_if_fail(a_chain_cell && a_chain_cell->chain, -1);
-    dap_chain_t *l_chain = a_chain_cell->chain;
-
     if (a_new_atom_hash) { // Atom is new and need to be distributed for the net
-        dap_cluster_t *l_net_cluster = dap_cluster_find(dap_guuid_compose(l_chain->net_id.uint64, 0));
+        dap_cluster_t *l_net_cluster = dap_cluster_find(dap_guuid_compose(a_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, l_chain->id,
-                                                             a_chain_cell->id, a_atom, a_atom_size,
+            dap_chain_ch_pkt_t *l_pkt = dap_chain_ch_pkt_new(a_chain->net_id, a_chain->id,
+                                                             a_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);
@@ -827,7 +795,7 @@ ssize_t dap_chain_atom_save(dap_chain_cell_t *a_chain_cell, const uint8_t *a_ato
             }
         }
     }
-    return dap_chain_cell_file_append(a_chain_cell, a_atom, a_atom_size);
+    return dap_chain_cell_file_append(a_chain, a_cell_id, a_atom, a_atom_size, a_atom_map);
 }
 
 /**
@@ -870,51 +838,43 @@ const char* dap_chain_get_path(dap_chain_t *a_chain)
     return DAP_CHAIN_PVT(a_chain)->file_storage_dir;
 }
 
-void dap_chain_atom_notify(dap_chain_cell_t *a_chain_cell, dap_hash_fast_t *a_hash, const uint8_t *a_atom, size_t a_atom_size) {
+void dap_chain_atom_notify(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id, dap_hash_fast_t *a_hash, const uint8_t *a_atom, size_t a_atom_size) {
 #ifdef DAP_CHAIN_BLOCKS_TEST
     return;
 #endif
 
-    if ( !a_chain_cell->chain->atom_notifiers )
+    if ( !a_chain->atom_notifiers )
         return;
     dap_list_t *l_iter;
-    DL_FOREACH(a_chain_cell->chain->atom_notifiers, l_iter) {
+    DL_FOREACH(a_chain->atom_notifiers, l_iter) {
         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, "%s", c_error_memory_alloc);
-            continue;
-        }
+        struct chain_thread_notifier *l_arg = DAP_NEW_Z_RET_IF_FAIL(struct chain_thread_notifier);
         *l_arg = (struct chain_thread_notifier) {
             .callback = l_notifier->callback, .callback_arg = l_notifier->arg,
-            .chain = a_chain_cell->chain,     .cell_id = a_chain_cell->id,
+            .chain = a_chain,     .cell_id = a_cell_id,
             .hash = *a_hash,
-            .atom = a_chain_cell->chain->is_mapped ? (byte_t*)a_atom : DAP_DUP_SIZE((byte_t*)a_atom, a_atom_size),
+            .atom = a_chain->is_mapped ? (byte_t*)a_atom : DAP_DUP_SIZE((byte_t*)a_atom, a_atom_size),
             .atom_size = a_atom_size };
         dap_proc_thread_callback_add_pri(l_notifier->proc_thread, s_notify_atom_on_thread, l_arg, DAP_QUEUE_MSG_PRIORITY_LOW);
     }
 }
 
-void dap_chain_datum_notify(dap_chain_cell_t *a_chain_cell,  dap_hash_fast_t *a_hash, dap_hash_fast_t *a_atom_hash, const uint8_t *a_datum, size_t a_datum_size, int a_ret_code, uint32_t a_action, dap_chain_srv_uid_t a_uid) {
+void dap_chain_datum_notify(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id, dap_hash_fast_t *a_hash, dap_hash_fast_t *a_atom_hash, const uint8_t *a_datum, size_t a_datum_size, int a_ret_code, uint32_t a_action, dap_chain_srv_uid_t a_uid) {
 #ifdef DAP_CHAIN_BLOCKS_TEST
     return;
 #endif
 
-    if ( !a_chain_cell->chain->datum_notifiers )
+    if ( !a_chain->datum_notifiers )
         return;
     dap_list_t *l_iter;
-    DL_FOREACH(a_chain_cell->chain->datum_notifiers, l_iter) {
+    DL_FOREACH(a_chain->datum_notifiers, l_iter) {
         dap_chain_datum_notifier_t *l_notifier = (dap_chain_datum_notifier_t*)l_iter->data;
-        struct chain_thread_datum_notifier *l_arg = DAP_NEW_Z(struct chain_thread_datum_notifier);
-        if (!l_arg) {
-            log_it(L_CRITICAL, "%s", c_error_memory_alloc);
-            continue;
-        }
+        struct chain_thread_datum_notifier *l_arg = DAP_NEW_Z_RET_IF_FAIL(struct chain_thread_datum_notifier);
         *l_arg = (struct chain_thread_datum_notifier) {
             .callback = l_notifier->callback, .callback_arg = l_notifier->arg,
-            .chain = a_chain_cell->chain,     .cell_id = a_chain_cell->id,
+            .chain = a_chain,     .cell_id = a_cell_id,
             .hash = *a_hash,
-            .datum = a_chain_cell->chain->is_mapped ? (byte_t*)a_datum : DAP_DUP_SIZE((byte_t*)a_datum, a_datum_size),
+            .datum = a_chain->is_mapped ? (byte_t*)a_datum : DAP_DUP_SIZE((byte_t*)a_datum, a_datum_size),
             .datum_size = a_datum_size,
             .ret_code = a_ret_code,
             .action = a_action,
@@ -923,15 +883,15 @@ void dap_chain_datum_notify(dap_chain_cell_t *a_chain_cell,  dap_hash_fast_t *a_
     }
 }
 
-void dap_chain_datum_removed_notify(dap_chain_cell_t *a_chain_cell,  dap_hash_fast_t *a_hash) {
+void dap_chain_datum_removed_notify(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id, dap_hash_fast_t *a_hash) {
 #ifdef DAP_CHAIN_BLOCKS_TEST
     return;
 #endif
 
-    if ( !a_chain_cell->chain->datum_removed_notifiers )
+    if ( !a_chain->datum_removed_notifiers )
         return;
     dap_list_t *l_iter;
-    DL_FOREACH(a_chain_cell->chain->datum_removed_notifiers, l_iter) {
+    DL_FOREACH(a_chain->datum_removed_notifiers, l_iter) {
         dap_chain_datum_removed_notifier_t *l_notifier = (dap_chain_datum_removed_notifier_t*)l_iter->data;
         struct chain_thread_datum_removed_notifier *l_arg = DAP_NEW_Z(struct chain_thread_datum_removed_notifier);
         if (!l_arg) {
@@ -940,7 +900,7 @@ void dap_chain_datum_removed_notify(dap_chain_cell_t *a_chain_cell,  dap_hash_fa
         }
         *l_arg = (struct chain_thread_datum_removed_notifier) {
             .callback = l_notifier->callback, .callback_arg = l_notifier->arg,
-            .chain = a_chain_cell->chain,     .cell_id = a_chain_cell->id,
+            .chain = a_chain,     .cell_id = a_cell_id,
             .hash = *a_hash};
         dap_proc_thread_callback_add_pri(l_notifier->proc_thread, s_notify_datum_removed_on_thread, l_arg, DAP_QUEUE_MSG_PRIORITY_LOW);
     }
diff --git a/modules/chain/dap_chain_cell.c b/modules/chain/dap_chain_cell.c
index 1e9eb3e6efce5317beebb3682c199b85f4a389df..46236b6d1b623468f827c883bc7285deb309a230 100644
--- a/modules/chain/dap_chain_cell.c
+++ b/modules/chain/dap_chain_cell.c
@@ -42,6 +42,9 @@
 #define DAP_CHAIN_CELL_FILE_TYPE_RAW 0
 #define DAP_CHAIN_CELL_FILE_TYPE_COMPRESSED 1
 #define DAP_MAPPED_VOLUME_LIMIT ( 1 << 28 ) // 256 MB for now, may be should be configurable?
+
+#define CELL_FILE_EXT "dchaincell"
+
 /**
   * @struct dap_chain_cell_file_header
   */
@@ -55,6 +58,23 @@ typedef struct dap_chain_cell_file_header
     dap_chain_cell_id_t cell_id;
 } DAP_ALIGN_PACKED dap_chain_cell_file_header_t;
 
+typedef struct dap_chain_cell_mmap_volume {
+#ifdef DAP_OS_DARWIN
+    off_t offset;
+#endif
+    off_t size;
+    char *base;
+    struct dap_chain_cell_mmap_volume *prev, *next;
+} dap_chain_cell_mmap_volume_t;
+
+typedef struct dap_chain_cell_mmap_data {
+#ifdef DAP_OS_WINDOWS
+    HANDLE section;
+#endif
+    dap_chain_cell_mmap_volume_t *volume;
+    char *cursor;
+} dap_chain_cell_mmap_data_t;
+
 #ifdef DAP_OS_WINDOWS
 typedef NTSTATUS (*pfn_NtCreateSection)(
     OUT PHANDLE SectionHandle, IN ACCESS_MASK DesiredAccess,
@@ -103,298 +123,131 @@ int dap_chain_cell_init(void)
     }
     
 #endif
-    //s_cells_path = dap_config_get_item_str(g_config,"resources","cells_storage");
-    return  0;
+    return 0;
 }
 
 #ifndef DAP_OS_WINDOWS
-DAP_STATIC_INLINE void s_cell_reclaim_cur_volume(dap_chain_cell_t *a_cell) {
+DAP_STATIC_INLINE void s_cell_reclaim_cur_volume(dap_chain_cell_mmap_volume_t *a_vol) {
     if (
 #ifdef MADV_PAGEOUT
-    //madvise(a_cell->map, (size_t)(a_cell->map_end - a_cell->map), MADV_PAGEOUT) &&
+    //madvise(a_vol->base, a_vol->size, MADV_PAGEOUT) &&
 #endif
-    madvise(a_cell->map, (size_t)(a_cell->map_end - a_cell->map), MADV_DONTNEED) )
+    madvise(a_vol->base, a_vol->size, MADV_DONTNEED) )
         log_it(L_ERROR, "Unable to reclaim the previous volume, errno %d: \"%s\"", errno, dap_strerror(errno));
 }
 #endif
 
-DAP_STATIC_INLINE int s_cell_file_write_header(dap_chain_cell_t *a_cell)
-{
-    dap_chain_cell_file_header_t l_hdr = {
-        .signature      = DAP_CHAIN_CELL_FILE_SIGNATURE,
-        .version        = DAP_CHAIN_CELL_FILE_VERSION,
-        .type           = DAP_CHAIN_CELL_FILE_TYPE_RAW,
-        .chain_id       = a_cell->chain->id,
-        .chain_net_id   = a_cell->chain->net_id,
-        .cell_id        = a_cell->id
-    };
-    return fwrite(&l_hdr, sizeof(l_hdr), 1, a_cell->file_storage) ? fflush(a_cell->file_storage) : -1;
-}
-
-DAP_STATIC_INLINE int s_cell_map_new_volume(dap_chain_cell_t *a_cell, size_t a_fpos, bool a_load) {
+DAP_STATIC_INLINE int s_cell_map_new_volume(dap_chain_cell_t *a_cell, off_t a_fpos, bool a_load) {
 #ifdef DAP_OS_WINDOWS
-    HANDLE hSection = NULL;
     if ( !a_fpos ) {
-        //if (a_cell->map_range_bounds)
-        //    NtClose( (HANDLE)a_cell->map_range_bounds->data );
-        off_t l_ssize = !fseeko(a_cell->file_storage, 0, SEEK_END) ? ftello(a_cell->file_storage) : -1;
-        if (l_ssize < 0)
-            return log_it(L_ERROR, "Can't get chain size, error %d: \"%s\"", errno, dap_strerror(errno)), -1;
-        LARGE_INTEGER SectionSize = { 
-            .QuadPart = l_ssize 
-        };
-        
-        NTSTATUS err = pfnNtCreateSection(&hSection, SECTION_MAP_READ | SECTION_EXTEND_SIZE,
-                                          NULL, &SectionSize, PAGE_READWRITE, SEC_RESERVE, (HANDLE)_get_osfhandle(fileno(a_cell->file_storage)));
+        LARGE_INTEGER SectionSize = { .QuadPart = !fseeko(a_cell->file_storage, 0, SEEK_END) ? ftello(a_cell->file_storage) : -1 };
+        dap_return_val_if_pass_err(SectionSize.QuadPart < 0, -1, "Can't get chain size, error %d: \"%s\"", errno, dap_strerror(errno));
+        NTSTATUS err = pfnNtCreateSection( &a_cell->mapping->section, SECTION_MAP_READ | SECTION_EXTEND_SIZE,
+                                           NULL, &SectionSize, PAGE_READWRITE, SEC_RESERVE,
+                                           (HANDLE)_get_osfhandle(fileno(a_cell->file_storage)) );
         if ( !NT_SUCCESS(err) )
-            return log_it(L_ERROR, "NtCreateSection() failed, status %lx", err), -1;
-        a_cell->map_range_bounds = dap_list_append(a_cell->map_range_bounds, hSection);
+            return log_it(L_ERROR, "NtCreateSection() failed, status %lx: \"%s\"",
+                                   err, dap_str_ntstatus(err) ), -1;
     }
 #endif
-    size_t  l_map_size      = dap_page_roundup(DAP_MAPPED_VOLUME_LIMIT),
+    dap_chain_cell_mmap_volume_t *l_new_vol = DAP_NEW_Z(dap_chain_cell_mmap_volume_t);
+    l_new_vol->size = dap_page_roundup(DAP_MAPPED_VOLUME_LIMIT);
+    off_t l_volume_offset = a_fpos ?
 #ifdef DAP_OS_WINDOWS
-            l_volume_start  = a_fpos ? dap_64k_rounddown(a_fpos)    : 0,
+            dap_64k_rounddown(a_fpos)
 #else               
-            l_volume_start  = a_fpos ? dap_page_rounddown(a_fpos)   : 0,
-#endif                  
-            l_offset        = a_fpos - l_volume_start;
+            dap_page_rounddown(a_fpos)
+#endif
+            : 0,
+        l_offset = a_fpos - l_volume_offset;
 #ifdef DAP_OS_WINDOWS
-    hSection = (HANDLE)a_cell->map_range_bounds->data;
-    a_cell->map = NULL;
     int err = 0;
-    LARGE_INTEGER Offset = {
-        .QuadPart = l_volume_start
-    };
-    err = pfnNtMapViewOfSection(hSection, GetCurrentProcess(), (HANDLE)&a_cell->map, 0, 0, 
-                                &Offset, &l_map_size, ViewUnmap, MEM_RESERVE, PAGE_READONLY);
-    if ( !NT_SUCCESS(err) )
-        return NtClose(hSection), log_it(L_ERROR, "NtMapViewOfSection() failed, status %lx", err), -1;
+    LARGE_INTEGER Offset = { .QuadPart = l_volume_offset };
+    err = pfnNtMapViewOfSection(a_cell->mapping->section, GetCurrentProcess(), (HANDLE)&l_new_vol->base, 0, 0, 
+                                &Offset, &l_new_vol->size, ViewUnmap, MEM_RESERVE, PAGE_READONLY);
+    if ( !NT_SUCCESS(err) ) {
+        NtClose(a_cell->mapping->section);
+        log_it(L_ERROR, "NtMapViewOfSection() failed, status %lx: \"%s\"", err, dap_str_ntstatus(err) );
+        DAP_DELETE(l_new_vol);
+        return -1;
+    }
 #else
     if (a_load)
-        s_cell_reclaim_cur_volume(a_cell);
-    if (( a_cell->map = mmap(NULL, l_map_size, PROT_READ, MAP_PRIVATE,
-                             fileno(a_cell->file_storage), l_volume_start) ) == MAP_FAILED )
-        return log_it(L_ERROR, "Chain cell \"%s\" 0x%016"DAP_UINT64_FORMAT_X" cannot be mapped, errno %d",
-                                a_cell->file_storage_path, a_cell->id.uint64, errno), -1;
+        s_cell_reclaim_cur_volume(a_cell->mapping->volume);
+    l_new_vol->base = mmap( NULL, l_new_vol->size, PROT_READ, MAP_PRIVATE,
+                            fileno(a_cell->file_storage), l_volume_offset );
+    if ( l_new_vol->base == MAP_FAILED ) {
+        log_it(L_ERROR, "Chain cell \"%s\" 0x%016"DAP_UINT64_FORMAT_X" cannot be mapped, errno %d",
+                        a_cell->file_storage_path, a_cell->id.uint64, errno);
+        DAP_DELETE(l_new_vol);
+        return -1;
+    }
 #ifdef DAP_OS_DARWIN
-    a_cell->cur_vol_start = l_volume_start;
+    l_new_vol->offset = l_volume_offset;
 #endif
 #endif
-    a_cell->map_pos = a_cell->map + l_offset;
-    a_cell->map_range_bounds = dap_list_append(a_cell->map_range_bounds, a_cell->map);
-    a_cell->map_range_bounds = dap_list_append(a_cell->map_range_bounds, a_cell->map_end = a_cell->map + l_map_size);
+    a_cell->mapping->cursor = l_new_vol->base + l_offset;
 #ifndef DAP_OS_WINDOWS    
     if (a_load)
-        madvise(a_cell->map, l_map_size, MADV_SEQUENTIAL);
+        madvise(l_new_vol->base, l_new_vol->size, MADV_SEQUENTIAL);
 #endif
+    DL_PREPEND(a_cell->mapping->volume, l_new_vol);
     return 0;
 }
 
-/**
- * @brief dap_chain_cell_find_by_id
- * get dap_chain_cell_t object by cell (shard) id
- * @param a_chain dap_chain_t object
- * @param a_cell_id dap_chain_cell_id_t cell (shard) id
- * @return dap_chain_cell_t* 
- */
-dap_chain_cell_t * dap_chain_cell_find_by_id(dap_chain_t * a_chain, dap_chain_cell_id_t a_cell_id)
-{
-    if (!a_chain->cells)
-        return NULL;
-    dap_chain_cell_t *l_cell = NULL;
-    pthread_rwlock_rdlock(&a_chain->cell_rwlock);
-    HASH_FIND(hh, a_chain->cells, &a_cell_id, sizeof(dap_chain_cell_id_t), l_cell);
-    pthread_rwlock_unlock(&a_chain->cell_rwlock);
-    return l_cell;
-}
-
-/**
- * @brief 
- * a_cell_id if < 0 then not used
- * @param a_chain dap_chain_t object
- * @param a_cell_id dap_chain_cell_id_t cell (shard) id
- * @return dap_chain_cell_t* 
- */
-dap_chain_cell_t * dap_chain_cell_create_fill(dap_chain_t * a_chain, dap_chain_cell_id_t a_cell_id)
-{
-    dap_chain_cell_t * l_cell = NULL;
-    pthread_rwlock_wrlock(&a_chain->cell_rwlock);
-    HASH_FIND(hh, a_chain->cells, &a_cell_id, sizeof(dap_chain_cell_id_t), l_cell);
-    if (l_cell) {
-        pthread_rwlock_unlock(&a_chain->cell_rwlock);
-        return l_cell;
-    }
-    char file_storage_path[MAX_PATH];
-    snprintf(file_storage_path, MAX_PATH, "%s/%0"DAP_UINT64_FORMAT_x".dchaincell",
-             DAP_CHAIN_PVT(a_chain)->file_storage_dir, a_cell_id.uint64);
-    FILE *l_file = NULL;
-#define CLEANUP_AND_RET return ({ if (l_file) fclose(l_file); \
-    DAP_DELETE(l_cell); \
-    pthread_rwlock_unlock(&a_chain->cell_rwlock); \
-    NULL; })
-    if ( !(l_file = fopen(file_storage_path, "a+b")) ) {
-        log_it(L_ERROR, "Chain cell \"%s\" 0x%016"DAP_UINT64_FORMAT_X" cannot be opened, error %d",
-                        file_storage_path, a_cell_id.uint64, errno);
-        CLEANUP_AND_RET;
-    }
-    if ( !(l_cell = DAP_NEW_Z(dap_chain_cell_t)) )
-        CLEANUP_AND_RET;
-    *l_cell = (dap_chain_cell_t) {
-        .id             = a_cell_id,
-        .chain          = a_chain,
-        .file_storage   = l_file,
-        .storage_rwlock = PTHREAD_RWLOCK_INITIALIZER
-    };
-    off_t l_size = !fseeko(l_file, 0, SEEK_END) ? ftello(l_file) : -1;
-    if (l_size < 0)
-        CLEANUP_AND_RET;
-    else if ( (size_t)l_size < sizeof(dap_chain_cell_file_header_t) ) {
-        if ( l_size ) {
-            log_it(L_INFO, "Possibly corrupt cell storage 0x%016"DAP_UINT64_FORMAT_X" \"%s\", rewriting it",
-                            a_cell_id.uint64, file_storage_path);
-            l_file = freopen(file_storage_path, "w+b", l_file);
-        }
-        if ( s_cell_file_write_header(l_cell) < 0 ) {
-            log_it(L_ERROR, "Can't init file storage for cell 0x%016"DAP_UINT64_FORMAT_X" \"%s\", errno %d",
-                             a_cell_id.uint64, file_storage_path, errno);
-            CLEANUP_AND_RET;
-        }
-        log_it(L_NOTICE, "Initialized file storage for cell 0x%016"DAP_UINT64_FORMAT_X" \"%s\"",
-                          a_cell_id.uint64, file_storage_path);
-        fflush(l_file);
-    }
-
-    if ( a_chain->is_mapped && s_cell_map_new_volume(l_cell, 0, true) ) {
-        CLEANUP_AND_RET;
-    }
-#undef CLEANUP_AND_RET
-    memcpy(l_cell->file_storage_path, file_storage_path, sizeof(file_storage_path));
-    debug_if (s_debug_more && a_chain->is_mapped, L_DEBUG, "Mapped volume size is %lu", (size_t)(l_cell->map_end - l_cell->map));
-    HASH_ADD(hh, a_chain->cells, id, sizeof(dap_chain_cell_id_t), l_cell);
-    pthread_rwlock_unlock(&a_chain->cell_rwlock);
-    return l_cell;
-}
-
-/**
- * @brief
- * close a_cell->file_storage file object
- * @param a_cell dap_chain_cell_t object
- */
-void dap_chain_cell_close(dap_chain_cell_t *a_cell)
-{
-    if(!a_cell)
-        return;
+DAP_STATIC_INLINE int s_cell_close(dap_chain_cell_t *a_cell) {
+    //pthread_rwlock_wrlock(&a_cell->storage_rwlock);
     if(a_cell->file_storage) {
         fclose(a_cell->file_storage);
         a_cell->file_storage = NULL;
     }
     if (a_cell->chain->is_mapped) {
-        dap_list_t *l_iter = a_cell->map_range_bounds;
-#ifdef DAP_OS_WINDOWS
-        l_iter = l_iter->next;
-#endif
-        for (; l_iter; l_iter = l_iter->next) {
-            if (l_iter->next) {
-                debug_if(s_debug_more, L_DEBUG, "Unmap volume %p (%lu bytes)", l_iter->data, (size_t)(l_iter->next->data - l_iter->data));
+        a_cell->mapping->cursor = NULL;
+        int i = 0;
+        dap_chain_cell_mmap_volume_t *l_vol, *l_tmp;
+        DL_FOREACH_SAFE(a_cell->mapping->volume, l_vol, l_tmp) {
+            debug_if(s_debug_more, L_DEBUG, "Unmap volume #%d, %lu bytes", i++, l_vol->size);
 #ifdef DAP_OS_WINDOWS
-                pfnNtUnmapViewOfSection(GetCurrentProcess(), l_iter->data);
+            pfnNtUnmapViewOfSection(GetCurrentProcess(), l_vol->base);
 #else
-                munmap(l_iter->data, (size_t)(l_iter->next->data - l_iter->data));
+            munmap(l_vol->base, l_vol->size);
 #endif
-                l_iter = l_iter->next;
-            }
+            DL_DELETE(a_cell->mapping->volume, l_vol);
+            DAP_DELETE(l_vol);
         }
 #ifdef DAP_OS_WINDOWS
-        NtClose(a_cell->map_range_bounds->data);
+        NtClose(a_cell->mapping->section);
 #endif
-        dap_list_free(a_cell->map_range_bounds);
     }
-#ifdef DAP_OS_WINDOWS
-    char *l_new = strstr(a_cell->file_storage_path, ".new");
-    if (l_new) {
-        char *l_orig = dap_strdup(a_cell->file_storage_path);
-        *l_new = '\0';
-        remove(a_cell->file_storage_path);
-        rename(l_orig, a_cell->file_storage_path);
-        DAP_DELETE(l_orig);
-    }
-#endif
+    //pthread_rwlock_unlock(&a_cell->storage_rwlock);
+    //pthread_rwlock_destroy(&a_cell->storage_rwlock);
+    return 0;
 }
 
 /**
- * @brief 
- * free chain cell objects
+ * @brief
+ * close a_cell->file_storage file object
  * @param a_cell dap_chain_cell_t object
  */
-void dap_chain_cell_delete(dap_chain_cell_t *a_cell)
+void dap_chain_cell_close(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id)
 {
-    if(!a_cell)
-        return;
-    dap_chain_cell_close(a_cell);
-    if (a_cell->chain->cells) {
-        dap_chain_cell_t *l_cell = NULL;
-        dap_chain_cell_id_t l_cell_id = {
-            .uint64 = a_cell->id.uint64
-        };
-        pthread_rwlock_wrlock(&a_cell->chain->cell_rwlock);
-        HASH_FIND(hh, a_cell->chain->cells, &l_cell_id, sizeof(dap_chain_cell_id_t), l_cell);
-        if (l_cell)
-            HASH_DEL(a_cell->chain->cells, l_cell);
-        pthread_rwlock_unlock(&a_cell->chain->cell_rwlock);
-    }
-    a_cell->chain = NULL;
-    a_cell->file_storage_path[0] = '\0';
-    pthread_rwlock_destroy(&a_cell->storage_rwlock);
-    DAP_DELETE(a_cell);
-}
-
-void dap_chain_cell_delete_all_and_free_file(dap_chain_t *a_chain) {
-    if (!a_chain)
-        return;
-    pthread_rwlock_wrlock(&a_chain->cell_rwlock);
-    dap_chain_cell_t *l_cell, *l_tmp;
-    HASH_ITER(hh, a_chain->cells, l_cell, l_tmp) {
-        char *l_fsp = dap_strdup(l_cell->file_storage_path);
-        dap_chain_cell_id_t l_cell_id = l_cell->id;
-        dap_chain_cell_close(l_cell);
-
-        dap_chain_cell_t * l_cell_nh = DAP_NEW_Z(dap_chain_cell_t);
-        FILE *l_file = fopen(l_fsp, "w+b");
-        if ( !l_file ) {
-            log_it(L_ERROR, "Chain cell \"%s\" 0x%016"DAP_UINT64_FORMAT_X" cannot be opened, error %d",
-                   l_fsp, l_cell_id.uint64, errno);
-        }
-        *l_cell_nh = (dap_chain_cell_t) {
-                .id             = l_cell_id,
-                .chain          = a_chain,
-                .file_storage   = l_file
-        };
-        if ( s_cell_file_write_header(l_cell_nh) < 0 ) {
-            log_it(L_ERROR, "Can't init file storage for cell 0x%016"DAP_UINT64_FORMAT_X" \"%s\", errno %d",
-                   l_cell_id.uint64, l_fsp, errno);
-        } else {
-            log_it(L_NOTICE, "Reinitialized file storage for cell 0x%016"DAP_UINT64_FORMAT_X" \"%s\"",
-                   l_cell_id.uint64, l_fsp);
-        }
-        dap_chain_cell_close(l_cell_nh);
-
-        DAP_DELETE(l_fsp);
-        HASH_DEL(a_chain->cells, l_cell);
-        pthread_rwlock_destroy(&l_cell->storage_rwlock);
-        DAP_DELETE(l_cell);
-    }
-    pthread_rwlock_unlock(&a_chain->cell_rwlock);
+    dap_return_if_fail(a_chain);
+    dap_chain_cell_t *l_cell = dap_chain_cell_capture_by_id(a_chain, a_cell_id);
+    dap_return_if_fail_err(l_cell, "Cell 0x%016"DAP_UINT64_FORMAT_X" not found in chain \"%s : %s\"",
+                                    a_cell_id.uint64, a_chain->net_name, a_chain->name);
+    s_cell_close(l_cell);
+    HASH_DEL(a_chain->cells, l_cell);
+    dap_chain_cell_remit(l_cell);
+    DAP_DELETE(l_cell);
 }
 
-void dap_chain_cell_delete_all(dap_chain_t *a_chain) {
-    if (!a_chain)
-        return;
+void dap_chain_cell_close_all(dap_chain_t *a_chain) {
+    dap_return_if_fail(a_chain);
     pthread_rwlock_wrlock(&a_chain->cell_rwlock);
     dap_chain_cell_t *l_cell, *l_tmp;
     HASH_ITER(hh, a_chain->cells, l_cell, l_tmp) {
-        dap_chain_cell_close(l_cell);
+        s_cell_close(l_cell);
         HASH_DEL(a_chain->cells, l_cell);
-        pthread_rwlock_destroy(&l_cell->storage_rwlock);
         DAP_DELETE(l_cell);
     }
     pthread_rwlock_unlock(&a_chain->cell_rwlock);
@@ -407,172 +260,259 @@ void dap_chain_cell_delete_all(dap_chain_t *a_chain) {
  * @param a_cell_file_path contains name of chain, for example "0.dchaincell" 
  * @return
  */
-int dap_chain_cell_load(dap_chain_t *a_chain, dap_chain_cell_t *a_cell)
+DAP_STATIC_INLINE int s_cell_load_from_file(dap_chain_cell_t *a_cell)
 {
-    if (!a_cell)
-        return -1;
-    off_t l_full_size = !fseeko(a_cell->file_storage, 0, SEEK_END) ? ftello(a_cell->file_storage) : -1;
-    if (l_full_size < 0)
-        return log_it(L_ERROR, "Can't get chain size, error %d: \"%s\"", errno, dap_strerror(errno)), -1;
-    if ( l_full_size < (off_t)sizeof(dap_chain_cell_file_header_t) ) {
-        log_it(L_ERROR, "Chain cell \"%s\" is corrupt, create new file", a_cell->file_storage_path);
-        return -1;
-    }
-    dap_chain_cell_file_header_t *l_hdr = NULL;
-    if (a_chain->is_mapped) {
-        l_hdr = (dap_chain_cell_file_header_t*)a_cell->map;
-    } else {
-        fseeko(a_cell->file_storage, 0, SEEK_SET);
-        l_hdr = DAP_NEW(dap_chain_cell_file_header_t);
-        if ( fread(l_hdr, 1, sizeof(*l_hdr), a_cell->file_storage) != sizeof(*l_hdr) ) {
-            log_it(L_ERROR,"Can't read chain header \"%s\"", a_cell->file_storage_path);
-            fclose(a_cell->file_storage);
-            DAP_DELETE(l_hdr);
-            return -2;
+    off_t l_pos, l_full_size = !fseeko(a_cell->file_storage, 0, SEEK_END) ? ftello(a_cell->file_storage) : -1;
+    dap_return_val_if_fail_err(l_full_size < 0, 1, "Can't get chain size, error %d: \"%s\"", errno, dap_strerror(errno));
+    dap_return_val_if_fail_err(l_full_size < (off_t)sizeof(dap_chain_cell_file_header_t), 2, "Chain cell \"%s\" is corrupt, create new file", a_cell->file_storage_path);
+
+    /* Load header */
+    {
+        dap_chain_cell_file_header_t *l_hdr = DAP_NEW_STACK(dap_chain_cell_file_header_t);
+        if (a_cell->chain->is_mapped) {
+            dap_return_val_if_pass_err( s_cell_map_new_volume(a_cell, 0, false), -3, "Error on mapping the first volume" );
+            l_hdr = (dap_chain_cell_file_header_t*)a_cell->mapping->volume->base;
+        } else {
+            fseeko(a_cell->file_storage, 0, SEEK_SET);
+            dap_return_val_if_fail_err( fread(l_hdr, 1, sizeof(*l_hdr), a_cell->file_storage) != sizeof(*l_hdr), -4,
+                                        "Can't read chain header \"%s\"", a_cell->file_storage_path );
         }
-    }
-    if (l_hdr->signature != DAP_CHAIN_CELL_FILE_SIGNATURE) {
-        log_it(L_ERROR, "Wrong signature in chain \"%s\", possible file corrupt", a_cell->file_storage_path);
-        fclose(a_cell->file_storage);
-        if (!a_chain->is_mapped) DAP_DELETE(l_hdr);
-        return -3;
-    }
-    if (l_hdr->version < DAP_CHAIN_CELL_FILE_VERSION ){
-        log_it(L_ERROR, "Too low chain version, backup files");
-        fclose(a_cell->file_storage);
-        if (!a_chain->is_mapped) DAP_DELETE(l_hdr);
-        return -4;
-    }
-    off_t l_pos = sizeof(*l_hdr);
-    if (a_chain->is_mapped)
-        a_cell->map_pos = a_cell->map + l_pos;
-    if (l_full_size == l_pos) {
-        return fseeko(a_cell->file_storage, l_pos, SEEK_SET);
+        dap_return_val_if_fail_err( l_hdr->cell_id.uint64 == a_cell->id.uint64, 5,
+                                    "Wrong cell id, %lu != %lu", l_hdr->cell_id.uint64, a_cell->id.uint64);
+        dap_return_val_if_fail_err( l_hdr->signature == DAP_CHAIN_CELL_FILE_SIGNATURE, 5,
+                                    "Wrong signature in chain \"%s\", possible file corrupt", a_cell->file_storage_path );
+        dap_return_val_if_fail_err( l_hdr->version >= DAP_CHAIN_CELL_FILE_VERSION, -6,
+                                    "Too low chain version %d < %d, create a backup", l_hdr->version, DAP_CHAIN_CELL_FILE_VERSION );
+        l_pos = sizeof(*l_hdr);
+        if (a_cell->chain->is_mapped)
+            a_cell->mapping->cursor = a_cell->mapping->volume->base + l_pos;
+        if (l_full_size == l_pos)
+            return 0;
     }
 
+    /* Load atoms */
     int l_ret = 0;    
-    uint64_t l_el_size = 0, q = 0;
-    if (a_chain->is_mapped) {
-        dap_hash_fast_t l_atom_hash;
-        for ( off_t l_vol_rest = 0; l_pos + sizeof(uint64_t) < (size_t)l_full_size; ++q, l_pos += l_el_size + sizeof(uint64_t) ) {
-            l_vol_rest = (off_t)(a_cell->map_end - a_cell->map_pos) - sizeof(uint64_t);
-            if ( l_vol_rest <= 0 || (uint64_t)l_vol_rest < *(uint64_t*)a_cell->map_pos )
-                if ( s_cell_map_new_volume(a_cell, l_pos, true) ) {
-                    l_ret = -2;
-                    break;
-                }
-            l_el_size = *(uint64_t*)a_cell->map_pos;
-            if ( !l_el_size || l_el_size > (size_t)(l_full_size - l_pos) )
+    off_t l_el_size = 0, q = 0;
+    dap_chain_atom_ptr_t l_atom;
+    dap_hash_fast_t l_atom_hash;
+    if (a_cell->chain->is_mapped) {
+        for ( off_t l_vol_rest = 0; l_pos + sizeof(uint64_t) < (size_t)l_full_size; ++q, l_pos += sizeof(uint64_t) + l_el_size ) {
+            l_vol_rest = (off_t)( a_cell->mapping->volume->base + a_cell->mapping->volume->size - a_cell->mapping->cursor - sizeof(uint64_t) );
+            if ( l_vol_rest <= 0 || l_vol_rest < ( l_el_size = *(uint64_t*)a_cell->mapping->cursor ) )
+                dap_return_val_if_pass_err( s_cell_map_new_volume(a_cell, l_pos, true), -7, "Error on mapping a new volume" );
+            if ( !l_el_size || l_el_size > l_full_size - l_pos )
                 break;
-            a_cell->map_pos += sizeof(uint64_t);
-            dap_chain_atom_ptr_t l_atom = (dap_chain_atom_ptr_t)(a_cell->map_pos);
+            l_atom = (dap_chain_atom_ptr_t)(a_cell->mapping->cursor + sizeof(uint64_t));
             dap_hash_fast(l_atom, l_el_size, &l_atom_hash);
-            a_chain->callback_atom_add(a_chain, l_atom, l_el_size, &l_atom_hash, false);
-            a_cell->map_pos += l_el_size;
-            a_chain->load_progress = (int)((float)l_pos/l_full_size * 100 + 0.5);
+            dap_chain_atom_verify_res_t l_verif = a_cell->chain->callback_atom_prefetch
+                ? a_cell->chain->callback_atom_prefetch(a_cell->chain, l_atom, l_el_size, &l_atom_hash)
+                : a_cell->chain->callback_atom_add(a_cell->chain, l_atom, l_el_size, &l_atom_hash, false);
+            if ( l_verif == ATOM_CORRUPTED ) {
+                log_it(L_ERROR, "Atom #%ld is corrupted, can't proceed with loading chain \"%s : %s\" cell 0x%016"DAP_UINT64_FORMAT_X"",
+                                q, a_cell->chain->net_name, a_cell->chain->name, a_cell->id.uint64);
+                l_ret = 8;
+                break;
+            }
+            a_cell->mapping->cursor += sizeof(uint64_t) + l_el_size;
+            if ( !a_cell->chain->callback_atom_prefetch )
+                a_cell->chain->load_progress = (int)((float)l_pos/l_full_size * 100 + 0.5);
         }
 #ifndef DAP_OS_WINDOWS
-        s_cell_reclaim_cur_volume(a_cell);
+        /* Reclaim the last volume */
+        s_cell_reclaim_cur_volume(a_cell->mapping->volume);
 #endif
     } else { 
-        DAP_DELETE(l_hdr);
         size_t l_read = 0;
-        while ((l_read = fread(&l_el_size, 1, sizeof(l_el_size), a_cell->file_storage)) && !feof(a_cell->file_storage)) {
-            if (l_read != sizeof(l_el_size) || l_el_size == 0) {
+        while (( l_read = fread(&l_el_size, 1, sizeof(l_el_size), a_cell->file_storage) ) && !feof(a_cell->file_storage) ) {
+            if ( !l_el_size || l_read != sizeof(l_el_size) ) {
                 log_it(L_ERROR, "Corrupted element size %zu, chain %s is damaged", l_el_size, a_cell->file_storage_path);
-                l_ret = -4;
+                l_ret = 8;
                 break;
             }
-            dap_chain_atom_ptr_t l_element = DAP_NEW_SIZE(dap_chain_atom_ptr_t, l_el_size);
-            if (!l_element) {
+            l_atom = DAP_NEW_SIZE(dap_chain_atom_ptr_t, l_el_size);
+            if (!l_atom) {
                 log_it(L_CRITICAL, "Memory allocation error");
-                l_ret = -5;
+                l_ret = -9;
                 break;
             }
-            l_read = fread((void*)l_element, 1, l_el_size, a_cell->file_storage);
-            if (l_read != l_el_size) {
+            l_read = fread((void*)l_atom, 1, l_el_size, a_cell->file_storage);
+            if (l_read != (size_t)l_el_size) {
                 log_it(L_ERROR, "Read only %lu of %zu bytes, stop cell loading", l_read, l_el_size);
-                DAP_DELETE(l_element);
-                l_ret = -6;
+                DAP_DELETE(l_atom);
+                l_ret = 10;
                 break;
             }
-            l_pos += sizeof(uint64_t) + l_read;
-            a_chain->load_progress = (int)((float)l_pos/l_full_size * 100 + 0.5);
-            dap_hash_fast_t l_atom_hash = {};
-            dap_hash_fast(l_element, l_el_size, &l_atom_hash);
-            dap_chain_atom_verify_res_t l_res = a_chain->callback_atom_add(a_chain, l_element, l_el_size, &l_atom_hash, false);
-            if (l_res != ATOM_ACCEPT && l_res != ATOM_FORK) {
-                DAP_DELETE(l_element);
+            dap_hash_fast(l_atom, l_el_size, &l_atom_hash);
+            dap_chain_atom_verify_res_t l_verif = a_cell->chain->callback_atom_prefetch
+                ? a_cell->chain->callback_atom_prefetch(a_cell->chain, l_atom, l_el_size, &l_atom_hash)
+                : a_cell->chain->callback_atom_add(a_cell->chain, l_atom, l_el_size, &l_atom_hash, false);
+            DAP_DELETE(l_atom);
+            if ( l_verif == ATOM_CORRUPTED ) {
+                log_it(L_ERROR, "Atom #%ld is corrupted, can't proceed with loading chain \"%s : %s\" cell 0x%016"DAP_UINT64_FORMAT_X"",
+                                q, a_cell->chain->net_name, a_cell->chain->name, a_cell->id.uint64);
+                l_ret = 11;
+                break;
             }
             ++q;
+            l_pos += sizeof(uint64_t) + l_read;
+            if ( !a_cell->chain->callback_atom_prefetch )
+                a_cell->chain->load_progress = (int)((float)l_pos/l_full_size * 100 + 0.5);
         }
     }
-    if ( l_pos < l_full_size ) {
+    if ( l_pos < l_full_size && l_ret > 0 ) {
         log_it(L_ERROR, "Chain \"%s\" has incomplete tail, truncating %zu bytes",
                         a_cell->file_storage_path, l_full_size - l_pos );
 #ifdef DAP_OS_WINDOWS
         if (a_cell->chain->is_mapped) {
             LARGE_INTEGER SectionSize = (LARGE_INTEGER) { .QuadPart = l_pos };
-            HANDLE hSection = (HANDLE)a_cell->map_range_bounds->data;
-            NTSTATUS err = pfnNtExtendSection(hSection, &SectionSize);
-            if ( !NT_SUCCESS(err) ) {
+            NTSTATUS err = pfnNtExtendSection(a_cell->mapping->section, &SectionSize);
+            if ( !NT_SUCCESS(err) )
                 log_it(L_ERROR, "NtExtendSection() failed, status %lx", err);
-            }
         } else
 #endif
             ftruncate(fileno(a_cell->file_storage), l_pos);
     }
     fseeko(a_cell->file_storage, l_pos, SEEK_SET);
-    log_it(L_INFO, "Loaded %lu atoms in cell %s", q, a_cell->file_storage_path);
+    if ( a_cell->chain->callback_atoms_prefetched_add )
+        a_cell->chain->callback_atoms_prefetched_add(a_cell->chain);
+    log_it(L_INFO, "Loaded %lu atoms in chain \"%s : %s\" cell 0x%016"DAP_UINT64_FORMAT_X"",
+                    q, a_cell->chain->net_name, a_cell->chain->name, a_cell->id.uint64);
     return l_ret;
 }
 
-static int s_cell_file_atom_add(dap_chain_cell_t *a_cell, dap_chain_atom_ptr_t a_atom, uint64_t a_atom_size)
-{
-    if (!a_atom || !a_atom_size) {
-        log_it(L_CRITICAL, "Invalid arguments");
-        return -1;
+DAP_STATIC_INLINE int s_cell_open(dap_chain_t *a_chain, const char *a_filename, const char a_mode) {
+    dap_chain_cell_id_t l_cell_id = { };
+    { /* Check filename */
+        char l_fmt[20] = "", l_ext[ sizeof(CELL_FILE_EXT) ] = "", l_ext2 = '\0';
+        snprintf(l_fmt, sizeof(l_fmt), "%s%lu%s", "%"DAP_UINT64_FORMAT_x".%", sizeof(CELL_FILE_EXT) - 1, "[^.].%c");
+
+        switch ( sscanf(a_filename, l_fmt, &l_cell_id.uint64, l_ext, &l_ext2) ) {
+        case 3:
+            // TODO: X.dchaincell.*
+        case 2:
+            if ( !dap_strncmp(l_ext, CELL_FILE_EXT, sizeof(l_ext)) )
+                break;
+        default:
+            return log_it(L_ERROR, "Invalid cell file name \"%s\"", a_filename), EINVAL;
+        }
     }
-    if (a_cell->chain->is_mapped) {
-        off_t l_pos = !fseeko(a_cell->file_storage, 0, SEEK_END) ? ftello(a_cell->file_storage) : -1;
-        if (l_pos < 0)
-            return log_it(L_ERROR, "Can't get chain size, error %d: \"%s\"", errno, dap_strerror(errno)), -1;
-        debug_if (s_debug_more, L_DEBUG, "Before filling volume for atom size %ld, stream pos of %s is %lu, map pos is %lu, space left in map %lu",
-                      a_atom_size, a_cell->file_storage_path, l_pos, (size_t)(a_cell->map_pos - a_cell->map), (size_t)(a_cell->map_end - a_cell->map_pos));
-        if ( a_atom_size + sizeof(uint64_t) > (size_t)(a_cell->map_end - a_cell->map_pos) )
-            if ( s_cell_map_new_volume(a_cell, (size_t)l_pos, false) )
-                return -2;
+    char file_storage_path[MAX_PATH], mode[] = { a_mode, '+', 'b', '\0' };
+    snprintf(file_storage_path, MAX_PATH, "%s/%s", DAP_CHAIN_PVT(a_chain)->file_storage_dir, a_filename);
+    dap_chain_cell_t *l_cell = NULL;
+
+#define m_ret_err(err, ...) return ({ if (l_cell->file_storage) fclose(l_cell->file_storage); \
+                                      DAP_DELETE(l_cell); log_it(L_ERROR, ##__VA_ARGS__), err; })
+
+    dap_chain_cell_mmap_data_t l_cell_map_data = { };
+    HASH_FIND(hh, a_chain->cells, &l_cell_id, sizeof(dap_chain_cell_id_t), l_cell);
+    if (l_cell) {
+        if (a_mode == 'w') {
+            /* Attention! File rewriting requires that ledger was already purged */
+            s_cell_close(l_cell);
+            HASH_DEL(a_chain->cells, l_cell);
+            DAP_DELETE(l_cell);
+        } else
+            m_ret_err(EEXIST, "Cell \"%s\" is already loaded in chain \"%s : %s\"",
+                              a_filename, a_chain->net_name, a_chain->name);
     }
-    
-    debug_if (s_debug_more && a_cell->chain->is_mapped, L_DEBUG, "Before writing an atom of size %lu, stream pos of %s is %ld and pos is %lu, space left in map %lu", 
-                                            a_atom_size, a_cell->file_storage_path, ftello(a_cell->file_storage),
-                                            (size_t)(a_cell->map_pos - a_cell->map), (size_t)(a_cell->map_end - a_cell->map_pos));
-
-    if (fwrite(&a_atom_size, sizeof(a_atom_size), 1, a_cell->file_storage) != 1) {
-        log_it (L_ERROR, "Can't write atom data size from cell 0x%016"DAP_UINT64_FORMAT_X" in \"%s\"",
-                a_cell->id.uint64,
-                a_cell->file_storage_path);
-        return -2;
+    FILE *l_file = fopen(file_storage_path, mode);
+    if ( !l_file )
+        m_ret_err(errno, "Cell \"%s : %s / \"%s\" cannot be opened, error %d",
+                         a_chain->net_name, a_chain->name, a_filename, errno);
+
+    l_cell = DAP_NEW_Z(dap_chain_cell_t);
+    *l_cell = (dap_chain_cell_t) {
+        .id             = l_cell_id,
+        .chain          = a_chain,
+        .file_storage   = l_file,
+        //.storage_rwlock = PTHREAD_RWLOCK_INITIALIZER
+    };
+    dap_strncpy(l_cell->file_storage_path, file_storage_path, MAX_PATH);
+
+    switch (*mode) {
+    case 'a': {
+        int l_load_res = s_cell_load_from_file(l_cell);
+        if ( !l_load_res )
+            break;
+        else if (l_load_res < 0)
+            m_ret_err(errno, "Cell \"%s : %s / \"%s\" cannot be loaded, code %d",
+                             a_chain->net_name, a_chain->name, a_filename, l_load_res);
+        // Otherwise, rewrite the file from scratch
+        ftruncate(fileno(l_cell->file_storage), 0);
+        *mode = 'w';
     }
-    if (fwrite(a_atom, a_atom_size, 1, a_cell->file_storage) != 1) {
-        log_it(L_ERROR, "Can't write atom (%zu b) to file \"%s\", err %d: \"%s\"",
-                        a_atom_size, a_cell->file_storage_path, errno, dap_strerror(errno) );
-        return -3;
+    case 'w': {
+        dap_chain_cell_file_header_t l_hdr = {
+            .signature      = DAP_CHAIN_CELL_FILE_SIGNATURE,
+            .version        = DAP_CHAIN_CELL_FILE_VERSION,
+            .type           = DAP_CHAIN_CELL_FILE_TYPE_RAW,
+            .chain_id       = a_chain->id,
+            .chain_net_id   = a_chain->net_id,
+            .cell_id        = l_cell_id
+        };
+        if ( !fwrite(&l_hdr, sizeof(l_hdr), 1, l_cell->file_storage) )
+            m_ret_err(errno, "fwrite() error %d", errno);
+        fflush(l_cell->file_storage);
+        l_cell->file_storage = freopen(file_storage_path, "a+b", l_cell->file_storage);
+        if ( a_chain->is_mapped && s_cell_map_new_volume(l_cell, 0, false) )
+            m_ret_err(EINVAL, "Error on mapping the first volume");
     }
-    debug_if (s_debug_more && a_cell->chain->is_mapped, L_DEBUG, "After writing an atom of size %lu, stream pos of %s is %lu and map shift is %lu", 
-                                            a_atom_size, a_cell->file_storage_path, ftello(a_cell->file_storage),
-                                            (size_t)(a_cell->map_pos - a_cell->map));
-#ifdef DAP_OS_DARWIN
-    fflush(a_cell->file_storage);
+    default:
+        break;
+    }
+    HASH_ADD(hh, a_chain->cells, id, sizeof(dap_chain_cell_id_t), l_cell);
+    log_it(L_INFO, "Cell storage \"%s\" is %s for chain \"%s : %s\"",
+                    a_filename, *mode == 'w' ? "created" : "opened", a_chain->net_name, a_chain->name);
+    return 0;
+#undef m_ret_err
+}
+
+int dap_chain_cell_open(dap_chain_t *a_chain, const char *a_filename, const char a_mode) {
+    pthread_rwlock_wrlock(&a_chain->cell_rwlock);
+    int l_ret = s_cell_open(a_chain, a_filename, a_mode);
+    pthread_rwlock_unlock(&a_chain->cell_rwlock);
+    return l_ret;
+}
+
+static int s_cell_file_atom_add(dap_chain_cell_t *a_cell, dap_chain_atom_ptr_t a_atom, uint64_t a_atom_size, char **a_atom_map)
+{
     if (a_cell->chain->is_mapped) {
-        if ( MAP_FAILED == (a_cell->map = mmap(a_cell->map, dap_page_roundup(DAP_MAPPED_VOLUME_LIMIT), PROT_READ,
-                                            MAP_PRIVATE|MAP_FIXED, fileno(a_cell->file_storage), a_cell->cur_vol_start)) ) {
-            log_it(L_ERROR, "Chain cell \"%s\" 0x%016"DAP_UINT64_FORMAT_X" cannot be remapped, errno %d",
-                            a_cell->file_storage_path, a_cell->id.uint64, errno);
-            return -1;
-        }
+        off_t l_pos = !fseeko(a_cell->file_storage, 0, SEEK_END) ? ftello(a_cell->file_storage) : -1;
+        dap_return_val_if_pass_err(l_pos < 0, -1, "Can't get \"%s : %s\" cell 0x%016"DAP_UINT64_FORMAT_X" size, error %d",
+                                                     a_cell->chain->net_name, a_cell->chain->name, a_cell->id.uint64, errno);
+        if ( a_atom_size + sizeof(uint64_t) > (size_t)(a_cell->mapping->volume->base + a_cell->mapping->volume->size - a_cell->mapping->cursor) )
+            dap_return_val_if_pass_err(
+                s_cell_map_new_volume(a_cell, l_pos, false), 
+                -2, "Failed to create new map volume for \"%s : %s\" cell 0x%016"DAP_UINT64_FORMAT_X"",
+                a_cell->chain->net_name, a_cell->chain->name, a_cell->id.uint64
+            );
     }
+    dap_return_val_if_fail_err(
+        fwrite(&a_atom_size, sizeof(a_atom_size), 1, a_cell->file_storage) == 1 &&
+        fwrite(a_atom,       a_atom_size,         1, a_cell->file_storage) == 1,
+        -3, "Can't write atom [%zu b] to \"%s : %s\" cell 0x%016"DAP_UINT64_FORMAT_X", error %d: \"%s\"",
+            a_atom_size, a_cell->chain->net_name, a_cell->chain->name, a_cell->id.uint64, errno, dap_strerror(errno)
+    );
+    fflush(a_cell->file_storage);
+
+    if (a_cell->chain->is_mapped) {
+#ifdef DAP_OS_DARWIN
+        a_cell->mapping->volume->base = mmap( a_cell->mapping->volume->base, a_cell->mapping->volume->size,
+                                              PROT_READ, MAP_PRIVATE | MAP_FIXED, fileno(a_cell->file_storage),
+                                              a_cell->mapping->volume->offset );
+        dap_return_val_if_pass_err( a_cell->mapping->volume->base == MAP_FAILED, -2,
+            "Chain cell \"%s\" 0x%016"DAP_UINT64_FORMAT_X" cannot be remapped, errno %d",
+            a_cell->file_storage_path, a_cell->id.uint64, errno );
+#elif defined DAP_OS_WINDOWS
+        LARGE_INTEGER SectionSize = (LARGE_INTEGER) { .QuadPart = ftello(a_cell->file_storage) };
+        NTSTATUS err = pfnNtExtendSection(a_cell->mapping->section, &SectionSize);
+        dap_return_val_if_fail_err( NT_SUCCESS(err), -2, "NtExtendSection() failed, status %lx: \"%s\"", err, dap_str_ntstatus(err) );
 #endif
+        /* Pass ptr to mapped area */
+        if (a_atom_map)
+            *a_atom_map = a_cell->mapping->cursor + sizeof(uint64_t);
+        a_cell->mapping->cursor += sizeof(uint64_t) + a_atom_size;
+    }
     return 0;
 }
 
@@ -581,109 +521,28 @@ static int s_cell_file_atom_add(dap_chain_cell_t *a_cell, dap_chain_atom_ptr_t a
  * add atoms to selected chain
  * @param a_cell - cell object. Contains file path to cell storage data, for example - "0.dchaincell"
  * a_cell->chain contains 
- *  name - "zerochain"
- *  net_name - "kelvin-testnet"
- *  filepath - "C:\\Users\\Public\\Documents\\cellframe-node\\var\\lib\\network\\kelvin-testnet\\zerochain\\/0.dchaincell"
+ *  name
+ *  net_name
+ *  filepath
  * @param a_atom
  * @param a_atom_size
  * @return
  */
-ssize_t dap_chain_cell_file_append(dap_chain_cell_t *a_cell, const void *a_atom, size_t a_atom_size)
+int dap_chain_cell_file_append(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id, const void *a_atom, size_t a_atom_size, char **a_atom_map)
 {
-    if(!a_cell)
-        return -1;
-    if (!a_atom && !a_cell->chain) {
-        log_it(L_WARNING,"Chain not found for cell 0x%016"DAP_UINT64_FORMAT_X" ( %s )",
-                               a_cell->id.uint64, a_cell->file_storage_path);
-        return -1;
-    }
-    size_t l_total_res = 0, l_count = 0;
-    bool l_err = false;
-    pthread_rwlock_wrlock(&a_cell->storage_rwlock);
-    if (!a_atom || !a_atom_size) {
-#ifdef DAP_OS_WINDOWS
-        strcat(a_cell->file_storage_path, ".new");
-#endif
-        a_cell->file_storage = freopen(a_cell->file_storage_path, "w+b", a_cell->file_storage);
-        debug_if (s_debug_more,L_DEBUG, "Rewinding file %s", a_cell->file_storage_path);
-        bool was_mapped = a_cell->chain->is_mapped;
-        a_cell->chain->is_mapped = false;
-        if ( s_cell_file_write_header(a_cell) < 0 ) {
-            log_it(L_ERROR, "Chain cell \"%s\" 0x%016"DAP_UINT64_FORMAT_X": can't fill header",
-                            a_cell->file_storage_path, a_cell->id.uint64);
-            a_cell->chain->is_mapped = was_mapped;
-            pthread_rwlock_unlock(&a_cell->storage_rwlock);
-            return -2;
-        }
-        l_total_res += sizeof(dap_chain_cell_file_header_t);
-        dap_chain_atom_iter_t *l_atom_iter = a_cell->chain->callback_atom_iter_create(a_cell->chain, a_cell->id, NULL);
-        dap_chain_atom_ptr_t l_atom;
-        uint64_t l_atom_size = 0;
-        for (l_atom = a_cell->chain->callback_atom_iter_get(l_atom_iter, DAP_CHAIN_ITER_OP_FIRST, &l_atom_size);
-             l_atom && l_atom_size;
-             l_atom = a_cell->chain->callback_atom_iter_get(l_atom_iter, DAP_CHAIN_ITER_OP_NEXT, &l_atom_size))
-        {
-            if ( s_cell_file_atom_add(a_cell, l_atom, l_atom_size) ) {
-                l_err = true;
-                break;
-            } else {
-                l_total_res += sizeof(uint64_t) + l_atom_size;
-                ++l_count;
-            }
-        }
-        a_cell->chain->is_mapped = was_mapped;
-        a_cell->chain->callback_atom_iter_delete(l_atom_iter);
-        debug_if (s_debug_more && a_cell->chain->is_mapped,L_DEBUG, "After rewriting file %s, stream pos is %lu and map pos is %lu",
-                      a_cell->file_storage_path, ftello(a_cell->file_storage),
-                      (size_t)(a_cell->map_pos - a_cell->map));
-    } else {
-        debug_if (s_debug_more && a_cell->chain->is_mapped,L_DEBUG, "Before appending an atom of size %lu, stream pos of %s is %lu, map pos is %lu",
-                      a_atom_size, a_cell->file_storage_path, ftello(a_cell->file_storage),
-                      (size_t)(a_cell->map_pos - a_cell->map));
-        if ( s_cell_file_atom_add(a_cell, a_atom, a_atom_size) ) {
-            log_it(L_ERROR, "Chain cell \"%s\" 0x%016"DAP_UINT64_FORMAT_X": can't save atom!",
-                   a_cell->file_storage_path, a_cell->id.uint64);
-            pthread_rwlock_unlock(&a_cell->storage_rwlock);
-            return -4;
-        }
-        debug_if (s_debug_more && a_cell->chain->is_mapped, L_DEBUG,"After appending an atom of size %lu, stream pos of %s is %lu, map pos is %lu",
-                                                a_atom_size, a_cell->file_storage_path, ftello(a_cell->file_storage),
-                                                (size_t)(a_cell->map_end - a_cell->map_pos));
-        ++l_count;
-        l_total_res = a_atom_size + sizeof(uint64_t);
-    }
-    
-    if (l_total_res) {
-#ifndef DAP_OS_DARWIN
-        fflush(a_cell->file_storage);
-#endif
-#ifdef DAP_OS_WINDOWS
-        if (a_cell->chain->is_mapped) {
-            off_t l_off = ftello(a_cell->file_storage);
-            if (l_off < 0) {
-                log_it(L_ERROR, "Can't get chain size!");
-                l_err = true;
-            } else {
-                LARGE_INTEGER SectionSize = (LARGE_INTEGER) { .QuadPart = l_off };
-                HANDLE hSection = (HANDLE)a_cell->map_range_bounds->data;
-                NTSTATUS err = pfnNtExtendSection(hSection, &SectionSize);
-                if ( !NT_SUCCESS(err) ) {
-                    log_it(L_ERROR, "NtExtendSection() failed, status %lx", err);
-                    l_err = true;
-                }
-            }
-        }
-#endif
-        log_it(L_DEBUG, "Chain cell \"%s\" 0x%016"DAP_UINT64_FORMAT_X": saved %zu atoms (%zu bytes)",
-               a_cell->file_storage_path, a_cell->id.uint64, l_count, l_total_res);
-        if (l_err) {
-            log_it(L_WARNING, "Not all data was saved due to writing error!");
-        }
-    } else {
-        log_it(L_ERROR, "Chain cell \"%s\" 0x%016"DAP_UINT64_FORMAT_X": nothing saved!",
-               a_cell->file_storage_path, a_cell->id.uint64);
-    }
-    pthread_rwlock_unlock(&a_cell->storage_rwlock);
-    return l_total_res;
+    dap_return_val_if_fail(a_atom && a_atom_size && a_chain, -1);
+    dap_chain_cell_t *l_cell = dap_chain_cell_capture_by_id(a_chain, a_cell_id);
+    dap_return_val_if_fail_err(l_cell, -2, "Cell #%"DAP_UINT64_FORMAT_x" not found in chain \"%s : %s\"",
+                                            a_cell_id.uint64, a_chain->net_name, a_chain->name);
+    //pthread_rwlock_wrlock(&l_cell->storage_rwlock);
+    int l_err = s_cell_file_atom_add(l_cell, a_atom, a_atom_size, a_atom_map);
+    if (l_err)
+        log_it(L_DEBUG, "Saved atom of size %zu bytes to chain \"%s : %s\", cell 0x%016"DAP_UINT64_FORMAT_X"",
+                        a_atom_size, a_chain->net_name, a_chain->name, a_cell_id.uint64);
+    else
+        log_it(L_ERROR, "Noting saved to chain \"%s : %s\", cell 0x%016"DAP_UINT64_FORMAT_X", error %d",
+                        a_chain->net_name, a_chain->name, a_cell_id.uint64, l_err);
+    //pthread_rwlock_unlock(&l_cell->storage_rwlock);
+    dap_chain_cell_remit(l_cell);
+    return 0;
 }
-
diff --git a/modules/chain/dap_chain_cs.c b/modules/chain/dap_chain_cs.c
index 124f0af805b790ac4f281279c5b5a8ba435276b6..d2e296b5771e4783152bd93433960fe917963fc5 100644
--- a/modules/chain/dap_chain_cs.c
+++ b/modules/chain/dap_chain_cs.c
@@ -95,8 +95,7 @@ int dap_chain_cs_load(dap_chain_t *a_chain, dap_config_t *a_chain_cfg)
 {
     dap_chain_cs_callbacks_item_t *l_item = NULL;
     HASH_FIND_STR(s_cs_callbacks, DAP_CHAIN_PVT(a_chain)->cs_name, l_item);
-    if (!l_item)
-        return log_it(L_ERROR, "Callbacks for cs %s not found!", DAP_CHAIN_PVT(a_chain)->cs_name), -1;
+    dap_return_val_if_fail_err(l_item, -1, "Callbacks for cs %s not found!", DAP_CHAIN_PVT(a_chain)->cs_name);
     return l_item->callbacks.callback_load
         ? l_item->callbacks.callback_load(a_chain, a_chain_cfg)
         : 0;
@@ -106,8 +105,7 @@ int dap_chain_cs_class_delete(dap_chain_t *a_chain)
 {
     dap_chain_cs_class_callbacks_item_t *l_item = NULL;
     HASH_FIND_STR(s_class_callbacks, DAP_CHAIN_PVT(a_chain)->cs_type, l_item);
-    if (!l_item)
-        return log_it(L_ERROR, "Callbacks for cs %s not found!", DAP_CHAIN_PVT(a_chain)->cs_name), -1;
+    dap_return_val_if_fail_err(l_item, -1, "Callbacks for cs %s not found!", DAP_CHAIN_PVT(a_chain)->cs_name);
     return l_item->callbacks.callback_delete
         ? l_item->callbacks.callback_delete(a_chain)
         : 0;
@@ -117,8 +115,7 @@ int dap_chain_cs_class_purge(dap_chain_t *a_chain)
 {
     dap_chain_cs_class_callbacks_item_t *l_item = NULL;
     HASH_FIND_STR(s_class_callbacks, DAP_CHAIN_PVT(a_chain)->cs_type, l_item);
-    if (!l_item)
-        return log_it(L_ERROR, "Callbacks for cs %s not found!", DAP_CHAIN_PVT(a_chain)->cs_name), -1;
+    dap_return_val_if_fail_err(l_item, -1, "Callbacks for cs %s not found!", DAP_CHAIN_PVT(a_chain)->cs_name);
     return l_item->callbacks.callback_purge
         ? l_item->callbacks.callback_purge(a_chain)
         : 0;
diff --git a/modules/chain/include/dap_chain.h b/modules/chain/include/dap_chain.h
index 320756219fbd9e78fd8594472e64a5a8e86c6a3e..b2912ac1b197fe150784ad61e22f9aa2530b1a8e 100644
--- a/modules/chain/include/dap_chain.h
+++ b/modules/chain/include/dap_chain.h
@@ -71,15 +71,16 @@ typedef struct dap_chain_datum_iter {
 } dap_chain_datum_iter_t;
 
 typedef enum dap_chain_atom_verify_res{
-    ATOM_ACCEPT = 0, ATOM_PASS, ATOM_REJECT, ATOM_MOVE_TO_THRESHOLD, ATOM_FORK
+    ATOM_ACCEPT = 0, ATOM_PASS, ATOM_REJECT, ATOM_MOVE_TO_THRESHOLD, ATOM_FORK, ATOM_CORRUPTED
 } dap_chain_atom_verify_res_t;
 
 static const char* const dap_chain_atom_verify_res_str[] = {
-    [ATOM_ACCEPT]   = "accepted",
-    [ATOM_PASS]     = "skipped",
-    [ATOM_REJECT]   = "rejected",
-    [ATOM_MOVE_TO_THRESHOLD] = "thresholded",
-    [ATOM_FORK] = "forked"
+    [ATOM_ACCEPT]           = "accepted",
+    [ATOM_PASS]             = "skipped",
+    [ATOM_REJECT]           = "rejected",
+    [ATOM_MOVE_TO_THRESHOLD]= "thresholded",
+    [ATOM_FORK]             = "forked",
+    [ATOM_CORRUPTED]        = "corrupted"
 };
 
 typedef enum dap_chain_iter_op {
@@ -96,6 +97,7 @@ 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 *a_chain, dap_chain_atom_ptr_t a_atom, size_t a_atom_size, dap_hash_fast_t *a_atom_hash, bool a_atom_new);
+typedef unsigned (*dap_chain_callback_atoms_t)(dap_chain_t*);
 typedef dap_chain_atom_ptr_t (*dap_chain_callback_atom_form_treshold_t)(dap_chain_t *, size_t *);
 typedef json_object *(*dap_chain_callback_atom_to_json)(json_object **a_arr_out, dap_chain_t *a_chain, dap_chain_atom_ptr_t a_atom, size_t a_atom_size, const char *a_hex_out_type);
 typedef dap_chain_atom_verify_res_t (*dap_chain_callback_atom_verify_t)(dap_chain_t *, dap_chain_atom_ptr_t , size_t, dap_hash_fast_t*);
@@ -193,6 +195,8 @@ typedef struct dap_chain {
 
     pthread_rwlock_t cell_rwlock;
 
+    dap_chain_callback_atom_verify_t callback_atom_prefetch;
+    dap_chain_callback_atoms_t callback_atoms_prefetched_add;
     dap_chain_callback_atom_t callback_atom_add;
     dap_chain_callback_atom_form_treshold_t callback_atom_add_from_treshold;
     dap_chain_callback_atom_verify_t callback_atom_verify;
@@ -275,11 +279,8 @@ typedef struct dap_chain_atom_confirmed_notifier {
 
 typedef struct dap_chain_pvt {
     char *file_storage_dir;
-    char *cs_name;
-    char *cs_type;
+    char *cs_name, *cs_type;
     bool cs_started;
-    bool need_reorder;
-
 } dap_chain_pvt_t;
 
 #define DAP_CHAIN_PVT(a) ((dap_chain_pvt_t *)a->_pvt)
@@ -300,24 +301,22 @@ void dap_chain_deinit(void);
 
 dap_chain_t *dap_chain_create(const char *a_chain_net_name, const char *a_chain_name, dap_chain_net_id_t a_chain_net_id, dap_chain_id_t a_chain_id);
 void dap_chain_set_cs_type(dap_chain_t *a_chain, const char *a_cs_type);
-int dap_chain_purge(dap_chain_t *a_chain);
 
 int dap_chain_load_all(dap_chain_t *a_chain);
-int dap_chain_save_all(dap_chain_t *a_chain);
 bool dap_chain_has_file_store(dap_chain_t *a_chain);
 
 dap_chain_t *dap_chain_find_by_id(dap_chain_net_id_t a_chain_net_id,dap_chain_id_t a_chain_id);
 dap_chain_t *dap_chain_load_from_cfg(const char *a_chain_net_name, dap_chain_net_id_t a_chain_net_id, dap_config_t *a_cfg);
 void dap_chain_info_dump_log(dap_chain_t *a_chain);
 
-void dap_chain_delete(dap_chain_t * a_chain);
+void dap_chain_delete(dap_chain_t *a_chain);
 void dap_chain_add_callback_notify(dap_chain_t *a_chain, dap_chain_callback_notify_t a_callback, dap_proc_thread_t *a_thread, void *a_arg);
 void dap_chain_add_callback_datum_index_notify(dap_chain_t *a_chain, dap_chain_callback_datum_notify_t a_callback, dap_proc_thread_t *a_thread, void *a_callback_arg);
 void dap_chain_add_callback_datum_removed_from_index_notify(dap_chain_t *a_chain, dap_chain_callback_datum_removed_notify_t a_callback, dap_proc_thread_t *a_thread, void *a_callback_arg);
 void dap_chain_atom_confirmed_notify_add(dap_chain_t *a_chain, dap_chain_callback_notify_t a_callback, void *a_arg, uint64_t a_conf_cnt);
-void dap_chain_atom_notify(dap_chain_cell_t *a_chain_cell,  dap_hash_fast_t *a_hash, const uint8_t *a_atom, size_t a_atom_size);
-void dap_chain_datum_notify(dap_chain_cell_t *a_chain_cell,  dap_hash_fast_t *a_hash, dap_chain_hash_fast_t *a_atom_hash, const uint8_t *a_datum, size_t a_datum_size, int a_ret_code, uint32_t a_action, dap_chain_srv_uid_t a_uid);
-void dap_chain_datum_removed_notify(dap_chain_cell_t *a_chain_cell,  dap_hash_fast_t *a_hash);
+void dap_chain_atom_notify(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id, dap_hash_fast_t *a_hash, const uint8_t *a_atom, size_t a_atom_size);
+void dap_chain_datum_notify(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id,  dap_hash_fast_t *a_hash, dap_chain_hash_fast_t *a_atom_hash, const uint8_t *a_datum, size_t a_datum_size, int a_ret_code, uint32_t a_action, dap_chain_srv_uid_t a_uid);
+void dap_chain_datum_removed_notify(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id, dap_hash_fast_t *a_hash);
 void dap_chain_atom_add_from_threshold(dap_chain_t *a_chain);
 dap_chain_atom_ptr_t dap_chain_get_atom_by_hash(dap_chain_t * a_chain, dap_chain_hash_fast_t * a_atom_hash, size_t * a_atom_size);
 bool dap_chain_get_atom_last_hash_num_ts(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id, dap_hash_fast_t *a_atom_hash, uint64_t *a_atom_num, dap_time_t *a_atom_timestamp);
@@ -325,7 +324,7 @@ DAP_STATIC_INLINE bool dap_chain_get_atom_last_hash(dap_chain_t *a_chain, dap_ch
 {
     return dap_chain_get_atom_last_hash_num_ts(a_chain, a_cell_id, a_atom_hash, NULL, NULL);
 }
-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_chain_atom_save(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id, const uint8_t *a_atom, size_t a_atom_size, dap_hash_fast_t *a_new_atom_hash, char **a_atom_map);
 int dap_cert_chain_file_save(dap_chain_datum_t *datum, char *net_name);
 
 const char *dap_chain_type_to_str(dap_chain_type_t a_chain_type);
diff --git a/modules/chain/include/dap_chain_cell.h b/modules/chain/include/dap_chain_cell.h
index db47d0150aad1ece5511b0683dd016f2fe73d567..74efe15fdb29a4be2bb698a9ff8689ac0b8e05d0 100644
--- a/modules/chain/include/dap_chain_cell.h
+++ b/modules/chain/include/dap_chain_cell.h
@@ -29,15 +29,15 @@
 #include "dap_chain.h"
 #include "dap_chain_common.h"
 
+typedef struct dap_chain_cell_mmap_data dap_chain_cell_mmap_data_t;
+
 typedef struct dap_chain_cell {
     dap_chain_cell_id_t id;
-    dap_chain_t * chain;
-
+    dap_chain_t *chain;
     char file_storage_path[MAX_PATH];
-    char *map, *map_pos, *map_end;
+    dap_chain_cell_mmap_data_t *mapping;
     FILE *file_storage;
     uint8_t file_storage_type;
-    dap_list_t *map_range_bounds;
 #ifdef DAP_OS_DARWIN
     size_t cur_vol_start;
 #endif
@@ -76,14 +76,23 @@ typedef struct dap_chain_cell_decl{
 
 
 int dap_chain_cell_init(void);
-dap_chain_cell_t *dap_chain_cell_create_fill(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id);
-dap_chain_cell_t *dap_chain_cell_find_by_id(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id);
-void dap_chain_cell_close(dap_chain_cell_t *a_cell);
-void dap_chain_cell_delete(dap_chain_cell_t *a_cell);
-void dap_chain_cell_delete_all_and_free_file(dap_chain_t *a_chain);
-void dap_chain_cell_delete_all(dap_chain_t *a_chain);
-int dap_chain_cell_load(dap_chain_t *a_chain, dap_chain_cell_t *a_cell);
-ssize_t dap_chain_cell_file_append(dap_chain_cell_t *a_cell,const void *a_atom, size_t a_atom_size);
-DAP_STATIC_INLINE ssize_t dap_chain_cell_file_update(dap_chain_cell_t *a_cell) {
-    return dap_chain_cell_file_append(a_cell, NULL, 0);
+int dap_chain_cell_open(dap_chain_t *a_chain, const char *a_filename, const char a_mode);
+
+DAP_INLINE dap_chain_cell_t *dap_chain_cell_find_by_id(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id) {
+    dap_chain_cell_t *l_cell = NULL;
+    HASH_FIND(hh, a_chain->cells, &a_cell_id, sizeof(dap_chain_cell_id_t), l_cell);
+    return l_cell;
+}
+DAP_INLINE dap_chain_cell_t *dap_chain_cell_capture_by_id(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id) {
+    pthread_rwlock_rdlock(&a_chain->cell_rwlock);
+    return dap_chain_cell_find_by_id(a_chain, a_cell_id);
 }
+DAP_INLINE void dap_chain_cell_remit(const dap_chain_cell_t *a_cell) {
+    pthread_rwlock_unlock(&a_cell->chain->cell_rwlock);
+}
+
+void dap_chain_cell_close(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id);
+void dap_chain_cell_close_all(dap_chain_t *a_chain);
+int dap_chain_cell_file_append(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id,
+                                   const void *a_atom, size_t a_atom_size, char **a_atom_map);
+
diff --git a/modules/chain/include/dap_chain_common.h b/modules/chain/include/dap_chain_common.h
index 5de3ac83a020bb0cc4f3c972892adde288a9984a..74706f6d1bb9a316153b07f65212dd6ed98c9300 100644
--- a/modules/chain/include/dap_chain_common.h
+++ b/modules/chain/include/dap_chain_common.h
@@ -80,14 +80,14 @@ typedef union dap_chain_node_role{
 DAP_STATIC_INLINE const char *dap_chain_node_role_to_str(dap_chain_node_role_t a_node_role)
 {
     switch (a_node_role.enums) {
-        case NODE_ROLE_ROOT_MASTER: return "NODE_ROLE_ROOT_MASTER";
-        case NODE_ROLE_ROOT: return "NODE_ROLE_ROOT";
-        case NODE_ROLE_ARCHIVE: return "NODE_ROLE_ARCHIVE";
-        case NODE_ROLE_CELL_MASTER: return "NODE_ROLE_CELL_MASTER";
-        case NODE_ROLE_MASTER: return "NODE_ROLE_MASTER";
-        case NODE_ROLE_FULL: return "NODE_ROLE_FULL";
-        case NODE_ROLE_LIGHT: return "NODE_ROLE_LIGHT";
-        default: return "UNDEFINED";
+        case NODE_ROLE_ROOT_MASTER: return "root master";
+        case NODE_ROLE_ROOT: return "root";
+        case NODE_ROLE_ARCHIVE: return "archive";
+        case NODE_ROLE_CELL_MASTER: return "cell master";
+        case NODE_ROLE_MASTER: return "master";
+        case NODE_ROLE_FULL: return "full";
+        case NODE_ROLE_LIGHT: return "liht";
+        default: return "none";
     }
 }
 
diff --git a/modules/chain/tests/dap_chain_ledger_tests.c b/modules/chain/tests/dap_chain_ledger_tests.c
index bccf77f99e31a1a171a6008e0e18f67588c1a683..6c284f7f951b7997476a568eb6e3710e1028d237 100644
--- a/modules/chain/tests/dap_chain_ledger_tests.c
+++ b/modules/chain/tests/dap_chain_ledger_tests.c
@@ -1025,7 +1025,7 @@ void dap_ledger_test_run(void){
     dap_assert_PIF(dap_chain_cs_create(l_chain_main, &l_cfg) == 0, "Chain esbocs cs creating: ");
     DL_APPEND(l_net->pub.chains, l_chain_main);
 
-    dap_assert_PIF(!dap_ledger_decree_create(l_net->pub.ledger), "Decree initialization:");
+    dap_ledger_decree_init(l_net->pub.ledger);
 
     char *l_seed_ph = "H58i9GJKbn91238937^#$t6cjdf";
     size_t l_seed_ph_size = strlen(l_seed_ph);
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 a7199037e1e0cfeddfe0696cd6f81010b5bb52d8..a026bc1dc1a51f6ed9948fb8c8d627d0158db8dd 100644
--- a/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c
+++ b/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c
@@ -351,11 +351,7 @@ static int s_callback_new(dap_chain_t *a_chain, dap_config_t * a_chain_cfg)
         return -1;
     }
     dap_chain_cs_dag_t *l_dag = DAP_CHAIN_CS_DAG(a_chain);
-    dap_chain_cs_dag_poa_t *l_poa = DAP_NEW_Z(dap_chain_cs_dag_poa_t);
-    if (!l_poa) {
-        log_it(L_CRITICAL, "%s", c_error_memory_alloc);
-        return -1;
-    }
+    dap_chain_cs_dag_poa_t *l_poa = DAP_NEW_Z_RET_VAL_IF_FAIL(dap_chain_cs_dag_poa_t, -1);
     l_dag->_inheritor = l_poa;
     l_dag->callback_delete = s_callback_delete;
     l_dag->callback_cs_verify = s_callback_event_verify;
@@ -379,11 +375,7 @@ static int s_callback_new(dap_chain_t *a_chain, dap_config_t * a_chain_cfg)
         l_poa_pvt->auth_certs_count = dap_config_get_item_uint16_default(a_chain_cfg,"dag-poa","auth_certs_number",0);
         l_poa_pvt->auth_certs_count_verify = dap_config_get_item_uint16_default(a_chain_cfg,"dag-poa","auth_certs_number_verify",0);
         if (l_poa_pvt->auth_certs_count && l_poa_pvt->auth_certs_count_verify) {
-            l_poa_pvt->auth_certs = DAP_NEW_Z_SIZE ( dap_cert_t *, l_poa_pvt->auth_certs_count * sizeof(dap_cert_t *));
-            if (!l_poa_pvt->auth_certs) {
-                log_it(L_CRITICAL, "%s", c_error_memory_alloc);
-                return -1;
-            }
+            l_poa_pvt->auth_certs = DAP_NEW_Z_COUNT_RET_VAL_IF_FAIL(dap_cert_t*, l_poa_pvt->auth_certs_count, -1);
             char l_cert_name[MAX_PATH + 1];
             int l_pos;
             for (uint16_t i = 0; i < l_poa_pvt->auth_certs_count ; ++i) {
@@ -691,35 +683,33 @@ static int s_callback_created(dap_chain_t * a_chain, dap_config_t *a_chain_net_c
     dap_chain_cs_dag_t * l_dag = DAP_CHAIN_CS_DAG ( a_chain );
     dap_chain_cs_dag_poa_t * l_poa = DAP_CHAIN_CS_DAG_POA( l_dag );
 
-    const char * l_events_sign_cert = NULL;
-    if ( ( l_events_sign_cert = dap_config_get_item_str(a_chain_net_cfg,"dag-poa","events-sign-cert") ) != NULL ) {
-        if ( ( PVT(l_poa)->events_sign_cert = dap_cert_find_by_name(l_events_sign_cert)) == NULL ){
-            log_it(L_ERROR,"Can't load events sign certificate, name \"%s\" is wrong",l_events_sign_cert);
-        }else
-            log_it(L_NOTICE,"Loaded \"%s\" certificate to sign poa event", l_events_sign_cert);
-
+    const char *l_events_sign_cert = dap_config_get_item_str(a_chain_net_cfg,"dag-poa","events-sign-cert");
+    if ( l_events_sign_cert ) {
+        if (!( PVT(l_poa)->events_sign_cert = dap_cert_find_by_name(l_events_sign_cert) ))
+            log_it(L_ERROR,"Can't load events sign certificate, name \"%s\" is wrong", l_events_sign_cert);
+        else
+            log_it(L_NOTICE, "Loaded \"%s\" certificate to sign poa events", l_events_sign_cert);
     }
+
     dap_chain_net_t *l_net = dap_chain_net_by_name(a_chain->net_name);
     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, DAG_ROUND_NEW_TTL, true,
                                                                        DAP_GDB_MEMBER_ROLE_NOBODY, DAP_CLUSTER_TYPE_AUTONOMIC);
-    if (!l_dag_cluster) {
-        log_it(L_ERROR, "Can't create cluster for consensus communication. Can't start the DAG consensus");
-        return -1;
-    }
+    dap_return_val_if_fail_err(l_dag_cluster, -1, "Can't create cluster for consensus communication. Can't start the DAG consensus");
+
     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);
     PVT(l_poa)->mempool_timer = dap_interval_timer_create(15000, s_timer_process_callback, a_chain);
 
     switch ( dap_chain_net_get_role(l_net).enums ) {
-        case NODE_ROLE_ROOT_MASTER:
-        case NODE_ROLE_ROOT:
-            dap_global_db_get_all(l_dag->gdb_group_events_round_new, 0, s_callback_sync_all_on_start, l_dag);
-        default:
-            break;
+    case NODE_ROLE_ROOT_MASTER:
+    case NODE_ROLE_ROOT:
+        dap_global_db_get_all(l_dag->gdb_group_events_round_new, 0, s_callback_sync_all_on_start, l_dag);
+    default:
+        break;
     }
     return 0;
 }
@@ -920,11 +910,9 @@ dap_list_t *dap_chain_cs_dag_poa_get_auth_certs(dap_chain_t *a_chain, size_t *a_
         *a_count_verify = l_poa_pvt->auth_certs_count_verify;
 
     dap_list_t *l_keys_list = NULL;
-    for(size_t i = 0; i < l_poa_pvt->auth_certs_count; i++)
+    for (size_t i = 0; i < l_poa_pvt->auth_certs_count; ++i)
     {
-        dap_pkey_t *l_pkey = dap_cert_to_pkey(l_poa_pvt->auth_certs[i]);
-        l_keys_list = dap_list_append(l_keys_list, l_pkey);
+        l_keys_list = dap_list_append(l_keys_list, dap_cert_to_pkey(l_poa_pvt->auth_certs[i]));
     }
-
     return l_keys_list;
 }
diff --git a/modules/consensus/esbocs/dap_chain_cs_esbocs.c b/modules/consensus/esbocs/dap_chain_cs_esbocs.c
index 0acc30261178d1157d100d22b4ce8ad48fc87516..fd7f38e5a2562db12c6db1bf3de4a45fa2fbc146 100644
--- a/modules/consensus/esbocs/dap_chain_cs_esbocs.c
+++ b/modules/consensus/esbocs/dap_chain_cs_esbocs.c
@@ -264,7 +264,7 @@ static int s_callback_new(dap_chain_t *a_chain, dap_config_t *a_chain_cfg)
     dap_chain_net_t *l_net = dap_chain_net_by_id(a_chain->net_id);
     int l_dot_pos = strlen(l_auth_certs_prefix), l_len = l_dot_pos + 16, l_pos2 = 0;
     char l_cert_name[l_len];
-    strncpy(l_cert_name, l_auth_certs_prefix, l_dot_pos);
+    dap_strncpy(l_cert_name, l_auth_certs_prefix, l_dot_pos);
     for (i = 0; i < l_auth_certs_count; ++i) {
         dap_cert_t *l_cert_cur;
         l_pos2 = snprintf(l_cert_name + l_dot_pos, 16, ".%u", i);
diff --git a/modules/ledger/dap_chain_ledger.c b/modules/ledger/dap_chain_ledger.c
index af987a86b160d3454b471ed21e5a49d3ef56da27..74ca761fac7bb0361ef6eeccaa40787e096b0bd8 100644
--- a/modules/ledger/dap_chain_ledger.c
+++ b/modules/ledger/dap_chain_ledger.c
@@ -244,23 +244,12 @@ void dap_ledger_deinit()
  */
 static dap_ledger_t *dap_ledger_handle_new(void)
 {
-    dap_ledger_t *l_ledger = DAP_NEW_Z(dap_ledger_t);
-    if ( !l_ledger ) {
-        log_it(L_CRITICAL, "%s", c_error_memory_alloc);
-        return NULL;
-    }
-    dap_ledger_private_t * l_ledger_pvt;
-    l_ledger->_internal = l_ledger_pvt = DAP_NEW_Z(dap_ledger_private_t);
-    if ( !l_ledger_pvt ) {
-        log_it(L_CRITICAL, "%s", c_error_memory_alloc);
-        DAP_DELETE(l_ledger);
-        return NULL;
-    }
-    // Initialize Read/Write Lock Attribute
+    dap_ledger_t *l_ledger = DAP_NEW_Z_RET_VAL_IF_FAIL(dap_ledger_t, NULL);
+    dap_ledger_private_t *l_ledger_pvt = l_ledger->_internal = DAP_NEW_Z_RET_VAL_IF_FAIL(dap_ledger_private_t, NULL, l_ledger);
     pthread_rwlock_init(&l_ledger_pvt->ledger_rwlock, NULL);
     pthread_rwlock_init(&l_ledger_pvt->tokens_rwlock, NULL);
-    pthread_rwlock_init(&l_ledger_pvt->threshold_txs_rwlock , NULL);
-    pthread_rwlock_init(&l_ledger_pvt->balance_accounts_rwlock , NULL);
+    pthread_rwlock_init(&l_ledger_pvt->threshold_txs_rwlock, NULL);
+    pthread_rwlock_init(&l_ledger_pvt->balance_accounts_rwlock, NULL);
     pthread_rwlock_init(&l_ledger_pvt->stake_lock_rwlock, NULL);
     pthread_rwlock_init(&l_ledger_pvt->rewards_rwlock, NULL);
     return l_ledger;
@@ -275,7 +264,6 @@ void dap_ledger_handle_free(dap_ledger_t *a_ledger)
 {
     if(!a_ledger)
         return;
-    log_it(L_INFO,"Ledger for network %s destroyed", a_ledger->net->pub.name);
     // Destroy Read/Write Lock
     pthread_rwlock_destroy(&PVT(a_ledger)->ledger_rwlock);
     pthread_rwlock_destroy(&PVT(a_ledger)->tokens_rwlock);
@@ -283,8 +271,8 @@ void dap_ledger_handle_free(dap_ledger_t *a_ledger)
     pthread_rwlock_destroy(&PVT(a_ledger)->balance_accounts_rwlock);
     pthread_rwlock_destroy(&PVT(a_ledger)->stake_lock_rwlock);
     pthread_rwlock_destroy(&PVT(a_ledger)->rewards_rwlock);
-    DAP_DELETE(PVT(a_ledger));
-    DAP_DELETE(a_ledger);
+    DAP_DEL_MULTY(PVT(a_ledger), a_ledger);
+    log_it(L_INFO,"Ledger for network %s destroyed", a_ledger->net->pub.name);
 
 }
 
@@ -606,34 +594,36 @@ json_object *dap_ledger_balance_info(dap_ledger_t *a_ledger, size_t a_limit, siz
 
 int dap_ledger_pvt_threshold_txs_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash)
 {
-    dap_ledger_tx_item_t *l_item_tmp = NULL;
+    dap_ledger_tx_item_t *l_item = NULL;
     dap_ledger_private_t *l_ledger_pvt = PVT(a_ledger);
     unsigned l_hash_value = 0;
     HASH_VALUE(a_tx_hash, sizeof(*a_tx_hash), l_hash_value);
-    pthread_rwlock_rdlock(&l_ledger_pvt->threshold_txs_rwlock);
-    HASH_FIND_BYHASHVALUE(hh, l_ledger_pvt->threshold_txs, a_tx_hash, sizeof(*a_tx_hash), l_hash_value, l_item_tmp);
+    pthread_rwlock_wrlock(&l_ledger_pvt->threshold_txs_rwlock);
+    HASH_FIND_BYHASHVALUE(hh, l_ledger_pvt->threshold_txs, a_tx_hash, sizeof(*a_tx_hash), l_hash_value, l_item);
     unsigned long long l_threshold_txs_count = HASH_COUNT(l_ledger_pvt->threshold_txs);
-    if (!l_item_tmp) {
+    if (!l_item) {
         if (l_threshold_txs_count >= s_threshold_txs_max) {
+            pthread_rwlock_unlock(&l_ledger_pvt->threshold_txs_rwlock);
             debug_if(g_debug_ledger, L_WARNING, "Threshold for transactions is overfulled (%zu max), dropping down tx %s, added nothing",
                                                 s_threshold_txs_max, dap_hash_fast_to_str_static(a_tx_hash));
             return -2;
         }
-        l_item_tmp = DAP_NEW_Z(dap_ledger_tx_item_t);
-        if ( !l_item_tmp ) {
+        if (!( l_item = DAP_NEW_Z(dap_ledger_tx_item_t) )) {
+            pthread_rwlock_unlock(&l_ledger_pvt->threshold_txs_rwlock);
             log_it(L_CRITICAL, "%s", c_error_memory_alloc);
             return -1;
         }
-        l_item_tmp->tx_hash_fast = *a_tx_hash;
-        l_item_tmp->tx = l_ledger_pvt->mapped ? a_tx : DAP_DUP_SIZE(a_tx, dap_chain_datum_tx_get_size(a_tx));
-        if ( !l_item_tmp->tx ) {
-            DAP_DELETE(l_item_tmp);
+        l_item->tx_hash_fast = *a_tx_hash;
+        l_item->tx = is_ledger_mapped(l_ledger_pvt) ? a_tx : DAP_DUP_SIZE(a_tx, dap_chain_datum_tx_get_size(a_tx));
+        if ( !l_item->tx ) {
+            DAP_DELETE(l_item);
+            pthread_rwlock_unlock(&l_ledger_pvt->threshold_txs_rwlock);
             log_it(L_CRITICAL, "%s", c_error_memory_alloc);
             return -1;
         }
-        l_item_tmp->ts_added = dap_nanotime_now();
-        l_item_tmp->cache_data.ts_created = a_tx->header.ts_created;
-        HASH_ADD_BYHASHVALUE(hh, l_ledger_pvt->threshold_txs, tx_hash_fast, sizeof(dap_chain_hash_fast_t), l_hash_value, l_item_tmp);
+        l_item->ts_added = dap_nanotime_now();
+        l_item->cache_data.ts_created = a_tx->header.ts_created;
+        HASH_ADD_BYHASHVALUE(hh, l_ledger_pvt->threshold_txs, tx_hash_fast, sizeof(dap_chain_hash_fast_t), l_hash_value, l_item);
         debug_if(g_debug_ledger, L_DEBUG, "Tx %s added to threshold", dap_hash_fast_to_str_static(a_tx_hash));
     }
     pthread_rwlock_unlock(&l_ledger_pvt->threshold_txs_rwlock);
@@ -653,7 +643,7 @@ void dap_ledger_pvt_threshold_txs_proc(dap_ledger_t *a_ledger)
             if (l_res != DAP_CHAIN_CS_VERIFY_CODE_TX_NO_EMISSION &&
                     l_res != DAP_CHAIN_CS_VERIFY_CODE_TX_NO_PREVIOUS) {
                 HASH_DEL(l_ledger_pvt->threshold_txs, l_tx_item);
-                if ( !l_ledger_pvt->mapped )
+                if ( !is_ledger_mapped(l_ledger_pvt) )
                     DAP_DELETE(l_tx_item->tx);
                 DAP_DELETE(l_tx_item);
                 l_success = true;
@@ -679,7 +669,7 @@ static void s_threshold_txs_free(dap_ledger_t *a_ledger)
             HASH_DEL(l_pvt->threshold_txs, l_current);
             char l_tx_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE];
             dap_chain_hash_fast_to_str(&l_current->tx_hash_fast, l_tx_hash_str, sizeof(l_tx_hash_str));
-            if ( !l_pvt->mapped )
+            if ( !is_ledger_mapped(l_pvt) )
                 DAP_DELETE(l_current->tx);
             DAP_DELETE(l_current);
             log_it(L_NOTICE, "Removed transaction %s form threshold ledger", l_tx_hash_str);
@@ -757,28 +747,18 @@ void dap_ledger_load_cache(dap_ledger_t *a_ledger)
  * create ledger for specific net
  * load ledger cache
  * @param a_check_flags checking flags
- *          DAP_LEDGER_CHECK_TOKEN_EMISSION
- *          DAP_LEDGER_CHECK_CELLS_DS
- *          DAP_LEDGER_CHECK_CELLS_DS
  * @param a_net_name char * network name, for example "kelvin-testnet"
  * @return dap_ledger_t*
  */
 dap_ledger_t *dap_ledger_create(dap_chain_net_t *a_net, uint16_t a_flags)
 {
     dap_ledger_t *l_ledger = dap_ledger_handle_new();
-    if (!l_ledger) {
-        log_it(L_CRITICAL, "%s", c_error_memory_alloc);
-        return NULL;
-    }
+    dap_return_val_if_fail(l_ledger, NULL);
+
     l_ledger->net = a_net;
     dap_ledger_private_t *l_ledger_pvt = PVT(l_ledger);
-    l_ledger_pvt->check_ds = a_flags & DAP_LEDGER_CHECK_LOCAL_DS;
-    l_ledger_pvt->check_cells_ds = a_flags & DAP_LEDGER_CHECK_CELLS_DS;
-    l_ledger_pvt->check_token_emission = a_flags & DAP_LEDGER_CHECK_TOKEN_EMISSION;
-    l_ledger_pvt->cached = a_flags & DAP_LEDGER_CACHE_ENABLED;
-    l_ledger_pvt->mapped = a_flags & DAP_LEDGER_MAPPED;
-    l_ledger_pvt->threshold_enabled = a_flags & DAP_LEDGER_THRESHOLD_ENABLED;
-    if (l_ledger_pvt->threshold_enabled)
+    l_ledger_pvt->flags = a_flags;
+    if ( is_ledger_threshld(l_ledger_pvt) )
         l_ledger_pvt->threshold_txs_free_timer = dap_interval_timer_create(s_threshold_free_timer_tick,
                                                                       (dap_timer_callback_t)s_threshold_txs_free, l_ledger);
     pthread_cond_init(&l_ledger_pvt->load_cond, NULL);
@@ -801,13 +781,12 @@ dap_ledger_t *dap_ledger_create(dap_chain_net_t *a_net, uint16_t a_flags)
         }
         log_it(L_DEBUG, "Chain %s.%s has %d datums in HAL and %d datums in HRL", a_net->pub.name, l_chain->name, l_whitelist_size, l_blacklist_size);
     }
-    if ( l_ledger_pvt->cached )
+    if ( is_ledger_cached(l_ledger_pvt) )
         // load ledger cache from GDB
         dap_ledger_load_cache(l_ledger);
 #endif
     // Decrees initializing
-    dap_ledger_decree_create(l_ledger);
-
+    dap_ledger_decree_init(l_ledger);
     return l_ledger;
 }
 
@@ -992,9 +971,9 @@ void dap_ledger_purge(dap_ledger_t *a_ledger, bool a_preserve_db)
     char *l_gdb_group;
     HASH_ITER(hh, l_ledger_pvt->ledger_items , l_item_current, l_item_tmp) {
         HASH_DEL(l_ledger_pvt->ledger_items, l_item_current);
-        if (!l_ledger_pvt->mapped)
+        if (!is_ledger_mapped(l_ledger_pvt))
             DAP_DELETE(l_item_current->tx);
-        DAP_DEL_Z(l_item_current);
+        DAP_DELETE(l_item_current);
     }
     if (!a_preserve_db) {
         l_gdb_group = dap_ledger_get_gdb_group(a_ledger, DAP_LEDGER_TXS_STR);
@@ -1006,8 +985,7 @@ void dap_ledger_purge(dap_ledger_t *a_ledger, bool a_preserve_db)
     dap_ledger_wallet_balance_t *l_balance_current, *l_balance_tmp;
     HASH_ITER(hh, l_ledger_pvt->balance_accounts, l_balance_current, l_balance_tmp) {
         HASH_DEL(l_ledger_pvt->balance_accounts, l_balance_current);
-        DAP_DELETE(l_balance_current->key);
-        DAP_DELETE(l_balance_current);
+        DAP_DEL_MULTY(l_balance_current->key, l_balance_current);
     }
     if (!a_preserve_db) {
         l_gdb_group = dap_ledger_get_gdb_group(a_ledger, DAP_LEDGER_BALANCES_STR);
@@ -1023,19 +1001,12 @@ void dap_ledger_purge(dap_ledger_t *a_ledger, bool a_preserve_db)
         pthread_rwlock_wrlock(&l_token_current->token_emissions_rwlock);
         HASH_ITER(hh, l_token_current->token_emissions, l_emission_current, l_emission_tmp) {
             HASH_DEL(l_token_current->token_emissions, l_emission_current);
-            DAP_DELETE(l_emission_current->datum_token_emission);
-            DAP_DEL_Z(l_emission_current);
+            DAP_DEL_MULTY(l_emission_current->datum_token_emission, l_emission_current);
         }
         pthread_rwlock_unlock(&l_token_current->token_emissions_rwlock);
-        DAP_DELETE(l_token_current->datum_token);
-        DAP_DELETE(l_token_current->auth_pkeys);
-        DAP_DELETE(l_token_current->auth_pkey_hashes);
-        DAP_DEL_Z(l_token_current->tx_recv_allow);
-        DAP_DEL_Z(l_token_current->tx_recv_block);
-        DAP_DEL_Z(l_token_current->tx_send_allow);
-        DAP_DEL_Z(l_token_current->tx_send_block);
         pthread_rwlock_destroy(&l_token_current->token_emissions_rwlock);
-        DAP_DELETE(l_token_current);
+        DAP_DEL_MULTY(l_token_current->datum_token, l_token_current->datum_token, l_token_current->auth_pkeys, l_token_current->auth_pkey_hashes,
+            l_token_current->tx_recv_allow, l_token_current->tx_recv_block, l_token_current->tx_send_allow, l_token_current->tx_send_block, l_token_current);
     }
     if (!a_preserve_db) {
         l_gdb_group = dap_ledger_get_gdb_group(a_ledger, DAP_LEDGER_TOKENS_STR);
@@ -1061,9 +1032,9 @@ void dap_ledger_purge(dap_ledger_t *a_ledger, bool a_preserve_db)
     /* Delete threshold transactions */
     HASH_ITER(hh, l_ledger_pvt->threshold_txs, l_item_current, l_item_tmp) {
         HASH_DEL(l_ledger_pvt->threshold_txs, l_item_current);
-        if (!l_ledger_pvt->mapped)
+        if (!is_ledger_mapped(l_ledger_pvt))
             DAP_DELETE(l_item_current->tx);
-        DAP_DEL_Z(l_item_current);
+        DAP_DELETE(l_item_current);
     }
 
     l_ledger_pvt->ledger_items         = NULL;
@@ -1607,5 +1578,5 @@ dap_list_t *dap_ledger_get_list_tx_cond_outs(dap_ledger_t *a_ledger, const dap_c
 
 bool dap_ledger_cache_enabled(dap_ledger_t *a_ledger)
 {
-    return PVT(a_ledger)->cached;
+    return is_ledger_cached(PVT(a_ledger));
 }
diff --git a/modules/ledger/dap_chain_ledger_decree.c b/modules/ledger/dap_chain_ledger_decree.c
index 76f11129d126df362758e31ff60283480640505e..95b561c6e67483678d199f3f7905df908c66bcd8 100644
--- a/modules/ledger/dap_chain_ledger_decree.c
+++ b/modules/ledger/dap_chain_ledger_decree.c
@@ -43,31 +43,14 @@ static int s_common_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain
 static int s_service_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain_net_t *a_net, bool a_apply);
 
 // Public functions
-int dap_ledger_decree_create(dap_ledger_t *a_ledger)
-{
-    dap_return_val_if_fail(a_ledger, -106);
-
-    size_t l_auth_certs_count = 0;
-    dap_list_t *l_net_keys = NULL;
-    uint16_t l_count_verify = 0;
-    for (dap_chain_t *l_chain = a_ledger->net->pub.chains; l_chain; l_chain = l_chain->next) {
-        if (!l_chain->callback_get_poa_certs)
-            continue;
-        l_net_keys = l_chain->callback_get_poa_certs(l_chain, &l_auth_certs_count, &l_count_verify);
-        if (l_net_keys)
-            break;
-    }
 
-    if (!l_net_keys || !l_auth_certs_count) {
-        log_it(L_WARNING, "Certificates for net %s not found.", a_ledger->net->pub.name);
-        return -1;
-    }
+void dap_ledger_decree_init(dap_ledger_t *a_ledger) {
     dap_ledger_private_t *l_ledger_pvt = PVT(a_ledger);
-    l_ledger_pvt->decree_min_num_of_signers = l_count_verify;
-    l_ledger_pvt->decree_num_of_owners = l_auth_certs_count;
-    l_ledger_pvt->decree_owners_pkeys = l_net_keys;
-
-    return 0;
+    l_ledger_pvt->decree_min_num_of_signers = a_ledger->net->pub.keys_min_count;
+    l_ledger_pvt->decree_num_of_owners = dap_list_length(a_ledger->net->pub.keys);
+    l_ledger_pvt->decree_owners_pkeys = a_ledger->net->pub.keys;
+    if ( !l_ledger_pvt->decree_owners_pkeys )
+        log_it(L_WARNING, "PoA certificates for net %s not found", a_ledger->net->pub.name);
 }
 
 static int s_decree_clear(dap_ledger_t *a_ledger)
@@ -89,7 +72,7 @@ static int s_decree_clear(dap_ledger_t *a_ledger)
 void dap_ledger_decree_purge(dap_ledger_t *a_ledger)
 {
     s_decree_clear(a_ledger);
-    dap_ledger_decree_create(a_ledger);
+    //dap_ledger_decree_create(a_ledger);
 }
 
 static int s_decree_verify(dap_chain_net_t *a_net, dap_chain_datum_decree_t *a_decree, size_t a_data_size, dap_chain_hash_fast_t *a_decree_hash, bool a_anchored)
diff --git a/modules/ledger/dap_chain_ledger_token.c b/modules/ledger/dap_chain_ledger_token.c
index 3c91f2a6c8fce8e25ec92d30a5087f12bb5110e6..4a3e5a32786bf43425de378a50275af1983a0549 100644
--- a/modules/ledger/dap_chain_ledger_token.c
+++ b/modules/ledger/dap_chain_ledger_token.c
@@ -1078,7 +1078,7 @@ dap_chain_datum_token_t *dap_ledger_token_ticker_check(dap_ledger_t *a_ledger, c
  */
 void s_ledger_token_cache_update(dap_ledger_t *a_ledger, dap_ledger_token_item_t *l_token_item)
 {
-    if (!PVT(a_ledger)->cached)
+    if (! is_ledger_cached(PVT(a_ledger)) )
         return;
     char *l_gdb_group = dap_ledger_get_gdb_group(a_ledger, DAP_LEDGER_TOKENS_STR);
     size_t l_cache_size = l_token_item->datum_token_size + sizeof(uint256_t);
@@ -1392,7 +1392,7 @@ int s_emission_add_check(dap_ledger_t *a_ledger, byte_t *a_token_emission, size_
         return DAP_LEDGER_CHECK_ALREADY_CACHED;
     }
 
-    if (!PVT(a_ledger)->check_token_emission)
+    if (! is_ledger_ems_chk(PVT(a_ledger)) )
         goto ret_success;
 
     // Check emission correctness
@@ -1514,7 +1514,7 @@ int dap_ledger_token_emission_add_check(dap_ledger_t *a_ledger, byte_t *a_token_
 
 void dap_ledger_pvt_emission_cache_update(dap_ledger_t *a_ledger, dap_ledger_token_emission_item_t *a_emission_item)
 {
-    if (!PVT(a_ledger)->cached)
+    if (! is_ledger_cached(PVT(a_ledger)) )
         return;
     char *l_gdb_group = dap_ledger_get_gdb_group(a_ledger, DAP_LEDGER_EMISSIONS_STR);
     size_t l_cache_size = a_emission_item->datum_token_emission_size + sizeof(dap_hash_fast_t);
@@ -1581,7 +1581,7 @@ int dap_ledger_token_emission_add(dap_ledger_t *a_ledger, byte_t *a_token_emissi
                        l_balance, l_emission->hdr.ticker,
                        dap_chain_addr_to_str_static(&(l_emission->hdr.address)));
     }
-    if (PVT(a_ledger)->threshold_enabled)
+    if ( is_ledger_threshld(PVT(a_ledger)) )
         dap_ledger_pvt_threshold_txs_proc(a_ledger);
     return DAP_LEDGER_CHECK_OK;
 }
diff --git a/modules/ledger/dap_chain_ledger_tx.c b/modules/ledger/dap_chain_ledger_tx.c
index f5fa8cb1652bfdbaee1011dfb3ac81b360edd006..9558151998491e6141ccd9ce02d3940f1bb960f8 100644
--- a/modules/ledger/dap_chain_ledger_tx.c
+++ b/modules/ledger/dap_chain_ledger_tx.c
@@ -1148,7 +1148,7 @@ static struct json_object *s_wallet_info_json_collect(dap_ledger_t *a_ledger, da
  */
 static int s_balance_cache_update(dap_ledger_t *a_ledger, dap_ledger_wallet_balance_t *a_balance)
 {
-    if (PVT(a_ledger)->cached) {
+    if ( is_ledger_cached(PVT(a_ledger)) ) {
         char *l_gdb_group = dap_ledger_get_gdb_group(a_ledger, DAP_LEDGER_BALANCES_STR);
         if (dap_global_db_set(l_gdb_group, a_balance->key, &a_balance->balance, sizeof(uint256_t), false, NULL, NULL)) {
             debug_if(g_debug_ledger, L_WARNING, "Ledger cache mismatch");
@@ -1269,7 +1269,7 @@ int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_ha
                                                        l_main_token_ticker, &l_tag, &l_action, false))) {
         if ((l_ret_check == DAP_CHAIN_CS_VERIFY_CODE_TX_NO_PREVIOUS ||
                 l_ret_check == DAP_CHAIN_CS_VERIFY_CODE_TX_NO_EMISSION) &&
-                l_ledger_pvt->threshold_enabled && !dap_chain_net_get_load_mode(a_ledger->net)) {
+                is_ledger_threshld(l_ledger_pvt) && !dap_chain_net_get_load_mode(a_ledger->net)) {
             if (!l_from_threshold)
                 dap_ledger_pvt_threshold_txs_add(a_ledger, a_tx, &l_tx_hash);
         } else {
@@ -1294,7 +1294,7 @@ int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_ha
     dap_list_t *l_trackers_mover = NULL;
     dap_store_obj_t *l_cache_used_outs = NULL;
     char *l_ledger_cache_group = NULL;
-    if (PVT(a_ledger)->cached) {
+    if ( is_ledger_cached(l_ledger_pvt) ) {
         l_cache_used_outs = DAP_NEW_Z_SIZE(dap_store_obj_t, sizeof(dap_store_obj_t) * (l_outs_used + 1));
         if ( !l_cache_used_outs ) {
             log_it(L_CRITICAL, "%s", c_error_memory_alloc);
@@ -1402,7 +1402,7 @@ int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_ha
                                                   l_prev_item_out->out_metadata[l_bound_item->prev_out_idx].trackers, a_tx->header.ts_created);
         // add a used output
         l_prev_item_out->cache_data.n_outs_used++;
-        if (PVT(a_ledger)->cached) {
+        if ( is_ledger_cached(l_ledger_pvt) ) {
             // mirror it in the cache
             size_t l_cache_size = sizeof(l_prev_item_out->cache_data) + l_prev_item_out->cache_data.n_outs * sizeof(dap_chain_hash_fast_t);
             size_t l_tx_size = dap_chain_datum_tx_get_size(l_prev_item_out->tx);
@@ -1546,11 +1546,11 @@ int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_ha
     }
     l_tx_item->tx_hash_fast = l_tx_hash;
     size_t l_tx_size = dap_chain_datum_tx_get_size(a_tx);
-    l_tx_item->tx = l_ledger_pvt->mapped ? a_tx : DAP_DUP_SIZE(a_tx, l_tx_size);
+    l_tx_item->tx = is_ledger_mapped(l_ledger_pvt) ? a_tx : DAP_DUP_SIZE(a_tx, l_tx_size);
     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;
-    dap_stpcpy(l_tx_item->cache_data.token_ticker, l_main_token_ticker);
+    dap_strncpy(l_tx_item->cache_data.token_ticker, l_main_token_ticker, sizeof(l_tx_item->cache_data.token_ticker));
 
     // Moving colour to new outputs
     size_t i = 0;
@@ -1647,7 +1647,7 @@ int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_ha
             l_notify->callback(a_ledger, a_tx, &l_tx_hash, l_notify->arg, DAP_LEDGER_NOTIFY_OPCODE_ADDED);
         }
     }
-    if (PVT(a_ledger)->cached) {
+    if ( is_ledger_cached(l_ledger_pvt) ) {
         // Add it to cache
         size_t l_cache_size = sizeof(l_tx_item->cache_data) + l_tx_item->cache_data.n_outs * sizeof(dap_chain_hash_fast_t);
         size_t l_tx_cache_sz = l_tx_size + l_cache_size + sizeof(dap_ledger_cache_gdb_record_t);
@@ -1666,7 +1666,7 @@ int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_ha
         if (dap_global_db_set_raw(l_cache_used_outs, l_outs_used + 1, NULL, NULL))
             debug_if(g_debug_ledger, L_WARNING, "Ledger cache mismatch");
     }
-    if (!a_from_threshold && l_ledger_pvt->threshold_enabled)
+    if (!a_from_threshold && is_ledger_threshld(l_ledger_pvt))
         dap_ledger_pvt_threshold_txs_proc(a_ledger);
 FIN:
     if (l_trackers_mover)
@@ -1675,7 +1675,7 @@ FIN:
         dap_list_free_full(l_list_bound_items, NULL);
     if (l_list_tx_out)
         dap_list_free(l_list_tx_out);
-    if (PVT(a_ledger)->cached) {
+    if ( is_ledger_cached(l_ledger_pvt) ) {
         if (l_cache_used_outs) {
             for (size_t i = 1; i < l_outs_used; ++i) {
                 DAP_DEL_MULTY(l_cache_used_outs[i].key, l_cache_used_outs[i].value);
@@ -1731,7 +1731,7 @@ int dap_ledger_tx_remove(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap
 
     dap_store_obj_t *l_cache_used_outs = NULL;
     char *l_ledger_cache_group = NULL;
-    if (PVT(a_ledger)->cached) {
+    if ( is_ledger_cached(l_ledger_pvt) ) {
         l_cache_used_outs = DAP_NEW_Z_COUNT(dap_store_obj_t, l_outs_used);
         if ( !l_cache_used_outs ) {
             log_it(L_CRITICAL, "Memory allocation error");
@@ -1821,7 +1821,7 @@ int dap_ledger_tx_remove(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap
         dap_ledger_tx_item_t *l_prev_item_out = l_bound_item->prev_item;
         l_prev_item_out->out_metadata[l_bound_item->prev_out_idx].tx_spent_hash_fast = (dap_hash_fast_t){ };
         l_prev_item_out->cache_data.n_outs_used--;
-        if (PVT(a_ledger)->cached) {
+        if ( is_ledger_cached(l_ledger_pvt) ) {
             // mirror it in the cache
             size_t l_tx_size = dap_chain_datum_tx_get_size(l_prev_item_out->tx);
             size_t l_cache_size = sizeof(l_prev_item_out->cache_data) + l_prev_item_out->cache_data.n_outs * sizeof(dap_chain_hash_fast_t);
@@ -1957,7 +1957,7 @@ int dap_ledger_tx_remove(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap
         dap_list_free_full(l_tx_item->out_metadata[i].trackers, NULL);
     DAP_DELETE(l_tx_item);
 
-    if (PVT(a_ledger)->cached) {
+    if ( is_ledger_cached(l_ledger_pvt) ) {
         // Add it to cache
         dap_global_db_del_sync(l_ledger_cache_group, l_tx_hash_str);
         // Apply it with single DB transaction
@@ -1969,7 +1969,7 @@ FIN:
         dap_list_free_full(l_list_bound_items, NULL);
     if (l_list_tx_out)
         dap_list_free(l_list_tx_out);
-    if (PVT(a_ledger)->cached) {
+    if ( is_ledger_cached(l_ledger_pvt) ) {
         if (l_cache_used_outs) {
             for (size_t i = 1; i < l_outs_used; i++) {
                 DAP_DELETE(l_cache_used_outs[i].key);
@@ -2003,7 +2003,7 @@ int dap_ledger_tx_load(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_c
 
 static void s_ledger_stake_lock_cache_update(dap_ledger_t *a_ledger, dap_ledger_stake_lock_item_t *a_stake_lock_item)
 {
-    if (!PVT(a_ledger)->cached)
+    if (!is_ledger_cached(PVT(a_ledger)))
         return;
     char l_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE];
     dap_chain_hash_fast_to_str(&a_stake_lock_item->tx_for_stake_lock_hash, l_hash_str, sizeof(l_hash_str));
diff --git a/modules/ledger/include/dap_chain_ledger.h b/modules/ledger/include/dap_chain_ledger.h
index 0dd292916e7933c72e973fd8862bbb4a075ce96f..65ca7447d18752446c44075340a1fb6b8ab4493e 100644
--- a/modules/ledger/include/dap_chain_ledger.h
+++ b/modules/ledger/include/dap_chain_ledger.h
@@ -492,7 +492,8 @@ dap_chain_tx_out_cond_t* dap_chain_ledger_get_tx_out_cond_linked_to_tx_in_cond(d
 void dap_ledger_load_end(dap_ledger_t *a_ledger);
 dap_pkey_t *dap_ledger_find_pkey_by_hash(dap_ledger_t *a_ledger, dap_chain_hash_fast_t *a_pkey_hash);
 
-int dap_ledger_decree_create(dap_ledger_t *a_ledger);
+//int dap_ledger_decree_create(dap_ledger_t *a_ledger);
+void dap_ledger_decree_init(dap_ledger_t *a_ledger);
 void dap_ledger_decree_purge(dap_ledger_t *a_ledger);
 
 uint16_t dap_ledger_decree_get_min_num_of_signers(dap_ledger_t *a_ledger);
diff --git a/modules/ledger/include/dap_chain_ledger_pvt.h b/modules/ledger/include/dap_chain_ledger_pvt.h
index 62eb273e503398c16c15a8a4cdf068ec66eb60a6..b94a9fb3ac0a2d822748a7c84b56660b3f328437 100644
--- a/modules/ledger/include/dap_chain_ledger_pvt.h
+++ b/modules/ledger/include/dap_chain_ledger_pvt.h
@@ -186,12 +186,13 @@ typedef struct dap_ledger_private {
     dap_ledger_decree_item_t *decrees;
     dap_ledger_anchor_item_t *anchors;
 
-    // Save/load operations condition
+    // Save/load cache operations condition
     pthread_mutex_t load_mutex;
     pthread_cond_t load_cond;
     bool load_end;
     // Ledger flags
-    bool check_ds, check_cells_ds, check_token_emission, cached, mapped, threshold_enabled;
+    //bool check_ds, check_cells_ds, check_token_emission, cached, mapped, threshold_enabled;
+    uint16_t flags;
     //notifiers
     dap_list_t *bridged_tx_notifiers;
     dap_list_t *tx_add_notifiers;
@@ -202,6 +203,13 @@ typedef struct dap_ledger_private {
 
 #define PVT(a) ( (dap_ledger_private_t *) a->_internal )
 
+#define is_ledger_ds_chk(l)         ( l->flags & DAP_LEDGER_CHECK_LOCAL_DS )
+#define is_ledger_cells_ds_chk(l)   ( l->flags & DAP_LEDGER_CHECK_CELLS_DS )
+#define is_ledger_ems_chk(l)        ( l->flags & DAP_LEDGER_CHECK_TOKEN_EMISSION )
+#define is_ledger_mapped(l)         ( l->flags & DAP_LEDGER_MAPPED )
+#define is_ledger_cached(l)         ( l->flags & DAP_LEDGER_CACHE_ENABLED )
+#define is_ledger_threshld(l)       ( l->flags & DAP_LEDGER_THRESHOLD_ENABLED )
+
 extern bool g_debug_ledger;
 
 bool dap_ledger_pvt_cache_gdb_load_tokens_callback(dap_global_db_instance_t *a_dbi,
diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c
index 0b19b4fd8fc08830318612258b35dfaba8160ef0..4f3843f747689fe69eb2f77cff1181762bd4bbaa 100644
--- a/modules/net/dap_chain_net.c
+++ b/modules/net/dap_chain_net.c
@@ -222,6 +222,7 @@ static bool s_net_states_proc(void *a_arg);
 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_chains_init_all(dap_chain_net_t *a_net, const char *a_path, uint16_t *a_ledger_flags);
 static int s_net_init(const char *a_net_name, const char *a_path, uint16_t a_acl_idx);
 static void *s_net_load(void *a_arg);
 static int s_net_try_online(dap_chain_net_t *a_net);
@@ -551,7 +552,7 @@ int s_link_manager_fill_net_info(dap_link_t *a_link)
         }
     }
     dap_chain_node_info_t *l_node_info = NULL;
-    if (!l_host || !l_host[0] || !l_port) {
+    if (!l_host || !*l_host || !l_port) {
         for (dap_chain_net_t *net = s_nets_by_name; net; net = net->hh.next) {
             if (( l_node_info = dap_chain_node_info_read(net, &a_link->addr) ))
                 break;
@@ -719,10 +720,7 @@ static dap_chain_net_t *s_net_new(const char *a_net_name, dap_config_t *a_cfg)
                 *a_native_ticker= dap_config_get_item_str(a_cfg, "general", "native_ticker");
     dap_chain_net_id_t l_net_id;
 
-    if(!a_node_role)
-        return log_it(L_ERROR, "Can't create l_net, can't read node role config"), NULL;
-
-    if(!l_net_name_str || !l_net_id_str || dap_chain_net_id_parse(l_net_id_str, &l_net_id))
+    if (!l_net_name_str || !*l_net_name_str || !l_net_id_str || dap_chain_net_id_parse(l_net_id_str, &l_net_id))
         return log_it(L_ERROR, "Can't create l_net, can't read name or ID config"), NULL;
 
     dap_chain_net_t *l_net_sought = NULL;
@@ -737,38 +735,38 @@ static dap_chain_net_t *s_net_new(const char *a_net_name, dap_config_t *a_cfg)
                         l_net_sought->pub.id.uint64);
         return NULL;
     }
+
+    if (!a_native_ticker)
+        return log_it(L_ERROR, "Invalid native ticker, check [general] \"native_ticker\" in %s.cfg", l_net_name_str), NULL;
+
+    uint32_t l_role;
+    if (!a_node_role)
+        l_role = NODE_ROLE_FULL;
+    else if ( !strcmp(a_node_role, "root_master") )
+        l_role = NODE_ROLE_ROOT_MASTER;
+    else if ( !strcmp(a_node_role,"root") )
+        l_role = NODE_ROLE_ROOT;
+    else if ( !strcmp(a_node_role,"archive") )
+        l_role = NODE_ROLE_ARCHIVE;
+    else if ( !strcmp(a_node_role,"cell_master") )
+        l_role = NODE_ROLE_CELL_MASTER;
+    else if ( !strcmp(a_node_role,"master") )
+        l_role = NODE_ROLE_MASTER;
+    else if ( !strcmp(a_node_role,"full") )
+        l_role = NODE_ROLE_FULL;
+    else if ( !strcmp(a_node_role,"light") )
+        l_role = NODE_ROLE_LIGHT;
+    else
+        return log_it(L_ERROR,"Unknown node role \"%s\" for network '%s'", a_node_role, l_net_name_str), NULL;
+
     dap_chain_net_t *l_ret = DAP_NEW_Z_SIZE_RET_VAL_IF_FAIL(dap_chain_net_t, sizeof(dap_chain_net_t) + sizeof(dap_chain_net_pvt_t), NULL);
     PVT(l_ret)->node_info = DAP_NEW_Z_SIZE_RET_VAL_IF_FAIL(dap_chain_node_info_t, sizeof(dap_chain_node_info_t) + DAP_HOSTADDR_STRLEN + 1, NULL, l_ret);
 
     l_ret->pub.id = l_net_id;
-    if (strcmp (a_node_role, "root_master")==0){
-        PVT(l_ret)->node_role.enums = NODE_ROLE_ROOT_MASTER;
-    } else if (strcmp( a_node_role,"root") == 0){
-        PVT(l_ret)->node_role.enums = NODE_ROLE_ROOT;
-    } else if (strcmp( a_node_role,"archive") == 0){
-        PVT(l_ret)->node_role.enums = NODE_ROLE_ARCHIVE;
-    } else if (strcmp( a_node_role,"cell_master") == 0){
-        PVT(l_ret)->node_role.enums = NODE_ROLE_CELL_MASTER;
-    }else if (strcmp( a_node_role,"master") == 0){
-        PVT(l_ret)->node_role.enums = NODE_ROLE_MASTER;
-    }else if (strcmp( a_node_role,"full") == 0){
-        PVT(l_ret)->node_role.enums = NODE_ROLE_FULL;
-    }else if (strcmp( a_node_role,"light") == 0){
-        PVT(l_ret)->node_role.enums = NODE_ROLE_LIGHT;
-    }else{
-        log_it(L_ERROR,"Unknown node role \"%s\" for network '%s'", a_node_role, l_net_name_str);
-        DAP_DELETE(l_ret);
-        return NULL;
-    }
-    if (!( l_net_name_str ))
-        return DAP_DELETE(l_ret), log_it(L_ERROR, "Invalid net name, check [general] \"name\" in netconfig"), NULL;
-    dap_strncpy(l_ret->pub.name, l_net_name_str, sizeof(l_ret->pub.name));
-    if (!( l_ret->pub.native_ticker = a_native_ticker ))
-        return DAP_DEL_MULTY(l_ret->pub.name, l_ret),
-               log_it(L_ERROR, "Invalid native ticker, check [general] \"native_ticker\" in %s.cfg",
-                                l_net_name_str),
-                NULL;
+    PVT(l_ret)->node_role.enums = l_role;
     log_it (L_NOTICE, "Node role \"%s\" selected for network '%s'", a_node_role, l_net_name_str);
+    dap_strncpy(l_ret->pub.name, l_net_name_str, sizeof(l_ret->pub.name));
+    l_ret->pub.native_ticker = a_native_ticker;
     
     if (dap_chain_policy_net_add(l_ret->pub.id.uint64)) {
         log_it(L_ERROR, "Can't add net %s to policy module", l_ret->pub.name);
@@ -829,34 +827,19 @@ bool s_net_disk_load_notify_callback(UNUSED_ARG void *a_arg)
  */
 void dap_chain_net_load_all()
 {
-    if ( dap_config_get_item_bool_default(g_config, "server", "enabled", false) ) {
-        char l_local_ip[INET6_ADDRSTRLEN] = { '\0' };
-        uint16_t l_in_port = 0;
-        const char **l_listening = dap_config_get_array_str(g_config, "server", DAP_CFG_PARAM_LISTEN_ADDRS, NULL);
-        if ( l_listening ) {
-            if ( dap_net_parse_config_address(*l_listening, l_local_ip, &l_in_port, NULL, NULL) < 0 )
-                log_it(L_ERROR, "Invalid server IP address, check [server] section in cellframe-node.cfg");
-            else {
-                // power of short-circuit
-                if ( l_in_port || ( l_in_port = dap_config_get_item_int16_default(g_config, "server", DAP_CFG_PARAM_LEGACY_PORT, 8079 ))) {
-                    s_server_enabled = true;
-                    log_it(L_INFO, "Server is enabled on [%s : %u]", l_local_ip, l_in_port);
-                }
-            }
-        }
-    }
-    uint16_t l_nets_count = HASH_COUNT(s_nets_by_name);
+    int l_nets_count = HASH_COUNT(s_nets_by_name), i = 0, l_err;
     if (!l_nets_count)
         return log_it(L_ERROR, "No networks initialized!");
     pthread_t l_tids[l_nets_count];
-    dap_chain_net_t *l_net = s_nets_by_name;
     dap_timerfd_t *l_load_notify_timer = dap_timerfd_start(5000, (dap_timerfd_callback_t)s_net_disk_load_notify_callback, NULL);
-    for (int i = 0; i < l_nets_count; ++i) {
-        pthread_create(&l_tids[i], NULL, s_net_load, l_net);
-        l_net = l_net->hh.next;
+    for ( dap_chain_net_t *l_net = s_nets_by_name; l_net && !( l_err = pthread_create(&l_tids[i], NULL, s_net_load, l_net) ); l_net = l_net->hh.next, ++i );
+    if ( i < l_nets_count ) {
+        log_it(L_ERROR, "%s%d of %d nets are loading! Thread creation error %d: \"%s\"",
+                        i ? "Only " : "", i, l_nets_count, l_err, dap_strerror(l_err));
+        l_nets_count = i;
     }
-    for (int i = 0; i < l_nets_count; ++i) {
-        pthread_join(l_tids[i], NULL);
+    for ( i = 0; i < l_nets_count; l_err = pthread_join(l_tids[i++], NULL) ) {
+        debug_if(l_err, L_ERROR, "Thread %d join error %d: \"%s\"", i, l_err, dap_strerror(l_err));
     }
     dap_timerfd_delete(l_load_notify_timer->worker, l_load_notify_timer->esocket_uuid);
 }
@@ -945,21 +928,34 @@ void s_set_reply_text_node_status(void **a_str_reply, dap_chain_net_t * a_net){
  * @return true
  * @return false
  */
-void dap_chain_net_purge(dap_chain_net_t *l_net)
+void dap_chain_net_purge(dap_chain_net_t *a_net)
 {
-    dap_chain_srv_purge_all(l_net->pub.id);
-    dap_ledger_purge(l_net->pub.ledger, false);
-    dap_chain_t *l_chain = NULL;
-    DL_FOREACH(l_net->pub.chains, l_chain) {
-        dap_chain_purge(l_chain);
-        dap_chain_load_all(l_chain);
-        l_net->pub.fee_value = uint256_0;
-        l_net->pub.fee_addr = c_dap_chain_addr_blank;
+    dap_chain_net_pvt_t *l_pvt = PVT(a_net);
+    dap_global_db_cluster_t *l_mempool = l_pvt->mempool_clusters;
+    while (l_mempool) {
+        dap_global_db_cluster_t *l_next = l_mempool->next;
+        dap_global_db_cluster_delete(l_mempool);
+        l_mempool = l_next;
     }
-    DL_FOREACH(l_net->pub.chains, l_chain) {
-        if (l_chain->callback_atom_add_from_treshold) {
-            while (l_chain->callback_atom_add_from_treshold(l_chain, NULL))
-                debug_if(s_debug_more, L_DEBUG, "Added atom from treshold");
+    dap_global_db_cluster_delete(l_pvt->orders_cluster);
+    dap_global_db_cluster_delete(l_pvt->nodes_cluster);
+    dap_global_db_cluster_delete(l_pvt->nodes_states);
+    dap_global_db_cluster_delete(l_pvt->common_orders);
+    struct block_reward *l_reward, *l_tmp;
+    DL_FOREACH_SAFE(l_pvt->rewards, l_reward, l_tmp) {
+        DL_DELETE(l_pvt->rewards, l_reward);
+        DAP_DELETE(l_reward);
+    }
+    dap_chain_srv_purge_all(a_net->pub.id);
+    if (a_net->pub.ledger) {
+        dap_ledger_purge(a_net->pub.ledger, false);
+        dap_ledger_handle_free(a_net->pub.ledger);
+    }
+    if (a_net->pub.chains) {
+        dap_chain_t *l_chain = NULL, *l_tmp = NULL;
+        DL_FOREACH_SAFE(a_net->pub.chains, l_chain, l_tmp) {
+            DL_DELETE(a_net->pub.chains, l_chain);
+            dap_chain_delete(l_chain);
         }
     }
 }
@@ -1794,37 +1790,16 @@ void dap_chain_net_deinit()
  */
 void dap_chain_net_delete(dap_chain_net_t *a_net)
 {
-    // Synchronously going to offline state
-    PVT(a_net)->state = PVT(a_net)->state_target = NET_STATE_OFFLINE;
-    s_net_states_proc(a_net);
-    dap_global_db_cluster_t *l_mempool = PVT(a_net)->mempool_clusters;
-    while (l_mempool) {
-        dap_global_db_cluster_t *l_next = l_mempool->next;
-        dap_global_db_cluster_delete(l_mempool);
-        l_mempool = l_next;
-    }
-    dap_global_db_cluster_delete(PVT(a_net)->orders_cluster);
-    dap_global_db_cluster_delete(PVT(a_net)->nodes_cluster);
-    dap_global_db_cluster_delete(PVT(a_net)->nodes_states);
-    dap_global_db_cluster_delete(PVT(a_net)->common_orders);
-
-    DAP_DELETE(PVT(a_net)->node_info);
-    if (a_net->pub.ledger) {
-        dap_ledger_purge(a_net->pub.ledger, true);
-        dap_ledger_handle_free(a_net->pub.ledger);
-    }
-    if (a_net->pub.chains) {
-        dap_chain_t
-            *l_cur = NULL,
-            *l_tmp = NULL;
-        DL_FOREACH_SAFE(a_net->pub.chains, l_cur, l_tmp) {
-            DL_DELETE(a_net->pub.chains, l_cur);
-            dap_chain_delete(l_cur);
-        }
-    }
-    dap_chain_policy_net_remove(a_net->pub.id.uint64);
+    dap_chain_net_pvt_t *l_pvt = PVT(a_net);
+    dap_chain_net_purge(a_net);
+    DAP_DEL_ARRAY(l_pvt->permanent_links_hosts, l_pvt->permanent_links_hosts_count);
+    DAP_DEL_ARRAY(l_pvt->seed_nodes_hosts, l_pvt->seed_nodes_count);
+    DAP_DEL_MULTY(l_pvt->permanent_links_hosts, l_pvt->seed_nodes_hosts, l_pvt->permanent_links_addrs, l_pvt->node_info);
+    // TODO: delete sync_timer and whatever else is initialized AFTER chains load
     HASH_DEL(s_nets_by_name, a_net);
     HASH_DELETE(hh2, s_nets_by_id, a_net);
+    dap_chain_policy_net_remove(a_net->pub.id.uint64);
+    dap_config_close(a_net->pub.config);
     DAP_DELETE(a_net);
 }
 
@@ -1873,104 +1848,20 @@ static int s_nodes_hosts_init(dap_chain_net_t *a_net, dap_config_t *a_cfg, const
     return 0;
 }
 
-/**
- * @brief load network config settings from cellframe-node.cfg file
- *
- * @param a_net_name const char *: network name, for example "home21-network"
- * @param a_acl_idx currently 0
- * @return int
- */
-int s_net_init(const char *a_net_name, const char *a_path, uint16_t a_acl_idx)
-{
-    dap_config_t *l_cfg = dap_config_open(a_path);
-    if (!l_cfg)
-        return log_it(L_ERROR,"Can't open default network config %s", a_path), -1;
-
-    dap_chain_net_t *l_net = s_net_new(a_net_name, l_cfg);
-    if ( !l_net )
-        return log_it(L_ERROR, "Can't create net \"%s\"", a_net_name), dap_config_close(l_cfg), -1;
-
-    dap_chain_net_pvt_t *l_net_pvt = PVT(l_net);
-    l_net_pvt->acl_idx = a_acl_idx;
-    // Transaction can be sent to bridged networks
-    uint16_t l_net_ids_count = 0;
-    const char **l_bridged_net_ids = dap_config_get_array_str(l_cfg, "general", "bridged_network_ids", &l_net_ids_count);
-    if (l_net_ids_count) {
-        l_net->pub.bridged_networks = DAP_NEW_Z_COUNT(dap_chain_net_id_t, l_net_ids_count);
-        unsigned i, j;
-        for (i = 0, j = 0; i < l_net_ids_count; ++i) {
-            if (dap_chain_net_id_parse(l_bridged_net_ids[i], &l_net->pub.bridged_networks[j]) != 0) {
-                log_it(L_ERROR, "Can't add invalid net id \"%s\" to bridged net list of \"%s\"",
-                       l_bridged_net_ids[i], a_net_name);
-                continue;
-            }
-            ++j;
-        }
-        l_net->pub.bridged_networks_count = j;
-        if (j < i)
-            l_net->pub.bridged_networks = DAP_REALLOC_COUNT(l_net->pub.bridged_networks, j); // Can be NULL, it's ok
-    }
-
-    // read nodes addrs and hosts
-    if (
-        dap_config_stream_addrs_parse(l_cfg, "general", "permanent_nodes_addrs", &l_net_pvt->permanent_links_addrs, &l_net_pvt->permanent_links_addrs_count) ||
-        s_nodes_hosts_init(l_net, l_cfg, "permanent_nodes_hosts", &l_net_pvt->permanent_links_hosts, &l_net_pvt->permanent_links_hosts_count) ||
-        s_nodes_hosts_init(l_net, l_cfg, "seed_nodes_hosts", &l_net_pvt->seed_nodes_hosts, &l_net_pvt->seed_nodes_count) ||
-        (!l_net_pvt->seed_nodes_count && s_nodes_hosts_init(l_net, l_cfg, "bootstrap_hosts", &l_net_pvt->seed_nodes_hosts, &l_net_pvt->seed_nodes_count) )
-    ) {
-        dap_chain_net_delete(l_net);
-        dap_config_close(l_cfg);
-        return -4;
-    }
-    if (!l_net_pvt->seed_nodes_count)
-        log_it(L_WARNING, "Can't read seed nodes addresses, work with local balancer only");
-
-    // Get list chains name for enabled debug mode
-    bool is_esbocs_debug = dap_config_get_item_bool_default(l_cfg, "esbocs", "consensus_debug", false);
-
-    struct dirent *l_dir_entry;
-    // Services register & configure
-    dap_chain_srv_start(l_net->pub.id, DAP_CHAIN_NET_SRV_XCHANGE_LITERAL, NULL);        // Harcoded core service starting for exchange capability
-    dap_chain_srv_start(l_net->pub.id, DAP_CHAIN_NET_SRV_STAKE_POS_DELEGATE_LITERAL, NULL);    // Harcoded core service starting for delegated keys storage
-    char *l_services_path = dap_strdup_printf("%s/network/%s/services", dap_config_path(), l_net->pub.name);
-    DIR *l_service_cfg_dir = opendir(l_services_path);
-    DAP_DELETE(l_services_path);
-    while (l_service_cfg_dir && (l_dir_entry = readdir(l_service_cfg_dir)) != NULL) {
-        if (l_dir_entry->d_name[0] == '\0')
-            continue;
-        const char *l_entry_name = l_dir_entry->d_name;
-        size_t l_entry_len = strlen(l_entry_name);
-        if (l_entry_len < 4 || // It has non zero name excluding file extension
-                strncmp(l_entry_name + l_entry_len - 4, ".cfg", 4) != 0) // its not a .cfg file
-            continue;
-        log_it(L_DEBUG, "Opening service config \"%s\"...", l_entry_name);
-        char *l_service_cfg_path = dap_strdup_printf("network/%s/services/%s", l_net->pub.name, l_entry_name);
-        dap_config_t *l_cfg_new = dap_config_open(l_service_cfg_path);
-        if (l_cfg_new) {
-            char *l_service_name = DAP_DUP_SIZE((char *)l_entry_name, l_entry_len - 3);
-            l_service_name[l_entry_len - 4] = 0;
-            dap_chain_srv_start(l_net->pub.id, l_service_name, l_cfg_new);
-            dap_config_close(l_cfg_new);
-            DAP_DELETE(l_service_name);
-        }
-        DAP_DELETE(l_service_cfg_path);
-    }
-    if (l_service_cfg_dir)
-        closedir(l_service_cfg_dir);
-
-    /* *** Chains init by configs *** */
+static int s_chains_init_all(dap_chain_net_t *a_net, const char *a_path, uint16_t *a_ledger_flags) {
     DIR *l_chains_dir = opendir(a_path);
     if (!l_chains_dir)
-        return log_it(L_ERROR, "Can't find any chains for network %s", l_net->pub.name), dap_chain_net_delete(l_net), -7;
-
+        return log_it(L_ERROR, "Can't find any chains for network %s", a_net->pub.name), -1;
+    bool is_esbocs_debug = dap_config_get_item_bool_default(a_net->pub.config, "esbocs", "consensus_debug", false);
     dap_config_t *l_chain_config, *l_all_chain_configs = NULL, *l_tmp_cfg;
     char l_chain_cfg_path[MAX_PATH + 1] = { '\0' };
-    int l_pos = snprintf(l_chain_cfg_path, MAX_PATH, "network/%s/", a_net_name);
+    int l_pos = snprintf(l_chain_cfg_path, MAX_PATH, "network/%s/", a_net->pub.name);
+    struct dirent *l_dir_entry = NULL;
     while (( l_dir_entry = readdir(l_chains_dir) )) {
         unsigned short l_len = strlen(l_dir_entry->d_name);
         if ( l_len > 4 && !dap_strncmp(l_dir_entry->d_name + l_len - 4, ".cfg", 4) ) {
             *(l_dir_entry->d_name + l_len - 4) = '\0';
-            log_it(L_DEBUG, "Opening chain config \"%s.%s\"", a_net_name, l_dir_entry->d_name);
+            log_it(L_DEBUG, "Opening chain config \"%s.%s\"", a_net->pub.name, l_dir_entry->d_name);
             dap_strncpy(l_chain_cfg_path + l_pos, l_dir_entry->d_name, MAX_PATH - l_pos);
             if (!( l_chain_config = dap_config_open(l_chain_cfg_path) )) {
                 log_it(L_ERROR, "Can't open chain config %s, skip it", l_dir_entry->d_name);
@@ -1981,15 +1872,16 @@ int s_net_init(const char *a_net_name, const char *a_path, uint16_t a_acl_idx)
     }
     closedir(l_chains_dir);
     if (!l_all_chain_configs)
-        return log_it(L_ERROR, "Can't find any chains for network %s", l_net->pub.name), dap_chain_net_delete(l_net), -8;
+        return log_it(L_ERROR, "Can't find any chains for network %s", a_net->pub.name), -2;
 
     HASH_SORT(l_all_chain_configs, s_cmp_cfg_pri);
     dap_chain_t *l_chain;
     dap_chain_type_t *l_types_arr;
     char l_occupied_default_types[CHAIN_TYPE_MAX] = { 0 };
+    int l_poa_signers = 0, l_poa_signers_min = 0;
     HASH_ITER(hh, l_all_chain_configs, l_chain_config, l_tmp_cfg) {
-        if (( l_chain = dap_chain_load_from_cfg(l_net->pub.name, l_net->pub.id, l_chain_config) )) {
-            DL_APPEND(l_net->pub.chains, l_chain);
+        if (( l_chain = dap_chain_load_from_cfg(a_net->pub.name, a_net->pub.id, l_chain_config) )) {
+            DL_APPEND(a_net->pub.chains, l_chain);
             l_types_arr = l_chain->default_datum_types;
             uint16_t
                 i = 0,
@@ -1997,8 +1889,7 @@ int s_net_init(const char *a_net_name, const char *a_path, uint16_t a_acl_idx)
             for ( ; i < k; ++i) {
                 if ( l_occupied_default_types[l_types_arr[i]] ) {
                     if ( i < k - 1 )
-                        l_types_arr[i] =
-                            l_types_arr[k - 1];
+                        l_types_arr[i] = l_types_arr[k - 1];
                     --i;
                     --k;
                 } else
@@ -2008,24 +1899,59 @@ int s_net_init(const char *a_net_name, const char *a_path, uint16_t a_acl_idx)
                 l_chain->default_datum_types_count = k;
                 l_chain->default_datum_types = DAP_REALLOC_COUNT(l_chain->default_datum_types, k);
             }
-            if (!dap_strcmp(DAP_CHAIN_PVT(l_chain)->cs_name, "esbocs") && is_esbocs_debug) {
+            if ( !dap_strcmp(DAP_CHAIN_PVT(l_chain)->cs_name, "esbocs") && is_esbocs_debug )
                 dap_chain_esbocs_change_debug_mode(l_chain, true);
+            if (l_chain->callback_load_from_gdb && a_ledger_flags) {
+                *a_ledger_flags &= ~DAP_LEDGER_MAPPED;
+                *a_ledger_flags |= DAP_LEDGER_THRESHOLD_ENABLED;
+            }
+            if ( l_chain->callback_get_poa_certs ) {
+                uint16_t l_min_count = 0;
+                a_net->pub.keys = dap_list_append(a_net->pub.keys, l_chain->callback_get_poa_certs(l_chain, NULL, &l_min_count));
+                a_net->pub.keys_min_count += l_min_count;
             }
         } else {
             HASH_DEL(l_all_chain_configs, l_chain_config);
             dap_config_close(l_chain_config);
-            dap_chain_net_delete(l_net);
-            return -5;
+            return -3;
         }
     }
     HASH_CLEAR(hh, l_all_chain_configs);
+    return 0;
+}
 
-    // LEDGER model
+int s_chain_net_preload(dap_chain_net_t *a_net) {
+    // Services register & configure
+    dap_chain_srv_start(a_net->pub.id, DAP_CHAIN_NET_SRV_XCHANGE_LITERAL, NULL);        // Harcoded core service starting for exchange capability
+    dap_chain_srv_start(a_net->pub.id, DAP_CHAIN_NET_SRV_STAKE_POS_DELEGATE_LITERAL, NULL);    // Harcoded core service starting for delegated keys storage
+    char *l_services_path = dap_strdup_printf("%s/network/%s/services", dap_config_path(), a_net->pub.name);
+    DIR *l_service_cfg_dir = opendir(l_services_path);
+    DAP_DELETE(l_services_path);
+    if (l_service_cfg_dir) {
+        for ( struct dirent *l_dir_entry; ( l_dir_entry = readdir(l_service_cfg_dir) ); ) {
+            const char *l_entry_name = l_dir_entry->d_name;
+            size_t l_entry_len = strlen(l_entry_name);
+            if (l_entry_len < 4 || // It has non zero name excluding file extension
+                    strncmp(l_entry_name + l_entry_len - 4, ".cfg", 4) != 0) // its not a .cfg file
+                continue;
+            log_it(L_DEBUG, "Opening service config \"%s\"...", l_entry_name);
+            char *l_service_cfg_path = dap_strdup_printf("network/%s/services/%s", a_net->pub.name, l_entry_name);
+            dap_config_t *l_cfg_new = dap_config_open(l_service_cfg_path);
+            if (l_cfg_new) {
+                char l_service_name[l_entry_len - 3];
+                dap_strncpy(l_service_name, l_entry_name, l_entry_len - 4);
+                dap_chain_srv_start(a_net->pub.id, l_service_name, l_cfg_new);
+                dap_config_close(l_cfg_new);
+            }
+            DAP_DELETE(l_service_cfg_path);
+        }
+        closedir(l_service_cfg_dir);
+    }
     uint16_t l_ledger_flags = 0;
-    switch ( PVT( l_net )->node_role.enums ) {
+    switch ( PVT( a_net )->node_role.enums ) {
     case NODE_ROLE_LIGHT:
         //break;
-        PVT( l_net )->node_role.enums = NODE_ROLE_FULL; // TODO: implement light mode
+        PVT( a_net )->node_role.enums = NODE_ROLE_FULL; // TODO: implement light mode
     case NODE_ROLE_FULL:
         l_ledger_flags |= DAP_LEDGER_CHECK_LOCAL_DS;
         if (dap_config_get_item_bool_default(g_config, "ledger", "cache_enabled", false))
@@ -2036,185 +1962,156 @@ int s_net_init(const char *a_net_name, const char *a_path, uint16_t a_acl_idx)
     if (dap_config_get_item_bool_default(g_config, "ledger", "mapped", true))
         l_ledger_flags |= DAP_LEDGER_MAPPED;
 
-    for (dap_chain_t *l_chain = l_net->pub.chains; l_chain; l_chain = l_chain->next) {
-        if (l_chain->callback_load_from_gdb) {
-            l_ledger_flags &= ~DAP_LEDGER_MAPPED;
-            l_ledger_flags |= DAP_LEDGER_THRESHOLD_ENABLED;
-            continue;
+    int l_res = s_chains_init_all(a_net, a_net->pub.config->path, &l_ledger_flags);
+    if (!l_res)
+        a_net->pub.ledger = dap_ledger_create(a_net, l_ledger_flags);
+    
+    return l_res;
+    
+}
+
+/**
+ * @brief load network config settings from cellframe-node.cfg file
+ *
+ * @param a_net_name const char *: network name, for example "home21-network"
+ * @param a_acl_idx currently 0
+ * @return int
+ */
+int s_net_init(const char *a_net_name, const char *a_path, uint16_t a_acl_idx)
+{
+    dap_config_t *l_cfg = dap_config_open(a_path);
+    dap_return_val_if_fail_err(l_cfg, -1, "Can't open default network config %s", a_path);
+
+    dap_chain_net_t *l_net = s_net_new(a_net_name, l_cfg);
+    if ( !l_net )
+        return log_it(L_ERROR, "Can't create net \"%s\"", a_net_name), dap_config_close(l_cfg), -1;
+
+    dap_chain_net_pvt_t *l_net_pvt = PVT(l_net);
+    l_net_pvt->acl_idx = a_acl_idx;
+    // Transaction can be sent to bridged networks
+    uint16_t l_net_ids_count = 0;
+    const char **l_bridged_net_ids = dap_config_get_array_str(l_cfg, "general", "bridged_network_ids", &l_net_ids_count);
+    if (l_net_ids_count) {
+        l_net->pub.bridged_networks = DAP_NEW_Z_COUNT(dap_chain_net_id_t, l_net_ids_count);
+        unsigned i, j;
+        for (i = 0, j = 0; i < l_net_ids_count; ++i) {
+            if (dap_chain_net_id_parse(l_bridged_net_ids[i], &l_net->pub.bridged_networks[j]) != 0) {
+                log_it(L_ERROR, "Can't add invalid net id \"%s\" to bridged net list of \"%s\"",
+                       l_bridged_net_ids[i], a_net_name);
+                continue;
+            }
+            ++j;
         }
-        if (!l_chain->callback_get_poa_certs)
-            continue;
-        if (!l_net->pub.keys)
-            l_net->pub.keys = l_chain->callback_get_poa_certs(l_chain, NULL, NULL);
+        l_net->pub.bridged_networks_count = j;
+        if (j < i)
+            l_net->pub.bridged_networks = j
+                ? DAP_REALLOC_COUNT(l_net->pub.bridged_networks, j)
+                : ( DAP_DELETE(l_net->pub.bridged_networks), NULL ); // No bridged nets is OK
     }
-    if (!l_net->pub.keys)
-        log_it(L_WARNING, "PoA certificates for net %s not found", l_net->pub.name);
 
-    // init LEDGER model
-    l_net->pub.ledger = dap_ledger_create(l_net, l_ledger_flags);
-    return 0;
+    // read nodes addrs and hosts
+    if (
+        dap_config_stream_addrs_parse(l_cfg, "general", "permanent_nodes_addrs", &l_net_pvt->permanent_links_addrs, &l_net_pvt->permanent_links_addrs_count)
+     || s_nodes_hosts_init(l_net, l_cfg, "permanent_nodes_hosts", &l_net_pvt->permanent_links_hosts, &l_net_pvt->permanent_links_hosts_count)
+     || s_nodes_hosts_init(l_net, l_cfg, "seed_nodes_hosts", &l_net_pvt->seed_nodes_hosts, &l_net_pvt->seed_nodes_count)
+     || ( !l_net_pvt->seed_nodes_count && s_nodes_hosts_init(l_net, l_cfg, "bootstrap_hosts", &l_net_pvt->seed_nodes_hosts, &l_net_pvt->seed_nodes_count) )
+    ) {
+        dap_chain_net_delete(l_net);
+        return -4;
+    }
+    if ( !l_net_pvt->seed_nodes_count )
+        log_it(L_WARNING, "Can't read seed nodes addresses, work with local balancer only");
+
+    if ( dap_server_enabled() && ( l_net_pvt->node_info->ext_port = dap_config_get_item_uint16(g_config, "server", "ext_port") ))
+        log_it(L_INFO, "Set external port %u for adding in node list", l_net_pvt->node_info->ext_port);
+
+    int l_ret = s_chain_net_preload(l_net);
+    return l_ret ? dap_chain_net_delete(l_net), l_ret : 0;
+
 }
 
 static void *s_net_load(void *a_arg)
 {
     dap_chain_net_t *l_net = a_arg;
-    int l_err_code = 0;
-
-    if (!l_net->pub.config) {
-        log_it(L_ERROR,"Can't open default network config");
-        l_err_code = -1;
-        goto ret;
-    }
+    dap_return_val_if_fail_err(l_net->pub.config, NULL, "Can't open network %s config", l_net->pub.name);
 
     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)) {
-        log_it(L_WARNING,"Start one time ledger cache reloading");
-        dap_ledger_purge(l_net->pub.ledger, false);
-        dap_chain_srv_purge_all(l_net->pub.id);
-    }
-    //else dap_chain_net_srv_stake_load_cache(l_net); // TODO rework ledger and staking caches
-    // load chains
-    dap_chain_t *l_chain = l_net->pub.chains;
-    clock_t l_chain_load_start_time; 
-    l_chain_load_start_time = clock(); 
-    while (l_chain) {
+    l_net_pvt->balancer_type = dap_config_get_item_bool_default(l_net->pub.config, "general", "use_dns_links", false);
+    char l_gdb_groups_mask[DAP_GLOBAL_DB_GROUP_NAME_SIZE_MAX];
+    dap_chain_t *l_chain;
+    DL_FOREACH(l_net->pub.chains, l_chain) {
         l_net->pub.fee_value = uint256_0;
         l_net->pub.fee_addr = c_dap_chain_addr_blank;
-        if (!dap_chain_load_all(l_chain)) {
-            log_it (L_NOTICE, "Loaded chain files");
-            if ( DAP_CHAIN_PVT(l_chain)->need_reorder ) // # unsafe crutch, need to escape reorder usage
-            {
-                log_it(L_DAP, "Reordering chain files for chain %s", l_chain->name);
-                if (l_chain->callback_atom_add_from_treshold) {
-                    while (l_chain->callback_atom_add_from_treshold(l_chain, NULL))
-                        log_it(L_DEBUG, "Added atom from treshold");
-                }
-                dap_chain_save_all(l_chain);
-                
-                DAP_CHAIN_PVT(l_chain)->need_reorder = false;
-                dap_chain_purge(l_chain);
-                dap_ledger_purge(l_net->pub.ledger, false);
-                l_net->pub.fee_value = uint256_0;
-                l_net->pub.fee_addr = c_dap_chain_addr_blank;
-                dap_chain_load_all(l_chain);
-            }
-            if (l_chain->callback_atom_add_from_treshold) {
-                while (l_chain->callback_atom_add_from_treshold(l_chain, NULL))
-                    log_it(L_DEBUG, "Added atom from treshold");
-            }
-        } else {
-            //dap_chain_save_all( l_chain );
-            log_it (L_NOTICE, "Initialized chain files");
-        }
+        int l_ret = dap_chain_load_all(l_chain);
         l_chain->atom_num_last = 0;
-        time_t l_chain_load_time_taken = clock() - l_chain_load_start_time; 
-        double time_taken = ((double)l_chain_load_time_taken)/CLOCKS_PER_SEC; // in seconds 
-        log_it(L_NOTICE, "[%s] Chain [%s] processing took %f seconds", l_chain->net_name, l_chain->name, time_taken);
-        l_chain = l_chain->next;
-    }
-    dap_ledger_load_end(l_net->pub.ledger);
-
-    // Do specific role actions post-chain created
-    l_net_pvt->state_target = NET_STATE_OFFLINE;
-    switch ( l_net_pvt->node_role.enums ) {
-        case NODE_ROLE_ROOT_MASTER:{
-            // Set to process everything in datum pool
-            dap_chain_t * l_chain = NULL;
-            DL_FOREACH(l_net->pub.chains, l_chain)
-                l_chain->is_datum_pool_proc = true;
-            log_it(L_INFO,"Root master node role established");
-        } // Master root includes root
-        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;
-            log_it(L_INFO,"Root node role established");
-        } break;
+        switch ( l_net_pvt->node_role.enums ) {
+        case NODE_ROLE_ROOT_MASTER:
+        /* Processes everything in mempool*/
+            l_chain->is_datum_pool_proc = true;
+            break;
+        case NODE_ROLE_ROOT:
+        /* Processes zerochain only */
+            l_chain->is_datum_pool_proc = !l_chain->id.uint64;
+            break;
         case NODE_ROLE_CELL_MASTER:
-        case NODE_ROLE_MASTER:{
-            uint16_t l_proc_chains_count=0;
-            const char **l_proc_chains = dap_config_get_array_str(l_net->pub.config, "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 );
-                    if (l_chain)
-                        l_chain->is_datum_pool_proc = true;
-                    else
-                        log_it(L_WARNING, "Can't find chain id 0x%016" DAP_UINT64_FORMAT_X, l_chain_id.uint64);
-                }
-            }
-            log_it(L_INFO,"Master node role established");
+        case NODE_ROLE_MASTER: {
+        /* Processes specified chains only */
+            uint16_t k = 0;
+            dap_chain_id_t l_chain_id;
+            const char **l_proc_chains = dap_config_get_array_str(l_net->pub.config, "role-master", "proc_chains", &k);
+            while (k--)
+                l_chain->is_datum_pool_proc = ( !dap_chain_id_parse(l_proc_chains[k], &l_chain_id) && (l_chain->id.uint64 == l_chain_id.uint64) );
         } break;
-        case NODE_ROLE_FULL:{
-            log_it(L_INFO,"Full node role established");
-        } break;
-        case NODE_ROLE_LIGHT:
-        default:
-            log_it(L_INFO,"Light node role established");
-
-    }
-
-    l_net_pvt->balancer_type = dap_config_get_item_bool_default(l_net->pub.config, "general", "use_dns_links", false);
-
-    // Init GlobalDB clusters for mempool, service and nodes (with aliases)
-    char *l_gdb_groups_mask = NULL;
-    DL_FOREACH(l_net->pub.chains, l_chain) {
+        default: break;
+        }
         // Personal chain mempool cluster for each chain
-        l_gdb_groups_mask = dap_strdup_printf("%s.chain-%s.mempool", l_net->pub.gdb_groups_prefix, l_chain->name);
+        snprintf(l_gdb_groups_mask, sizeof(l_gdb_groups_mask), "%s.chain-%s.mempool",
+                                                               l_net->pub.gdb_groups_prefix, l_chain->name);
         dap_global_db_cluster_t *l_cluster = dap_global_db_cluster_add(
                                                 dap_global_db_instance_get_default(), l_net->pub.name,
                                                 dap_guuid_compose(l_net->pub.id.uint64, 0), l_gdb_groups_mask,
                                                 dap_config_get_item_int32_default(l_net->pub.config, "global_db", "mempool_ttl", DAP_CHAIN_NET_MEMPOOL_TTL),
                                                 true, DAP_GDB_MEMBER_ROLE_USER, DAP_CLUSTER_TYPE_EMBEDDED);
-        if (!l_cluster) {
-            log_it(L_ERROR, "Can't initialize mempool cluster for network %s", l_net->pub.name);
-            l_err_code = -2;
-            goto ret;
-        }
+        dap_return_val_if_fail_err(l_cluster, NULL, "Net \"%s\" loading error %d: can't initialize mempool cluster",
+                                                    l_net->pub.name, -2);
         dap_chain_net_add_auth_nodes_to_cluster(l_net, l_cluster);
-        DAP_DELETE(l_gdb_groups_mask);
         if (l_net->pub.chains == l_chain)   // Pointer for first mempool cluster in global double-linked list of clusters
             l_net_pvt->mempool_clusters = l_cluster;
     }
+    dap_ledger_load_end(l_net->pub.ledger);
+    log_it(L_INFO, "Node role \"%s\" established in net %s", dap_chain_node_role_to_str(l_net_pvt->node_role), l_net->pub.name);
+    l_net_pvt->state_target = NET_STATE_OFFLINE;
+
+    // Init GlobalDB clusters for service and nodes (with aliases)
     // Service orders cluster
-    l_gdb_groups_mask = dap_strdup_printf("%s.service.orders", l_net->pub.gdb_groups_prefix);
+    snprintf(l_gdb_groups_mask, sizeof(l_gdb_groups_mask), "%s.service.orders", l_net->pub.gdb_groups_prefix);
     l_net_pvt->orders_cluster = dap_global_db_cluster_add(dap_global_db_instance_get_default(),
                                                           l_net->pub.name, dap_guuid_compose(l_net->pub.id.uint64, 0),
                                                           l_gdb_groups_mask, 0, true,
                                                           DAP_GDB_MEMBER_ROLE_GUEST,
                                                           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);
-        goto ret;
-    }
+    dap_return_val_if_fail_err(l_net_pvt->orders_cluster, NULL, "Net \"%s\" loading error %d: can't initialize orders cluster",
+                                                                l_net->pub.name, -3);
     dap_chain_net_add_auth_nodes_to_cluster(l_net, l_net_pvt->orders_cluster);
-    DAP_DELETE(l_gdb_groups_mask);
     // Common orders cluster
-    l_gdb_groups_mask = dap_strdup_printf("%s.orders", l_net->pub.gdb_groups_prefix);
+    snprintf(l_gdb_groups_mask, sizeof(l_gdb_groups_mask), "%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, 0, true,
                                                           DAP_GDB_MEMBER_ROLE_USER,
                                                           DAP_CLUSTER_TYPE_EMBEDDED);
-    if (!l_net_pvt->common_orders) {
-        log_it(L_ERROR, "Can't initialize orders cluster for network %s", l_net->pub.name);
-        goto ret;
-    }
+    dap_return_val_if_fail_err(l_net_pvt->common_orders, NULL, "Net \"%s\" loading error %d: can't initialize common orders cluster",
+                                                               l_net->pub.name, -4);
     dap_chain_net_add_auth_nodes_to_cluster(l_net, l_net_pvt->common_orders);
-    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);
+    snprintf(l_gdb_groups_mask, sizeof(l_gdb_groups_mask), "%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, DAP_CHAIN_NET_NODES_TTL, true,
                                                         DAP_GDB_MEMBER_ROLE_USER,
                                                         DAP_CLUSTER_TYPE_EMBEDDED);
-    DAP_DELETE(l_gdb_groups_mask);
+    dap_return_val_if_fail_err(l_net_pvt->nodes_states, NULL, "Net \"%s\" loading error %d: can't initialize node states cluster",
+                                                               l_net->pub.name, -5);
     // Nodes and its aliases cluster
     snprintf(l_net->pub.gdb_nodes, sizeof(l_net->pub.gdb_nodes), "%s.%s", l_net->pub.gdb_groups_prefix, s_gdb_nodes_postfix);
     l_net_pvt->nodes_cluster = dap_global_db_cluster_add(dap_global_db_instance_get_default(),
@@ -2222,28 +2119,18 @@ static void *s_net_load(void *a_arg)
                                                          l_net->pub.gdb_nodes, 7200, true,
                                                          DAP_GDB_MEMBER_ROLE_GUEST,
                                                          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);
-        l_err_code = -3;
-        goto ret;
-    }
+    dap_return_val_if_fail_err(l_net_pvt->nodes_cluster, NULL, "Net \"%s\" loading error %d: can't initialize nodes cluster",
+                                                               l_net->pub.name, -6);
     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);
 
-    if (dap_link_manager_add_net(l_net->pub.id.uint64, l_net_pvt->nodes_cluster->links_cluster,
-                                dap_config_get_item_uint16_default(l_net->pub.config,
-                                                                   "general", "links_required", 3))) {
+    if ( dap_link_manager_add_net(l_net->pub.id.uint64, l_net_pvt->nodes_cluster->links_cluster,
+                                  dap_config_get_item_uint16_default(l_net->pub.config, "general", "links_required", 3)) )
         log_it(L_WARNING, "Can't add net %s to link manager", l_net->pub.name);
-    }
 
     DL_FOREACH(l_net->pub.chains, l_chain)
         dap_chain_cs_load(l_chain, l_net->pub.config);
 
-    if ( s_server_enabled ) {
-        if (( l_net_pvt->node_info->ext_port = dap_config_get_item_uint16(g_config, "server", "ext_port") ))
-            log_it(L_INFO, "Set external port %u for adding in node list", l_net_pvt->node_info->ext_port);
-    }
-
     l_net_pvt->node_info->address.uint64 = g_node_addr.uint64;
 
     log_it(L_NOTICE, "Net load information: node_addr " NODE_ADDR_FP_STR ", seed links %u, cell_id 0x%016"DAP_UINT64_FORMAT_X,
@@ -2254,7 +2141,7 @@ static void *s_net_load(void *a_arg)
     // TODO rework alias concept
     const char * l_node_addr_type = dap_config_get_item_str_default(l_net->pub.config ,
                                                                     "general", "node_addr_type", "auto");
-    if (!dap_strcmp(l_node_addr_type, "static")) {
+    if ( !dap_strcmp(l_node_addr_type, "static") ) {
         const char *l_node_alias_str = dap_config_get_item_str_default(l_net->pub.config, "general", "node-addr",
                                                                        dap_config_get_item_str(l_net->pub.config,
                                                                                                "general", "node-alias"));
@@ -2270,13 +2157,10 @@ static void *s_net_load(void *a_arg)
 
     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, c_sync_timer_period);
-
-    log_it(L_INFO, "Chain network \"%s\" initialized", l_net->pub.name);
+    // TODO! Delete the timer in "purge()"
+    log_it(L_INFO, "Network \"%s\" initialized", l_net->pub.name);
     l_net_pvt->state = NET_STATE_OFFLINE;
-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);
-    return NULL;
+    return l_net;
 }
 
 dap_global_db_cluster_t *dap_chain_net_get_mempool_cluster(dap_chain_t *a_chain)
@@ -2907,11 +2791,7 @@ int dap_chain_net_add_reward(dap_chain_net_t *a_net, uint256_t a_reward, uint64_
         log_it(L_ERROR, "Can't add retrospective reward for block");
         return -2;
     }
-    struct block_reward *l_new_reward = DAP_NEW_Z(struct block_reward);
-    if (!l_new_reward) {
-        log_it(L_CRITICAL, "Out of memory");
-        return -3;
-    }
+    struct block_reward *l_new_reward = DAP_NEW_Z_RET_VAL_IF_FAIL(struct block_reward, -3);
     l_new_reward->block_number = a_block_num;
     l_new_reward->reward = a_reward;
     // Place new reward at begining
@@ -3384,18 +3264,14 @@ DAP_INLINE dap_chain_net_state_t dap_chain_net_get_target_state(dap_chain_net_t
 bool dap_chain_net_stop(dap_chain_net_t *a_net)
 {
     int l_attempts_count = 0;
-    bool l_ret = false;
-    if (dap_chain_net_get_target_state(a_net) == NET_STATE_ONLINE) {
-        dap_chain_net_state_go_to(a_net, NET_STATE_OFFLINE);
-        l_ret = true;
-    } else if (dap_chain_net_get_state(a_net) != NET_STATE_OFFLINE) {
+    if ( dap_chain_net_get_target_state(a_net) == NET_STATE_ONLINE || dap_chain_net_get_state(a_net) != NET_STATE_OFFLINE )
         dap_chain_net_state_go_to(a_net, NET_STATE_OFFLINE);
+
+    while (dap_chain_net_get_state(a_net) != NET_STATE_OFFLINE && l_attempts_count++ < 5) {
+        sched_yield();
+        sleep(1);
     }
-    while (dap_chain_net_get_state(a_net) != NET_STATE_OFFLINE && l_attempts_count++ < 5) { sleep(1); }
-    if (dap_chain_net_get_state(a_net) != NET_STATE_OFFLINE) {
-        log_it(L_ERROR, "Can't stop net %s", a_net->pub.name);
-    }
-    return l_ret;
+    return dap_chain_net_get_state(a_net) == NET_STATE_OFFLINE;
 }
 
 /*------------------------------------State machine block end---------------------------------*/
diff --git a/modules/net/include/dap_chain_net.h b/modules/net/include/dap_chain_net.h
index 8dd926f725522fa068abc3622a557d1dba4baef7..e6c4a41d506cf1cd0ff80ddf4f9767ef702b1720 100644
--- a/modules/net/include/dap_chain_net.h
+++ b/modules/net/include/dap_chain_net.h
@@ -62,7 +62,10 @@ typedef struct dap_chain_net {
         dap_chain_net_id_t id;
         char name[DAP_CHAIN_NET_NAME_MAX + 1], gdb_nodes[DAP_CHAIN_NET_NAME_MAX + sizeof(s_gdb_nodes_postfix) + 1];
         const char *gdb_groups_prefix, *native_ticker;
+        // PoA section
         dap_list_t *keys;               // List of PoA certs for net
+        uint16_t keys_min_count;        // PoA minimum required number
+        //
         dap_chain_t *chains;            // double-linked list of chains
         dap_ledger_t *ledger;
         uint256_t fee_value;            // Net fee
diff --git a/modules/node-cli/dap_chain_node_cli_cmd_token.c b/modules/node-cli/dap_chain_node_cli_cmd_token.c
index 93bdf576912165a4241532c32af2277cb1c418cd..545bdf336c7bb6d0f6a78fec59bca1eaa6f33a78 100644
--- a/modules/node-cli/dap_chain_node_cli_cmd_token.c
+++ b/modules/node-cli/dap_chain_node_cli_cmd_token.c
@@ -425,31 +425,24 @@ static int s_parse_common_token_decl_arg(int a_argc, char ** a_argv, json_object
  */
 dap_list_t* s_parse_wallet_addresses(const char *a_tx_address, dap_list_t *l_tsd_list, size_t *l_tsd_total_size, uint32_t flag)
 {
-    if (!a_tx_address){
-       log_it(L_DEBUG,"a_tx_address is null");
-       return l_tsd_list;
-    }
-
-    char ** l_str_wallet_addr = NULL;
-    l_str_wallet_addr = dap_strsplit(a_tx_address,",",0xffff);
+    dap_return_val_if_fail(a_tx_address, l_tsd_list);
 
-    if (!l_str_wallet_addr){
-       log_it(L_DEBUG,"Error in wallet addresses array parsing in tx_receiver_allowed parameter");
-       return l_tsd_list;
-    }
+    char **l_str_wallet_addr = dap_strsplit(a_tx_address,",",0xffff);
+    if (!l_str_wallet_addr)
+       return log_it(L_ERROR, "Can't split \"%s\" by commas!", a_tx_address), l_tsd_list;
 
-    while (l_str_wallet_addr && *l_str_wallet_addr){
-        log_it(L_DEBUG,"Processing wallet address: %s", *l_str_wallet_addr);
-        dap_chain_addr_t *addr_to = dap_chain_addr_from_str(*l_str_wallet_addr);
+    for (char **l_cur = l_str_wallet_addr; l_cur && *l_cur; ++l_cur) {
+        log_it(L_DEBUG, "Processing wallet address: %s", *l_cur);
+        dap_chain_addr_t *addr_to = dap_chain_addr_from_str(*l_cur);
         if (addr_to){
-            dap_tsd_t * l_tsd = dap_tsd_create(flag, addr_to, sizeof(dap_chain_addr_t));
+            dap_tsd_t *l_tsd = dap_tsd_create(flag, addr_to, sizeof(dap_chain_addr_t));
             l_tsd_list = dap_list_append(l_tsd_list, l_tsd);
             *l_tsd_total_size += dap_tsd_size(l_tsd);
-        }else{
-            log_it(L_DEBUG,"Error in wallet address parsing");
-        }
-        l_str_wallet_addr++;
+            DAP_DELETE(addr_to);
+        } else
+            log_it(L_ERROR, "Can't convert it to address!");
     }
+    dap_strfreev(l_str_wallet_addr);
     return l_tsd_list;
 }
 
@@ -478,16 +471,16 @@ static int s_parse_additional_token_decl_arg(int a_argc, char ** a_argv, json_ob
     if (!a_update_token) {
         if (a_params->ext.flags){   // Flags
             l_str_flags = dap_strsplit(a_params->ext.flags,",",0xffff );
-            while (l_str_flags && *l_str_flags){
-                uint16_t l_flag = dap_chain_datum_token_flag_from_str(*l_str_flags);
+            for (char **l_cur = l_str_flags; l_cur && *l_cur; ++l_cur) {
+                uint16_t l_flag = dap_chain_datum_token_flag_from_str(*l_cur);
                 if (l_flag == DAP_CHAIN_DATUM_TOKEN_FLAG_UNDEFINED ){
                     dap_json_rpc_error_add(a_json_arr_reply, DAP_CHAIN_NODE_CLI_CMD_VALUES_PARSE_NET_CHAIN_ERR_FLAG_UNDEF,
                                "Flag can't be \"%s\"",*l_str_flags);
                     return -20;
                 }
                 l_flags |= l_flag; // if we have multiple flags
-                l_str_flags++;
             }
+            dap_strfreev(l_str_flags);
         }
     } else {
         const char *l_set_flags = NULL;
diff --git a/modules/node-cli/dap_chain_node_cli_cmd_tx.c b/modules/node-cli/dap_chain_node_cli_cmd_tx.c
index 1cffdda399e6f5c9c979f9a91cd024d57338722f..b620ce583d425bec2c375481d7946701d2f2e03a 100644
--- a/modules/node-cli/dap_chain_node_cli_cmd_tx.c
+++ b/modules/node-cli/dap_chain_node_cli_cmd_tx.c
@@ -2769,9 +2769,7 @@ int com_tx_create(int a_argc, char **a_argv, void **a_json_arr_reply)
             dap_enc_key_delete(l_priv_key);
             dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_TX_CREATE_EQ_SOURCE_DESTINATION_ADDRESS, "The transaction cannot be directed to the same address as the source.");
             json_object_put(l_jobj_result);
-            for (size_t j = 0; j < l_addr_el_count; ++j) {
-                    DAP_DELETE(l_addr_to[j]);
-            }
+            DAP_DEL_ARRAY(l_addr_to, l_addr_el_count);
             DAP_DEL_MULTY(l_addr_to, l_value);
             return DAP_CHAIN_NODE_CLI_COM_TX_CREATE_EQ_SOURCE_DESTINATION_ADDRESS;
         }
diff --git a/modules/service/datum/dap_chain_net_srv_datum.c b/modules/service/datum/dap_chain_net_srv_datum.c
index 768e158fb136c8f26829c39c618f1cabdfdb5c20..25eb125b062b4219124385db1b2a83717683ac0e 100644
--- a/modules/service/datum/dap_chain_net_srv_datum.c
+++ b/modules/service/datum/dap_chain_net_srv_datum.c
@@ -221,7 +221,7 @@ void s_order_notficator(dap_store_obj_t *a_obj, void *a_arg)
     dap_chain_net_srv_price_t *l_price = NULL;
 
     if ((l_order->price_unit.uint32 != SERV_UNIT_PCS) || (l_order->direction != SERV_DIR_BUY) ||
-            (strncmp(l_order->price_ticker, l_price->token, DAP_CHAIN_TICKER_SIZE_MAX)) ||
+            (dap_strncmp(l_order->price_ticker, l_price->token, DAP_CHAIN_TICKER_SIZE_MAX)) ||
             (!compare256(l_order->price, l_price->value_datoshi))) {
         char *l_balance_order = dap_chain_balance_coins_print(l_order->price);
         char *l_balance_service = dap_chain_balance_coins_print(l_price->value_datoshi);
diff --git a/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c b/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c
index a10cf022ac8394a13c02545b546964693c3da415..4b2e0769f388cc9dead37cf9b9d22d8fda6df377 100644
--- a/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c
+++ b/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c
@@ -415,7 +415,7 @@ static dap_chain_datum_tx_t *s_taking_tx_sign(json_object *a_json_arr_reply, dap
         m_sign_fail(ERROR_TX_MISMATCH, "Requested conditional transaction restrict provided sign key");
     size_t l_my_pkey_size = 0;
     byte_t *l_my_pkey = dap_enc_key_serialize_pub_key(a_enc_key, &l_my_pkey_size);
-    if (l_my_pkey)
+    if (!l_my_pkey)
         m_sign_fail(ERROR_COMPOSE, "Can't serialize sign public key");
     size_t l_tsd_hashes_count = l_cond->tsd_size / (sizeof(dap_tsd_t) + sizeof(dap_hash_fast_t));
     size_t l_signs_limit = l_tsd_hashes_count * 2;
diff --git a/modules/type/blocks/dap_chain_cs_blocks.c b/modules/type/blocks/dap_chain_cs_blocks.c
index f15476b4c10eb549d5b0b85a1b541da7fb4f37c7..253c1ad2dd480d81ce43864744c4ab974ef49e69 100644
--- a/modules/type/blocks/dap_chain_cs_blocks.c
+++ b/modules/type/blocks/dap_chain_cs_blocks.c
@@ -285,11 +285,7 @@ void dap_chain_cs_blocks_deinit()
 
 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) {
-        log_it(L_CRITICAL, "%s", c_error_memory_alloc);
-        return -1;
-    }
+    dap_chain_cs_blocks_t * l_cs_blocks = DAP_NEW_Z_RET_VAL_IF_FAIL(dap_chain_cs_blocks_t, -1);
     a_chain->_inheritor = l_cs_blocks;
     l_cs_blocks->chain = a_chain;
 
@@ -1520,7 +1516,7 @@ static int s_callback_cs_blocks_purge(dap_chain_t *a_chain)
         l_datum_index = NULL;
     }
     pthread_rwlock_unlock(&PVT(l_blocks)->datums_rwlock);
-    dap_chain_cell_delete_all(a_chain);
+    dap_chain_cell_close_all(a_chain);
     return 0;
 }
 
@@ -1576,8 +1572,8 @@ static int s_add_atom_datums(dap_chain_cs_blocks_t *a_blocks, dap_chain_block_ca
             pthread_rwlock_wrlock(&PVT(a_blocks)->datums_rwlock);
             HASH_ADD(hh, PVT(a_blocks)->datum_index, datum_hash, sizeof(*l_datum_hash), l_datum_index);
             pthread_rwlock_unlock(&PVT(a_blocks)->datums_rwlock);
-            dap_chain_cell_t *l_cell = dap_chain_cell_find_by_id(a_blocks->chain, a_blocks->chain->active_cell_id);
-            dap_chain_datum_notify(l_cell, l_datum_hash, &l_datum_index->block_cache->block_hash, (byte_t *)l_datum, l_datum_size, l_res, l_datum_index_data.action, l_datum_index_data.uid);
+            dap_chain_datum_notify(a_blocks->chain, a_block_cache->block->hdr.cell_id, l_datum_hash, &l_datum_index->block_cache->block_hash,
+                                   (byte_t*)l_datum, l_datum_size, l_res, l_datum_index_data.action, l_datum_index_data.uid);
         }
     }
     debug_if(s_debug_more, L_DEBUG, "Block %s checked, %s", a_block_cache->block_hash_str,
@@ -1610,8 +1606,7 @@ static int s_delete_atom_datums(dap_chain_cs_blocks_t *a_blocks, dap_chain_block
             l_ret++;
             HASH_DEL(PVT(a_blocks)->datum_index, l_datum_index);
             // notify datum removed
-            dap_chain_cell_t *l_cell = dap_chain_cell_find_by_id(a_blocks->chain, a_blocks->chain->active_cell_id);
-            dap_chain_datum_removed_notify(l_cell, l_datum_hash);
+            dap_chain_datum_removed_notify(a_blocks->chain, a_block_cache->block->hdr.cell_id, l_datum_hash);
         }
     }
     debug_if(s_debug_more, L_DEBUG, "Block %s checked, %s", a_block_cache->block_hash_str,
@@ -1632,7 +1627,7 @@ static void s_add_atom_to_blocks(dap_chain_cs_blocks_t *a_blocks, dap_chain_bloc
 }
 
 
-static bool s_select_longest_branch(dap_chain_cs_blocks_t * a_blocks, dap_chain_block_cache_t * a_bcache, uint64_t a_main_branch_length, dap_chain_cell_t *a_cell)
+static bool s_select_longest_branch(dap_chain_cs_blocks_t * a_blocks, dap_chain_block_cache_t * a_bcache, uint64_t a_main_branch_length)
 {
     dap_chain_cs_blocks_t * l_blocks = a_blocks;
     if (!a_blocks){
@@ -1697,7 +1692,7 @@ static bool s_select_longest_branch(dap_chain_cs_blocks_t * a_blocks, dap_chain_
             HASH_ADD(hh, PVT(l_blocks)->blocks, block_hash, sizeof(l_curr_atom->block_hash), l_curr_atom);
             debug_if(s_debug_more, L_DEBUG, "Verified atom %p: ACCEPTED", l_curr_atom);
             s_add_atom_datums(l_blocks, l_curr_atom);
-            dap_chain_atom_notify(a_cell, &l_curr_atom->block_hash, (byte_t*)l_curr_atom->block, l_curr_atom->block_size);
+            dap_chain_atom_notify(a_blocks->chain, l_curr_atom->block->hdr.cell_id, &l_curr_atom->block_hash, (byte_t*)l_curr_atom->block, l_curr_atom->block_size);
             HASH_DEL(new_main_branch, l_item);
         }
         // Next we save pointer to new forked branch (former main branch) instead of it
@@ -1730,27 +1725,22 @@ static dap_chain_atom_verify_res_t s_callback_atom_add(dap_chain_t * a_chain, da
 
     switch (ret) {
     case ATOM_ACCEPT:{
-        dap_chain_cell_t *l_cell = dap_chain_cell_find_by_id(a_chain, l_block->hdr.cell_id);
-#ifndef DAP_CHAIN_BLOCKS_TEST
         dap_chain_net_t *l_net = dap_chain_net_by_id(a_chain->net_id);
+#ifndef DAP_CHAIN_BLOCKS_TEST
         assert(l_net);
         if ( !dap_chain_net_get_load_mode(l_net) ) {
-            if ( dap_chain_atom_save(l_cell, a_atom, a_atom_size, a_atom_new ? &l_block_hash : NULL) < 0 ) {
-                log_it(L_ERROR, "Can't save atom to file");
+            int l_err = dap_chain_atom_save(a_chain, l_block->hdr.cell_id, a_atom, a_atom_size, a_atom_new ? &l_block_hash : NULL, (char**)&l_block);
+            if (l_err) {
                 dap_chain_net_srv_stake_switch_table(a_chain->net_id, false);
+                log_it(L_ERROR, "Can't save atom to file, code %d", l_err);
                 return ATOM_REJECT;
-            } else if (a_chain->is_mapped) {
-                l_block = (dap_chain_block_t*)( l_cell->map_pos += sizeof(uint64_t) );  // Switching to mapped area
-                l_cell->map_pos += a_atom_size;
             }
-            ret = ATOM_ACCEPT;
         }
 #endif
-        l_block_cache = dap_chain_block_cache_new(&l_block_hash, l_block, a_atom_size, PVT(l_blocks)->blocks_count + 1, !a_chain->is_mapped);
-        if (!l_block_cache) {
-            log_it(L_DEBUG, "%s", "... corrupted block");
+        if (!( l_block_cache = dap_chain_block_cache_new(&l_block_hash, l_block, a_atom_size, PVT(l_blocks)->blocks_count + 1, !a_chain->is_mapped) )) {
             dap_chain_net_srv_stake_switch_table(a_chain->net_id, false);
-            return ATOM_REJECT;
+            log_it(L_ERROR, "Block %s is corrupted!", l_block_cache->block_hash_str);
+            return dap_chain_net_get_load_mode(l_net) ? ATOM_CORRUPTED : ATOM_REJECT;
         }
         debug_if(s_debug_more, L_DEBUG, "... new block %s", l_block_cache->block_hash_str);
 
@@ -1762,7 +1752,7 @@ static dap_chain_atom_verify_res_t s_callback_atom_add(dap_chain_t * a_chain, da
                 HASH_ADD(hh, PVT(l_blocks)->blocks, block_hash, sizeof(l_block_cache->block_hash), l_block_cache);
                 debug_if(s_debug_more, L_DEBUG, "Verified atom %p: ACCEPTED", a_atom);
                 s_add_atom_datums(l_blocks, l_block_cache);
-                dap_chain_atom_notify(l_cell, &l_block_cache->block_hash, (byte_t*)l_block, a_atom_size);
+                dap_chain_atom_notify(a_chain, l_block->hdr.cell_id, &l_block_cache->block_hash, (byte_t*)l_block, a_atom_size);
                 dap_chain_atom_add_from_threshold(a_chain);
                 pthread_rwlock_unlock(&PVT(l_blocks)->rwlock);
 
@@ -1790,8 +1780,6 @@ static dap_chain_atom_verify_res_t s_callback_atom_add(dap_chain_t * a_chain, da
 #endif
                 return ATOM_ACCEPT;
             }
-
-
             for (size_t i = 0; i < PVT(l_blocks)->forked_br_cnt; i++){
                 dap_chain_block_forked_branch_t *l_cur_branch = PVT(l_blocks)->forked_branches[i];
                 dap_chain_block_forked_branch_atoms_table_t *l_last = HASH_LAST(l_cur_branch->forked_branch_atoms);
@@ -1806,7 +1794,7 @@ static dap_chain_atom_verify_res_t s_callback_atom_add(dap_chain_t * a_chain, da
                     l_block_cache->block_number = l_last->block_cache->block_number + 1;
                     HASH_ADD(hh, l_cur_branch->forked_branch_atoms, block_hash, sizeof(dap_hash_fast_t), l_new_item);
                     uint64_t l_main_branch_length = PVT(l_blocks)->blocks_count - l_cur_branch->connected_block->block_number;
-                    if (s_select_longest_branch(l_blocks, l_cur_branch->connected_block, l_main_branch_length, l_cell)){
+                    if ( s_select_longest_branch(l_blocks, l_cur_branch->connected_block, l_main_branch_length) ) {
                         dap_chain_block_cache_t *l_bcache_last = HASH_LAST(PVT(l_blocks)->blocks);
                         // Send it to notificator listeners
 #ifndef DAP_CHAIN_BLOCKS_TEST
@@ -1849,7 +1837,7 @@ static dap_chain_atom_verify_res_t s_callback_atom_add(dap_chain_t * a_chain, da
             ++PVT(l_blocks)->blocks_count;
             debug_if(s_debug_more, L_DEBUG, "Verified genesis atom %p: ACCEPTED", a_atom);
             s_add_atom_datums(l_blocks, l_block_cache);
-            dap_chain_atom_notify(l_cell, &l_block_cache->block_hash, (byte_t*)l_block, a_atom_size);
+            dap_chain_atom_notify(a_chain, l_block->hdr.cell_id, &l_block_cache->block_hash, (byte_t*)l_block, a_atom_size);
             dap_chain_atom_add_from_threshold(a_chain);
             pthread_rwlock_unlock(&PVT(l_blocks)->rwlock);
             return ret;
@@ -1872,16 +1860,10 @@ static dap_chain_atom_verify_res_t s_callback_atom_add(dap_chain_t * a_chain, da
         debug_if(s_debug_more, L_DEBUG, "Verified atom %p with hash %s: REJECTED", a_atom, dap_chain_hash_fast_to_str_static(&l_block_hash));
         break;
     case ATOM_FORK:{
-        dap_chain_cell_t *l_cell = dap_chain_cell_find_by_id(a_chain, l_block->hdr.cell_id);
 #ifndef DAP_CHAIN_BLOCKS_TEST
         if ( !dap_chain_net_get_load_mode( dap_chain_net_by_id(a_chain->net_id)) ) {
-            if ( (ret = dap_chain_atom_save(l_cell, a_atom, a_atom_size, a_atom_new ? &l_block_hash : NULL)) < 0 ) {
-                log_it(L_ERROR, "Can't save atom to file, code %d", ret);
-                return ATOM_REJECT;
-            } else if (a_chain->is_mapped) {
-                l_block = (dap_chain_block_t*)( l_cell->map_pos += sizeof(uint64_t) );  // Switching to mapped area
-                l_cell->map_pos += a_atom_size;
-            }
+            int l_err = dap_chain_atom_save(a_chain, l_block->hdr.cell_id, a_atom, a_atom_size, a_atom_new ? &l_block_hash : NULL, (char**)&l_block);
+            dap_return_val_if_pass_err(l_err, ATOM_REJECT, "Can't save atom to file, code %d", l_err);
             ret = ATOM_FORK;
         }
 #endif
@@ -1922,6 +1904,9 @@ static dap_chain_atom_verify_res_t s_callback_atom_add(dap_chain_t * a_chain, da
     case ATOM_PASS:
         debug_if(s_debug_more, L_DEBUG, "... %s is already present", dap_chain_hash_fast_to_str_static(&l_block_hash));
         break;
+    case ATOM_CORRUPTED:
+        debug_if(s_debug_more, L_DEBUG, "... atom is corrupted.%s", dap_chain_net_get_load_mode(dap_chain_net_by_id(a_chain->net_id))
+            ? " The file will be truncated!" : "");
     default:
         debug_if(s_debug_more, L_DEBUG, "Unknown verification ret code %d", ret);
         break;
@@ -1939,6 +1924,8 @@ static dap_chain_atom_verify_res_t s_callback_atom_add(dap_chain_t * a_chain, da
 static dap_chain_atom_verify_res_t s_callback_atom_verify(dap_chain_t *a_chain, dap_chain_atom_ptr_t a_atom, size_t a_atom_size, dap_chain_hash_fast_t *a_atom_hash)
 {
     dap_return_val_if_fail(a_chain && a_atom && a_atom_size && a_atom_hash, ATOM_REJECT);
+    dap_chain_net_t *l_net = dap_chain_net_by_id(a_chain->net_id);
+    bool l_load_mode = l_net ? dap_chain_net_get_load_mode(l_net) : false;
     dap_chain_cs_blocks_t * l_blocks = DAP_CHAIN_CS_BLOCKS(a_chain);
     assert(l_blocks);
     dap_chain_cs_blocks_pvt_t *l_blocks_pvt = PVT(l_blocks);
@@ -1947,14 +1934,14 @@ static dap_chain_atom_verify_res_t s_callback_atom_verify(dap_chain_t *a_chain,
     dap_chain_hash_fast_t l_block_hash = *a_atom_hash;
 
     if (sizeof(l_block->hdr) >= a_atom_size) {
-        log_it(L_WARNING, "Size of block %s is %zd that is equal or less then block's header size %zd",
+        log_it(L_WARNING, "Block %s size %zd <= block header size %zd",
                                 dap_hash_fast_to_str_static(a_atom_hash), a_atom_size, sizeof(l_block->hdr));
-        return ATOM_REJECT;
+        return l_load_mode ? ATOM_CORRUPTED : ATOM_REJECT;
     }
     size_t l_offset = dap_chain_block_get_sign_offset(l_block, a_atom_size);
     if (!l_offset) {
         log_it(L_WARNING, "Block %s with size %zu parsing error", dap_hash_fast_to_str_static(a_atom_hash), a_atom_size);
-        return ATOM_REJECT;
+        return l_load_mode ? ATOM_CORRUPTED : ATOM_REJECT;
     }
     if ((l_block->hdr.version >= 2 || /* Old bug, crutch for it */ l_block->hdr.meta_n_datum_n_signs_size != l_offset) &&
             l_block->hdr.meta_n_datum_n_signs_size + sizeof(l_block->hdr) != a_atom_size) {
@@ -1964,7 +1951,7 @@ static dap_chain_atom_verify_res_t s_callback_atom_verify(dap_chain_t *a_chain,
         if (!l_hash_found) {
             log_it(L_WARNING, "Incorrect size %zu of block %s, expected %zu", l_block->hdr.meta_n_datum_n_signs_size + sizeof(l_block->hdr),
                                                                     dap_hash_fast_to_str_static(a_atom_hash), a_atom_size);
-            return ATOM_REJECT;
+            return l_load_mode ? ATOM_CORRUPTED : ATOM_REJECT;
         }
     }
     while (sizeof(l_block->hdr) + l_offset + sizeof(dap_sign_t) < a_atom_size) {
@@ -1981,7 +1968,7 @@ static dap_chain_atom_verify_res_t s_callback_atom_verify(dap_chain_t *a_chain,
         if (!l_hash_found) {
             log_it(L_WARNING, "Incorrect size %zu of block %s, expected %zu", l_offset + sizeof(l_block->hdr),
                                                                     dap_hash_fast_to_str_static(a_atom_hash), a_atom_size);
-            return ATOM_REJECT;
+            return l_load_mode ? ATOM_CORRUPTED : ATOM_REJECT;
         }
     }
 
diff --git a/modules/type/dag/dap_chain_cs_dag.c b/modules/type/dag/dap_chain_cs_dag.c
index bef0bb74dec721794975e9e843dc7deda5bf2ecd..c4421022f9a159369dd8f631c99e1ab1f44b6294 100644
--- a/modules/type/dag/dap_chain_cs_dag.c
+++ b/modules/type/dag/dap_chain_cs_dag.c
@@ -78,14 +78,11 @@ typedef struct dap_chain_cs_dag_blocked {
 
 typedef struct dap_chain_cs_dag_pvt {
     pthread_mutex_t events_mutex;
-    dap_chain_cs_dag_event_item_t * events;
-    dap_chain_cs_dag_event_item_t * datums;
-    dap_chain_cs_dag_event_item_t * events_treshold;
-    dap_chain_cs_dag_event_item_t * events_treshold_conflicted;
-    dap_chain_cs_dag_event_item_t * events_lasts_unlinked;
+    dap_chain_cs_dag_event_item_t *events_prefetched, *events, *events_treshold, *events_treshold_conflicted, *events_lasts_unlinked, *datums;
     dap_chain_cs_dag_blocked_t *removed_events_from_treshold;
     dap_interval_timer_t treshold_free_timer;
     uint64_t tx_count;
+    bool need_reorder;
 } dap_chain_cs_dag_pvt_t;
 
 #define PVT(a) ((dap_chain_cs_dag_pvt_t *) a->_pvt )
@@ -97,7 +94,9 @@ static void s_threshold_free(dap_chain_cs_dag_t *a_dag);
 static dap_chain_cs_dag_event_item_t *s_dag_proc_treshold(dap_chain_cs_dag_t *a_dag);
 
 // Atomic element organization callbacks
-static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_chain, dap_chain_atom_ptr_t , size_t, dap_hash_fast_t *a_atom_hash, bool a_atom_new);                      //    Accept new event in dag
+static dap_chain_atom_verify_res_t s_chain_callback_atom_read(dap_chain_t * a_chain, dap_chain_atom_ptr_t , size_t, dap_hash_fast_t *a_atom_hash);
+static unsigned s_chain_callback_prefetched_atoms_add(dap_chain_t *a_chain);
+static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_chain, dap_chain_atom_ptr_t , size_t, dap_hash_fast_t *a_atom_hash, bool a_atom_new); //    Accept new event in dag
 static dap_chain_atom_ptr_t s_chain_callback_atom_add_from_treshold(dap_chain_t * a_chain, size_t *a_event_size_out);                    //    Accept new event in dag from treshold
 static dap_chain_atom_verify_res_t s_chain_callback_atom_verify(dap_chain_t * a_chain, dap_chain_atom_ptr_t , size_t, dap_hash_fast_t *a_atom_hash);                   //    Verify new event in dag
 static size_t s_chain_callback_atom_get_static_hdr_size(void);                               //    Get dag event header size
@@ -213,7 +212,10 @@ static int s_chain_cs_dag_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg)
     pthread_mutexattr_destroy(&l_mutex_attr);
 
     // Atom element callbacks
+
+    a_chain->callback_atom_prefetch = s_chain_callback_atom_read; // Prefetching
     a_chain->callback_atom_add = s_chain_callback_atom_add ;  // Accept new element in chain
+    a_chain->callback_atoms_prefetched_add = s_chain_callback_prefetched_atoms_add;
     a_chain->callback_atom_add_from_treshold = s_chain_callback_atom_add_from_treshold;  // Accept new elements in chain from treshold
     a_chain->callback_atom_verify = s_chain_callback_atom_verify ;  // Verify new element in chain
     a_chain->callback_atom_get_hdr_static_size = s_chain_callback_atom_get_static_hdr_size; // Get dag event hdr size
@@ -372,7 +374,7 @@ static int s_chain_cs_dag_purge(dap_chain_t *a_chain)
         DAP_DELETE(l_event_current);
     }
     pthread_mutex_unlock(&l_dag_pvt->events_mutex);
-    dap_chain_cell_delete_all(a_chain);
+    dap_chain_cell_close_all(a_chain);
     return 0;
 }
 
@@ -400,20 +402,11 @@ static int s_chain_cs_dag_delete(dap_chain_t * a_chain)
 static int s_dap_chain_add_atom_to_events_table(dap_chain_cs_dag_t *a_dag, dap_chain_cs_dag_event_item_t *a_event_item)
 {
     dap_chain_datum_t *l_datum = (dap_chain_datum_t*) dap_chain_cs_dag_event_get_datum(a_event_item->event, a_event_item->event_size);
-    if (!l_datum) {
-        log_it(L_WARNING, "Corrupted event, failed to extract datum from event.");
-        return -2;
-    }
-    if(a_event_item->event_size < sizeof(l_datum->header) ){
-        log_it(L_WARNING, "Corrupted event, too small to fit datum in it");
-        return -1;
-    }
-    size_t l_datum_size = dap_chain_datum_size(l_datum);
-    size_t l_datum_size_max = dap_chain_cs_dag_event_get_datum_size_maximum(a_event_item->event, a_event_item->event_size);
-    if(l_datum_size >l_datum_size_max ){
-        log_it(L_WARNING, "Corrupted event, too big size %zd in header when event's size max is only %zd", l_datum_size, l_datum_size_max);
-        return -1;
-    }
+    dap_return_val_if_fail_err( l_datum, -2, "Corrupted event, failed to extract datum" );
+    dap_return_val_if_pass_err( a_event_item->event_size < sizeof(l_datum->header), -1, "Corrupted event, size too small");
+    size_t l_datum_size = dap_chain_datum_size(l_datum),
+        l_datum_size_max = dap_chain_cs_dag_event_get_datum_size_maximum(a_event_item->event, a_event_item->event_size);
+    dap_return_val_if_pass_err( l_datum_size > l_datum_size_max, -1, "Event size exeeds max size permitted, %zd > %zd", l_datum_size, l_datum_size_max );
     dap_hash_fast_t l_datum_hash;
     dap_chain_datum_calc_hash(l_datum, &l_datum_hash);
     int l_ret = dap_chain_datum_add(a_dag->chain, l_datum, l_datum_size, &l_datum_hash, NULL);
@@ -432,12 +425,9 @@ static int s_dap_chain_add_atom_to_events_table(dap_chain_cs_dag_t *a_dag, dap_c
         HASH_ADD_BYHASHVALUE(hh_datums, PVT(a_dag)->datums, datum_hash, sizeof(l_datum_hash),
                              l_hash_item_hashv, a_event_item);
     pthread_mutex_unlock(&PVT(a_dag)->events_mutex);
-    if (s_debug_more) {
-        char l_buf_hash[DAP_CHAIN_HASH_FAST_STR_SIZE] = {'\0'};
-        dap_chain_hash_fast_to_str(&a_event_item->hash, l_buf_hash, sizeof(l_buf_hash));
-        log_it(L_INFO, "Dag event %s checked, ret code %d : %s", l_buf_hash, l_ret,
-               l_ret ? dap_chain_net_verify_datum_err_code_to_str(l_datum, l_ret) : "Ok");
-    }
+    debug_if(s_debug_more, L_INFO, "Dag event %s checked, ret code %d : %s",
+             dap_chain_hash_fast_to_str_static(&a_event_item->hash), l_ret,
+             l_ret ? dap_chain_net_verify_datum_err_code_to_str(l_datum, l_ret) : "Ok");
     return l_ret;
 }
 
@@ -454,6 +444,71 @@ static int s_sort_event_item(dap_chain_cs_dag_event_item_t* a, dap_chain_cs_dag_
     return a->ts_created < b->ts_created ? -1 : a->ts_created == b->ts_created ? 0 : 1;
 }
 
+static dap_chain_atom_verify_res_t s_dag_event_integrity_check(dap_chain_cs_dag_t *a_dag, uint64_t a_chain_id, dap_chain_cs_dag_event_t *a_event,
+                                                               size_t a_event_size, dap_chain_hash_fast_t *a_atom_hash)
+{
+    dap_return_val_if_pass_err( a_event_size < sizeof(dap_chain_cs_dag_event_t), ATOM_CORRUPTED,
+                                "Too small event size %zu", a_event_size );
+    dap_return_val_if_pass_err( a_event->header.version, ATOM_CORRUPTED,
+                                "Unsupported event version %u", a_event->header.version );
+    dap_return_val_if_fail_err( a_event->header.chain_id.uint64 == a_chain_id, ATOM_CORRUPTED,
+                                "Wrong chain id %zu", a_event->header.chain_id.uint64 );
+    if ( a_dag->hal ) {
+        dap_chain_cs_dag_hal_item_t *l_hash_search = NULL;
+        HASH_FIND(hh, a_dag->hal, a_atom_hash, sizeof(*a_atom_hash), l_hash_search);
+        if (l_hash_search)
+            return ATOM_ACCEPT;
+    }
+    size_t l_atom_size = dap_chain_cs_dag_event_calc_size(a_event, a_event_size);
+    dap_return_val_if_fail_err( l_atom_size == a_event_size, ATOM_CORRUPTED,
+                                "Invalid event size, %zu != %zu", l_atom_size, a_event_size );
+    return ATOM_PASS;
+}
+
+static dap_chain_atom_verify_res_t s_chain_callback_atom_read(dap_chain_t *a_chain, dap_chain_atom_ptr_t a_atom, size_t a_atom_size, dap_chain_hash_fast_t *a_atom_hash)
+{
+    dap_chain_cs_dag_t *l_dag = DAP_CHAIN_CS_DAG(a_chain);
+    dap_chain_cs_dag_event_t *l_event = (dap_chain_cs_dag_event_t*)a_atom, *l_tmp;
+    dap_chain_atom_verify_res_t l_verif = s_dag_event_integrity_check(l_dag, a_chain->id.uint64, l_event, a_atom_size, a_atom_hash);
+    dap_return_val_if_pass_err( l_verif == ATOM_CORRUPTED, l_verif, "Event %s is corrupted", dap_hash_fast_to_str_static(a_atom_hash) );
+
+    dap_chain_cs_dag_event_item_t *l_event_item = NULL;
+    unsigned hashval = 0;
+    static dap_time_t l_last_ts = 0;
+    HASH_VALUE(a_atom_hash, sizeof(*a_atom_hash), hashval);
+    HASH_FIND_BYHASHVALUE(hh, PVT(l_dag)->events_prefetched, a_atom_hash, sizeof(*a_atom_hash), hashval, l_event_item);
+    if (!l_event_item) {
+        l_event_item = DAP_NEW(dap_chain_cs_dag_event_item_t);
+        *l_event_item = (dap_chain_cs_dag_event_item_t) {
+            .hash       = *a_atom_hash,
+            .event      = a_chain->is_mapped ? l_event : DAP_DUP_SIZE(l_event, a_atom_size),
+            .event_size = a_atom_size,
+            .ts_created = l_event->header.ts_created
+        };
+        HASH_ADD_BYHASHVALUE(hh, PVT(l_dag)->events_prefetched, hash, sizeof(*a_atom_hash), hashval, l_event_item);
+        if ( l_last_ts > l_event_item->ts_created )
+            PVT(l_dag)->need_reorder = true;
+        l_last_ts = l_event_item->ts_created;
+    }
+    return ATOM_ACCEPT;
+}
+
+static unsigned s_chain_callback_prefetched_atoms_add(dap_chain_t *a_chain) {
+    dap_chain_cs_dag_t *l_dag = DAP_CHAIN_CS_DAG(a_chain);
+    if ( PVT(l_dag)->need_reorder ) {
+        HASH_SORT( PVT(l_dag)->events_prefetched, s_sort_event_item );
+        PVT(l_dag)->need_reorder = false;
+    }
+    unsigned i = 0, q = HASH_COUNT(PVT(l_dag)->events_prefetched);
+    dap_chain_cs_dag_event_item_t *l_event_item, *l_tmp;
+    HASH_ITER(hh, PVT(l_dag)->events_prefetched, l_event_item, l_tmp) {
+        HASH_DEL(PVT(l_dag)->events_prefetched, l_event_item);
+        s_chain_callback_atom_add(a_chain, l_event_item->event, l_event_item->event_size, &l_event_item->datum_hash, false);
+        a_chain->load_progress = (int)((float)++i/q * 100 + 0.5);
+    }
+    return i;
+}
+
 /**
  * @brief s_chain_callback_atom_add Accept new event in dag
  * @param a_chain DAG object
@@ -463,20 +518,19 @@ static int s_sort_event_item(dap_chain_cs_dag_event_item_t* a, dap_chain_cs_dag_
  */
 static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_chain, dap_chain_atom_ptr_t a_atom, size_t a_atom_size, dap_hash_fast_t *a_atom_hash, bool a_atom_new)
 {
-    dap_chain_cs_dag_t * l_dag = DAP_CHAIN_CS_DAG(a_chain);
-    dap_chain_cs_dag_event_t * l_event = (dap_chain_cs_dag_event_t *) a_atom;
+    dap_chain_cs_dag_t *l_dag = DAP_CHAIN_CS_DAG(a_chain);
+    dap_chain_cs_dag_event_t * l_event = (dap_chain_cs_dag_event_t*)a_atom;
 
-    dap_chain_hash_fast_t l_event_hash = *a_atom_hash;
-    debug_if(s_debug_more, L_DEBUG, "Processing event: %s ... (size %zd)",  dap_chain_hash_fast_to_str_static(&l_event_hash), a_atom_size);
+    debug_if(s_debug_more, L_DEBUG, "Processing event: %s ... (size %zd)",  dap_chain_hash_fast_to_str_static(a_atom_hash), a_atom_size);
     pthread_mutex_lock(&PVT(l_dag)->events_mutex);
     // check if we already have this event
-    dap_chain_atom_verify_res_t ret = s_dap_chain_check_if_event_is_present(PVT(l_dag)->events, &l_event_hash) ||
-            s_dap_chain_check_if_event_is_present(PVT(l_dag)->events_treshold, &l_event_hash) ? ATOM_PASS : ATOM_ACCEPT;
+    dap_chain_atom_verify_res_t ret = s_dap_chain_check_if_event_is_present(PVT(l_dag)->events, a_atom_hash) ||
+            s_dap_chain_check_if_event_is_present(PVT(l_dag)->events_treshold, a_atom_hash) ? ATOM_PASS : ATOM_ACCEPT;
 
     // verify hashes and consensus
     switch (ret) {
     case ATOM_ACCEPT:
-        ret = s_chain_callback_atom_verify(a_chain, a_atom, a_atom_size, &l_event_hash);
+        ret = s_chain_callback_atom_verify(a_chain, a_atom, a_atom_size, a_atom_hash);
         if (ret == ATOM_MOVE_TO_THRESHOLD) {
             if (!s_threshold_enabled /*&& !dap_chain_net_get_load_mode(dap_chain_net_by_id(a_chain->net_id))*/)
                 ret = ATOM_REJECT;
@@ -490,28 +544,30 @@ static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_cha
     default:
         break;
     }
-    dap_chain_cs_dag_event_item_t *l_event_item = DAP_NEW_Z(dap_chain_cs_dag_event_item_t);
-    if ( !l_event_item ) {
-        log_it(L_CRITICAL, "%s", c_error_memory_alloc);
-        pthread_mutex_unlock(&PVT(l_dag)->events_mutex);
-        return ATOM_REJECT;
+    bool l_load_mode = dap_chain_net_get_load_mode(dap_chain_net_by_id(a_chain->net_id));
+    dap_chain_cs_dag_event_item_t *l_event_item;
+    if (l_load_mode) {
+        l_event_item = (dap_chain_cs_dag_event_item_t*)(a_atom_hash); // Guaranteed by C1x §6.7.2.1.13
+        l_event_item->ts_added = dap_time_now();
+    } else {
+        l_event_item = DAP_NEW(dap_chain_cs_dag_event_item_t);
+        *l_event_item = (dap_chain_cs_dag_event_item_t) {
+            .hash       = *a_atom_hash,
+            .ts_added   = dap_time_now(),
+            .event      = a_chain->is_mapped ? l_event : DAP_DUP_SIZE(l_event, a_atom_size),
+            .event_size = a_atom_size,
+            .ts_created = l_event->header.ts_created
+        };
     }
-    *l_event_item = (dap_chain_cs_dag_event_item_t) {
-        .hash       = l_event_hash,
-        .ts_added   = dap_time_now(),
-        .event      = a_chain->is_mapped ? l_event : DAP_DUP_SIZE(l_event, a_atom_size),
-        .event_size = a_atom_size,
-        .ts_created = l_event->header.ts_created
-    };
 
     switch (ret) {
     case ATOM_MOVE_TO_THRESHOLD: {
         dap_chain_cs_dag_blocked_t *el = NULL;
-        HASH_FIND(hh, PVT(l_dag)->removed_events_from_treshold, &l_event_hash, sizeof(dap_chain_hash_fast_t), el);
+        HASH_FIND(hh, PVT(l_dag)->removed_events_from_treshold, a_atom_hash, sizeof(dap_chain_hash_fast_t), el);
         if (!el) {
-            if ( a_chain->is_mapped && dap_chain_net_get_load_mode(dap_chain_net_by_id(a_chain->net_id)) )
+            if ( a_chain->is_mapped && l_load_mode )
                 l_event_item->mapped_region = (char*)l_event;
-            HASH_ADD(hh, PVT(l_dag)->events_treshold, hash, sizeof(l_event_hash), l_event_item);
+            HASH_ADD(hh, PVT(l_dag)->events_treshold, hash, sizeof(*a_atom_hash), l_event_item);
             debug_if(s_debug_more, L_DEBUG, "... added to threshold");
         } else {
             ret = ATOM_REJECT;
@@ -520,15 +576,12 @@ static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_cha
         break;
     }
     case ATOM_ACCEPT: {
-        dap_chain_cell_t *l_cell = dap_chain_cell_find_by_id(a_chain, l_event->header.cell_id);
-        if ( !dap_chain_net_get_load_mode( dap_chain_net_by_id(a_chain->net_id)) ) {
-            if ( dap_chain_atom_save(l_cell, a_atom, a_atom_size, a_atom_new ? &l_event_hash : NULL) < 0 ) {
-                log_it(L_ERROR, "Can't save atom to file");
+        if ( !l_load_mode ) {
+            int l_err = dap_chain_atom_save(a_chain, l_event->header.cell_id, a_atom, a_atom_size, a_atom_new ? a_atom_hash : NULL, (char**)&l_event_item->event);
+            if (l_err) {
+                log_it(L_ERROR, "Can't save atom to file, code %d", l_err);
                 ret = ATOM_REJECT;
                 break;
-            } else if (a_chain->is_mapped) {
-                l_event_item->event = (dap_chain_cs_dag_event_t*)( l_cell->map_pos += sizeof(uint64_t) );
-                l_cell->map_pos += a_atom_size;
             }
         }
         int l_consensus_check = s_dap_chain_add_atom_to_events_table(l_dag, l_event_item);
@@ -546,19 +599,9 @@ static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_cha
             debug_if(s_debug_more, L_WARNING, "... added with ledger code %d", l_consensus_check);
             break;
         }
-        
-        dap_chain_cs_dag_event_item_t *l_tail = HASH_LAST(PVT(l_dag)->events);
-        if (l_tail && l_tail->ts_created > l_event->header.ts_created) {
-            DAP_CHAIN_PVT(a_chain)->need_reorder = true;
-        
-            HASH_ADD_INORDER(hh, PVT(l_dag)->events, hash, sizeof(l_event_item->hash), l_event_item, s_sort_event_item);
-            dap_chain_cs_dag_event_item_t *it = PVT(l_dag)->events;
-            for (uint64_t i = 0; it; it = it->hh.next)  // renumber chain events
-                it->event_number = ++i;
-        } else
-            HASH_ADD(hh, PVT(l_dag)->events, hash, sizeof(l_event_item->hash), l_event_item);
+
         s_dag_events_lasts_process_new_last_event(l_dag, l_event_item);
-        dap_chain_atom_notify(l_cell, &l_event_item->hash, (const byte_t*)l_event_item->event, l_event_item->event_size);
+        dap_chain_atom_notify(l_dag->chain, l_event_item->event->header.cell_id, &l_event_item->hash, (const byte_t*)l_event_item->event, l_event_item->event_size);
         dap_chain_atom_add_from_threshold(a_chain);
     } break;
     default:
@@ -745,60 +788,39 @@ dap_chain_cs_dag_event_t* dap_chain_cs_dag_find_event_by_hash(dap_chain_cs_dag_t
  */
 static dap_chain_atom_verify_res_t s_chain_callback_atom_verify(dap_chain_t *a_chain, dap_chain_atom_ptr_t a_atom, size_t a_atom_size, dap_chain_hash_fast_t *a_atom_hash)
 {
-    dap_chain_cs_dag_t * l_dag = DAP_CHAIN_CS_DAG(a_chain);
-    dap_chain_cs_dag_event_t * l_event = (dap_chain_cs_dag_event_t *) a_atom;
-    dap_chain_atom_verify_res_t res = ATOM_ACCEPT;
-    pthread_mutex_t *l_events_mutex = &PVT(l_dag)->events_mutex;
-    if (a_atom_size < sizeof(dap_chain_cs_dag_event_t)) {
-        log_it(L_WARNING, "Too small event size %zu, less than event header", a_atom_size);
-        return ATOM_REJECT;
-    }
-    if (l_event->header.version) {
-        log_it(L_WARNING, "Unsupported event version, possible corrupted event");
-        return ATOM_REJECT;
-    }
-    if (l_event->header.chain_id.uint64 != a_chain->id.uint64) {
-        log_it(L_WARNING, "Event from another chain, possible corrupted event");
-        return ATOM_REJECT;
-    }
-    dap_chain_hash_fast_t l_event_hash = *a_atom_hash;
-    // Hard accept list
-    if (l_dag->hal) {
-        dap_chain_cs_dag_hal_item_t *l_hash_found = NULL;
-        pthread_mutex_lock(l_events_mutex);
-        HASH_FIND(hh, l_dag->hal, &l_event_hash, sizeof(l_event_hash), l_hash_found);
-        pthread_mutex_unlock(l_events_mutex);
-        if (l_hash_found) {
+    dap_chain_cs_dag_event_t *l_event = (dap_chain_cs_dag_event_t*)a_atom;
+    dap_chain_cs_dag_t *l_dag = DAP_CHAIN_CS_DAG(a_chain);
+    if ( dap_chain_net_get_load_mode(dap_chain_net_by_id(a_chain->net_id)) ) {
+        if ( l_dag->hal ) {
+            /* We should check HAL twice, because we can't tell HAL'ed event from passed after prefetching */
+            dap_chain_cs_dag_hal_item_t *l_hash_search = NULL;
+            HASH_FIND(hh, l_dag->hal, a_atom_hash, sizeof(*a_atom_hash), l_hash_search);
+            if (l_hash_search)
+                return ATOM_ACCEPT;
+        }
+    } else
+        switch ( s_dag_event_integrity_check(l_dag, a_chain->id.uint64, l_event, a_atom_size, a_atom_hash) ) {
+        case ATOM_ACCEPT:
             return ATOM_ACCEPT;
+        case ATOM_CORRUPTED:
+            return ATOM_REJECT;
+        default:
+            break;
         }
-    }
-    size_t l_atom_size = dap_chain_cs_dag_event_calc_size(l_event, a_atom_size);
-    if (l_atom_size != a_atom_size) {
-        log_it(L_WARNING, "Event size %zu not equal to expected %zu", l_atom_size, a_atom_size);
-        return  ATOM_REJECT;
-    }
-
+    dap_chain_atom_verify_res_t res = ATOM_ACCEPT;
+    pthread_mutex_t *l_events_mutex = &PVT(l_dag)->events_mutex;
     // genesis or seed mode
-    if (l_event->header.hash_count == 0){
-        if(s_seed_mode && !PVT(l_dag)->events){
-            log_it(L_NOTICE,"Accepting genesis event");
+    if ( !l_event->header.hash_count ) {
+        if ( s_seed_mode ) /* TODO: lock with mutex too. Is this yet used?...*/
+            return PVT(l_dag)->events
+                ? log_it(L_NOTICE,"Treating event %s as genesis. Time to turn seed mode off!", dap_hash_fast_to_str_static(a_atom_hash)), ATOM_ACCEPT
+                : ( log_it(L_ERROR, "Genesis event is already present! Turn off seed mode and try again!"), ATOM_REJECT );
+        if ( l_dag->is_static_genesis_event ) {
+            dap_return_val_if_pass_err( memcmp( a_atom_hash, &l_dag->static_genesis_event_hash, sizeof(*a_atom_hash) ),
+                                        /* l_load_mode ? ATOM_CORRUPTED : */ ATOM_REJECT, "Wrong genesis event: preconfigured \"%s\" != \"%s\"",
+                                        dap_hash_fast_to_str_static(&l_dag->static_genesis_event_hash), dap_hash_fast_to_str_static(a_atom_hash) );
+            debug_if(s_debug_more, L_INFO, "Accepting static genesis event \"%s\"", dap_hash_fast_to_str_static(a_atom_hash));
             return ATOM_ACCEPT;
-        }else if(s_seed_mode){
-            log_it(L_WARNING,"Cant accept genesis event: already present data in DAG, ->events is not NULL");
-            return  ATOM_REJECT;
-        }
-
-        if (l_dag->is_static_genesis_event ){
-            if ( memcmp( &l_event_hash, &l_dag->static_genesis_event_hash, sizeof(l_event_hash) ) != 0 ){
-                char l_event_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE], l_genesis_event_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE];
-                dap_chain_hash_fast_to_str(&l_event_hash, l_event_hash_str, sizeof(l_event_hash_str));
-                dap_chain_hash_fast_to_str(&l_dag->static_genesis_event_hash, l_genesis_event_hash_str, sizeof(l_genesis_event_hash_str));
-                log_it(L_WARNING, "Wrong genesis event %s (staticly predefined %s)",l_event_hash_str, l_genesis_event_hash_str);
-                return ATOM_REJECT;
-            } else {
-                debug_if(s_debug_more, L_INFO, "Accepting static genesis event");
-                return ATOM_ACCEPT;
-            }
         }
     }
 
@@ -821,10 +843,7 @@ static dap_chain_atom_verify_res_t s_chain_callback_atom_verify(dap_chain_t *a_c
     }
 
     //consensus
-    if (res == ATOM_ACCEPT && l_dag->callback_cs_verify(l_dag, l_event, a_atom_hash))
-        res = ATOM_REJECT;
-
-    return res;
+    return res == ATOM_ACCEPT && l_dag->callback_cs_verify(l_dag, l_event, a_atom_hash) ? ATOM_REJECT : res;
 }
 
 /**
@@ -937,15 +956,13 @@ dap_chain_cs_dag_event_item_t* s_dag_proc_treshold(dap_chain_cs_dag_t * a_dag)
         if (ret == DAP_THRESHOLD_OK) {
             debug_if(s_debug_more, L_DEBUG, "Processing event (threshold): %s...",
                     dap_chain_hash_fast_to_str_static(&l_event_item->hash));
-            dap_chain_cell_t *l_cell = dap_chain_cell_find_by_id(a_dag->chain, l_event_item->event->header.cell_id);
             if ( !l_event_item->mapped_region ) {
-                if ( dap_chain_atom_save(l_cell, (const byte_t*)l_event_item->event, l_event_item->event_size, NULL) < 0 ) {
-                    log_it(L_CRITICAL, "Can't move atom from threshold to file");
+                int l_err = dap_chain_atom_save(a_dag->chain, l_event_item->event->header.cell_id, (const byte_t*)l_event_item->event,
+                                                l_event_item->event_size, NULL, (char**)&l_event_item->event);
+                if (l_err) {
+                    log_it(L_CRITICAL, "Can't move atom from threshold to file, code %d", l_err);
                     res = false;
                     break;
-                } else if (a_dag->chain->is_mapped) {
-                    l_event_item->event = (dap_chain_cs_dag_event_t*)( l_cell->map_pos += sizeof(uint64_t) );
-                    l_cell->map_pos += l_event_item->event_size;
                 }
             }
             int l_add_res = s_dap_chain_add_atom_to_events_table(a_dag, l_event_item);
@@ -954,7 +971,7 @@ dap_chain_cs_dag_event_item_t* s_dag_proc_treshold(dap_chain_cs_dag_t * a_dag)
                 HASH_ADD(hh, PVT(a_dag)->events, hash, sizeof(l_event_item->hash), l_event_item);
                 s_dag_events_lasts_process_new_last_event(a_dag, l_event_item);
                 debug_if(s_debug_more, L_INFO, "... moved from threshold to chain");
-                dap_chain_atom_notify(l_cell, &l_event_item->hash, (byte_t*)l_event_item->event, l_event_item->event_size);
+                dap_chain_atom_notify(a_dag->chain, l_event_item->event->header.cell_id, &l_event_item->hash, (byte_t*)l_event_item->event, l_event_item->event_size);
                 res = true;
             } else {
                 // TODO clear other threshold items linked with this one
@@ -1428,7 +1445,7 @@ static int s_cli_dag(int argc, char ** argv, void **a_str_reply)
                 }
             }
             // write events to file and delete events from db
-            if(l_list_to_del) {
+            /* if(l_list_to_del) {
                 if (dap_chain_cell_file_update(l_chain->cells) > 0) {
                     // delete events from db
                     dap_list_t *l_el;
@@ -1438,7 +1455,7 @@ static int s_cli_dag(int argc, char ** argv, void **a_str_reply)
                 }
                 dap_chain_cell_close(l_chain->cells);
                 dap_list_free(l_list_to_del);
-            }
+            } */ // TODO!
 
             // Cleaning up
             dap_global_db_objs_delete(l_objs, l_objs_size);