diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4ed57cfbe6ed61d42b951aa773bb95b6fa6896eb..4cad786450e8bc9b9d7016fd84913178d93287ad 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,7 +2,7 @@ project(cellframe-sdk C)
 cmake_minimum_required(VERSION 2.8)
 
 set(CMAKE_C_STANDARD 11)
-set(CELLFRAME_SDK_NATIVE_VERSION "2.5-20")
+set(CELLFRAME_SDK_NATIVE_VERSION "2.6-6")
 add_definitions ("-DCELLFRAME_SDK_VERSION=\"${CELLFRAME_SDK_NATIVE_VERSION}\"")
 
 set(DAPSDK_MODULES "")
@@ -55,7 +55,7 @@ endif()
 # Networking
 if (CELLFRAME_MODULES MATCHES "network")
     message("[+] Module 'network'")
-    set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_server_core dap_enc_server dap_http_server dap_session
+    set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_server_core dap_json_rpc dap_enc_server dap_http_server dap_session
 	dap_stream dap_stream_ch dap_client dap_stream_ch_chain dap_stream_ch_chain_net dap_chain_net dap_chain_mempool magic)
 endif()
 
diff --git a/dap-sdk/crypto/include/dap_enc_base58.h b/dap-sdk/crypto/include/dap_enc_base58.h
index 8392fb617e0f0c29a391484feaddb65a4e9193fe..8652d7bfd01a8626748f4cca624ba3925b0f8a79 100755
--- a/dap-sdk/crypto/include/dap_enc_base58.h
+++ b/dap-sdk/crypto/include/dap_enc_base58.h
@@ -47,6 +47,7 @@ char* dap_enc_base58_encode_hash_to_str(dap_chain_hash_fast_t *a_in_hash);
 char* dap_enc_base58_from_hex_str_to_str(const char *a_in_str);
 // convert from "Bura1HFrKsqbdytEXQVrxpbovtvLhR1VbrJs65JBx3gc" to "0xA21F1E865B6740A28E8708798ECF25D2C0AA596DF5EB1FD724186B6AD7FF2199"
 char* dap_enc_base58_to_hex_str_from_str(const char *a_in_str);
+int dap_enc_base58_hex_to_hash(const char * a_hex_str,  dap_chain_hash_fast_t * a_datum_hash);
 
 #ifdef __cplusplus
 }
diff --git a/dap-sdk/crypto/src/dap_enc_base58.c b/dap-sdk/crypto/src/dap_enc_base58.c
index acbfe8fcc550e359a81542ea00ab35564fe77636..fba7d9a63399290516220f17d4bf207fed7242bc 100755
--- a/dap-sdk/crypto/src/dap_enc_base58.c
+++ b/dap-sdk/crypto/src/dap_enc_base58.c
@@ -219,6 +219,34 @@ char* dap_enc_base58_encode_hash_to_str(dap_chain_hash_fast_t *a_in_hash)
     return dap_enc_base58_encode_to_str(a_in_hash->raw, sizeof(dap_chain_hash_fast_t));
 }
 
+/**
+ * @brief dap_enc_base58_hex_to_hash
+ * @param a_hex_str
+ * @param a_datum_hash
+ * @return
+ */
+int dap_enc_base58_hex_to_hash(const char * a_hex_str,  dap_chain_hash_fast_t * a_datum_hash)
+{
+    assert(a_datum_hash);
+
+    if (a_hex_str){
+        char* l_datum_base58 = dap_enc_base58_from_hex_str_to_str(a_hex_str);
+        void * l_decoded = DAP_NEW_Z_SIZE(void,strlen(l_datum_base58));
+        size_t l_decoded_size;
+        if (( l_decoded_size = dap_enc_base58_decode(l_datum_base58, l_decoded))!= sizeof (*a_datum_hash) ){
+            memcpy( a_datum_hash, l_decoded, l_decoded_size);
+            return 0;
+        }else{
+            log_it(L_ERROR,"Wrong hash format: can't parse \"%s\", decoded size %zd when expected %zd", a_hex_str, l_decoded_size,
+                                                                                                       sizeof (*a_datum_hash));
+            return -1;
+        }
+
+    }else
+        return -1;
+}
+
+
 // convert from "0xA21F1E865B6740A28E8708798ECF25D2C0AA596DF5EB1FD724186B6AD7FF2199" to "Bura1HFrKsqbdytEXQVrxpbovtvLhR1VbrJs65JBx3gc"
 char* dap_enc_base58_from_hex_str_to_str(const char *a_in_str)
 {
diff --git a/dap-sdk/net/core/dap_events.c b/dap-sdk/net/core/dap_events.c
index fd786c671c1b1831f49cb734c6239ffa6f35185e..f29f7f3d8fde6dc2c51966100a673972b5739ccb 100644
--- a/dap-sdk/net/core/dap_events.c
+++ b/dap-sdk/net/core/dap_events.c
@@ -39,7 +39,7 @@
 #include <sys/stat.h>
 #endif
 
-#include <netdb.h>
+//#include <netdb.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <errno.h>
diff --git a/dap-sdk/net/core/include/dap_events_socket.h b/dap-sdk/net/core/include/dap_events_socket.h
index 474c26ad4ced342b3971f73dfb8d6a111fe74c40..0b9f6dcd07e380d975fc7c2a3a7eb94913c4fa4b 100644
--- a/dap-sdk/net/core/include/dap_events_socket.h
+++ b/dap-sdk/net/core/include/dap_events_socket.h
@@ -54,12 +54,12 @@
     #define DAP_EVENTS_CAPS_PIPE_POSIX
 #endif
 
-#if defined(DAP_EVENTS_CAPS_EPOLL)
-#include <sys/epoll.h>
-#define EPOLL_HANDLE  int
-#elif defined (DAP_EVENTS_CAPS_WEPOLL)
+#if defined(DAP_EVENTS_CAPS_WEPOLL)
 #include "wepoll.h"
 #define EPOLL_HANDLE  HANDLE
+#elif defined (DAP_EVENTS_CAPS_EPOLL)
+#include <sys/epoll.h>
+#define EPOLL_HANDLE  int
 #endif
 
 #define BIT( x ) ( 1 << x )
diff --git a/dap-sdk/net/server/CMakeLists.txt b/dap-sdk/net/server/CMakeLists.txt
index dfc4ed963be9cd4d6bfd7e7d7dbaa46d5bbf32e8..498ed08f7e69ff297e6a347ddc215c5cdfc56b08 100644
--- a/dap-sdk/net/server/CMakeLists.txt
+++ b/dap-sdk/net/server/CMakeLists.txt
@@ -7,6 +7,7 @@ endif()
 
 add_subdirectory(http_server)
 add_subdirectory(enc_server)
+add_subdirectory(json_rpc)
 
 if (BUILD_LIB_DAP_SERVER_TESTS)
     enable_testing()
diff --git a/dap-sdk/net/server/http_server/http_client/dap_http_client.c b/dap-sdk/net/server/http_server/http_client/dap_http_client.c
index 59f30cf660aefe3d5977ac80c5397f792e3355b6..8ee096e68d2b2fc0ad95c50161e7394e300c7a64 100644
--- a/dap-sdk/net/server/http_server/http_client/dap_http_client.c
+++ b/dap-sdk/net/server/http_server/http_client/dap_http_client.c
@@ -369,7 +369,7 @@ void dap_http_client_read( dap_events_socket_t *a_esocket, void *arg )
 
                 char *l_query_string;
                 if( (l_query_string = strchr(l_http_client->url_path, '?')) != NULL ) {
-                    size_t len_after = strlen( l_query_string + 1 );
+                    size_t len_after = MIN(strlen( l_query_string + 1 ), sizeof (l_http_client->url_path)-1);
 
                     if ( len_after ) {
                         if( len_after > (sizeof(l_http_client->in_query_string) - 1) ){
diff --git a/dap-sdk/net/server/json_rpc/CMakeLists.txt b/dap-sdk/net/server/json_rpc/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..7c6ac9cea29ad497ba58da6433ec80bfb2b8e1d3
--- /dev/null
+++ b/dap-sdk/net/server/json_rpc/CMakeLists.txt
@@ -0,0 +1,17 @@
+project(dap_json_rpc C)
+cmake_minimum_required(VERSION 3.0)
+
+add_definitions ("-D_GNU_SOURCE")
+add_definitions("-Dfpic")
+
+file(GLOB JSON_RPC_HEADERS include/*.h)
+file(GLOB JSON_RPC_SRCS src/*.c)
+
+include_directories(${PROJECT_NAME} include/)
+
+add_library(${PROJECT_NAME} STATIC ${JSON_RPC_HEADERS} ${JSON_RPC_SRCS})
+target_include_directories(${PROJECT_NAME} INTERFACE . include/)
+target_include_directories(${PROJECT_NAME} PUBLIC include)
+
+target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_server_core dap_http_server dap_client json-c )
+#target_link_libraries(${PROJECT_NAME} dap_core)# dap_http_server json-c)
diff --git a/modules/type/block/include/dap_chain_cs_blocks.h b/dap-sdk/net/server/json_rpc/include/dap_json_rpc.h
similarity index 55%
rename from modules/type/block/include/dap_chain_cs_blocks.h
rename to dap-sdk/net/server/json_rpc/include/dap_json_rpc.h
index ae1dc4c701f888759bc73026ff47dc9917bfa925..8032fa93860dc67564100bfe949135da45d5d591 100644
--- a/modules/type/block/include/dap_chain_cs_blocks.h
+++ b/dap-sdk/net/server/json_rpc/include/dap_json_rpc.h
@@ -1,9 +1,9 @@
 /*
  * Authors:
- * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net>
+ * Alexey V. Stratulat <alexey.stratulat@demlabs.net>
  * DeM Labs Inc.   https://demlabs.net
- * Kelvin Project https://github.com/kelvinblockchain
- * Copyright  (c) 2017-2018
+ * DeM Labs Open source community https://gitlab.demlabs.net/cellframe/cellframe-sdk
+ * Copyright  (c) 2017-2020
  * All rights reserved.
 
  This file is part of DAP (Deus Applications Prototypes) the open source project
@@ -21,23 +21,27 @@
     You should have received a copy of the GNU General Public License
     along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
 */
-#pragma once
-
-#include "dap_chain.h"
-#include "dap_chain_block.h"
-#include "dap_chain_block_cache.h"
-
-typedef struct dap_chain_cs_blocks
-{
-    dap_chain_t * chain;
-    void * _pvt;
-    void * _iheritor;
-} dap_chain_cs_blocks_t;
 
-typedef int (*dap_chain_blocks_block_callback_ptr_t)(dap_chain_cs_blocks_t *, dap_chain_block_t *);
 
-int dap_chain_cs_blocks_init();
-void dap_chain_cs_blocks_deinit();
-
-dap_chain_block_cache_t* dap_chain_cs_blocks_allocate_next_block(dap_chain_cs_blocks_t * a_cs_blocks);
-void dap_chain_cs_blocks_new(dap_chain_t * a_chain);
+#pragma once
+#include "dap_http_simple.h"
+#include "include/http_status_code.h"
+#include "dap_strfuncs.h"
+#include "dap_json_rpc_request.h"
+#include "dap_json_rpc_request_handler.h"
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+typedef enum dap_json_rpc_version{
+    RPC_VERSION_1
+}dap_json_rpc_version_t;
+
+int dap_json_rpc_init();
+void dap_json_rpc_deinit();
+void dap_json_rpc_add_proc_http(struct dap_http *sh, const char *URL);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/dap-sdk/net/server/json_rpc/include/dap_json_rpc_errors.h b/dap-sdk/net/server/json_rpc/include/dap_json_rpc_errors.h
new file mode 100644
index 0000000000000000000000000000000000000000..c0811b0afbdbfb33a61de35f6a67879f143d2eb0
--- /dev/null
+++ b/dap-sdk/net/server/json_rpc/include/dap_json_rpc_errors.h
@@ -0,0 +1,70 @@
+/*
+ * Authors:
+ * Alexey V. Stratulat <alexey.stratulat@demlabs.net>
+ * DeM Labs Inc.   https://demlabs.net
+ * DeM Labs Open source community https://gitlab.demlabs.net/cellframe/cellframe-sdk
+ * Copyright  (c) 2017-2020
+ * All rights reserved.
+
+ This file is part of DAP (Deus Applications Prototypes) the open source project
+
+    DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    DAP is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#pragma once
+
+#include "dap_common.h"
+#include "dap_strfuncs.h"
+#include "utlist.h"
+#include "json-c/json.h"
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+typedef struct dap_json_rpc_error
+{
+    int code_error;
+    char *msg;
+    void *next;
+}dap_json_rpc_error_t;
+
+typedef struct dap_json_rpc_error_JSON
+{
+    json_object *obj_code;
+    json_object *obj_msg;
+}dap_json_rpc_error_JSON_t;
+
+int dap_json_rpc_error_init(void);
+void dap_json_rpc_error_deinit(void);
+
+dap_json_rpc_error_JSON_t * dap_json_rpc_error_JSON_create();
+void dap_json_rpc_error_JSON_free(dap_json_rpc_error_JSON_t *a_error_json);
+dap_json_rpc_error_JSON_t * dap_json_rpc_error_JSON_add_data(int code, const char *msg);
+
+int dap_json_rpc_error_add(int a_code_error, const char *a_msg);
+
+dap_json_rpc_error_t *dap_json_rpc_error_search_by_code(int a_code_error);
+
+char *dap_json_rpc_error_get_json(dap_json_rpc_error_t *a_error);
+
+dap_json_rpc_error_t *dap_json_rpc_create_from_json(const char *a_json);
+
+dap_json_rpc_error_t *dap_json_rpc_create_from_json_object(json_object *a_jobj);
+
+void dap_json_rpc_add_standart_erros(void);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/modules/type/block/include/dap_chain_block_cache.h b/dap-sdk/net/server/json_rpc/include/dap_json_rpc_notification.h
similarity index 50%
rename from modules/type/block/include/dap_chain_block_cache.h
rename to dap-sdk/net/server/json_rpc/include/dap_json_rpc_notification.h
index b2949d276da6b6ee459bfe7838e61e28c796a0bb..239ac8ecfea0bef24862d386b0ac6216aeb02819 100644
--- a/modules/type/block/include/dap_chain_block_cache.h
+++ b/dap-sdk/net/server/json_rpc/include/dap_json_rpc_notification.h
@@ -1,9 +1,9 @@
 /*
  * Authors:
- * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net>
+ * Alexey V. Stratulat <alexey.stratulat@demlabs.net>
  * DeM Labs Inc.   https://demlabs.net
- * Kelvin Project https://github.com/kelvinblockchain
- * Copyright  (c) 2017-2018
+ * DeM Labs Open source community https://gitlab.demlabs.net/cellframe/cellframe-sdk
+ * Copyright  (c) 2017-2020
  * All rights reserved.
 
  This file is part of DAP (Deus Applications Prototypes) the open source project
@@ -22,19 +22,28 @@
     along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
 */
 #pragma once
-#include "dap_chain_block.h"
-#include "dap_hash.h"
 
-typedef struct dap_chain_block_cache{
-    dap_chain_hash_t block_hash;
-    uint32_t sections_size;
+#include "dap_json_rpc_request.h"
+#include "uthash.h"
 
-    double block_mine_time;
-    dap_chain_block_t * block;
-} dap_chain_block_cache_t;
+#ifdef __cplusplus
+extern "C"{
+#endif
 
-dap_chain_block_cache_t * dap_chain_block_cache_new(dap_chain_block_t * a_block);
-void dap_chain_block_cache_delete(dap_chain_block_cache_t * a_block_cache);
-dap_chain_block_t* dap_chain_block_cache_sections_size_grow(dap_chain_block_cache_t * a_block_cache,size_t a_sections_size_grow );
+typedef void (notification_handler_func_t)(dap_json_rpc_params_t *a_param);
 
-void dap_chain_block_cache_dump(dap_chain_block_cache_t * a_block_cache);
+typedef struct dap_json_rpc_notification_handler
+{
+    char *method;
+    notification_handler_func_t *func;
+    UT_hash_handle  hh;
+}dap_json_rpc_notification_handler_t;
+
+int dap_json_rpc_notification_registration(const char *a_method, notification_handler_func_t *a_notification_func);
+void dap_json_rpc_notification_unregistration(const char *a_method);
+
+void dap_json_rpc_notification_handler(const char *a_name_method, dap_json_rpc_params_t *a_params);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/dap-sdk/net/server/json_rpc/include/dap_json_rpc_params.h b/dap-sdk/net/server/json_rpc/include/dap_json_rpc_params.h
new file mode 100644
index 0000000000000000000000000000000000000000..9068f4a0ff217aee3e8a8533599c558882140601
--- /dev/null
+++ b/dap-sdk/net/server/json_rpc/include/dap_json_rpc_params.h
@@ -0,0 +1,73 @@
+/*
+ * Authors:
+ * Alexey V. Stratulat <alexey.stratulat@demlabs.net>
+ * DeM Labs Inc.   https://demlabs.net
+ * DeM Labs Open source community https://gitlab.demlabs.net/cellframe/cellframe-sdk
+ * Copyright  (c) 2017-2020
+ * All rights reserved.
+
+ This file is part of DAP (Deus Applications Prototypes) the open source project
+
+    DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    DAP is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#pragma once
+#include "dap_common.h"
+#include "dap_strfuncs.h"
+#include "json-c/json.h"
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+typedef enum dap_json_rpc_type_param{
+    TYPE_PARAM_NULL,
+    TYPE_PARAM_STRING,
+    TYPE_PARAM_INTEGER,
+    TYPE_PARAM_DOUBLE,
+    TYPE_PARAM_BOOLEAN
+}dap_json_rpc_type_param_t;
+
+typedef struct dap_json_rpc_param
+{
+    void *value_param;
+    enum dap_json_rpc_type_param type;
+}dap_json_rpc_param_t;
+
+typedef struct dap_json_rpc_params
+{
+    uint32_t lenght;
+    dap_json_rpc_param_t **params;
+}dap_json_rpc_params_t;
+
+dap_json_rpc_params_t* dap_json_rpc_params_create(void);
+
+void dap_json_rpc_params_add_data(dap_json_rpc_params_t *a_params, const void *a_value,
+                                  dap_json_rpc_type_param_t a_type);
+void dap_json_rpc_params_add_param(dap_json_rpc_params_t *a_params, dap_json_rpc_param_t *a_param);
+
+void dap_json_rpc_params_remove_all(dap_json_rpc_params_t *a_params);
+
+uint32_t dap_json_rpc_params_lenght(dap_json_rpc_params_t *a_params);
+void *dap_json_rpc_params_get(dap_json_rpc_params_t *a_params, uint32_t index);
+dap_json_rpc_type_param_t dap_json_rpc_params_get_type_param(dap_json_rpc_params_t *a_params, uint32_t index);
+
+void dap_json_rpc_param_remove(dap_json_rpc_param_t *param);
+
+dap_json_rpc_params_t * dap_json_rpc_params_create_from_array_list(json_object *a_array_list);
+char *dap_json_rpc_params_get_string_json(dap_json_rpc_params_t * a_params);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/dap-sdk/net/server/json_rpc/include/dap_json_rpc_request.h b/dap-sdk/net/server/json_rpc/include/dap_json_rpc_request.h
new file mode 100644
index 0000000000000000000000000000000000000000..9182f64c757982166eaf5e6c6557a1a281aa5e4c
--- /dev/null
+++ b/dap-sdk/net/server/json_rpc/include/dap_json_rpc_request.h
@@ -0,0 +1,57 @@
+/*
+ * Authors:
+ * Alexey V. Stratulat <alexey.stratulat@demlabs.net>
+ * DeM Labs Inc.   https://demlabs.net
+ * DeM Labs Open source community https://gitlab.demlabs.net/cellframe/cellframe-sdk
+ * Copyright  (c) 2017-2020
+ * All rights reserved.
+
+ This file is part of DAP (Deus Applications Prototypes) the open source project
+
+    DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    DAP is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#pragma once
+#include "dap_common.h"
+#include "dap_json_rpc_params.h"
+#include "json-c/json.h"
+#include "dap_json_rpc_response_handler.h"
+#include "dap_string.h"
+#include "dap_client_http.h"
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+typedef struct dap_json_rpc_request
+{
+    char* method;
+    dap_json_rpc_params_t *params;
+    uint64_t id;
+}dap_json_rpc_request_t;
+
+int dap_json_rpc_request_init(const char *a_url_service);
+
+dap_json_rpc_request_t *dap_json_rpc_request_creation(const char *a_method, dap_json_rpc_params_t *a_params, int64_t a_id);
+
+dap_json_rpc_request_t *dap_json_rpc_request_from_json(const char *a_data);
+char *dap_json_rpc_request_to_json(const dap_json_rpc_request_t *a_request);
+
+void dap_json_rpc_request_send(dap_json_rpc_request_t *a_request, dap_json_rpc_response_handler_func_t *response_handler,
+                               const char *a_uplink_addr, const uint16_t a_uplink_port,
+                               dap_client_http_callback_error_t func_error);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/dap-sdk/net/server/json_rpc/include/dap_json_rpc_request_handler.h b/dap-sdk/net/server/json_rpc/include/dap_json_rpc_request_handler.h
new file mode 100644
index 0000000000000000000000000000000000000000..64f9adc60e9ef37180c78894436ddd8235df4c50
--- /dev/null
+++ b/dap-sdk/net/server/json_rpc/include/dap_json_rpc_request_handler.h
@@ -0,0 +1,56 @@
+/*
+ * Authors:
+ * Alexey V. Stratulat <alexey.stratulat@demlabs.net>
+ * DeM Labs Inc.   https://demlabs.net
+ * DeM Labs Open source community https://gitlab.demlabs.net/cellframe/cellframe-sdk
+ * Copyright  (c) 2017-2020
+ * All rights reserved.
+
+ This file is part of DAP (Deus Applications Prototypes) the open source project
+
+    DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    DAP is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#pragma once
+
+#include "dap_common.h"
+#include "dap_strfuncs.h"
+#include "dap_json_rpc_request.h"
+#include "dap_json_rpc_params.h"
+#include "dap_http_simple.h"
+#include "dap_json_rpc_errors.h"
+#include "dap_json_rpc_response.h"
+#include "dap_json_rpc_notification.h"
+#include "uthash.h"
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+typedef void (handler_func_t)(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+
+typedef  struct dap_json_rpc_request_handler
+{
+    char *name;
+    handler_func_t *func;
+    UT_hash_handle hh;
+}dap_json_rpc_request_handler_t;
+
+int dap_json_rpc_registration_request_handler(const char *a_name, handler_func_t *a_func);
+int dap_json_rpc_unregistration_request_handler(const char *a_name);
+
+void dap_json_rpc_request_handler(dap_json_rpc_request_t *a_request, dap_http_simple_t *a_client);
+#ifdef __cplusplus
+}
+#endif
diff --git a/dap-sdk/net/server/json_rpc/include/dap_json_rpc_response.h b/dap-sdk/net/server/json_rpc/include/dap_json_rpc_response.h
new file mode 100644
index 0000000000000000000000000000000000000000..40ef6ac826e0b774eea4b2ea04a65ecfdbf693f0
--- /dev/null
+++ b/dap-sdk/net/server/json_rpc/include/dap_json_rpc_response.h
@@ -0,0 +1,74 @@
+/*
+ * Authors:
+ * Alexey V. Stratulat <alexey.stratulat@demlabs.net>
+ * DeM Labs Inc.   https://demlabs.net
+ * DeM Labs Open source community https://gitlab.demlabs.net/cellframe/cellframe-sdk
+ * Copyright  (c) 2017-2020
+ * All rights reserved.
+
+ This file is part of DAP (Deus Applications Prototypes) the open source project
+
+    DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    DAP is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#pragma once
+
+#include "dap_http_simple.h"
+#include "dap_json_rpc_errors.h"
+#include "json-c/json.h"
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+typedef enum dap_json_rpc_response_type_result{
+    TYPE_RESPONSE_NULL,
+    TYPE_RESPONSE_STRING,
+    TYPE_RESPONSE_INTEGER,
+    TYPE_RESPONSE_DOUBLE,
+    TYPE_RESPONSE_BOOLEAN
+}dap_json_rpc_response_type_result_t;
+
+typedef struct dap_json_rpc_response_JSON
+{
+    json_object *obj_result;
+    json_object *obj_error;
+    dap_json_rpc_error_JSON_t *struct_error;
+    json_object *obj_id;
+}dap_json_rpc_request_JSON_t;
+
+void dap_json_rpc_request_JSON_free(dap_json_rpc_request_JSON_t *l_request_JSON);
+
+typedef struct dap_json_rpc_response
+{
+    dap_json_rpc_response_type_result_t type_result;
+    char* result_string;
+    int64_t result_int;
+    double result_double;
+    bool result_boolean;
+    dap_json_rpc_error_t* error;
+    int64_t id;
+}dap_json_rpc_response_t;
+
+
+void dap_json_rpc_response_free(dap_json_rpc_response_t *a_response);
+
+void dap_json_rpc_response_send(dap_json_rpc_response_t *a_response, dap_http_simple_t *a_client);
+
+dap_json_rpc_response_t *dap_json_rpc_response_from_json(char *a_data_json);
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/dap-sdk/net/server/json_rpc/include/dap_json_rpc_response_handler.h b/dap-sdk/net/server/json_rpc/include/dap_json_rpc_response_handler.h
new file mode 100644
index 0000000000000000000000000000000000000000..1861ac2ce9a8bd08b738b498389529d356a9769f
--- /dev/null
+++ b/dap-sdk/net/server/json_rpc/include/dap_json_rpc_response_handler.h
@@ -0,0 +1,55 @@
+/*
+ * Authors:
+ * Alexey V. Stratulat <alexey.stratulat@demlabs.net>
+ * DeM Labs Inc.   https://demlabs.net
+ * DeM Labs Open source community https://gitlab.demlabs.net/cellframe/cellframe-sdk
+ * Copyright  (c) 2017-2020
+ * All rights reserved.
+
+ This file is part of DAP (Deus Applications Prototypes) the open source project
+
+    DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    DAP is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#pragma once
+
+#include "dap_json_rpc_response.h"
+#include "uthash.h"
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+typedef void (dap_json_rpc_response_handler_func_t)(dap_json_rpc_response_t *a_response);
+
+typedef struct dap_json_rpc_response_handler
+{
+    dap_json_rpc_response_handler_func_t *func;
+    uint64_t id;
+    UT_hash_handle hh;
+}dap_json_rpc_response_handler_t;
+
+int dap_json_rpc_response_registration_with_id(uint64_t a_id, dap_json_rpc_response_handler_func_t *func);
+uint64_t dap_json_rpc_response_registration(dap_json_rpc_response_handler_func_t *func);
+void dap_json_rpc_response_unregistration(uint64_t a_id);
+
+void dap_json_rpc_response_handler(dap_json_rpc_response_t *a_response);
+
+uint64_t dap_json_rpc_response_get_new_id(void);
+
+void dap_json_rpc_response_accepted(void *a_data, size_t a_size_data, void *a_obj);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/dap-sdk/net/server/json_rpc/src/dap_json_rpc.c b/dap-sdk/net/server/json_rpc/src/dap_json_rpc.c
new file mode 100644
index 0000000000000000000000000000000000000000..57832ccd9438745f63b2b641dacd9382e9ce5a98
--- /dev/null
+++ b/dap-sdk/net/server/json_rpc/src/dap_json_rpc.c
@@ -0,0 +1,35 @@
+#include "dap_json_rpc.h"
+
+#define LOG_TAG "dap_json_rpc_rpc"
+
+static bool init_module = false;
+
+int dap_json_rpc_init()
+{
+    init_module = true;
+    return 0;
+}
+
+void dap_json_rpc_deinit()
+{
+    //
+}
+
+void _json_rpc_http_proc(struct dap_http_simple *a_client, void *a_arg)
+{
+    log_it(L_DEBUG, "Proc json_rpc request");
+    http_status_code_t *l_http_code = (http_status_code_t*)a_arg;
+    dap_json_rpc_request_t *l_request = dap_json_rpc_request_from_json(a_client->request);
+    if (l_request){
+        dap_json_rpc_request_handler(l_request, a_client);
+    } else {
+        *l_http_code = Http_Status_NotFound;
+    }
+    *l_http_code = Http_Status_OK;
+}
+
+void dap_json_rpc_add_proc_http(struct dap_http *sh, const char *URL)
+{
+    dap_http_simple_proc_add(sh, URL, 140000, _json_rpc_http_proc);
+    dap_json_rpc_request_init(URL);
+}
diff --git a/dap-sdk/net/server/json_rpc/src/dap_json_rpc_errors.c b/dap-sdk/net/server/json_rpc/src/dap_json_rpc_errors.c
new file mode 100644
index 0000000000000000000000000000000000000000..6d465ddcc6553e861eede6ab1ccd7870f9b97696
--- /dev/null
+++ b/dap-sdk/net/server/json_rpc/src/dap_json_rpc_errors.c
@@ -0,0 +1,120 @@
+#include "dap_json_rpc_errors.h"
+
+#define LOG_TAG "dap_json_rpc_errors"
+
+static dap_json_rpc_error_t *s_errors;
+int _dap_json_rpc_error_cmp_by_code(dap_json_rpc_error_t *a_error, int a_code_error);
+
+int dap_json_rpc_error_init(void)
+{
+    s_errors = NULL;
+    return  0;
+}
+void dap_json_rpc_error_deinit(void)
+{
+    dap_json_rpc_error_t *err, *tmp;
+    if (s_errors != NULL){
+        LL_FOREACH_SAFE(s_errors, err, tmp){
+            LL_DELETE(s_errors, err);
+            DAP_FREE(err->msg);
+            DAP_FREE(err);
+        }
+    }
+}
+
+dap_json_rpc_error_JSON_t * dap_json_rpc_error_JSON_create()
+{
+    dap_json_rpc_error_JSON_t *l_json = DAP_NEW(dap_json_rpc_error_JSON_t);
+    l_json->obj_msg = NULL;
+    l_json->obj_code = NULL;
+    return l_json;
+}
+void dap_json_rpc_error_JSON_free(dap_json_rpc_error_JSON_t *a_error_json)
+{
+    json_object_put(a_error_json->obj_code);
+    json_object_put(a_error_json->obj_msg);
+    DAP_FREE(a_error_json);
+}
+dap_json_rpc_error_JSON_t * dap_json_rpc_error_JSON_add_data(int code, const char *msg)
+{
+    dap_json_rpc_error_JSON_t *l_json_err = dap_json_rpc_error_JSON_create();
+    l_json_err->obj_code = json_object_new_int(code);
+    l_json_err->obj_msg = json_object_new_string(msg);
+    return l_json_err;
+}
+
+int dap_json_rpc_error_add(int a_code_error, const char *a_msg)
+{
+    dap_json_rpc_error_t *l_el_search =dap_json_rpc_error_search_by_code(a_code_error);
+    if (l_el_search != NULL)
+        return 1;
+    dap_json_rpc_error_t *l_error = DAP_NEW(dap_json_rpc_error_t);
+    l_error->code_error = a_code_error;
+    l_error->msg = dap_strdup(a_msg);
+    LL_APPEND(s_errors, l_error);
+    log_it(L_NOTICE, "Registration type error. Code error: %d message: %s", a_code_error, a_msg);
+    return 0;
+}
+
+int _dap_json_rpc_error_cmp_by_code(dap_json_rpc_error_t *a_error, int a_code_error)
+{
+    if (a_error->code_error == a_code_error)
+        return 0;
+    if (a_error->code_error < a_code_error)
+        return -1;
+    if (a_error->code_error > a_code_error)
+        return 1;
+}
+
+dap_json_rpc_error_t *dap_json_rpc_error_search_by_code(int a_code_error)
+{
+    dap_json_rpc_error_t *l_element = NULL;
+    LL_SEARCH(s_errors, l_element, a_code_error, _dap_json_rpc_error_cmp_by_code);
+    return l_element;
+}
+
+char *dap_json_rpc_error_get_json(dap_json_rpc_error_t *a_error)
+{
+    log_it(L_NOTICE, "Translation JSON string to struct dap_json_rpc_error");
+    json_object *l_jobj_code = json_object_new_int64(a_error->code_error);
+    json_object *l_jobj_msg = json_object_new_string(a_error->msg);
+    json_object *l_jobj = json_object_new_object();
+    json_object_object_add(l_jobj, "code", l_jobj_code);
+    json_object_object_add(l_jobj, "message", l_jobj_msg);
+    json_object *l_jobj_err = json_object_new_object();
+    json_object_object_add(l_jobj_err, "error", l_jobj);
+    char *l_json_str = dap_strdup(json_object_to_json_string(l_jobj_err));
+    json_object_put(l_jobj_err);
+    json_object_put(l_jobj_code);
+    json_object_put(l_jobj_msg);
+    json_object_put(l_jobj);
+    return l_json_str;
+}
+
+dap_json_rpc_error_t *dap_json_rpc_create_from_json(const char *a_json)
+{
+    log_it(L_NOTICE, "Translation struct dap_json_rpc_error to JSON string");
+    json_object *l_jobj = json_tokener_parse(a_json);
+    dap_json_rpc_error_t *l_error = dap_json_rpc_create_from_json_object(l_jobj);
+    json_object_put(l_jobj);
+    return l_error;
+}
+
+void dap_json_rpc_add_standart_erros(void)
+{
+    log_it(L_DEBUG, "Registration standart type erros");
+    dap_json_rpc_error_add(0, "Unknown error");
+    dap_json_rpc_error_add(1, "Not found handler for this request");
+}
+
+dap_json_rpc_error_t *dap_json_rpc_create_from_json_object(json_object *a_jobj)
+{
+    dap_json_rpc_error_t *l_error = DAP_NEW(dap_json_rpc_error_t);
+    json_object *l_jobj_code_eror = json_object_object_get(a_jobj, "code");
+    json_object *l_jobj_msg = json_object_object_get(a_jobj, "message");
+    l_error->code_error = json_object_get_int64(l_jobj_code_eror);
+    l_error->msg = dap_strdup(json_object_get_string(l_jobj_msg));
+    json_object_put(l_jobj_code_eror);
+    json_object_put(l_jobj_msg);
+    return l_error;
+}
diff --git a/dap-sdk/net/server/json_rpc/src/dap_json_rpc_notification.c b/dap-sdk/net/server/json_rpc/src/dap_json_rpc_notification.c
new file mode 100644
index 0000000000000000000000000000000000000000..8c4e973bab1d1e57ab1c9b94c61f4b834b556b65
--- /dev/null
+++ b/dap-sdk/net/server/json_rpc/src/dap_json_rpc_notification.c
@@ -0,0 +1,44 @@
+#include "dap_json_rpc_notification.h"
+
+#define LOG_TAG "dap_json_rpc_notification"
+
+static dap_json_rpc_notification_handler_t *s_handler_notifications = NULL;
+
+
+int dap_json_rpc_notification_registration(const char *a_method, notification_handler_func_t *a_notification_func)
+{
+    dap_json_rpc_notification_handler_t *l_handler;
+    HASH_FIND_STR(s_handler_notifications, a_method, l_handler);
+    if (l_handler == 0){
+        l_handler = DAP_NEW(dap_json_rpc_notification_handler_t);
+        l_handler->method = dap_strdup(a_method);
+        l_handler->func = a_notification_func;
+        HASH_ADD_STR(s_handler_notifications, method, l_handler);
+        log_it(L_NOTICE, "Registration method %s for handler notification", a_method);
+        return 0;
+    }
+    return 1;
+}
+void dap_json_rpc_notification_unregistration(const char *a_method)
+{
+    dap_json_rpc_notification_handler_t *l_handler;
+    HASH_FIND_STR(s_handler_notifications, a_method, l_handler);
+    if (l_handler != NULL){
+        HASH_DEL(s_handler_notifications, l_handler);
+        DAP_FREE(l_handler->method);
+        DAP_FREE(l_handler);
+        log_it(L_NOTICE, "Unregistration method %s. This method handler notification", a_method);
+    }
+}
+
+void dap_json_rpc_notification_handler(const char *a_name_method, dap_json_rpc_params_t *a_params)
+{
+    dap_json_rpc_notification_handler_t *l_handler = NULL;
+    HASH_FIND_STR(s_handler_notifications, a_name_method, l_handler);
+    if (l_handler != NULL){
+        l_handler->func(a_params);
+        log_it(L_DEBUG, "Call method handling notfication: %s", a_name_method);
+    } else {
+        log_it(L_NOTICE, "Not found method %s. This method handler notification");
+    }
+}
diff --git a/dap-sdk/net/server/json_rpc/src/dap_json_rpc_params.c b/dap-sdk/net/server/json_rpc/src/dap_json_rpc_params.c
new file mode 100644
index 0000000000000000000000000000000000000000..07d3835e8eb5269cebd9485dc6b7c1e1c4f831f8
--- /dev/null
+++ b/dap-sdk/net/server/json_rpc/src/dap_json_rpc_params.c
@@ -0,0 +1,160 @@
+#include "dap_json_rpc_params.h"
+
+#define LOG_TAG "dap_json_rpc_params"
+
+dap_json_rpc_params_t* dap_json_rpc_params_create(void)
+{
+    dap_json_rpc_params_t *l_params = DAP_NEW(dap_json_rpc_params_t);
+    l_params->lenght = 0;
+    return l_params;
+}
+
+
+void dap_json_rpc_params_add_data(dap_json_rpc_params_t *a_params, const void *a_value,
+                                  dap_json_rpc_type_param_t a_type)
+{
+    log_it(L_DEBUG, "Add data in params");
+    dap_json_rpc_param_t *l_param = DAP_NEW(dap_json_rpc_param_t);
+    //l_param->name_param = dap_strdup(a_name);
+    l_param->type = a_type;
+    size_t l_len_value;
+    switch (a_type) {
+    case TYPE_PARAM_STRING:
+        l_param->value_param = dap_strdup((char*)a_value);
+        break;
+    case TYPE_PARAM_BOOLEAN:
+        l_len_value = sizeof(bool);
+        l_param->value_param = DAP_NEW(bool);
+        memcpy(l_param->value_param, a_value, l_len_value);
+        break;
+    case TYPE_PARAM_INTEGER:
+        l_len_value = sizeof(int64_t);
+        l_param->value_param = DAP_NEW(int64_t);
+        memcpy(l_param->value_param, a_value, l_len_value);
+        break;
+    case TYPE_PARAM_DOUBLE:
+        l_len_value = sizeof(double);
+        l_param->value_param = DAP_NEW(double);
+        memcpy(l_param->value_param, a_value, l_len_value);
+        break;
+    default:
+        l_param->value_param = NULL;
+        break;
+    }
+    dap_json_rpc_params_add_param(a_params, l_param);
+}
+void dap_json_rpc_params_add_param(dap_json_rpc_params_t *a_params, dap_json_rpc_param_t *a_param)
+{
+    uint32_t l_len_new_params = a_params->lenght + 1;
+    dap_json_rpc_param_t **l_new_params = DAP_NEW_SIZE(dap_json_rpc_param_t*, l_len_new_params);
+    memcpy(l_new_params, a_params->params, sizeof(dap_json_rpc_param_t*) * a_params->lenght);
+    memcpy(l_new_params+a_params->lenght, &a_param, sizeof(dap_json_rpc_param_t*));
+    if (a_params->lenght != 0)
+        DAP_FREE(a_params->params);
+    a_params->params = l_new_params;
+    a_params->lenght++;
+}
+
+void dap_json_rpc_params_remove_all(dap_json_rpc_params_t *a_params)
+{
+    log_it(L_DEBUG, "Clean params");
+    for (uint32_t i=0x0 ; i < dap_json_rpc_params_lenght(a_params); i++){
+        dap_json_rpc_param_remove(a_params->params[i]);
+    }
+    DAP_FREE(a_params);
+}
+
+uint32_t dap_json_rpc_params_lenght(dap_json_rpc_params_t *a_params)
+{
+    return a_params->lenght;
+}
+
+void *dap_json_rpc_params_get(dap_json_rpc_params_t *a_params, uint32_t index)
+{
+    if (a_params->lenght > index)
+        return a_params->params[index]->value_param;
+    return NULL;
+}
+
+dap_json_rpc_type_param_t dap_json_rpc_params_get_type_param(dap_json_rpc_params_t *a_params, uint32_t index)
+{
+    if (a_params->lenght > index)
+        return a_params->params[index]->type;
+    return TYPE_PARAM_NULL;
+}
+
+void dap_json_rpc_param_remove(dap_json_rpc_param_t *param)
+{
+    DAP_FREE(param->value_param);
+    DAP_FREE(param);
+}
+
+dap_json_rpc_params_t * dap_json_rpc_params_create_from_array_list(json_object *a_array_list)
+{
+    log_it(L_NOTICE, "Translation json_object to dap_json_rpc_params");
+    if (a_array_list == NULL)
+        return NULL;
+    dap_json_rpc_params_t *l_params = dap_json_rpc_params_create();
+    int l_lenght = json_object_array_length(a_array_list);
+    for (int i = 0; i < l_lenght; i++){
+        json_object *l_jobj = json_object_array_get_idx(a_array_list, i);
+        json_type l_jobj_type = json_object_get_type(l_jobj);
+        char *l_str_tmp = NULL;
+        bool l_bool_tmp;
+        int64_t l_int_tmp;
+        double l_double_tmp;
+        switch (l_jobj_type) {
+        case json_type_string:
+            l_str_tmp = dap_strdup(json_object_get_string(l_jobj));
+            dap_json_rpc_params_add_data(l_params, l_str_tmp, TYPE_PARAM_STRING);
+            DAP_FREE(l_str_tmp);
+            break;
+        case json_type_boolean:
+            l_bool_tmp = json_object_get_boolean(l_jobj);
+            dap_json_rpc_params_add_data(l_params, &l_bool_tmp, TYPE_PARAM_BOOLEAN);
+            break;
+        case json_type_int:
+            l_int_tmp = json_object_get_int64(l_jobj);
+            dap_json_rpc_params_add_data(l_params, &l_int_tmp, TYPE_PARAM_INTEGER);
+            break;
+        case json_type_double:
+            l_double_tmp = json_object_get_double(l_jobj);
+            dap_json_rpc_params_add_data(l_params, &l_double_tmp, TYPE_PARAM_DOUBLE);
+            break;
+        default:
+            dap_json_rpc_params_add_data(l_params, NULL, TYPE_PARAM_NULL);
+        }
+    }
+    return  l_params;
+}
+
+char *dap_json_rpc_params_get_string_json(dap_json_rpc_params_t * a_params)
+{
+    log_it(L_NOTICE, "Translation struct params to JSON string");
+    json_object *l_jobj_array = json_object_new_array();
+    for (uint32_t i = 0; i <= a_params->lenght; i++){
+        json_object *l_jobj_tmp = NULL;
+        switch (a_params->params[i]->type) {
+        case TYPE_PARAM_NULL:
+            l_jobj_tmp = json_object_new_object();
+            break;
+        case TYPE_PARAM_STRING:
+            l_jobj_tmp = json_object_new_string((char*)a_params->params[i]->value_param);
+            break;
+        case TYPE_PARAM_INTEGER:
+            l_jobj_tmp = json_object_new_int64(*((int64_t*)a_params->params[i]->value_param));
+            break;
+        case TYPE_PARAM_DOUBLE:
+            l_jobj_tmp = json_object_new_double(*((double*)a_params->params[i]->value_param));
+            break;
+        case TYPE_PARAM_BOOLEAN:
+            l_jobj_tmp = json_object_new_boolean(*((bool*)a_params->params[i]->value_param));
+            break;
+        }
+        json_object_array_add(l_jobj_array, l_jobj_tmp);
+        json_object_put(l_jobj_tmp);
+    };
+    char *l_str = dap_strjoin(NULL, "\"params\":", json_object_to_json_string(l_jobj_array), NULL);
+    json_object_put(l_jobj_array);
+    return l_str;
+}
diff --git a/dap-sdk/net/server/json_rpc/src/dap_json_rpc_request.c b/dap-sdk/net/server/json_rpc/src/dap_json_rpc_request.c
new file mode 100644
index 0000000000000000000000000000000000000000..1754423f852b97fe8d3f8ad8e5f19533dd43530c
--- /dev/null
+++ b/dap-sdk/net/server/json_rpc/src/dap_json_rpc_request.c
@@ -0,0 +1,85 @@
+#include "dap_json_rpc_request.h"
+
+#define LOG_TAG "dap_json_rpc_request"
+
+static char *s_url_service = NULL;
+
+int dap_json_rpc_request_init(const char *a_url_service)
+{
+    if (s_url_service == NULL){
+        s_url_service = dap_strdup(a_url_service);
+        return  0;
+    }
+    return 1;
+}
+
+dap_json_rpc_request_t *dap_json_rpc_request_creation(const char *a_method, dap_json_rpc_params_t *a_params, int64_t a_id)
+{
+    dap_json_rpc_request_t *l_request = DAP_NEW(dap_json_rpc_request_t);
+    l_request->method = dap_strdup(a_method);
+    l_request->params = a_params;
+    l_request->id = a_id;
+    return l_request;
+}
+
+dap_json_rpc_request_t *dap_json_rpc_request_from_json(const char *a_data)
+{
+    log_it(L_DEBUG, "Translation JSON string to struct dap_json_rpc_request");
+    enum json_tokener_error l_jterr;
+    json_object *l_jobj = json_tokener_parse_verbose(a_data, &l_jterr);
+    json_object *l_jobj_id = NULL;
+    json_object *l_jobj_method = NULL;
+    json_object *l_jobj_params = NULL;
+    dap_json_rpc_request_t *l_request = DAP_NEW(dap_json_rpc_request_t);
+    l_request->params = NULL;
+    bool l_err_parse_request = false;
+    if (l_jterr == json_tokener_success){
+        if (json_object_object_get_ex(l_jobj, "id", &l_jobj_id)){
+            l_request->id = json_object_get_int64(l_jobj_id);
+        }else{
+            log_it(L_ERROR, "Error parse JSON string, Can't searching id request");
+            l_err_parse_request = true;
+        }
+        if (json_object_object_get_ex(l_jobj, "method", &l_jobj_method)){
+            l_request->method = dap_strdup(json_object_get_string(l_jobj_method));
+        }else{
+            log_it(L_ERROR, "Error parse JSON string, Can't searching method for request with id: %lu", l_request->id);
+            l_err_parse_request = true;
+        }
+        if (json_object_object_get_ex(l_jobj, "params", &l_jobj_params) && !l_err_parse_request){
+            l_request->params = dap_json_rpc_params_create_from_array_list(l_jobj_params);
+        }else{
+            log_it(L_ERROR, "Error parse JSON string, Can't searching array params for request with id: %lu", l_request->id);
+            l_err_parse_request = true;
+        }
+    } else {
+        log_it(L_ERROR, "Error parse json tokener: %s", json_tokener_error_desc(l_jterr));
+        l_err_parse_request = true;
+    }
+    if (l_err_parse_request){
+        DAP_FREE(l_request->method);
+        DAP_FREE(l_request);
+        return NULL;
+    }
+    return l_request;
+
+}
+char *dap_json_rpc_request_to_json(const dap_json_rpc_request_t *a_request)
+{
+    log_it(L_DEBUG, "Translation struct dap_json_rpc_request to JSON string");
+    char *l_str = dap_strjoin(NULL, "{\"method=\":", "\"", a_request->method, "\"", "\"", "\"params\":",
+                              dap_json_rpc_params_get_string_json(a_request->params), ", \"id\": ", a_request->id, "}", NULL);
+    return l_str;
+}
+
+void dap_json_rpc_request_send(dap_json_rpc_request_t *a_request, dap_json_rpc_response_handler_func_t *response_handler,
+                               const char *a_uplink_addr, const uint16_t a_uplink_port,
+                               dap_client_http_callback_error_t func_error)
+{
+    uint64_t l_id_response = dap_json_rpc_response_registration(response_handler);
+    a_request->id = l_id_response;
+    char *l_str = dap_json_rpc_request_to_json(a_request);
+    log_it(L_NOTICE, "Sending request in address: %s", a_uplink_addr);
+    dap_client_http_request(a_uplink_addr, a_uplink_port, "POST", "application/json", s_url_service, l_str, strlen(l_str),
+                            NULL, dap_json_rpc_response_accepted, func_error, NULL, NULL);
+}
diff --git a/dap-sdk/net/server/json_rpc/src/dap_json_rpc_request_handler.c b/dap-sdk/net/server/json_rpc/src/dap_json_rpc_request_handler.c
new file mode 100644
index 0000000000000000000000000000000000000000..593c9c2104cf11600a7c501dcbdbfd2433d22c4e
--- /dev/null
+++ b/dap-sdk/net/server/json_rpc/src/dap_json_rpc_request_handler.c
@@ -0,0 +1,58 @@
+#include "dap_json_rpc_request_handler.h"
+
+#define LOG_TAG "dap_json_rpc_request_handler"
+
+static dap_json_rpc_request_handler_t *s_handler_hash_table = NULL;
+
+int dap_json_rpc_registration_request_handler(const char *a_name, handler_func_t *a_func)
+{
+    dap_json_rpc_request_handler_t *l_handler;
+    HASH_FIND_STR(s_handler_hash_table, a_name, l_handler);
+    if (l_handler == NULL){
+        l_handler = DAP_NEW(dap_json_rpc_request_handler_t);
+        l_handler->name = dap_strdup(a_name);
+        l_handler->func = a_func;
+        HASH_ADD_STR(s_handler_hash_table, name, l_handler);
+        log_it(L_NOTICE, "Registration handler for request name: %s", a_name);
+        return 0;
+    }
+    return 1;
+}
+int dap_json_rpc_unregistration_request_handler(const char *a_name)
+{
+    dap_json_rpc_request_handler_t *l_handler;
+    HASH_FIND_STR(s_handler_hash_table, a_name, l_handler);
+    if (l_handler == NULL){
+        return 1;
+    } else {
+    	log_it(L_NOTICE, "Unregistration for handler request name: %s", a_name);
+        HASH_DEL(s_handler_hash_table, l_handler);
+        DAP_FREE(l_handler->name);
+        DAP_FREE(l_handler);
+        return 0;
+    }
+}
+
+void dap_json_rpc_request_handler(dap_json_rpc_request_t *a_request,  dap_http_simple_t *a_client)
+{
+	log_it(L_DEBUG, "Processing request");
+    if (a_request->id == 0){
+        dap_json_rpc_notification_handler(a_request->method, a_request->params);
+    } else {
+        dap_json_rpc_response_t *l_response = DAP_NEW(dap_json_rpc_response_t);
+        l_response->id = a_request->id;
+        dap_json_rpc_request_handler_t *l_handler = NULL;
+        HASH_FIND_STR(s_handler_hash_table, a_request->method, l_handler);
+        if (l_handler == NULL){
+            dap_json_rpc_error_t *l_err = dap_json_rpc_error_search_by_code(1);
+            l_response->type_result = TYPE_RESPONSE_NULL;
+            l_response->error = l_err;
+            log_it(L_NOTICE, "Can't processing the request. Handler %s not registration. ", a_request->method);
+        } else {
+            l_response->error = NULL;
+            l_handler->func(a_request->params, l_response);
+            log_it(L_NOTICE, "Calling handler request name: %s", a_request->method);
+        }
+        dap_json_rpc_response_send(l_response, a_client);
+    }
+}
diff --git a/dap-sdk/net/server/json_rpc/src/dap_json_rpc_response.c b/dap-sdk/net/server/json_rpc/src/dap_json_rpc_response.c
new file mode 100644
index 0000000000000000000000000000000000000000..ee3e4b3e16766825ed06ea5188967fb722a6e34f
--- /dev/null
+++ b/dap-sdk/net/server/json_rpc/src/dap_json_rpc_response.c
@@ -0,0 +1,106 @@
+#include "dap_json_rpc_response.h"
+
+#define LOG_TAG "dap_json_rpc_response"
+
+void dap_json_rpc_request_JSON_free(dap_json_rpc_request_JSON_t *l_request_JSON)
+{
+    json_object_put(l_request_JSON->obj_error);
+    if (l_request_JSON->struct_error)
+        dap_json_rpc_error_JSON_free(l_request_JSON->struct_error);
+    json_object_put(l_request_JSON->obj_id);
+    json_object_put(l_request_JSON->obj_result);
+    DAP_FREE(l_request_JSON);
+}
+
+void dap_json_rpc_response_free(dap_json_rpc_response_t *a_response)
+{
+    DAP_FREE(a_response->error);
+    if (a_response->type_result == TYPE_RESPONSE_STRING){
+        DAP_FREE(a_response->result_string);
+    }
+    DAP_FREE(a_response);
+}
+
+void dap_json_rpc_response_send(dap_json_rpc_response_t *a_response, dap_http_simple_t *a_client)
+{
+    dap_json_rpc_request_JSON_t *l_JSON = DAP_NEW(dap_json_rpc_request_JSON_t);
+    json_object *l_jobj = json_object_new_object();
+    l_JSON->obj_id = json_object_new_int64(a_response->id);
+    l_JSON->obj_error = NULL;
+    l_JSON->obj_result = NULL;
+    l_JSON->struct_error = NULL;
+    char *str_response = NULL;
+    if (a_response->error == NULL){
+        switch (a_response->type_result) {
+        case TYPE_RESPONSE_STRING:
+            l_JSON->obj_result = json_object_new_string(a_response->result_string);
+            break;
+        case TYPE_RESPONSE_DOUBLE:
+            l_JSON->obj_result = json_object_new_double(a_response->result_double);
+            break;
+        case TYPE_RESPONSE_BOOLEAN:
+            l_JSON->obj_result = json_object_new_boolean(a_response->result_boolean);
+            break;
+        case TYPE_RESPONSE_INTEGER:
+            l_JSON->obj_result = json_object_new_int64(a_response->result_int);
+            break;
+        }
+    }else{
+        l_JSON->struct_error = dap_json_rpc_error_JSON_add_data(a_response->error->code_error, a_response->error->msg);
+        l_JSON->obj_error = json_object_new_object();
+        json_object_object_add(l_JSON->obj_error, "code", l_JSON->struct_error->obj_code);
+        json_object_object_add(l_JSON->obj_error, "message", l_JSON->struct_error->obj_msg);
+    }
+    json_object_object_add(l_jobj, "result", l_JSON->obj_result);
+    json_object_object_add(l_jobj, "id", l_JSON->obj_id);
+    json_object_object_add(l_jobj, "error", l_JSON->obj_error);
+    str_response = dap_strdup(json_object_to_json_string(l_jobj));
+    dap_http_simple_reply(a_client, str_response, strlen(str_response));
+    DAP_FREE(str_response);
+    json_object_put(l_jobj);
+    dap_json_rpc_request_JSON_free(l_JSON);
+}
+
+dap_json_rpc_response_t *dap_json_rpc_response_from_json(char *a_data_json)
+{
+    json_object *l_jobj = json_tokener_parse(a_data_json);
+    json_object *l_jobj_result = json_object_object_get(l_jobj, "result");
+    json_object *l_jobj_error = json_object_object_get(l_jobj, "error");
+    json_object *l_jobj_id = json_object_object_get(l_jobj, "id");
+    dap_json_rpc_response_t *l_response = DAP_NEW(dap_json_rpc_response_t);
+    l_response->id = json_object_get_int64(l_jobj_id);
+    if (json_object_is_type(l_jobj_error, json_type_null)){
+        l_response->error = NULL;
+        switch(json_object_get_type(l_jobj_result)){
+        case json_type_int:
+            l_response->type_result = TYPE_RESPONSE_INTEGER;
+            l_response->result_int = json_object_get_int64(l_jobj_result);
+            break;
+        case json_type_double:
+            l_response->type_result = TYPE_RESPONSE_DOUBLE;
+            l_response->result_double = json_object_get_double(l_jobj_result);
+            break;
+        case json_type_boolean:
+            l_response->type_result = TYPE_RESPONSE_BOOLEAN;
+            l_response->result_boolean = json_object_get_boolean(l_jobj_result);
+            break;
+        case json_type_string:
+            l_response->type_result = TYPE_RESPONSE_STRING;
+            l_response->result_string = dap_strdup(json_object_get_string(l_jobj_result));
+            break;
+        default:
+            l_response->type_result = TYPE_RESPONSE_NULL;
+            break;
+        }
+    } else {
+        l_response->error = dap_json_rpc_create_from_json_object(l_jobj_error);
+        l_response->type_result = TYPE_RESPONSE_NULL;
+    }
+    json_object_put(l_jobj_id);
+    json_object_put(l_jobj_error);
+    json_object_put(l_jobj_result);
+    json_object_put(l_jobj);
+    return l_response;
+}
+
+
diff --git a/dap-sdk/net/server/json_rpc/src/dap_json_rpc_response_handler.c b/dap-sdk/net/server/json_rpc/src/dap_json_rpc_response_handler.c
new file mode 100644
index 0000000000000000000000000000000000000000..4419221d31e689ce06d101e563f764d3bf8f1138
--- /dev/null
+++ b/dap-sdk/net/server/json_rpc/src/dap_json_rpc_response_handler.c
@@ -0,0 +1,69 @@
+#include "dap_json_rpc_response_handler.h"
+
+#define LOG_TAG "dap_json_rpc_response_handler"
+
+static dap_json_rpc_response_handler_t *s_response_handlers = NULL;
+static uint64_t s_delta = 0;
+
+int dap_json_rpc_response_registration_with_id(uint64_t a_id, dap_json_rpc_response_handler_func_t *func)
+{
+    dap_json_rpc_response_handler_t *l_handler = NULL;
+    HASH_FIND_INT(s_response_handlers, &a_id, l_handler);
+    if (l_handler == NULL){
+        l_handler = DAP_NEW(dap_json_rpc_response_handler_t);
+        l_handler->id = a_id;
+        l_handler->func = func;
+        HASH_ADD_INT(s_response_handlers, id, l_handler);
+        log_it(L_NOTICE, "Registrayion handler response with id: %d", a_id);
+        return 0;
+    }
+    return 1;
+}
+uint64_t dap_json_rpc_response_registration(dap_json_rpc_response_handler_func_t *func)
+{
+    uint64_t l_id_registration_response = dap_json_rpc_response_get_new_id();
+    int res = dap_json_rpc_response_registration_with_id(l_id_registration_response, func);
+    return res;
+}
+void dap_json_rpc_response_unregistration(uint64_t a_id)
+{
+    dap_json_rpc_response_handler_t *l_handler = NULL;
+    HASH_FIND_INT(s_response_handlers, &a_id, l_handler);
+    if (l_handler != NULL){
+        HASH_DEL(s_response_handlers, l_handler);
+        DAP_FREE(l_handler);
+        log_it(L_NOTICE, "Unregistrayion handler response with id: %d", a_id);
+    }
+}
+
+void dap_json_rpc_response_handler(dap_json_rpc_response_t *a_response)
+{
+    dap_json_rpc_response_handler_t *l_handler = NULL;
+    HASH_FIND_INT(s_response_handlers, (void*)a_response->id, l_handler);
+    if (l_handler != NULL){
+        log_it(L_NOTICE, "Calling handler response id: %d", a_response->id);
+        l_handler->func(a_response);
+        dap_json_rpc_response_unregistration(a_response->id);
+    } else {
+        log_it(L_NOTICE, "Can't calling handler response id: %d. This handler not found", a_response->id);
+    }
+}
+
+uint64_t dap_json_rpc_response_get_new_id(void)
+{
+    uint64_t l_ret = s_delta;
+    s_delta++;
+    return l_ret;
+}
+
+void dap_json_rpc_response_accepted(void *a_data, size_t a_size_data, void *a_obj)
+{
+    (void) a_obj;
+    log_it(L_NOTICE, "Pre handling response");
+    char *l_str = DAP_NEW_SIZE(char, a_size_data);
+    memcpy(l_str, a_data, a_size_data);
+    dap_json_rpc_response_t *l_response = dap_json_rpc_response_from_json(l_str);
+    DAP_FREE(l_str);
+    dap_json_rpc_response_handler(l_response);
+    dap_json_rpc_response_free(l_response);
+}
diff --git a/dap-sdk/net/stream/session/dap_stream_session.c b/dap-sdk/net/stream/session/dap_stream_session.c
index 1dcfa0c62168210cf60170b677c5b31e0dbfe74b..5c1cb1a29a18aa997e723c3b7eb43a638bcfa1b2 100644
--- a/dap-sdk/net/stream/session/dap_stream_session.c
+++ b/dap-sdk/net/stream/session/dap_stream_session.c
@@ -64,6 +64,32 @@ void dap_stream_session_deinit()
     pthread_mutex_unlock(&sessions_mutex);
 }
 
+/**
+ *
+ * note: dap_stream_session_get_list_sessions_unlock() must be run after this function
+ */
+dap_list_t* dap_stream_session_get_list_sessions(void)
+{
+    dap_list_t *l_list = NULL;
+    dap_stream_session_t *current, *tmp;
+    pthread_mutex_lock(&sessions_mutex);
+    HASH_ITER(hh, sessions, current, tmp)
+    {
+        l_list = dap_list_append(l_list, current);
+        //dap_chain_net_srv_stream_session_t * l_srv_session = current->_inheritor;
+        //if(l_srv_session) {
+            //dap_net_stats_t *l_stats = DAP_NEW(dap_net_stats_t);
+            //memcpy(l_stats, l_srv_session->stats);
+            //l_list = dap_list_append(l_list, l_stats);
+        //}
+    }
+    return l_list;
+}
+
+void dap_stream_session_get_list_sessions_unlock(void)
+{
+    pthread_mutex_unlock(&sessions_mutex);
+}
 
 static void * session_check(void * data)
 {
diff --git a/dap-sdk/net/stream/session/include/dap_stream_session.h b/dap-sdk/net/stream/session/include/dap_stream_session.h
index 921c9ff700227301a39eef1d946e699925796eb7..9106aca423520d4cafad1ab2de868acf32e2ffe2 100644
--- a/dap-sdk/net/stream/session/include/dap_stream_session.h
+++ b/dap-sdk/net/stream/session/include/dap_stream_session.h
@@ -31,6 +31,7 @@
 #include "uthash.h"
 #include "dap_enc_key.h"
 #include "dap_hash.h"
+#include "dap_list.h"
 
 typedef enum stream_session_type {STREAM_SESSION_TYPE_MEDIA=0,STREAM_SESSION_TYPE_VPN} stream_session_type_t;
 typedef enum stream_session_connection_type {STEAM_SESSION_HTTP = 0, STREAM_SESSION_UDP, STREAM_SESSION_END_TYPE} stream_session_connection_type_t;
@@ -69,6 +70,8 @@ typedef struct dap_stream_session dap_stream_session_t;
 
 void dap_stream_session_init();
 void dap_stream_session_deinit();
+dap_list_t* dap_stream_session_get_list_sessions(void);
+void dap_stream_session_get_list_sessions_unlock(void);
 
 dap_stream_session_t * dap_stream_session_pure_new();
 dap_stream_session_t * dap_stream_session_new(unsigned int media_id, bool open_preview);
diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt
index 6d1abf4cf3a5c10ff884a89ed9cc27c5d21277ac..78ae7458e46f0e6299760dea12620a7d16d03a5b 100644
--- a/modules/CMakeLists.txt
+++ b/modules/CMakeLists.txt
@@ -7,6 +7,7 @@ endif()
 # Chains
 if (CELLFRAME_MODULES MATCHES "chains")
     add_subdirectory(chain)
+    add_subdirectory(chain/btc_rpc)
     add_subdirectory(wallet)
     add_subdirectory(global-db)
 endif()
@@ -37,8 +38,8 @@ if (CELLFRAME_MODULES MATCHES "cs-dag")
 endif()
 
 # Consensus type dag
-if (CELLFRAME_MODULES MATCHES "cs-block")
-    add_subdirectory(type/block)
+if (CELLFRAME_MODULES MATCHES "cs-blocks")
+    add_subdirectory(type/blocks)
 endif()
 
 # No consensus
diff --git a/modules/chain/btc_rpc/CMakeLists.txt b/modules/chain/btc_rpc/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..9e9ded64a179d2bda42ee9430c581d9fc0fc3ce0
--- /dev/null
+++ b/modules/chain/btc_rpc/CMakeLists.txt
@@ -0,0 +1,18 @@
+project(dap_chain_btc_rpc C)
+cmake_minimum_required(VERSION 3.0)
+
+add_definitions ("-D_GNU_SOURCE")
+add_definitions("-Dfpic")
+
+file(GLOB BTC_RPC_HEADERS include/*.h)
+file(GLOB BTC_RPC_SRCS *.c)
+
+include_directories(${PROJECT_NAME} include/)
+
+add_library(${PROJECT_NAME} STATIC ${BTC_RPC_HEADERS} ${BTC_RPC_SRCS})
+target_include_directories(${PROJECT_NAME} INTERFACE . include/)
+target_include_directories(${PROJECT_NAME} PUBLIC include)
+
+target_link_libraries(${PROJECT_NAME} dap_core dap_json_rpc)
+#target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_server_core dap_http_server dap_client json-c )
+#target_link_libraries(${PROJECT_NAME} dap_core)# dap_http_server json-c)
diff --git a/modules/chain/btc_rpc/dap_chain_btc_rpc.c b/modules/chain/btc_rpc/dap_chain_btc_rpc.c
new file mode 100644
index 0000000000000000000000000000000000000000..448528116b41719aa8000aa430b130b82a4e334c
--- /dev/null
+++ b/modules/chain/btc_rpc/dap_chain_btc_rpc.c
@@ -0,0 +1,9 @@
+#include "dap_chain_btc_rpc.h"
+
+int dap_chain_btc_rpc_init(){
+    dap_chain_btc_rpc_registration_handlers();
+    return 0;
+}
+void dap_chain_btc_rpc_deinit(){
+    dap_chain_btc_rpc_unregistration_handlers();
+}
diff --git a/modules/chain/btc_rpc/dap_chain_btc_rpc_handlers.c b/modules/chain/btc_rpc/dap_chain_btc_rpc_handlers.c
new file mode 100644
index 0000000000000000000000000000000000000000..e39ce1a2e702aa9f0b3fe55bf0952526c5241c17
--- /dev/null
+++ b/modules/chain/btc_rpc/dap_chain_btc_rpc_handlers.c
@@ -0,0 +1,143 @@
+#include "dap_chain_btc_rpc_handlers.h"
+
+void dap_chain_btc_rpc_registration_handlers(){
+    dap_json_rpc_registration_request_handler("addmultisigaddress", dap_chain_btc_rpc_handler_addmultisigaddress);
+    dap_json_rpc_registration_request_handler("addnode", dap_chain_btc_rpc_handler_addnode);
+    dap_json_rpc_registration_request_handler("backupwallet", dap_chain_btc_rpc_handler_backupwallet);
+    dap_json_rpc_registration_request_handler("createmultisig", dap_chain_btc_rpc_handler_createmultisig);
+    dap_json_rpc_registration_request_handler("createrawtransaction", dap_chain_btc_rpc_handler_createrawtransaction);
+    dap_json_rpc_registration_request_handler("decoderawtransaction", dap_chain_btc_rpc_handler_decoderawtransaction);
+    dap_json_rpc_registration_request_handler("dumpprivkey", dap_chain_btc_rpc_handler_dumpprivkey);
+    dap_json_rpc_registration_request_handler("dumpwallet", dap_chain_btc_rpc_handler_dumpwallet);
+    dap_json_rpc_registration_request_handler("encryptwallet", dap_chain_btc_rpc_handler_encryptwallet);
+    dap_json_rpc_registration_request_handler("getaccount", dap_chain_btc_rpc_handler_getaccount);
+    dap_json_rpc_registration_request_handler("getaccountaddress", dap_chain_btc_rpc_handler_getaccountaddress);
+    dap_json_rpc_registration_request_handler("getaddednodeinfo", dap_chain_btc_rpc_handler_getaddednodeinfo);
+    dap_json_rpc_registration_request_handler("getaddressesbyaccount", dap_chain_btc_rpc_handler_getaddressesbyaccount);
+    dap_json_rpc_registration_request_handler("getbalance", dap_chain_btc_rpc_handler_getbalance);
+    dap_json_rpc_registration_request_handler("getbestblockhash", dap_chain_btc_rpc_handler_getbestblockhash);
+    dap_json_rpc_registration_request_handler("getblock", dap_chain_btc_rpc_handler_getblock);
+    dap_json_rpc_registration_request_handler("getblockcount", dap_chain_btc_rpc_handler_getblockcount);
+    dap_json_rpc_registration_request_handler("getblockhash", dap_chain_btc_rpc_handler_getblockhash);
+    dap_json_rpc_registration_request_handler("getblocknumber", dap_chain_btc_rpc_handler_getblocknumber);
+    dap_json_rpc_registration_request_handler("getblocktemplate", dap_chain_btc_rpc_handler_getblocktemplate);
+    dap_json_rpc_registration_request_handler("getconnectioncount", dap_chain_btc_rpc_handler_getconnectioncount);
+    dap_json_rpc_registration_request_handler("getdifficulty", dap_chain_btc_rpc_handler_getdifficulty);
+    dap_json_rpc_registration_request_handler("getgenerate", dap_chain_btc_rpc_handler_getgenerate);
+    dap_json_rpc_registration_request_handler("gethashespersec", dap_chain_btc_rpc_handler_gethashespersec);
+    dap_json_rpc_registration_request_handler("getinfo", dap_chain_btc_rpc_handler_getinfo);
+    dap_json_rpc_registration_request_handler("getmemorypool", dap_chain_btc_rpc_handler_getmemorypool);
+    dap_json_rpc_registration_request_handler("getmininginfo", dap_chain_btc_rpc_handler_getmininginfo);
+    dap_json_rpc_registration_request_handler("getnewaddress", dap_chain_btc_rpc_handler_getnewaddress);
+    dap_json_rpc_registration_request_handler("getpeerinfo", dap_chain_btc_rpc_handler_getpeerinfo);
+    dap_json_rpc_registration_request_handler("getrawchangeaddress", dap_chain_btc_rpc_handler_getrawchangeaddress);
+    dap_json_rpc_registration_request_handler("getrawmempool", dap_chain_btc_rpc_handler_getrawmempool);
+    dap_json_rpc_registration_request_handler("getrawtransaction", dap_chain_btc_rpc_handler_getrawtransaction);
+    dap_json_rpc_registration_request_handler("getreceivedbyaccount", dap_chain_btc_rpc_handler_getreceivedbyaccount);
+    dap_json_rpc_registration_request_handler("getreceivedbyaddress", dap_chain_btc_rpc_handler_getreceivedbyaddress);
+    dap_json_rpc_registration_request_handler("gettransaction", dap_chain_btc_rpc_handler_gettransaction);
+    dap_json_rpc_registration_request_handler("gettxout", dap_chain_btc_rpc_handler_gettxout);
+    dap_json_rpc_registration_request_handler("gettxoutsetinfo", dap_chain_btc_rpc_handler_gettxoutsetinfo);
+    dap_json_rpc_registration_request_handler("getwork", dap_chain_btc_rpc_handler_getwork);
+    dap_json_rpc_registration_request_handler("help", dap_chain_btc_rpc_handler_help);
+    dap_json_rpc_registration_request_handler("importprivkey", dap_chain_btc_rpc_handler_importprivkey);
+    dap_json_rpc_registration_request_handler("invalidateblock", dap_chain_btc_rpc_handler_invalidateblock);
+    dap_json_rpc_registration_request_handler("keypoolrefill", dap_chain_btc_rpc_handler_keypoolrefill);
+    dap_json_rpc_registration_request_handler("listaccounts", dap_chain_btc_rpc_handler_listaccounts);
+    dap_json_rpc_registration_request_handler("listaddressgroupings", dap_chain_btc_rpc_handler_listaddressgroupings);
+    dap_json_rpc_registration_request_handler("listreceivedbyaccount", dap_chain_btc_rpc_handler_listreceivedbyaccount);
+    dap_json_rpc_registration_request_handler("listreceivedbyaddress", dap_chain_btc_rpc_handler_listreceivedbyaddress);
+    dap_json_rpc_registration_request_handler("listsinceblock", dap_chain_btc_rpc_handler_listsinceblock);
+    dap_json_rpc_registration_request_handler("listtransactions", dap_chain_btc_rpc_handler_listtransactions);
+    dap_json_rpc_registration_request_handler("listunspent", dap_chain_btc_rpc_handler_listunspent);
+    dap_json_rpc_registration_request_handler("listlockunspent", dap_chain_btc_rpc_handler_listlockunspent);
+    dap_json_rpc_registration_request_handler("lockunspent", dap_chain_btc_rpc_handler_lockunspent);
+    dap_json_rpc_registration_request_handler("move", dap_chain_btc_rpc_handler_move);
+    dap_json_rpc_registration_request_handler("sendfrom", dap_chain_btc_rpc_handler_sendfrom);
+    dap_json_rpc_registration_request_handler("sendmany", dap_chain_btc_rpc_handler_sendmany);
+    dap_json_rpc_registration_request_handler("sendrawtransaction", dap_chain_btc_rpc_handler_sendrawtransaction);
+    dap_json_rpc_registration_request_handler("sendtoaddress", dap_chain_btc_rpc_handler_sendtoaddress);
+    dap_json_rpc_registration_request_handler("setaccount", dap_chain_btc_rpc_handler_setaccount);
+    dap_json_rpc_registration_request_handler("setgenerate", dap_chain_btc_rpc_handler_setgenerate);
+    dap_json_rpc_registration_request_handler("settxfee", dap_chain_btc_rpc_handler_settxfee);
+    dap_json_rpc_registration_request_handler("signmessage", dap_chain_btc_rpc_handler_signmessage);
+    dap_json_rpc_registration_request_handler("signrawtransaction", dap_chain_btc_rpc_handler_signrawtransaction);
+    dap_json_rpc_registration_request_handler("stop", dap_chain_btc_rpc_handler_stop);
+    dap_json_rpc_registration_request_handler("submitblock", dap_chain_btc_rpc_handler_submitblock);
+    dap_json_rpc_registration_request_handler("validateaddress", dap_chain_btc_rpc_handler_validateaddress);
+    dap_json_rpc_registration_request_handler("verifymessage", dap_chain_btc_rpc_handler_verifymessage);
+    dap_json_rpc_registration_request_handler("walletlock", dap_chain_btc_rpc_handler_walletlock);
+    dap_json_rpc_registration_request_handler("walletpassphrase", dap_chain_btc_rpc_handler_walletpassphrase);
+    dap_json_rpc_registration_request_handler("walletpassphrasechange", dap_chain_btc_rpc_handler_walletpassphrasechange);
+}
+
+void dap_chain_btc_rpc_unregistration_handlers(){
+    dap_json_rpc_unregistration_request_handler("addmultisigaddress");
+    dap_json_rpc_unregistration_request_handler("addnode");
+    dap_json_rpc_unregistration_request_handler("backupwallet");
+    dap_json_rpc_unregistration_request_handler("createmultisig");
+    dap_json_rpc_unregistration_request_handler("createrawtransaction");
+    dap_json_rpc_unregistration_request_handler("decoderawtransaction");
+    dap_json_rpc_unregistration_request_handler("dumpprivkey");
+    dap_json_rpc_unregistration_request_handler("dumpwallet");
+    dap_json_rpc_unregistration_request_handler("encryptwallet");
+    dap_json_rpc_unregistration_request_handler("getaccount");
+    dap_json_rpc_unregistration_request_handler("getaccountaddress");
+    dap_json_rpc_unregistration_request_handler("getaddednodeinfo");
+    dap_json_rpc_unregistration_request_handler("getaddressesbyaccount");
+    dap_json_rpc_unregistration_request_handler("getbalance");
+    dap_json_rpc_unregistration_request_handler("getbestblockhash");
+    dap_json_rpc_unregistration_request_handler("getblock");
+    dap_json_rpc_unregistration_request_handler("getblockcount");
+    dap_json_rpc_unregistration_request_handler("getblockhash");
+    dap_json_rpc_unregistration_request_handler("getblocknumber");
+    dap_json_rpc_unregistration_request_handler("getblocktemplate");
+    dap_json_rpc_unregistration_request_handler("getconnectioncount");
+    dap_json_rpc_unregistration_request_handler("getdifficulty");
+    dap_json_rpc_unregistration_request_handler("getgenerate");
+    dap_json_rpc_unregistration_request_handler("gethashespersec");
+    dap_json_rpc_unregistration_request_handler("getinfo");
+    dap_json_rpc_unregistration_request_handler("getmemorypool");
+    dap_json_rpc_unregistration_request_handler("getmininginfo");
+    dap_json_rpc_unregistration_request_handler("getnewaddress");
+    dap_json_rpc_unregistration_request_handler("getpeerinfo");
+    dap_json_rpc_unregistration_request_handler("getrawchangeaddress");
+    dap_json_rpc_unregistration_request_handler("getrawmempool");
+    dap_json_rpc_unregistration_request_handler("getrawtransaction");
+    dap_json_rpc_unregistration_request_handler("getreceivedbyaccount");
+    dap_json_rpc_unregistration_request_handler("getreceivedbyaddress");
+    dap_json_rpc_unregistration_request_handler("gettransaction");
+    dap_json_rpc_unregistration_request_handler("gettxout");
+    dap_json_rpc_unregistration_request_handler("gettxoutsetinfo");
+    dap_json_rpc_unregistration_request_handler("getwork");
+    dap_json_rpc_unregistration_request_handler("help");
+    dap_json_rpc_unregistration_request_handler("importprivkey");
+    dap_json_rpc_unregistration_request_handler("invalidateblock");
+    dap_json_rpc_unregistration_request_handler("keypoolrefill");
+    dap_json_rpc_unregistration_request_handler("listaccounts");
+    dap_json_rpc_unregistration_request_handler("listaddressgroupings");
+    dap_json_rpc_unregistration_request_handler("listreceivedbyaccount");
+    dap_json_rpc_unregistration_request_handler("listreceivedbyaddress");
+    dap_json_rpc_unregistration_request_handler("listsinceblock");
+    dap_json_rpc_unregistration_request_handler("listtransactions");
+    dap_json_rpc_unregistration_request_handler("listunspent");
+    dap_json_rpc_unregistration_request_handler("listlockunspent");
+    dap_json_rpc_unregistration_request_handler("lockunspent");
+    dap_json_rpc_unregistration_request_handler("move");
+    dap_json_rpc_unregistration_request_handler("sendfrom");
+    dap_json_rpc_unregistration_request_handler("sendmany");
+    dap_json_rpc_unregistration_request_handler("sendrawtransaction");
+    dap_json_rpc_unregistration_request_handler("sendtoaddress");
+    dap_json_rpc_unregistration_request_handler("setaccount");
+    dap_json_rpc_unregistration_request_handler("setgenerate");
+    dap_json_rpc_unregistration_request_handler("settxfee");
+    dap_json_rpc_unregistration_request_handler("signmessage");
+    dap_json_rpc_unregistration_request_handler("signrawtransaction");
+    dap_json_rpc_unregistration_request_handler("stop");
+    dap_json_rpc_unregistration_request_handler("submitblock");
+    dap_json_rpc_unregistration_request_handler("validateaddress");
+    dap_json_rpc_unregistration_request_handler("verifymessage");
+    dap_json_rpc_unregistration_request_handler("walletlock");
+    dap_json_rpc_unregistration_request_handler("walletpassphrase");
+    dap_json_rpc_unregistration_request_handler("walletpassphrasechange");
+}
diff --git a/modules/chain/btc_rpc/include/dap_chain_btc_rpc.h b/modules/chain/btc_rpc/include/dap_chain_btc_rpc.h
new file mode 100644
index 0000000000000000000000000000000000000000..1196448f3ed1a4f94a81d491c3e3c9ace35cd16d
--- /dev/null
+++ b/modules/chain/btc_rpc/include/dap_chain_btc_rpc.h
@@ -0,0 +1,5 @@
+#pragma once
+#include "dap_chain_btc_rpc_handlers.h"
+
+int dap_chain_btc_rpc_init();
+void dap_chain_btc_rpc_deinit();
diff --git a/modules/chain/btc_rpc/include/dap_chain_btc_rpc_handlers.h b/modules/chain/btc_rpc/include/dap_chain_btc_rpc_handlers.h
new file mode 100644
index 0000000000000000000000000000000000000000..601c9dd1ff4aed16aec43cd25e18f7e1bc051752
--- /dev/null
+++ b/modules/chain/btc_rpc/include/dap_chain_btc_rpc_handlers.h
@@ -0,0 +1,84 @@
+#pragma once
+
+#include "dap_json_rpc_request_handler.h"
+
+void dap_chain_btc_rpc_registration_handlers();
+void dap_chain_btc_rpc_unregistration_handlers();
+
+void dap_chain_btc_rpc_handler_addmultisigaddress(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_addnode(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_backupwallet(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_createmultisig(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_createrawtransaction(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_decoderawtransaction(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_dumpprivkey(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_dumpwallet(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_encryptwallet(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_getaccount(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_getaccountaddress(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_getaddednodeinfo(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_getaddressesbyaccount(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_getbalance(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_getbestblockhash(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_getblock(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_getblockcount(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_getblockhash(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_getblocknumber(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_getblocktemplate(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_getconnectioncount(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_getdifficulty(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_getgenerate(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_gethashespersec(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_getinfo(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_getmemorypool(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_getmininginfo(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+
+void dap_chain_btc_rpc_handler_getnewaddress(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_getpeerinfo(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_getrawchangeaddress(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_getrawmempool(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_getrawtransaction(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_getreceivedbyaccount(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_getreceivedbyaddress(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_gettransaction(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_gettxout(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_gettxoutsetinfo(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_getwork(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+
+void dap_chain_btc_rpc_handler_help(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+
+void dap_chain_btc_rpc_handler_importprivkey(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_invalidateblock(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_keypoolrefill(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_listaccounts(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_listaddressgroupings(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_listreceivedbyaccount(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+
+void dap_chain_btc_rpc_handler_listreceivedbyaccount(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_listreceivedbyaddress(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_listsinceblock(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_listtransactions(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_listunspent(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_listlockunspent(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_lockunspent(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_move(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+
+void dap_chain_btc_rpc_handler_sendfrom(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_sendmany(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_sendrawtransaction(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_sendtoaddress(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_setaccount(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_setgenerate(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_settxfee(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_signmessage(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_signrawtransaction(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_stop(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_submitblock(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+
+void dap_chain_btc_rpc_handler_validateaddress(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_verifymessage(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_walletlock(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_walletpassphrase(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+void dap_chain_btc_rpc_handler_walletpassphrasechange(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response);
+
+
diff --git a/modules/chain/dap_chain.c b/modules/chain/dap_chain.c
index b7d05539b15f8fd2de45a09918ff039f52b82cfa..db90df595e0f8f19ad47e9a1343ae0a7f30b59bd 100644
--- a/modules/chain/dap_chain.c
+++ b/modules/chain/dap_chain.c
@@ -165,6 +165,21 @@ void dap_chain_delete(dap_chain_t * a_chain)
     pthread_rwlock_unlock(&s_chain_items_rwlock);
 }
 
+/**
+ * @brief dap_chain_get_atom_by_hash
+ * @param a_chain
+ * @param a_atom_hash
+ * @param a_atom_size
+ * @return
+ */
+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)
+{
+    dap_chain_atom_iter_t * l_iter = a_chain->callback_atom_iter_create(a_chain);
+    dap_chain_atom_ptr_t *l_ret = a_chain->callback_atom_find_by_hash(l_iter, a_atom_hash, a_atom_size);
+    a_chain->callback_atom_iter_delete(l_iter);
+    return l_ret;
+}
+
 /**
  * @brief dap_chain_find_by_id
  * @param a_chain_net_id
diff --git a/modules/chain/dap_chain_cell.c b/modules/chain/dap_chain_cell.c
index 5e229297e4c2650b97b13eb99e3225e34bca8a00..238e97a4a69df20aafab2d60b05c1d165f0dfa1c 100644
--- a/modules/chain/dap_chain_cell.c
+++ b/modules/chain/dap_chain_cell.c
@@ -131,7 +131,7 @@ int dap_chain_cell_load(dap_chain_t * a_chain, const char * a_cell_file_path)
                     size_t l_element_size = 0;
                     if ( fread(&l_element_size,1,sizeof(l_element_size),l_cell->file_storage) ==
                          sizeof(l_element_size) ){
-                        if ( l_element_size > 0 ){
+                        if ( l_element_size > 0){
                             dap_chain_atom_ptr_t * l_element = DAP_NEW_Z_SIZE (dap_chain_atom_ptr_t, l_element_size );
                             if ( l_element){
                                 size_t l_read_bytes = fread( l_element,1,l_element_size,l_cell->file_storage );
diff --git a/modules/chain/dap_chain_cs.c b/modules/chain/dap_chain_cs.c
index cc88a25baf6e5909289d9c3fde67996ad1acdaf7..491a35002a51330d1a2c4cb69dc8d37bf5d81046 100644
--- a/modules/chain/dap_chain_cs.c
+++ b/modules/chain/dap_chain_cs.c
@@ -66,7 +66,7 @@ void dap_chain_cs_deinit(void)
  * @param a_cs_str
  * @param a_callback_init
  */
-void dap_chain_class_add (const char * a_cs_str,  dap_chain_callback_new_cfg_t a_callback_init)
+void dap_chain_cs_type_add (const char * a_cs_str,  dap_chain_callback_new_cfg_t a_callback_init)
 {
     dap_chain_callback_new_cfg_item_t *l_item = DAP_NEW_Z ( dap_chain_callback_new_cfg_item_t );
     strncpy(l_item->name, a_cs_str, sizeof (l_item->name) );
@@ -80,7 +80,7 @@ void dap_chain_class_add (const char * a_cs_str,  dap_chain_callback_new_cfg_t a
  * @param a_chain_cfg
  * @return
  */
-int dap_chain_class_create(dap_chain_t * a_chain, dap_config_t * a_chain_cfg)
+int dap_chain_cs_type_create(dap_chain_t * a_chain, dap_config_t * a_chain_cfg)
 {
     dap_chain_callback_new_cfg_item_t *l_item = NULL;
 
@@ -123,7 +123,7 @@ int dap_chain_cs_create(dap_chain_t * a_chain, dap_config_t * a_chain_cfg)
     if ( l_item ) {
         log_it(L_NOTICE,"Consensus \"%s\" found, prepare to parse config file",l_item->name );
         l_item->callback_init( a_chain, a_chain_cfg);
-        // TODO
+        DAP_CHAIN_PVT(a_chain)->cs_name = l_item->name;
         return 0;
     } else {
         log_it(L_ERROR,"Can't find consensus \"%s\"",dap_config_get_item_str( a_chain_cfg, "chain", "consensus"));
diff --git a/modules/chain/dap_chain_ledger.c b/modules/chain/dap_chain_ledger.c
index e0cf28cbf82400ac48ceb062dd45b6956c66352f..0f66f0343ac4482091d452ee3de40a29048f30c1 100644
--- a/modules/chain/dap_chain_ledger.c
+++ b/modules/chain/dap_chain_ledger.c
@@ -52,7 +52,6 @@
 #include "dap_chain_datum_token.h"
 #include "dap_chain_mempool.h"
 #include "dap_chain_global_db.h"
-#include "dap_chain_net.h"
 #include "dap_chain_ledger.h"
 
 #define LOG_TAG "dap_chain_ledger"
@@ -69,18 +68,12 @@ static  pthread_rwlock_t s_verificators_rwlock;
 #define MAX_OUT_ITEMS   10
 typedef struct dap_chain_ledger_token_emission_item {
     dap_chain_hash_fast_t datum_token_emission_hash;
-    // while these are not needed
-    //dap_chain_hash_fast_t datum_tx_token_hash;
-    //dap_chain_tx_token_t * tx_token;
-
     dap_chain_datum_token_emission_t *datum_token_emission;
     UT_hash_handle hh;
 } dap_chain_ledger_token_emission_item_t;
 
 typedef struct dap_chain_ledger_token_item {
     char ticker[DAP_CHAIN_TICKER_SIZE_MAX];
-    dap_chain_hash_fast_t datum_token_hash;
-    uint8_t padding[6];
     dap_chain_datum_token_t * datum_token;
     uint64_t total_supply;
     pthread_rwlock_t token_emissions_rwlock;
@@ -88,17 +81,18 @@ typedef struct dap_chain_ledger_token_item {
     UT_hash_handle hh;
 } dap_chain_ledger_token_item_t;
 
-// ledger cache item - one of unspendet outputs
+// ledger cache item - one of unspent outputs
 typedef struct dap_chain_ledger_tx_item {
     dap_chain_hash_fast_t tx_hash_fast;
     dap_chain_datum_tx_t *tx;
-    time_t ts_created;
-    int n_outs;
-    int n_outs_used;
-    char token_tiker[10];
-    // TODO dynamically allocates the memory in order not to limit the number of outputs in transaction
-    dap_chain_hash_fast_t tx_hash_spent_fast[MAX_OUT_ITEMS]; // spent outs list
-    uint8_t padding[6];
+    struct {
+        time_t ts_created;
+        int n_outs;
+        int n_outs_used;
+        char token_tiker[10];
+        // TODO dynamically allocates the memory in order not to limit the number of outputs in transaction
+        dap_chain_hash_fast_t tx_hash_spent_fast[MAX_OUT_ITEMS]; // spent outs list
+    } cache_data;
     UT_hash_handle hh;
 } dap_chain_ledger_tx_item_t;
 
@@ -123,21 +117,24 @@ typedef struct dap_chain_ledger_tx_bound {
     dap_chain_ledger_tx_item_t *item_out;
 } dap_chain_ledger_tx_bound_t;
 
-// Gotta use a regular null-terminated string instead, for uthash usability
-/*typedef struct dap_ledger_wallet_balance_key{
-    dap_chain_addr_t addr;
-    char ticker[DAP_CHAIN_TICKER_SIZE_MAX];
-} DAP_ALIGN_PACKED dap_ledger_wallet_balance_key_t; */
-
 // in-memory wallet balance
 typedef struct dap_ledger_wallet_balance {
-    //dap_ledger_wallet_balance_key_t key;
     char *key;
     char token_ticker[DAP_CHAIN_TICKER_SIZE_MAX];
     uint128_t balance;
     UT_hash_handle hh;
 } dap_ledger_wallet_balance_t;
 
+typedef struct dap_ledger_cache_item {
+    dap_chain_hash_fast_t *hash;
+    bool found;
+} dap_ledger_cache_item_t;
+
+typedef struct dap_ledger_cache_str_item {
+    char *key;
+    bool found;
+} dap_ledger_cache_str_item_t;
+
 // dap_ledget_t private section
 typedef struct dap_ledger_private {
     // List of ledger - unspent transactions cache
@@ -163,6 +160,11 @@ typedef struct dap_ledger_private {
     bool check_cells_ds;
     bool check_token_emission;
     dap_chain_cell_id_t local_cell_id;
+    /* Cache section */
+    dap_ledger_cache_item_t last_tx;
+    dap_ledger_cache_item_t last_thres_tx;
+    dap_ledger_cache_item_t last_emit;
+    dap_ledger_cache_str_item_t last_ticker;
 } dap_ledger_private_t;
 #define PVT(a) ( (dap_ledger_private_t* ) a->_internal )
 
@@ -282,13 +284,19 @@ int dap_chain_ledger_token_add(dap_ledger_t * a_ledger,  dap_chain_datum_token_t
         l_token_item = DAP_NEW_Z(dap_chain_ledger_token_item_t);
         dap_snprintf(l_token_item->ticker,sizeof (l_token_item->ticker),"%s",a_token->ticker);
         pthread_rwlock_init(&l_token_item->token_emissions_rwlock,NULL);
-
         l_token_item->datum_token = DAP_NEW_Z_SIZE(dap_chain_datum_token_t, a_token_size);
-
         memcpy(l_token_item->datum_token, a_token,a_token_size);
-        dap_hash_fast(a_token,a_token_size, &l_token_item->datum_token_hash);
+        HASH_ADD_STR(PVT(a_ledger)->tokens, ticker, l_token_item);
+        // Add it to cache
+        dap_chain_datum_token_t *l_token_cache = DAP_NEW_Z_SIZE(dap_chain_datum_token_t, a_token_size);
+        memcpy(l_token_cache, a_token, a_token_size);
+        char *l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, "tokens");
+        if (!dap_chain_global_db_gr_set(dap_strdup(a_token->ticker), l_token_cache, a_token_size, l_gdb_group)) {
+            log_it(L_WARNING, "Ledger cache mismatch");
+            DAP_DELETE(l_token_cache);
+        }
+        DAP_DELETE(l_gdb_group);
 
-        HASH_ADD_STR(PVT(a_ledger)->tokens, ticker, l_token_item) ;
         switch(a_token->type){
             case DAP_CHAIN_DATUM_TOKEN_TYPE_SIMPLE:
                 l_token_item->total_supply = a_token->header_private.total_supply;
@@ -311,6 +319,15 @@ int dap_chain_ledger_token_add(dap_ledger_t * a_ledger,  dap_chain_datum_token_t
     return  0;
 }
 
+int dap_chain_ledger_token_load(dap_ledger_t *a_ledger,  dap_chain_datum_token_t *a_token, size_t a_token_size)
+{
+    if (PVT(a_ledger)->last_ticker.found) {
+        return dap_chain_ledger_token_add(a_ledger, a_token, a_token_size);
+    } else if (!strncmp(PVT(a_ledger)->last_ticker.key, a_token->ticker, DAP_CHAIN_TICKER_SIZE_MAX)) {
+        PVT(a_ledger)->last_ticker.found = true;
+    }
+    return 0;
+}
 /**
  * @brief s_treshold_emissions_proc
  * @param a_ledger
@@ -332,21 +349,120 @@ static void s_treshold_txs_proc( dap_ledger_t * a_ledger)
 }
 
 
+void dap_chain_ledger_load_cache(dap_ledger_t *a_ledger)
+{
+    dap_ledger_private_t *l_ledger_pvt = PVT(a_ledger);
+
+    char *l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, "tokens");
+    size_t l_objs_count = 0;
+    dap_global_db_obj_t *l_objs = dap_chain_global_db_gr_load(l_gdb_group, &l_objs_count);
+    for (size_t i = 0; i < l_objs_count; i++) {
+        dap_chain_ledger_token_item_t *l_token_item = DAP_NEW_Z(dap_chain_ledger_token_item_t);
+        strncpy(l_token_item->ticker, l_objs[i].key, sizeof(l_token_item->ticker));
+        l_token_item->datum_token = DAP_NEW_Z_SIZE(dap_chain_datum_token_t, l_objs[i].value_len);
+        memcpy(l_token_item->datum_token, l_objs[i].value, l_objs[i].value_len);
+        pthread_rwlock_init(&l_token_item->token_emissions_rwlock, NULL);
+        if (l_token_item->datum_token->type == DAP_CHAIN_DATUM_TOKEN_TYPE_SIMPLE) {
+            l_token_item->total_supply = l_token_item->datum_token->header_private.total_supply;
+        }
+        HASH_ADD_STR(PVT(a_ledger)->tokens, ticker, l_token_item);
+        if (i == l_objs_count - 1) {
+            l_ledger_pvt->last_ticker.key = l_token_item->ticker;
+        }
+    }
+    dap_chain_global_db_objs_delete(l_objs, l_objs_count);
+    DAP_DELETE(l_gdb_group);
+    if (l_objs_count == 0) {
+        l_ledger_pvt->last_ticker.found = true;
+    }
+
+    l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, "emissions");
+    l_objs_count = 0;
+    l_objs = dap_chain_global_db_gr_load(l_gdb_group, &l_objs_count);
+    for (size_t i = 0; i < l_objs_count; i++) {
+        dap_chain_ledger_token_emission_item_t *l_emission_item = DAP_NEW_Z(dap_chain_ledger_token_emission_item_t);
+        dap_chain_str_to_hash_fast(l_objs[i].key, &l_emission_item->datum_token_emission_hash);
+        l_emission_item->datum_token_emission = DAP_NEW_Z_SIZE(dap_chain_datum_token_emission_t, l_objs[i].value_len);
+        memcpy(l_emission_item->datum_token_emission, l_objs[i].value, l_objs[i].value_len);
+        const char * c_token_ticker = l_emission_item->datum_token_emission->hdr.ticker;
+        dap_chain_ledger_token_item_t *l_token_item = NULL;
+        HASH_FIND_STR(l_ledger_pvt->tokens, c_token_ticker, l_token_item);
+        if (l_token_item) {
+            HASH_ADD(hh, l_token_item->token_emissions, datum_token_emission_hash,
+                     sizeof(dap_chain_hash_fast_t), l_emission_item);
+        } else {
+            HASH_ADD(hh, l_ledger_pvt->treshold_emissions, datum_token_emission_hash,
+                     sizeof(dap_chain_hash_fast_t), l_emission_item);
+        }
+        if (i == l_objs_count - 1) {
+            l_ledger_pvt->last_emit.hash = &l_emission_item->datum_token_emission_hash;
+        }
+    }
+    dap_chain_global_db_objs_delete(l_objs, l_objs_count);
+    DAP_DELETE(l_gdb_group);
+    if (l_objs_count == 0) {
+        l_ledger_pvt->last_emit.found = true;
+    }
+
+    l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, "txs");
+    l_objs_count = 0;
+    l_objs = dap_chain_global_db_gr_load(l_gdb_group, &l_objs_count);
+    for (size_t i = 0; i < l_objs_count; i++) {
+        dap_chain_ledger_tx_item_t *l_tx_item = DAP_NEW_Z(dap_chain_ledger_tx_item_t);
+        dap_chain_str_to_hash_fast(l_objs[i].key, &l_tx_item->tx_hash_fast);
+        l_tx_item->tx = DAP_NEW_Z_SIZE(dap_chain_datum_tx_t, l_objs[i].value_len - sizeof(l_tx_item->cache_data));
+        memcpy(l_tx_item->tx, l_objs[i].value + sizeof(l_tx_item->cache_data), l_objs[i].value_len - sizeof(l_tx_item->cache_data));
+        memcpy(&l_tx_item->cache_data, l_objs[i].value, sizeof(l_tx_item->cache_data));
+        HASH_ADD(hh, l_ledger_pvt->ledger_items, tx_hash_fast, sizeof(dap_chain_hash_fast_t), l_tx_item);
+        if (i == l_objs_count - 1) {
+            PVT(a_ledger)->last_tx.hash = &l_tx_item->tx_hash_fast;
+        }
+    }
+    dap_chain_global_db_objs_delete(l_objs, l_objs_count);
+    DAP_DELETE(l_gdb_group);
+    if (l_objs_count == 0) {
+        l_ledger_pvt->last_tx.found = true;
+    }
+
+    //TODO add tx threshold cache if need
+    l_ledger_pvt->last_thres_tx.found = true;
+
+    l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, "balances");
+    l_objs_count = 0;
+    l_objs = dap_chain_global_db_gr_load(l_gdb_group, &l_objs_count);
+    for (size_t i = 0; i < l_objs_count; i++) {
+        dap_ledger_wallet_balance_t *l_balance_item = DAP_NEW_Z(dap_ledger_wallet_balance_t);
+        l_balance_item->key = DAP_NEW_Z_SIZE(char, strlen(l_objs[i].key) + 1);
+        strcpy(l_balance_item->key, l_objs[i].key);
+        char *l_ptr = strchr(l_balance_item->key, ' ');
+        if (l_ptr++) {
+            strcpy(l_balance_item->token_ticker, l_ptr);
+        }
+        l_balance_item->balance = *(uint128_t *)l_objs[i].value;
+        HASH_ADD_KEYPTR(hh, l_ledger_pvt->balance_accounts, l_balance_item->key,
+                        strlen(l_balance_item->key), l_balance_item);
+    }
+    dap_chain_global_db_objs_delete(l_objs, l_objs_count);
+    DAP_DELETE(l_gdb_group);
+}
+
 /**
  * @brief dap_chain_ledger_create
  * @param a_check_flags
  * @return dap_ledger_t
  */
-dap_ledger_t* dap_chain_ledger_create(uint16_t a_check_flags)
+dap_ledger_t* dap_chain_ledger_create(uint16_t a_check_flags, char *a_net_name)
 {
     dap_ledger_t *l_ledger = dap_chain_ledger_handle_new();
+    l_ledger->net_name = a_net_name;
     dap_ledger_private_t *l_ledger_priv = PVT(l_ledger);
     l_ledger_priv->check_flags = a_check_flags;
     l_ledger_priv->check_ds = a_check_flags & DAP_CHAIN_LEDGER_CHECK_LOCAL_DS;
     l_ledger_priv->check_cells_ds = a_check_flags & DAP_CHAIN_LEDGER_CHECK_CELLS_DS;
     l_ledger_priv->check_token_emission = a_check_flags & DAP_CHAIN_LEDGER_CHECK_TOKEN_EMISSION;
-    // load ledger from mempool
-    return l_ledger; //dap_chain_ledger_load(l_ledger, "kelvin-testnet", "plasma");
+    // load ledger cache from GDB
+    dap_chain_ledger_load_cache(l_ledger);
+    return l_ledger;
 }
 
 int dap_chain_ledger_token_emission_add_check(dap_ledger_t *a_ledger, const dap_chain_datum_token_emission_t *a_token_emission
@@ -430,16 +546,23 @@ int dap_chain_ledger_token_emission_add(dap_ledger_t *a_ledger,
             memcpy(l_token_emission_item->datum_token_emission, a_token_emission, a_token_emission_size);
             memcpy(&l_token_emission_item->datum_token_emission_hash,
                     l_token_emission_hash_ptr, sizeof(l_token_emission_hash));
-            dap_chain_ledger_token_emission_item_t * l_token_emissions =  l_token_item ?
-                        l_token_item->token_emissions : l_ledger_priv->treshold_emissions;
-            HASH_ADD(hh, l_token_emissions ,
-                     datum_token_emission_hash, sizeof(l_token_emission_hash),
-                    l_token_emission_item);
-            // save pointer to structure
-            if(l_token_item)
-                l_token_item->token_emissions = l_token_emissions;
-            else
-                l_ledger_priv->treshold_emissions = l_token_emissions;
+            if (l_token_item) {
+                HASH_ADD(hh, l_token_item->token_emissions, datum_token_emission_hash,
+                         sizeof(l_token_emission_hash), l_token_emission_item);
+            } else {
+                HASH_ADD(hh, l_ledger_priv->treshold_emissions, datum_token_emission_hash,
+                         sizeof(l_token_emission_hash), l_token_emission_item);
+            }
+            // Add it to cache
+            dap_chain_datum_token_emission_t *l_emission_cache = DAP_NEW_Z_SIZE(dap_chain_datum_token_emission_t, a_token_emission_size);
+            memcpy(l_emission_cache, a_token_emission, a_token_emission_size);
+            char *l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, "emissions");
+            if (!dap_chain_global_db_gr_set(dap_strdup(l_hash_str), l_emission_cache, a_token_emission_size, l_gdb_group)) {
+                log_it(L_WARNING, "Ledger cache mismatch");
+                DAP_DELETE(l_emission_cache);
+            }
+            DAP_DELETE(l_gdb_group);
+
             char * l_token_emission_address_str = dap_chain_addr_to_str( &(a_token_emission->hdr.address) );
             log_it(L_NOTICE,
              "Added token emission datum to %s: type=%s value=%.1llf token=%s to_addr=%s ",
@@ -466,6 +589,20 @@ int dap_chain_ledger_token_emission_add(dap_ledger_t *a_ledger,
     return ret;
 }
 
+int dap_chain_ledger_token_emission_load(dap_ledger_t *a_ledger, const dap_chain_datum_token_emission_t *a_token_emission, size_t a_token_emission_size)
+{
+    if (PVT(a_ledger)->last_emit.found) {
+        return dap_chain_ledger_token_emission_add(a_ledger, a_token_emission, a_token_emission_size);
+    } else {
+        dap_chain_hash_fast_t l_token_emission_hash = {};
+        dap_hash_fast(a_token_emission, a_token_emission_size, &l_token_emission_hash);
+        if (!memcmp(PVT(a_ledger)->last_emit.hash, &l_token_emission_hash, sizeof(dap_chain_hash_fast_t))) {
+            PVT(a_ledger)->last_emit.found = true;
+        }
+    }
+    return 0;
+}
+
 /**
  * @brief dap_chain_ledger_token_emission_find
  * @param a_token_ticker
@@ -522,7 +659,7 @@ const char* dap_chain_ledger_tx_get_token_ticker_by_hash(dap_ledger_t *a_ledger,
     pthread_rwlock_rdlock(&l_ledger_priv->ledger_rwlock);
     HASH_FIND(hh, l_ledger_priv->ledger_items, a_tx_hash, sizeof ( *a_tx_hash), l_item );
     pthread_rwlock_unlock(&l_ledger_priv->ledger_rwlock);
-    return l_item? l_item->token_tiker: NULL;
+    return l_item ? l_item->cache_data.token_tiker : NULL;
 }
 
 /**
@@ -548,7 +685,7 @@ void dap_chain_ledger_addr_get_token_ticker_all(dap_ledger_t *a_ledger, dap_chai
             for(size_t i = 0; i < l_tickers_size; i++) {
                 if (l_tickers[i]==NULL)
                     break;
-                if(l_tickers[i] && strcmp(l_tickers[i], l_tx_item->token_tiker) == 0) {
+                if(l_tickers[i] && strcmp(l_tickers[i], l_tx_item->cache_data.token_tiker) == 0) {
                     l_is_not_in_list = false;
                     break;
                 }
@@ -558,7 +695,7 @@ void dap_chain_ledger_addr_get_token_ticker_all(dap_ledger_t *a_ledger, dap_chai
                     l_tickers_size += (l_tickers_size / 2);
                     l_tickers = DAP_REALLOC(l_tickers, l_tickers_size);
                 }
-                l_tickers[l_tickers_pos] = dap_strdup(l_tx_item->token_tiker);
+                l_tickers[l_tickers_pos] = dap_strdup(l_tx_item->cache_data.token_tiker);
                 l_tickers_pos++;
             }
             dap_chain_hash_fast_t* l_tx_hash = dap_chain_node_datum_tx_calc_hash(l_tx_item->tx);
@@ -647,8 +784,8 @@ static bool dap_chain_ledger_item_is_used_out(dap_chain_ledger_tx_item_t *a_item
     }
     assert(a_idx_out < MAX_OUT_ITEMS);
     // if there are used 'out' items
-    if(a_item->n_outs_used > 0) {
-        if(!dap_hash_fast_is_blank(&(a_item->tx_hash_spent_fast[a_idx_out])))
+    if(a_item->cache_data.n_outs_used > 0) {
+        if(!dap_hash_fast_is_blank(&(a_item->cache_data.tx_hash_spent_fast[a_idx_out])))
             l_used_out = true;
     }
     return l_used_out;
@@ -888,7 +1025,7 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
             l_token = NULL;
         }
         if (!l_token || !*l_token) {
-            l_token = l_item_out->token_tiker;
+            l_token = l_item_out->cache_data.token_tiker;
         }
         if (!*l_token) {
             log_it(L_WARNING, "No token ticker found in previous transaction");
@@ -1057,6 +1194,19 @@ int dap_chain_ledger_tx_add_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *
     return 0;
 }
 
+int dap_chain_ledger_balance_cache_update(dap_ledger_t *a_ledger, dap_ledger_wallet_balance_t *a_balance)
+{
+    char *l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, "balances");
+    uint128_t *l_balance_value = DAP_NEW_Z(uint128_t);
+    *l_balance_value = a_balance->balance;
+    if (!dap_chain_global_db_gr_set(dap_strdup(a_balance->key), l_balance_value, sizeof(uint128_t), l_gdb_group)) {
+        log_it(L_WARNING, "Ledger cache mismatch");
+        DAP_DELETE(l_balance_value);
+        return -1;
+    }
+    return 0;
+}
+
 /**
  * Add new transaction to the cache list
  *
@@ -1113,8 +1263,8 @@ int dap_chain_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx)
         void *l_item_in = *(void **)&bound_item->in;
         dap_chain_tx_item_type_t l_type = *(uint8_t *)l_item_in;
         dap_chain_ledger_tx_item_t *l_prev_item_out = bound_item->item_out;
-        if (*l_prev_item_out->token_tiker) {
-            l_token_ticker = l_prev_item_out->token_tiker;
+        if (*l_prev_item_out->cache_data.token_tiker) {
+            l_token_ticker = l_prev_item_out->cache_data.token_tiker;
         } else { // Previous multichannel transaction
             l_token_ticker = bound_item->out.tx_prev_out_ext->token;
         }
@@ -1140,26 +1290,28 @@ int dap_chain_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx)
                                     bound_item->out.tx_prev_out_ext->header.value;
                 //log_it(L_DEBUG,"SPEND %lu from addr: %s", l_value, l_wallet_balance_key);
                 wallet_balance->balance -= l_value;
+                // Update the cache
+                dap_chain_ledger_balance_cache_update(a_ledger, wallet_balance);
             } else {
                 log_it(L_ERROR,"!!! Attempt to SPEND from some non-existent balance !!!: %s %s", l_addr_str, l_token_ticker);
             }
             DAP_DELETE(l_addr_str);
             DAP_DELETE(l_wallet_balance_key);
             /// Mark 'out' item in cache because it used
-            l_tx_prev_hash = &(l_prev_item_out->tx_hash_spent_fast[l_tx_in->header.tx_out_prev_idx]);
+            l_tx_prev_hash = &(l_prev_item_out->cache_data.tx_hash_spent_fast[l_tx_in->header.tx_out_prev_idx]);
         } else { // TX_ITEM_TYPE_IN_COND
             // all balance deducts performed with previous conditional transaction
             dap_chain_tx_in_cond_t *l_tx_in_cond = bound_item->in.tx_cur_in_cond;
             /// Mark 'out' item in cache because it used
-            l_tx_prev_hash = &(l_prev_item_out->tx_hash_spent_fast[l_tx_in_cond->header.tx_out_prev_idx]);
+            l_tx_prev_hash = &(l_prev_item_out->cache_data.tx_hash_spent_fast[l_tx_in_cond->header.tx_out_prev_idx]);
         }
         memcpy(l_tx_prev_hash, l_tx_hash, sizeof(dap_chain_hash_fast_t));
         // add a used output
-        l_prev_item_out->n_outs_used++;
+        l_prev_item_out->cache_data.n_outs_used++;
         char * l_tx_prev_hash_str = dap_chain_hash_fast_to_str_new(l_tx_prev_hash);
 
         // delete previous transactions from cache because all out is used
-        if(l_prev_item_out->n_outs_used == l_prev_item_out->n_outs) {
+        if(l_prev_item_out->cache_data.n_outs_used == l_prev_item_out->cache_data.n_outs) {
             dap_chain_hash_fast_t l_tx_prev_hash_to_del = bound_item->tx_prev_hash_fast;
             // remove from memory ledger
             int res = dap_chain_ledger_tx_remove(a_ledger, &l_tx_prev_hash_to_del);
@@ -1237,6 +1389,8 @@ int dap_chain_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx)
                 //log_it(L_DEBUG, "Balance item is present in cache");
                 wallet_balance->balance += l_value;
                 DAP_DELETE (l_wallet_balance_key);
+                // Update the cache
+                dap_chain_ledger_balance_cache_update(a_ledger, wallet_balance);
             } else {
                 wallet_balance = DAP_NEW_Z(dap_ledger_wallet_balance_t);
                 wallet_balance->key = l_wallet_balance_key;
@@ -1245,6 +1399,8 @@ int dap_chain_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx)
                 //log_it(L_DEBUG,"!!! Create new balance item: %s %s", l_addr_str, l_token_ticker);
                 HASH_ADD_KEYPTR(hh, PVT(a_ledger)->balance_accounts, wallet_balance->key,
                                 strlen(l_wallet_balance_key), wallet_balance);
+                // Add it to cache
+                dap_chain_ledger_balance_cache_update(a_ledger, wallet_balance);
             }
 #ifdef __ANDROID__
             log_it(L_INFO, "Updated balance +%.3Lf %s on addr %s",
@@ -1272,15 +1428,15 @@ int dap_chain_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx)
         l_item_tmp = DAP_NEW_Z(dap_chain_ledger_tx_item_t);
         memcpy(&l_item_tmp->tx_hash_fast, l_tx_hash, sizeof(dap_chain_hash_fast_t));
         l_item_tmp->tx = DAP_NEW_SIZE(dap_chain_datum_tx_t, dap_chain_datum_tx_get_size(a_tx));
-        l_item_tmp->ts_created = (time_t) a_tx->header.ts_created;
+        l_item_tmp->cache_data.ts_created = (time_t) a_tx->header.ts_created;
         //calculate l_item_tmp->n_outs;
 
         // If debug mode dump the UTXO
         if ( dap_log_level_get() == L_DEBUG){
-            l_item_tmp->n_outs = 0;
-            if( l_item_tmp->n_outs){
-                dap_list_t *l_tist_tmp = dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_OUT, &l_item_tmp->n_outs);
-                for (size_t i =0; i < (size_t) l_item_tmp->n_outs; i++){
+            l_item_tmp->cache_data.n_outs = 0;
+            if( l_item_tmp->cache_data.n_outs){
+                dap_list_t *l_tist_tmp = dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_OUT, &l_item_tmp->cache_data.n_outs);
+                for (size_t i =0; i < (size_t) l_item_tmp->cache_data.n_outs; i++){
                     // TODO list conditional outputs
                     dap_chain_tx_out_t * l_tx_out = l_tist_tmp->data;
                     char * l_tx_out_addr_str = dap_chain_addr_to_str( &l_tx_out->addr );
@@ -1303,10 +1459,20 @@ int dap_chain_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx)
             }
         }
         if (l_token_ticker && !l_multichannel)
-            strncpy(l_item_tmp->token_tiker, l_token_ticker, sizeof(l_item_tmp->token_tiker) - 1);
-
-        memcpy(l_item_tmp->tx, a_tx, dap_chain_datum_tx_get_size(a_tx));
-        HASH_ADD(hh, l_ledger_priv->ledger_items, tx_hash_fast, sizeof(dap_chain_hash_fast_t), l_item_tmp); // tx_hash_fast: name of key field
+            strncpy(l_item_tmp->cache_data.token_tiker, l_token_ticker, sizeof(l_item_tmp->cache_data.token_tiker) - 1);
+        size_t l_tx_size = dap_chain_datum_tx_get_size(a_tx);
+        memcpy(l_item_tmp->tx, a_tx, l_tx_size);
+        HASH_ADD(hh, l_ledger_priv->ledger_items, tx_hash_fast, sizeof(dap_chain_hash_fast_t), l_item_tmp); // tx_hash_fast: name of key field   
+        // Add it to cache
+        uint8_t *l_tx_cache = DAP_NEW_Z_SIZE(uint8_t, l_tx_size + sizeof(l_item_tmp->cache_data));
+        memcpy(l_tx_cache, &l_item_tmp->cache_data, sizeof(l_item_tmp->cache_data));
+        memcpy(l_tx_cache + sizeof(l_item_tmp->cache_data), a_tx, l_tx_size);
+        char *l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, "txs");
+        if (!dap_chain_global_db_gr_set(dap_strdup(l_tx_hash_str), l_tx_cache, l_tx_size + sizeof(l_item_tmp->cache_data), l_gdb_group)) {
+            log_it(L_WARNING, "Ledger cache mismatch");
+            DAP_DELETE(l_tx_cache);
+        }
+        DAP_DELETE(l_gdb_group);
         ret = 1;
     }
 FIN:
@@ -1316,6 +1482,25 @@ FIN:
     return ret;
 }
 
+int dap_chain_ledger_tx_load(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx)
+{
+    if (PVT(a_ledger)->last_tx.found && PVT(a_ledger)->last_thres_tx.found) {
+        return dap_chain_ledger_tx_add(a_ledger, a_tx);
+    } else {
+        dap_chain_hash_fast_t l_tx_hash = {};
+        dap_hash_fast(a_tx, dap_chain_datum_tx_get_size(a_tx), &l_tx_hash);
+        if (!PVT(a_ledger)->last_tx.found &&
+                !memcmp(PVT(a_ledger)->last_tx.hash, &l_tx_hash, sizeof(dap_chain_hash_fast_t))) {
+            PVT(a_ledger)->last_tx.found = true;
+        }
+        if (!PVT(a_ledger)->last_thres_tx.found &&
+                !memcmp(PVT(a_ledger)->last_thres_tx.hash, &l_tx_hash, sizeof(dap_chain_hash_fast_t))) {
+            PVT(a_ledger)->last_thres_tx.found = true;
+        }
+    }
+    return 1;
+}
+
 /**
  * Delete transaction from the cache
  *
@@ -1332,18 +1517,20 @@ int dap_chain_ledger_tx_remove(dap_ledger_t *a_ledger, dap_chain_hash_fast_t *a_
     HASH_FIND(hh, l_ledger_priv->ledger_items, a_tx_hash, sizeof(dap_chain_hash_fast_t), l_item_tmp);
     if(l_item_tmp != NULL) {
         HASH_DEL(l_ledger_priv->ledger_items, l_item_tmp);
+        // delete transaction
+        DAP_DELETE(l_item_tmp->tx);
+        // del struct for hash
+        DAP_DELETE(l_item_tmp);
+        // Remove it from cache
+        char *l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, "txs");
+        dap_chain_global_db_gr_del(dap_chain_hash_fast_to_str_new(a_tx_hash), l_gdb_group);
+        DAP_DELETE(l_gdb_group);
         l_ret = 1;
     }
     else
         // hash not found in the cache
         l_ret = -2;
     pthread_rwlock_unlock(&l_ledger_priv->ledger_rwlock);
-    if(!l_ret) {
-        // delete transaction
-        DAP_DELETE(l_item_tmp->tx);
-        // del struct for hash
-        DAP_DELETE(l_item_tmp);
-    }
     return l_ret;
 }
 
@@ -1353,16 +1540,82 @@ int dap_chain_ledger_tx_remove(dap_ledger_t *a_ledger, dap_chain_hash_fast_t *a_
 void dap_chain_ledger_purge(dap_ledger_t *a_ledger)
 {
     dap_ledger_private_t *l_ledger_priv = PVT(a_ledger);
-    dap_chain_ledger_tx_item_t *l_iter_current, *l_item_tmp;
+    const int l_hash_str_size = DAP_CHAIN_HASH_FAST_SIZE * 2 + 2;
+    char l_hash_str[l_hash_str_size];
     pthread_rwlock_wrlock(&l_ledger_priv->ledger_rwlock);
-    HASH_ITER(hh, l_ledger_priv->ledger_items , l_iter_current, l_item_tmp)
-    {
-        // delete transaction
-        DAP_DELETE(l_iter_current->tx);
-        // del struct for hash
-        HASH_DEL(l_ledger_priv->ledger_items, l_iter_current);
+    pthread_rwlock_wrlock(&l_ledger_priv->tokens_rwlock);
+    pthread_rwlock_wrlock(&l_ledger_priv->treshold_emissions_rwlock);
+    pthread_rwlock_wrlock(&l_ledger_priv->treshold_txs_rwlock);
+
+    // delete transactions
+    dap_chain_ledger_tx_item_t *l_item_current, *l_item_tmp;
+    char *l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, "txs");
+    HASH_ITER(hh, l_ledger_priv->ledger_items , l_item_current, l_item_tmp) {
+        DAP_DELETE(l_item_current->tx);
+        HASH_DEL(l_ledger_priv->ledger_items, l_item_current);
+        dap_chain_hash_fast_to_str(&l_item_current->tx_hash_fast, l_hash_str, l_hash_str_size);
+        dap_chain_global_db_gr_del(l_hash_str, l_gdb_group);
+        DAP_DELETE(l_item_current);
+    }
+    DAP_DELETE(l_gdb_group);
+
+    // delete threshold txs
+    l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, "thres_txs");
+    HASH_ITER(hh, l_ledger_priv->treshold_txs, l_item_current, l_item_tmp) {
+        HASH_DEL(l_ledger_priv->treshold_txs, l_item_current);
+        dap_chain_hash_fast_to_str(&l_item_current->tx_hash_fast, l_hash_str, l_hash_str_size);
+        dap_chain_global_db_gr_del(l_hash_str, l_gdb_group);
+        DAP_DELETE(l_item_current->tx);
+        DAP_DELETE(l_item_current);
+    }
+    DAP_DELETE(l_gdb_group);
+
+    // delete balances
+    dap_ledger_wallet_balance_t *l_balance_current, *l_balance_tmp;
+    l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, "balances");
+    HASH_ITER(hh, l_ledger_priv->balance_accounts, l_balance_current, l_balance_tmp) {
+        HASH_DEL(l_ledger_priv->balance_accounts, l_balance_current);
+        dap_chain_global_db_gr_del(l_balance_current->key, l_gdb_group);
+        DAP_DELETE(l_balance_current->key);
+        DAP_DELETE(l_balance_current);
     }
+    DAP_DELETE(l_gdb_group);
+
+    // delete threshold emissions
+    dap_chain_ledger_token_emission_item_t *l_emission_current, *l_emission_tmp;
+    char *l_emissions_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, "emissions");
+    HASH_ITER(hh, l_ledger_priv->treshold_emissions, l_emission_current, l_emission_tmp) {
+        HASH_DEL(l_ledger_priv->treshold_emissions, l_emission_current);
+        dap_chain_hash_fast_to_str(&l_emission_current->datum_token_emission_hash, l_hash_str, l_hash_str_size);
+        dap_chain_global_db_gr_del(l_hash_str, l_emissions_gdb_group);
+        DAP_DELETE(l_emission_current->datum_token_emission);
+        DAP_DELETE(l_emission_current);
+    }
+
+    // delete tokens & its emissions
+    dap_chain_ledger_token_item_t *l_token_current, *l_token_tmp;
+    l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, "tokens");
+    HASH_ITER(hh, l_ledger_priv->tokens, l_token_current, l_token_tmp) {
+        HASH_DEL(l_ledger_priv->tokens, l_token_current);
+        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_chain_hash_fast_to_str(&l_emission_current->datum_token_emission_hash, l_hash_str, l_hash_str_size);
+            dap_chain_global_db_gr_del(l_hash_str, l_emissions_gdb_group);
+            DAP_DELETE(l_emission_current->datum_token_emission);
+            DAP_DELETE(l_emission_current);
+        }
+        dap_chain_global_db_gr_del(l_token_current->ticker, l_gdb_group);
+        DAP_DELETE(l_token_current->datum_token);
+        pthread_rwlock_destroy(&l_token_current->token_emissions_rwlock);
+        DAP_DELETE(l_token_current);
+    }
+    DAP_DELETE(l_gdb_group);
+    DAP_DELETE(l_emissions_gdb_group);
+
     pthread_rwlock_unlock(&l_ledger_priv->ledger_rwlock);
+    pthread_rwlock_unlock(&l_ledger_priv->tokens_rwlock);
+    pthread_rwlock_unlock(&l_ledger_priv->treshold_emissions_rwlock);
+    pthread_rwlock_unlock(&l_ledger_priv->treshold_txs_rwlock);
 }
 
 /**
@@ -1370,16 +1623,7 @@ void dap_chain_ledger_purge(dap_ledger_t *a_ledger)
  */
 _dap_int128_t dap_chain_ledger_count(dap_ledger_t *a_ledger)
 {
-    _dap_int128_t l_ret = 0;
-    dap_ledger_private_t *l_ledger_priv = PVT(a_ledger);
-    dap_chain_ledger_tx_item_t *l_iter_current, *l_item_tmp;
-    pthread_rwlock_wrlock(&l_ledger_priv->ledger_rwlock);
-    HASH_ITER(hh, l_ledger_priv->ledger_items , l_iter_current, l_item_tmp)
-    {
-        l_ret++;
-    }
-    pthread_rwlock_unlock(&l_ledger_priv->ledger_rwlock);
-    return l_ret;
+    return HASH_COUNT(PVT(a_ledger)->ledger_items);
 }
 
 /**
@@ -1397,17 +1641,17 @@ uint64_t dap_chain_ledger_count_from_to(dap_ledger_t * a_ledger, time_t a_ts_fro
     pthread_rwlock_wrlock(&l_ledger_priv->ledger_rwlock);
     if ( a_ts_from && a_ts_to) {
         HASH_ITER(hh, l_ledger_priv->ledger_items , l_iter_current, l_item_tmp){
-            if ( l_iter_current->ts_created >= a_ts_from && l_iter_current->ts_created <= a_ts_to )
+            if ( l_iter_current->cache_data.ts_created >= a_ts_from && l_iter_current->cache_data.ts_created <= a_ts_to )
             l_ret++;
         }
     } else if ( a_ts_to ){
         HASH_ITER(hh, l_ledger_priv->ledger_items , l_iter_current, l_item_tmp){
-            if ( l_iter_current->ts_created <= a_ts_to )
+            if ( l_iter_current->cache_data.ts_created <= a_ts_to )
             l_ret++;
         }
     } else if ( a_ts_from ){
         HASH_ITER(hh, l_ledger_priv->ledger_items , l_iter_current, l_item_tmp){
-            if ( l_iter_current->ts_created >= a_ts_from )
+            if ( l_iter_current->cache_data.ts_created >= a_ts_from )
             l_ret++;
         }
     }else {
@@ -1512,7 +1756,7 @@ uint64_t dap_chain_ledger_calc_balance_full(dap_ledger_t *a_ledger, const dap_ch
             if (l_type == TX_ITEM_TYPE_OUT) {
                 const dap_chain_tx_out_t *l_tx_out = (const dap_chain_tx_out_t*) l_list_tmp->data;
                 // Check for token name
-                if (!strcmp(a_token_ticker, l_iter_current->token_tiker))
+                if (!strcmp(a_token_ticker, l_iter_current->cache_data.token_tiker))
                 {   // if transaction has the out item with requested addr
                     if (!memcmp(a_addr, &l_tx_out->addr, sizeof(dap_chain_addr_t))) {
                         // if 'out' item not used & transaction is valid
@@ -1563,7 +1807,8 @@ static dap_chain_ledger_tx_item_t* tx_item_find_by_addr(dap_ledger_t *a_ledger,
     HASH_ITER(hh, l_ledger_priv->ledger_items , l_iter_current, l_item_tmp)
     {
         // If a_token is setup we check if its not our token - miss it
-        if (a_token && *l_iter_current->token_tiker && dap_strcmp(l_iter_current->token_tiker, a_token))
+        if (a_token && *l_iter_current->cache_data.token_tiker &&
+                dap_strcmp(l_iter_current->cache_data.token_tiker, a_token))
             continue;
         // Now work with it
         dap_chain_datum_tx_t *l_tx = l_iter_current->tx;
@@ -1715,7 +1960,7 @@ dap_chain_datum_tx_t* dap_chain_ledger_tx_cache_find_out_cond(dap_ledger_t *a_le
             l_cur_tx = l_tx_tmp;
             memcpy(a_tx_first_hash, l_tx_hash_tmp, sizeof(dap_chain_hash_fast_t));
             if (a_token_ticker) {
-                strcpy(a_token_ticker, l_iter_current->token_tiker);
+                strcpy(a_token_ticker, l_iter_current->cache_data.token_tiker);
             }
             break;
         }
diff --git a/modules/chain/include/dap_chain.h b/modules/chain/include/dap_chain.h
index fc03b2f72db531bc7704eff954fbacecd549d25c..baad228c8660bfde5ac7a7cb9a425e7b0d6107c0 100644
--- a/modules/chain/include/dap_chain.h
+++ b/modules/chain/include/dap_chain.h
@@ -80,8 +80,8 @@ typedef dap_chain_atom_ptr_t * (*dap_chain_callback_atom_iter_get_atoms_t)(dap_c
 typedef dap_chain_atom_ptr_t (*dap_chain_callback_atom_iter_get_next_t)(dap_chain_atom_iter_t *  ,size_t*);
 typedef void (*dap_chain_callback_atom_iter_delete_t)(dap_chain_atom_iter_t *  );
 
-typedef size_t (*dap_chain_datum_callback_datum_pool_proc_add_t)(dap_chain_t * , dap_chain_datum_t **, size_t );
-typedef size_t (*dap_chain_datum_callback_datum_pool_proc_add_with_group_t)(dap_chain_t * , dap_chain_datum_t **, size_t, const char *);
+typedef size_t (*dap_chain_callback_add_datums_t)(dap_chain_t * , dap_chain_datum_t **, size_t );
+typedef size_t (*dap_chain_callback_add_datums_with_group_t)(dap_chain_t * , dap_chain_datum_t **, size_t, const char *);
 
 typedef void (*dap_chain_callback_notify_t)(void * a_arg, dap_chain_t *a_chain, dap_chain_cell_id_t a_id, void* a_atom, size_t a_atom_size); //change in chain happened
 
@@ -118,13 +118,14 @@ typedef struct dap_chain{
 
     dap_chain_callback_new_cfg_t callback_created;
     dap_chain_callback_t callback_delete;
+    dap_chain_callback_t callback_purge;
 
     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;
 
-    dap_chain_datum_callback_datum_pool_proc_add_t callback_datums_pool_proc;
-    dap_chain_datum_callback_datum_pool_proc_add_with_group_t callback_datums_pool_proc_with_group;
+    dap_chain_callback_add_datums_t callback_add_datums;
+    dap_chain_callback_add_datums_with_group_t callback_add_datums_with_group;
 
     dap_chain_callback_atom_get_hdr_size_t callback_atom_get_hdr_static_size; // Get atom header's size
 
@@ -173,3 +174,4 @@ dap_chain_t * dap_chain_load_from_cfg(dap_ledger_t* a_ledger,const char * a_chai
 
 void dap_chain_delete(dap_chain_t * a_chain);
 void dap_chain_add_callback_notify(dap_chain_t * a_chain, dap_chain_callback_notify_t a_callback, void * a_arg);
+dap_chain_atom_ptr_t dap_chain_get_atom_by_hash(dap_chain_t * a_chain, dap_chain_hash_fast_t * a_atom_hash, size_t * a_atom_size);
diff --git a/modules/chain/include/dap_chain_cs.h b/modules/chain/include/dap_chain_cs.h
index 9a5d4620a37fbb8bdbeaefb1e8a3dac94988471a..f76d443f57eabbf60e2fcc55287683f64fa68438 100644
--- a/modules/chain/include/dap_chain_cs.h
+++ b/modules/chain/include/dap_chain_cs.h
@@ -39,5 +39,5 @@ void dap_chain_cs_deinit(void);
 void dap_chain_cs_add (const char * a_cs_str,  dap_chain_callback_new_cfg_t a_callback_init);
 int dap_chain_cs_create(dap_chain_t * a_chain, dap_config_t * a_chain_cfg);
 
-void dap_chain_class_add (const char * a_cs_str,  dap_chain_callback_new_cfg_t a_callback_init);
-int dap_chain_class_create(dap_chain_t * a_chain, dap_config_t * a_chain_cfg);
+void dap_chain_cs_type_add (const char * a_cs_str,  dap_chain_callback_new_cfg_t a_callback_init);
+int dap_chain_cs_type_create(dap_chain_t * a_chain, dap_config_t * a_chain_cfg);
diff --git a/modules/chain/include/dap_chain_ledger.h b/modules/chain/include/dap_chain_ledger.h
index 29b7b7e9f0ecf06987174d0b66e1ca87b3370b82..3eb630475f066d7069f58607450e42edfd9e5265 100644
--- a/modules/chain/include/dap_chain_ledger.h
+++ b/modules/chain/include/dap_chain_ledger.h
@@ -38,6 +38,7 @@
 #include "dap_chain_datum_tx_items.h"
 
 typedef struct dap_ledger {
+    char *net_name;
     void *_internal;
 } dap_ledger_t;
 
@@ -52,7 +53,7 @@ typedef bool (* dap_chain_ledger_verificator_callback_t)(dap_chain_tx_out_cond_t
 // Check the double spending  in all cells
 #define DAP_CHAIN_LEDGER_CHECK_CELLS_DS          0x0100
 
-dap_ledger_t* dap_chain_ledger_create(uint16_t a_check_flags);
+dap_ledger_t* dap_chain_ledger_create(uint16_t a_check_flags, char *a_net_name);
 
 // Remove dap_ledger_t structure
 void dap_chain_ledger_handle_free(dap_ledger_t *a_ledger);
@@ -67,19 +68,28 @@ void dap_chain_ledger_set_local_cell_id(dap_ledger_t *a_ledger, dap_chain_cell_i
  * @param a_tx
  * @return
  */
-static inline dap_chain_hash_fast_t* dap_chain_node_datum_tx_calc_hash(dap_chain_datum_tx_t *a_tx)
+DAP_STATIC_INLINE dap_chain_hash_fast_t* dap_chain_node_datum_tx_calc_hash(dap_chain_datum_tx_t *a_tx)
 {
     dap_chain_hash_fast_t *tx_hash = DAP_NEW_Z(dap_chain_hash_fast_t);
     dap_hash_fast(a_tx, dap_chain_datum_tx_get_size(a_tx), tx_hash);
     return tx_hash;
 }
 
+DAP_STATIC_INLINE char *dap_chain_ledger_get_gdb_group(dap_ledger_t *a_ledger, const char *a_suffix)
+{
+   if (a_ledger) {
+       return dap_strdup_printf("local.ledger-cache.%s.%s", a_ledger->net_name, a_suffix);
+   }
+   return NULL;
+}
+
 /**
  * Add new transaction to the cache
  *
  * return 1 OK, -1 error
  */
 int dap_chain_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx);
+int dap_chain_ledger_tx_load(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx);
 
 
 int dap_chain_ledger_tx_add_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx);
@@ -97,6 +107,7 @@ int dap_chain_ledger_token_ticker_check(dap_ledger_t * a_ledger, const char *a_t
  */
 
 int dap_chain_ledger_token_add(dap_ledger_t * a_ledger,dap_chain_datum_token_t *a_token, size_t a_token_size);
+int dap_chain_ledger_token_load(dap_ledger_t * a_ledger,dap_chain_datum_token_t *a_token, size_t a_token_size);
 int dap_chain_ledger_token_decl_add_check(dap_ledger_t * a_ledger,dap_chain_datum_token_t *a_token);
 
 /**
@@ -104,6 +115,8 @@ int dap_chain_ledger_token_decl_add_check(dap_ledger_t * a_ledger,dap_chain_datu
  */
 int dap_chain_ledger_token_emission_add(dap_ledger_t *a_ledger,
         const dap_chain_datum_token_emission_t *a_token_emission, size_t a_token_emission_size);
+int dap_chain_ledger_token_emission_load(dap_ledger_t *a_ledger,
+        const dap_chain_datum_token_emission_t *a_token_emission, size_t a_token_emission_size);
 
 // Check if it addable
 int dap_chain_ledger_token_emission_add_check(dap_ledger_t *a_ledger,
diff --git a/modules/chain/include/dap_chain_pvt.h b/modules/chain/include/dap_chain_pvt.h
index d18e434a8f0300db0f245c688dc17e75f3f358c9..4af990d5fcdf6b2650e6ba1a44785a67400d26dd 100644
--- a/modules/chain/include/dap_chain_pvt.h
+++ b/modules/chain/include/dap_chain_pvt.h
@@ -41,6 +41,8 @@ typedef struct dap_chain_pvt
 {
     dap_chain_t * chain;
     char * file_storage_dir;
+    char * cs_name;
+    int celled;
 } dap_chain_pvt_t;
 
 #define DAP_CHAIN_PVT(a) ((dap_chain_pvt_t *) a->_pvt  )
diff --git a/modules/channel/chain/dap_stream_ch_chain.c b/modules/channel/chain/dap_stream_ch_chain.c
index 27e9d17d4c1de614755cf6cbc72720b54a983b7b..e7a5ce4f4d815fa870297537332323fa67776c8b 100644
--- a/modules/channel/chain/dap_stream_ch_chain.c
+++ b/modules/channel/chain/dap_stream_ch_chain.c
@@ -152,6 +152,9 @@ bool s_sync_chains_callback(dap_proc_thread_t *a_thread, void *a_arg)
                 l_ch_chain->request_cell_id, &l_request, sizeof(l_request));
         DAP_DEL_Z(l_ch_chain->request_atom_iter);
         l_ch_chain->state = CHAIN_STATE_IDLE;
+        if (l_ch_chain->callback_notify_packet_out)
+            l_ch_chain->callback_notify_packet_out(l_ch_chain, DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_CHAINS,
+                                                    NULL, 0, l_ch_chain->callback_notify_arg);
     }
     dap_stream_ch_set_ready_to_write_unsafe(l_ch, true);
     dap_events_socket_assign_on_worker_mt(l_ch->stream->esocket, l_ch->stream_worker->worker);
@@ -349,9 +352,9 @@ bool s_gdb_pkt_callback(dap_proc_thread_t *a_thread, void *a_arg)
         // apply received transaction
         dap_chain_t *l_chain = dap_chain_find_by_id(l_ch_chain->request_net_id, l_ch_chain->request_chain_id);
         if(l_chain) {
-            if(l_chain->callback_datums_pool_proc_with_group){
+            if(l_chain->callback_add_datums_with_group){
                 void * restrict l_store_obj_value = l_store_obj->value;
-                l_chain->callback_datums_pool_proc_with_group(l_chain,
+                l_chain->callback_add_datums_with_group(l_chain,
                         (dap_chain_datum_t** restrict) l_store_obj_value, 1,
                         l_store_obj[i].group);
             }
diff --git a/modules/common/include/dap_chain_datum.h b/modules/common/include/dap_chain_datum.h
index cd6f7b45b39591619545bd7ffe43c80f3dec065a..3293a2c3720093431032dccdb5101f03458e6839 100644
--- a/modules/common/include/dap_chain_datum.h
+++ b/modules/common/include/dap_chain_datum.h
@@ -88,7 +88,7 @@ typedef struct dap_chain_datum{
         /// Create timestamp (GM time)
         uint64_t ts_create;
     } DAP_ALIGN_PACKED header;
-    uint8_t data[]; /// Stored datum body
+    byte_t data[]; /// Stored datum body
 } DAP_ALIGN_PACKED dap_chain_datum_t;
 
 
diff --git a/modules/common/include/dap_chain_datum_token.h b/modules/common/include/dap_chain_datum_token.h
index d130cec690b5597b0cd196cf8b8974d980de3709..5d3b8644eae22e7b795c8f86cc03f6eef9294674 100644
--- a/modules/common/include/dap_chain_datum_token.h
+++ b/modules/common/include/dap_chain_datum_token.h
@@ -135,7 +135,7 @@ static inline uint16_t dap_chain_datum_token_flag_from_str(const char* a_str)
 // TSD section - Type-Size-Data
 typedef struct dap_chain_datum_token_tsd{
     uint16_t type; /// Section type
-    size_t size;   /// Data size trailing the section
+    uint32_t size;   /// Data size trailing the section
     byte_t data[]; /// Section's data
 } DAP_ALIGN_PACKED dap_chain_datum_token_tsd_t;
 
diff --git a/modules/consensus/none/dap_chain_cs_none.c b/modules/consensus/none/dap_chain_cs_none.c
index 82f54c1fcba42a767a57817e115ebb97428e5812..1e9b966aeaa474b3baba928adca1341b8f939ed1 100644
--- a/modules/consensus/none/dap_chain_cs_none.c
+++ b/modules/consensus/none/dap_chain_cs_none.c
@@ -65,8 +65,6 @@ typedef struct dap_chain_gdb_private
 
 #define PVT(a) ( (a) ? (dap_chain_gdb_private_t* ) (a)->_internal : NULL)
 
-static int dap_chain_gdb_ledger_load(dap_chain_gdb_t *a_gdb, dap_chain_net_t *a_net);
-
 // 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); //    Accept new event in gdb
 static dap_chain_atom_verify_res_t s_chain_callback_atom_verify(dap_chain_t * a_chain, dap_chain_atom_ptr_t, size_t); //    Verify new event in gdb
@@ -114,7 +112,7 @@ static int s_cs_callback_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg)
 int dap_chain_gdb_init(void)
 {
     dap_chain_cs_add(CONSENSUS_NAME, s_cs_callback_new);
-    dap_chain_class_add(CONSENSUS_NAME, dap_chain_gdb_new);
+    dap_chain_cs_type_add(CONSENSUS_NAME, dap_chain_gdb_new);
 
     log_it(L_NOTICE, "Initialized GDB chain items organization class");
     return 0;
@@ -138,10 +136,16 @@ static void s_history_callback_notify(void * a_arg, const char a_op_code, const
         dap_chain_net_t *l_net = dap_chain_net_by_id( l_gdb->chain->net_id);
         log_it(L_DEBUG,"%s.%s: op_code='%c' group=\"%s\" key=\"%s\" value_size=%u",l_net->pub.name,
                l_gdb->chain->name, a_op_code, a_group, a_key, a_value_size);
+        dap_chain_node_mempool_autoproc_notify((void *)l_net, a_op_code, a_prefix, a_group, a_key, a_value, a_value_size);
         dap_chain_net_sync_gdb_broadcast((void *)l_net, a_op_code, a_prefix, a_group, a_key, a_value, a_value_size);
     }
 }
 
+static void s_dap_chain_gdb_callback_purge(dap_chain_t *a_chain)
+{
+    PVT(DAP_CHAIN_GDB(a_chain))->is_load_mode = true;
+}
+
 /**
  * @brief dap_chain_gdb_new
  * @param a_chain
@@ -176,10 +180,10 @@ int dap_chain_gdb_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg)
 
     // load ledger
     l_gdb_priv->is_load_mode = true;
-    dap_chain_gdb_ledger_load(l_gdb, l_net);
-    l_gdb_priv->is_load_mode = false;
+    dap_chain_gdb_ledger_load(l_gdb_priv->group_datums, a_chain);
 
     a_chain->callback_delete = dap_chain_gdb_delete;
+    a_chain->callback_purge = s_dap_chain_gdb_callback_purge;
 
     // Atom element callbacks
     a_chain->callback_atom_add = s_chain_callback_atom_add; // Accept new element in chain
@@ -191,8 +195,8 @@ int dap_chain_gdb_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg)
     a_chain->callback_atom_iter_delete = s_chain_callback_atom_iter_delete;
 
     a_chain->callback_atom_find_by_hash = s_chain_callback_atom_iter_find_by_hash;
-    a_chain->callback_datums_pool_proc = s_chain_callback_datums_pool_proc;
-    a_chain->callback_datums_pool_proc_with_group = s_chain_callback_datums_pool_proc_with_group;
+    a_chain->callback_add_datums = s_chain_callback_datums_pool_proc;
+    a_chain->callback_add_datums_with_group = s_chain_callback_datums_pool_proc_with_group;
 
     // Linear pass through
     a_chain->callback_atom_iter_get_first = s_chain_callback_atom_iter_get_first; // Get the fisrt element from chain
@@ -258,23 +262,17 @@ const char* dap_chain_gdb_get_group(dap_chain_t * a_chain)
  *
  * return 0 if OK otherwise  negative error code
  */
-static int dap_chain_gdb_ledger_load(dap_chain_gdb_t *a_gdb, dap_chain_net_t *a_net)
+int dap_chain_gdb_ledger_load(char *a_gdb_group, dap_chain_t *a_chain)
 {
-    dap_chain_gdb_private_t *l_gdb_priv = PVT(a_gdb);
-    // protect from reloading
-    if(dap_chain_ledger_count( a_net->pub.ledger ) > 0)
-        return 0;
-
     size_t l_data_size = 0;
-
-
     //  Read the entire database into an array of size bytes
-    dap_global_db_obj_t *data = dap_chain_global_db_gr_load(l_gdb_priv->group_datums , &l_data_size);
+    dap_global_db_obj_t *data = dap_chain_global_db_gr_load(a_gdb_group, &l_data_size);
     // make list of datums
     for(size_t i = 0; i < l_data_size; i++) {
-        s_chain_callback_atom_add(a_gdb->chain,data[i].value, data[i].value_len);
+        s_chain_callback_atom_add(a_chain, data[i].value, data[i].value_len);
     }
     dap_chain_global_db_objs_delete(data, l_data_size);
+    PVT(DAP_CHAIN_GDB(a_chain))->is_load_mode = false;
     return 0;
 }
 
@@ -321,11 +319,11 @@ static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_cha
     switch (l_datum->header.type_id) {
         case DAP_CHAIN_DATUM_TOKEN_DECL:{
             dap_chain_datum_token_t *l_token = (dap_chain_datum_token_t*) l_datum->data;
-            dap_chain_ledger_token_add(a_chain->ledger,l_token, l_datum->header.data_size);
+            dap_chain_ledger_token_load(a_chain->ledger,l_token, l_datum->header.data_size);
         }break;
         case DAP_CHAIN_DATUM_TOKEN_EMISSION: {
             dap_chain_datum_token_emission_t *l_token_emission = (dap_chain_datum_token_emission_t*) l_datum->data;
-            dap_chain_ledger_token_emission_add(a_chain->ledger, l_token_emission, l_datum->header.data_size);
+            dap_chain_ledger_token_emission_load(a_chain->ledger, l_token_emission, l_datum->header.data_size);
         }break;
         case DAP_CHAIN_DATUM_TX:{
             dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t*) l_datum->data;
@@ -334,7 +332,7 @@ static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_cha
             //if(dap_chain_datum_tx_get_size(l_tx) == l_datum->header.data_size){
 
             // don't save bad transactions to base
-            if(dap_chain_ledger_tx_add(a_chain->ledger, l_tx) != 1)
+            if(dap_chain_ledger_tx_load(a_chain->ledger, l_tx) != 1)
                 return ATOM_REJECT;
             //}else
             //    return -2;
diff --git a/modules/consensus/none/include/dap_chain_cs_none.h b/modules/consensus/none/include/dap_chain_cs_none.h
index e40ae2184e63b48f74f699755053ed77c5420eb5..adf5cd6f0082c2239fd221d6c976fc6e74d60f31 100644
--- a/modules/consensus/none/include/dap_chain_cs_none.h
+++ b/modules/consensus/none/include/dap_chain_cs_none.h
@@ -39,4 +39,4 @@ int dap_chain_gdb_init(void);
 int dap_chain_gdb_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg);
 void dap_chain_gdb_delete(dap_chain_t * a_chain);
 const char* dap_chain_gdb_get_group(dap_chain_t * a_chain);
-
+int dap_chain_gdb_ledger_load(char *a_gdb_group, dap_chain_t *a_chain);
diff --git a/modules/mempool/dap_chain_mempool.c b/modules/mempool/dap_chain_mempool.c
index c5150e1cfd84094cb2abaee51480592e0c446545..b74867c4a7a55d236152bd947ca05eecd3ae44a7 100644
--- a/modules/mempool/dap_chain_mempool.c
+++ b/modules/mempool/dap_chain_mempool.c
@@ -568,7 +568,7 @@ dap_chain_hash_fast_t* dap_chain_proc_tx_create_cond(dap_chain_net_t * a_net,
 
     if(!l_datum)
         return NULL;
-    size_t l_datums_number = l_chain->callback_datums_pool_proc(l_chain, &l_datum, 1);
+    size_t l_datums_number = l_chain->callback_add_datums(l_chain, &l_datum, 1);
     if(!l_datums_number)
             return NULL;
 
diff --git a/modules/net/CMakeLists.txt b/modules/net/CMakeLists.txt
index e5d055725660d5a26b7aa656d5037c7616204d48..104d304db2ca5a35ca2cb8e215b77affb1e62b30 100644
--- a/modules/net/CMakeLists.txt
+++ b/modules/net/CMakeLists.txt
@@ -40,12 +40,12 @@ add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_NET_SRCS} ${DAP_CHAIN_NET_HEADERS
 
 if(WIN32)
   target_link_libraries(dap_chain_net dap_core dap_crypto dap_client dap_stream_ch_chain dap_stream_ch_chain_net dap_stream_ch_chain_net_srv dap_chain dap_chain_crypto dap_chain_wallet dap_chain_net_srv
-                            dap_chain_mempool dap_chain_global_db dap_chain_net_srv_stake)
+                            dap_chain_mempool dap_chain_global_db dap_chain_net_srv_stake dap_chain_cs_none)
 endif()
 
 if(UNIX)
     target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_client dap_stream_ch_chain dap_stream_ch_chain_net dap_stream_ch_chain_net_srv dap_chain
-      dap_chain_wallet dap_chain_net_srv dap_chain_mempool dap_chain_global_db dap_chain_net_srv_stake
+      dap_chain_wallet dap_chain_net_srv dap_chain_mempool dap_chain_global_db dap_chain_net_srv_stake dap_chain_cs_none
       resolv
       )
 endif()
diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c
index 10061b1e3eedd8f138ae46c1ea0919f6b0d59187..567229f2ef4811d02c137fdb6f4f66e198e37e97 100644
--- a/modules/net/dap_chain_net.c
+++ b/modules/net/dap_chain_net.c
@@ -67,10 +67,12 @@
 #include "dap_enc_http.h"
 #include "dap_chain_common.h"
 #include "dap_chain_net.h"
+#include "dap_chain_pvt.h"
 #include "dap_chain_node_client.h"
 #include "dap_chain_node_cli.h"
 #include "dap_chain_node_cli_cmd.h"
 #include "dap_chain_ledger.h"
+#include "dap_chain_cs_none.h"
 
 #include "dap_chain_global_db.h"
 #include "dap_chain_global_db_remote.h"
@@ -889,7 +891,8 @@ int dap_chain_net_init()
             "\tPrint list of authority cetificates from GDB group\n"
         "net -net <chain net name> ca del -hash <cert hash> [-H hex|base58(default)]\n"
             "\tDelete certificate from list of authority cetificates in GDB group by it's hash\n"
-                                        );
+        "net -net <chain net name> ledger reload\n"
+            "\tPurge the cache of chain net ledger and recalculate it from chain file\n"                                        );
     s_seed_mode = dap_config_get_item_bool_default(g_config,"general","seed_mode",false);
     dap_chain_global_db_add_history_group_prefix("global", GROUP_LOCAL_HISTORY);
 
@@ -1028,12 +1031,14 @@ static int s_cli_net( int argc, char **argv, void *arg_func, char **a_str_reply)
         const char *l_get_str = NULL;
         const char *l_stats_str = NULL;
         const char *l_ca_str = NULL;
+        const char *l_ledger_str = NULL;
         dap_chain_node_cli_find_option_val(argv, arg_index, argc, "sync", &l_sync_str);
         dap_chain_node_cli_find_option_val(argv, arg_index, argc, "link", &l_links_str);
         dap_chain_node_cli_find_option_val(argv, arg_index, argc, "go", &l_go_str);
         dap_chain_node_cli_find_option_val(argv, arg_index, argc, "get", &l_get_str);
         dap_chain_node_cli_find_option_val(argv, arg_index, argc, "stats", &l_stats_str);
         dap_chain_node_cli_find_option_val(argv, arg_index, argc, "ca", &l_ca_str);
+        dap_chain_node_cli_find_option_val(argv, arg_index, argc, "ledger", &l_ledger_str);
 
         if ( l_stats_str ){
             if ( strcmp(l_stats_str,"tx") == 0 ) {
@@ -1269,6 +1274,19 @@ static int s_cli_net( int argc, char **argv, void *arg_func, char **a_str_reply)
                                                   "Subcommand \"ca\" requires one of parameter: add, list, del\n");
                 ret = -5;
             }
+        } else if (l_ledger_str && !strcmp(l_ledger_str, "reload")) {
+            dap_chain_ledger_purge(l_net->pub.ledger);
+            dap_chain_t *l_chain;
+            DL_FOREACH(l_net->pub.chains, l_chain) {
+                if (l_chain->callback_purge) {
+                    l_chain->callback_purge(l_chain);
+                }
+                if (!strcmp(DAP_CHAIN_PVT(l_chain)->cs_name, "none")) {
+                    dap_chain_gdb_ledger_load((char *)dap_chain_gdb_get_group(l_chain), l_chain);
+                } else {
+                    dap_chain_load_all(l_chain);
+                }
+            }
         } else {
             dap_chain_node_cli_set_reply_text(a_str_reply,"Command requires one of subcomand: sync, links\n");
             ret = -1;
@@ -1405,7 +1423,7 @@ int s_net_load(const char * a_net_name, uint16_t a_acl_idx)
                 l_ledger_flags |= DAP_CHAIN_LEDGER_CHECK_LOCAL_DS;
         }
         // init LEDGER model
-        l_net->pub.ledger = dap_chain_ledger_create(l_ledger_flags);
+        l_net->pub.ledger = dap_chain_ledger_create(l_ledger_flags, l_net->pub.name);
         // Check if seed nodes are present in local db alias
         char **l_seed_aliases = dap_config_get_array_str( l_cfg , "general" ,"seed_nodes_aliases"
                                                              ,&PVT(l_net)->seed_aliases_count);
@@ -2099,7 +2117,7 @@ void dap_chain_net_proc_mempool (dap_chain_net_t * a_net)
                     }
                 }
             }
-            size_t l_objs_processed = l_chain->callback_datums_pool_proc(l_chain, l_datums, l_datums_size);
+            size_t l_objs_processed = l_chain->callback_add_datums(l_chain, l_datums, l_datums_size);
             // Delete processed objects
             size_t l_objs_processed_tmp = (l_objs_processed > 15) ? min(l_objs_processed, 10) : l_objs_processed;
             for(size_t i = 0; i < l_objs_processed; i++) {
diff --git a/modules/net/dap_chain_node.c b/modules/net/dap_chain_node.c
index 22484d478b6ae9870866abafc8c1b1719b48faba..a27bb9a8bde60d52cbd5d593efc48594ed1ea698 100644
--- a/modules/net/dap_chain_node.c
+++ b/modules/net/dap_chain_node.c
@@ -260,7 +260,7 @@ bool dap_chain_node_mempool_process(dap_chain_t *a_chain, dap_chain_node_role_t
             }
         }
     }
-    if (a_chain->callback_datums_pool_proc(a_chain, &a_datum, 1) != 1) {
+    if (a_chain->callback_add_datums(a_chain, &a_datum, 1) != 1) {
         return false;
     }
     return true;
diff --git a/modules/net/dap_chain_node_cli.c b/modules/net/dap_chain_node_cli.c
index 405fdedcdf7b9a4c59276ed65765734de7859c1e..4628c7a4d1aa98078fdfd1d9f79ed1f812af44ef 100644
--- a/modules/net/dap_chain_node_cli.c
+++ b/modules/net/dap_chain_node_cli.c
@@ -679,6 +679,32 @@ void dap_chain_node_cli_set_reply_text(char **str_reply, const char *str, ...)
     }
 }
 
+/**
+ * @brief dap_chain_node_cli_check_option
+ * @param argv
+ * @param arg_start
+ * @param arg_end
+ * @param opt_name
+ * @return
+ */
+int dap_chain_node_cli_check_option( char** argv, int arg_start, int arg_end, const char *opt_name)
+{
+    int arg_index = arg_start;
+    const char *arg_string;
+
+    while(arg_index < arg_end)
+    {
+        char * l_argv_cur = argv[arg_index];
+        arg_string = l_argv_cur;
+        // find opt_name
+        if(arg_string && opt_name && arg_string[0] && opt_name[0] && !strcmp(arg_string, opt_name)) {
+                return arg_index;
+        }
+        arg_index++;
+    }
+    return -1;
+}
+
 /**
  * find option value
  *
diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c
index 6c3f58918094a1439dc9d335ea7d3d682f56caec..c74f2a5ef470007ee523c993ba52fd39675b02f7 100644
--- a/modules/net/dap_chain_node_cli_cmd.c
+++ b/modules/net/dap_chain_node_cli_cmd.c
@@ -2245,8 +2245,8 @@ int com_mempool_proc(int argc, char ** argv, void *arg_func, char ** a_str_reply
                                              l_verify_datum);
                     ret = -9;
                 }else{
-                    if (l_chain->callback_datums_pool_proc){
-                        if (l_chain->callback_datums_pool_proc(l_chain, &l_datum, 1) ==0 ){
+                    if (l_chain->callback_add_datums){
+                        if (l_chain->callback_add_datums(l_chain, &l_datum, 1) ==0 ){
                             dap_string_append_printf(l_str_tmp, "Error! Datum doesn't pass verifications, examine node log files");
                             ret = -6;
                         }else{
diff --git a/modules/net/include/dap_chain_node_cli.h b/modules/net/include/dap_chain_node_cli.h
index e9f9e81285841034f5426920590532760acabcd3..f67aca3a3f0b0f945829720de690ea31e12d15a3 100644
--- a/modules/net/include/dap_chain_node_cli.h
+++ b/modules/net/include/dap_chain_node_cli.h
@@ -73,6 +73,7 @@ void dap_chain_node_cli_cmd_item_apply_overrides(const char * a_name, const dap_
 void dap_chain_node_cli_set_reply_text(char **str_reply, const char *str, ...);
 
 int dap_chain_node_cli_find_option_val( char** argv, int arg_start, int arg_end, const char *opt_name, const char **opt_value);
+int dap_chain_node_cli_check_option( char** argv, int arg_start, int arg_end, const char *opt_name);
 
 
 /**
diff --git a/modules/net/srv/dap_chain_net_srv_order.c b/modules/net/srv/dap_chain_net_srv_order.c
index 8aba700a30215b038b580b8d0ee49744bd6684e3..869461dc4f5340562c2a40ee97251d6fa451f224 100644
--- a/modules/net/srv/dap_chain_net_srv_order.c
+++ b/modules/net/srv/dap_chain_net_srv_order.c
@@ -524,17 +524,17 @@ static void s_srv_order_callback_notify(void *a_arg, const char a_op_code, const
     if (!strcmp(a_group, l_gdb_group_str)) {
         dap_chain_net_srv_order_t *l_order = (dap_chain_net_srv_order_t *)a_value;
         if (l_order->version == 1) {
-            dap_chain_global_db_gr_del((char *)a_key, a_group);
+            dap_chain_global_db_gr_del(dap_strdup(a_key), a_group);
         } else {
             dap_sign_t *l_sign = (dap_sign_t *)&l_order->ext[l_order->ext_size];
             if (!dap_sign_verify(l_sign, l_order, sizeof(dap_chain_net_srv_order_t) + l_order->ext_size)) {
-                dap_chain_global_db_gr_del((char *)a_key, a_group);
+                dap_chain_global_db_gr_del(dap_strdup(a_key), a_group);
                 DAP_DELETE(l_gdb_group_str);
                 return;
             }
             dap_chain_hash_fast_t l_pkey_hash;
             if (!dap_sign_get_pkey_hash(l_sign, &l_pkey_hash)) {
-                dap_chain_global_db_gr_del((char *)a_key, a_group);
+                dap_chain_global_db_gr_del(dap_strdup(a_key), a_group);
                 DAP_DELETE(l_gdb_group_str);
                 return;
             }
@@ -542,7 +542,7 @@ static void s_srv_order_callback_notify(void *a_arg, const char a_op_code, const
             dap_chain_addr_fill(&l_addr, l_sign->header.type, &l_pkey_hash, l_net->pub.id);
             uint64_t l_solvency = dap_chain_ledger_calc_balance(l_net->pub.ledger, &l_addr, l_order->price_ticker);
             if (l_solvency < l_order->price && !dap_chain_net_srv_stake_key_delegated(&l_addr)) {
-                dap_chain_global_db_gr_del((char *)a_key, a_group);
+                dap_chain_global_db_gr_del(dap_strdup(a_key), a_group);
             }
         }
         DAP_DELETE(l_gdb_group_str);
diff --git a/modules/service/vpn/dap_chain_net_srv_vpn.c b/modules/service/vpn/dap_chain_net_srv_vpn.c
index aaf563d863221a664b0a72364784bf60975043ec..4041396e1503f092f573f3cdd1c8bd821902e32a 100644
--- a/modules/service/vpn/dap_chain_net_srv_vpn.c
+++ b/modules/service/vpn/dap_chain_net_srv_vpn.c
@@ -69,6 +69,8 @@
 #include "dap_chain_net_srv_stream_session.h"
 #include "dap_chain_net_vpn_client.h"
 #include "dap_chain_net_vpn_client_tun.h"
+#include "dap_chain_net_srv_vpn_cmd.h"
+#include "dap_chain_node_cli.h"
 #include "dap_chain_ledger.h"
 #include "dap_events.h"
 
@@ -769,6 +771,10 @@ int dap_chain_net_srv_vpn_init(dap_config_t * g_config) {
     dap_stream_ch_proc_add(DAP_STREAM_CH_ID_NET_SRV_VPN, s_ch_vpn_new, s_ch_vpn_delete, s_ch_packet_in,
             s_ch_packet_out);
 
+    // add console command to display vpn statistics
+    dap_chain_node_cli_cmd_item_create ("vpn_stat", com_vpn_statistics, NULL, "VPN statistics",
+            "vpn_stat -net <net name> [-full]\n"
+            );
     return 0;
 }
 
@@ -934,9 +940,9 @@ void s_ch_vpn_new(dap_stream_ch_t* a_ch, void* a_arg)
  * @param ch
  * @param arg
  */
-void s_ch_vpn_delete(dap_stream_ch_t* ch, void* arg)
+void s_ch_vpn_delete(dap_stream_ch_t* a_ch, void* arg)
 {
-    dap_chain_net_srv_ch_vpn_t * l_ch_vpn = CH_VPN(ch);
+    dap_chain_net_srv_ch_vpn_t * l_ch_vpn = CH_VPN(a_ch);
     dap_chain_net_srv_vpn_t * l_srv_vpn =(dap_chain_net_srv_vpn_t *) l_ch_vpn->net_srv->_inhertor;
 
 
diff --git a/modules/service/vpn/dap_chain_net_srv_vpn_cmd.c b/modules/service/vpn/dap_chain_net_srv_vpn_cmd.c
index d676903d06a3d87c6d0dbd4f3930ba43bb5feee3..59d99cc44cdfb95f965756b980cfc2872276b2f5 100644
--- a/modules/service/vpn/dap_chain_net_srv_vpn_cmd.c
+++ b/modules/service/vpn/dap_chain_net_srv_vpn_cmd.c
@@ -1,8 +1,95 @@
-#include <dap_chain_node_cli.h>
+#include "dap_common.h"
+#include "dap_chain_node_cli.h"
 #include "dap_chain_node_cli_cmd.h"
 #include "dap_chain_net_srv_vpn_cmd.h"
 #include "dap_chain_net_vpn_client.h"
 
+
+static char* get_value_text(uintmax_t a_value)
+{
+    if(a_value < 2048)
+        return dap_strdup_printf("%d bytes", a_value);
+    else if(a_value < 2048 * 1024)
+        return dap_strdup_printf("%.2lf Kb", (double) a_value / 1024);
+    else if(a_value < 2048ll * 1024 * 1024)
+        return dap_strdup_printf("%.2lf Mb", (double) a_value / (1024 * 1024));
+    else if(a_value < 2048ll * 1024 * 1024 * 1024)
+        return dap_strdup_printf("%.2lf Gb", (double) a_value / (1024 * 1024 * 1024));
+    return dap_strdup_printf("%.2lf Tb", (double) a_value / (1024ll * 1024 * 1024 * 1024));
+}
+
+static void add_value_text(dap_string_t *l_str, char *l_addstr, uintmax_t a_value)
+{
+    char *l_str_val = get_value_text(a_value);
+    dap_string_append_printf(l_str, "%s.%s\n", l_addstr, l_str_val);
+    DAP_DELETE(l_str_val);
+}
+#include <arpa/inet.h>
+/**
+ * vpn_client command
+ *
+ * VPN statistics
+ */
+int com_vpn_statistics(int a_argc, char ** a_argv, void *arg_func, char **a_str_reply)
+{
+    dap_stream_ch_t* a_ch;
+    dap_stream_t * stream;
+    dap_stream_session_t * session;
+    // get statistics for all actual sessions
+    dap_list_t *l_list = dap_stream_session_get_list_sessions();
+    dap_string_t *l_str = dap_string_new(NULL);
+    int l_conn = 0;
+    // display statistic for all sessions
+    while(l_list) {
+        dap_stream_session_t * l_session = (dap_stream_session_t*) l_list->data;
+        dap_chain_net_srv_stream_session_t * l_srv_str_session = l_session->_inheritor;
+        if(l_srv_str_session) {
+            dap_net_stats_t l_stats = l_srv_str_session->stats; //(dap_net_stats_t*) l_list;
+            dap_string_append_printf(l_str, "VPN connection %d\n", l_conn);
+            l_conn++;
+            // time start/length
+            time_t l_time_len_sec = time(NULL) - l_session->time_created;
+            char l_buf[1024];
+            if(dap_time_to_str_rfc822(l_buf, sizeof(l_buf), l_session->time_created) > 0)
+                dap_string_append_printf(l_str, "  start at %s (length %02d:%02d:%02d)\n", l_buf,
+                        l_time_len_sec / 3600, (l_time_len_sec % 3600) / 60, l_time_len_sec % 60);
+            // client ip
+            const int l_tun_client_addr_str_len = 128;
+            char *l_tun_client_addr_str = DAP_NEW_S_SIZE(char, l_tun_client_addr_str_len);
+            if(inet_ntop(AF_INET, &(l_session->tun_client_addr), l_tun_client_addr_str, l_tun_client_addr_str_len))
+                dap_string_append_printf(l_str, "  client addr........%s\n", l_tun_client_addr_str);
+            else
+                dap_string_append(l_str, "  client addr........???\n");
+            add_value_text(l_str, "  recv..............", l_stats.bytes_recv);
+            add_value_text(l_str, "  recv lost.........", l_stats.bytes_recv_lost);
+            add_value_text(l_str, "  send..............", l_stats.bytes_sent);
+            add_value_text(l_str, "  send lost.........", l_stats.bytes_sent_lost);
+            dap_string_append_printf(l_str, "  packets recv.......%d\n", l_stats.packets_recv);
+            dap_string_append_printf(l_str, "  packets recv lost..%d\n", l_stats.packets_recv_lost);
+            dap_string_append_printf(l_str, "  packets send.......%d\n", l_stats.packets_sent);
+            dap_string_append_printf(l_str, "  packets send lost..%d\n", l_stats.packets_sent_lost);
+            // average bitrate
+            double l_bitrate = (l_stats.bytes_recv - l_stats.bytes_recv_lost +
+                    l_stats.bytes_sent - l_stats.bytes_sent_lost) * 1. / l_time_len_sec;
+            dap_string_append_printf(l_str, "  average bitrate....%.2lf kbps\n", l_bitrate / 1024.);
+            // not add line break after last session
+            if(l_list->next)
+                dap_string_append_printf(l_str, "\n");
+        }
+        // next session
+        l_list = dap_list_next(l_list);
+    }
+    // unlock sessions list
+    dap_stream_session_get_list_sessions_unlock();
+    if(l_conn>0)
+        dap_chain_node_cli_set_reply_text(a_str_reply, l_str->str);
+    else
+        dap_chain_node_cli_set_reply_text(a_str_reply, "No VPN connections");
+    // free tmp memory
+    dap_string_free(l_str, true);
+    return 0;
+}
+
 /**
  * vpn_client command
  *
diff --git a/modules/service/vpn/dap_chain_net_srv_vpn_cmd.h b/modules/service/vpn/dap_chain_net_srv_vpn_cmd.h
index 4ce2243e8703bc14aa9ead66b5120f38562e8b00..0a70e7791c640db79c8f12b506425c10efa1bdbe 100644
--- a/modules/service/vpn/dap_chain_net_srv_vpn_cmd.h
+++ b/modules/service/vpn/dap_chain_net_srv_vpn_cmd.h
@@ -1,4 +1,6 @@
 #pragma once
 
+//  VPN statistics
+int com_vpn_statistics(int a_argc, char ** a_argv, void *arg_func, char **a_str_reply);
 // vpn_client command
 int com_vpn_client(int a_argc, char ** a_argv, void *arg_func, char **a_str_reply);
diff --git a/modules/service/xchange/dap_chain_net_srv_xchange.c b/modules/service/xchange/dap_chain_net_srv_xchange.c
index b7bd5071492e047932395300fca186099c49d41c..6336a366903b8bb6b989257ab085598fd4846351 100644
--- a/modules/service/xchange/dap_chain_net_srv_xchange.c
+++ b/modules/service/xchange/dap_chain_net_srv_xchange.c
@@ -653,7 +653,6 @@ static int s_cli_srv_xchange_price(int a_argc, char **a_argv, int a_arg_index, c
                 }
                 DAP_DELETE(l_order_hash_str);
                 DAP_DELETE(l_price->wallet_str);
-                DAP_DELETE(l_price->key_ptr);
                 DAP_DELETE(l_price);
                 if (!l_str_reply->len) {
                     dap_string_append(l_str_reply, "Price successfully removed");
@@ -715,7 +714,7 @@ static int s_cli_srv_xchange_price(int a_argc, char **a_argv, int a_arg_index, c
                     return -14;
                 }
                 HASH_DEL(s_srv_xchange->pricelist, l_price);
-                dap_chain_global_db_gr_del(l_price->key_ptr, GROUP_LOCAL_XCHANGE);
+                dap_chain_global_db_gr_del(dap_strdup(l_price->key_ptr), GROUP_LOCAL_XCHANGE);
                 bool l_ret = s_xchage_tx_invalidate(l_price, l_wallet); // may be changed to old price later
                 dap_chain_wallet_close(l_wallet);
                 if (!l_ret) {
diff --git a/modules/type/block/dap_chain_block.c b/modules/type/block/dap_chain_block.c
deleted file mode 100644
index 9fce5b10c9aefc2e9eef2d51cc13ab0c77e48f91..0000000000000000000000000000000000000000
--- a/modules/type/block/dap_chain_block.c
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Authors:
- * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net>
- * DeM Labs Inc.   https://demlabs.net
- * Kelvin Project https://github.com/kelvinblockchain
- * Copyright  (c) 2017-2018
- * All rights reserved.
-
- This file is part of DAP (Deus Applications Prototypes) the open source project
-
-    DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    DAP is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "string.h"
-#include "dap_common.h"
-
-#include "dap_chain_block.h"
-
-#define LOG_TAG "dap_chain_block"
-
-/**
- * @brief dap_chain_block_init
- * @return
- */
-int dap_chain_block_init()
-{
-    return 0;
-}
-
-/**
- * @brief dap_chain_block_deinit
- */
-void dap_chain_block_deinit()
-{
-
-}
-
-
-/**
- * @brief dap_chain_block_new
- * @param a_prev_block
- * @return
- */
-dap_chain_block_t * dap_chain_block_new(dap_chain_hash_t * a_prev_block )
-{
-    dap_chain_block_t * l_block = DAP_NEW_Z_SIZE (dap_chain_block_t,sizeof(l_block->header));
-    if( l_block == NULL){
-        log_it(L_CRITICAL, "Can't allocate memory for the new block");
-        return NULL;
-    }else{
-        l_block->header.signature = DAP_CHAIN_BLOCK_SIGNATURE;
-        l_block->header.version = 1;
-        l_block->header.timestamp = time(NULL);
-        if( a_prev_block ){
-            memcpy(&l_block->header.prev_block,a_prev_block,sizeof(l_block->header.prev_block));
-        }else{
-            log_it(L_INFO, "Genesis block produced");
-            memset(&l_block->header.prev_block,0xff,sizeof(l_block->header.prev_block));
-        }
-
-        l_block->header.size = sizeof(l_block->header);
-        return l_block;
-    }
-}
-
-/**
- * @brief dap_chain_block_create_section
- * @param a_block
- * @param a_section_type
- * @param a_section_data_size
- * @return
- */
-dap_chain_datum_t * dap_chain_block_create_section(dap_chain_block_t * a_block, uint32_t a_section_offset,
-                                                     uint16_t a_section_type, uint32_t a_section_data_size )
-{
-    if ( a_block) {
-        uint32_t l_sections_size = ( a_block->header.size - sizeof(a_block->header) );
-        if(   l_sections_size > a_section_offset ){
-            if( l_sections_size > (a_section_offset + a_section_data_size ) ) {
-                dap_chain_datum_t * l_section = (dap_chain_datum_t *) ( a_block->datums +a_section_offset) ;
-                l_section->header.type_id = a_section_type;
-                return l_section;
-            }else{
-                log_it(L_ERROR, "Section data size %lu is bigger then left for sections in block (%lu)"
-                       ,a_section_data_size,l_sections_size - a_section_offset );
-                return NULL;
-            }
-        }else{
-            log_it(L_ERROR, "Section offset %lu is bigger then section size %lu",a_section_offset,l_sections_size);
-            return NULL;
-        }
-    }else{
-        log_it(L_ERROR, "Block is NULL");
-        return NULL;
-    }
-}
-
diff --git a/modules/type/block/dap_chain_block_cache.c b/modules/type/block/dap_chain_block_cache.c
deleted file mode 100644
index e8e7004b2eaa208d212a1cdfa169c5038eddee48..0000000000000000000000000000000000000000
--- a/modules/type/block/dap_chain_block_cache.c
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Authors:
- * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net>
- * DeM Labs Inc.   https://demlabs.net
- * Kelvin Project https://github.com/kelvinblockchain
- * Copyright  (c) 2017-2018
- * All rights reserved.
-
- This file is part of DAP (Deus Applications Prototypes) the open source project
-
-    DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    DAP is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
-*/
-#include <stdlib.h>
-#include <time.h>
-#include "dap_common.h"
-#include "dap_chain_block_cache.h"
-#include "dap_chain_datum_coin.h"
-#include "dap_chain_datum_tx.h"
-#include "dap_chain_datum_tx_in.h"
-#include "dap_chain_datum_tx_out.h"
-
-#define LOG_TAG "dap_chain_block_cache"
-
-dap_chain_block_cache_t * dap_chain_block_cache_new(dap_chain_block_t * a_block)
-{
-    dap_chain_block_cache_t * l_block_cache = DAP_NEW_Z(dap_chain_block_cache_t);
-    l_block_cache->block = a_block;
-    log_it(L_DEBUG,"Block cache created");
-    return l_block_cache;
-}
-
-/**
- * @brief dap_chain_block_cache_delete
- * @param a_block
- */
-void dap_chain_block_cache_delete(dap_chain_block_cache_t * a_block_cache)
-{
-    DAP_DELETE(a_block_cache);
-    log_it(L_DEBUG,"Block cache deleted");
-}
-
-/**
- * @brief dap_chain_block_cache_dump
- * @param a_block_cache
- */
-void dap_chain_block_cache_dump(dap_chain_block_cache_t * a_block_cache)
-{
-    if ( a_block_cache ) {
-        dap_chain_block_t * l_block = a_block_cache->block;
-        if( l_block ){
-            char * l_hash_str = dap_chain_hash_to_str_new(&a_block_cache->block_hash);
-            char * l_prev_hash_str = dap_chain_hash_to_str_new(&l_block->header.prev_block);
-            char * l_root_sections_str = dap_chain_hash_to_str_new(&l_block->header.root_sections);
-            log_it(L_INFO, "  **  block_hash        %s",l_hash_str);
-            log_it(L_INFO, "  **    version         %d",l_block->header.version);
-            log_it(L_INFO, "  **    timestamp       %s",  ctime(  (time_t*) &l_block->header.timestamp) );
-            log_it(L_INFO, "  **    difficulty      %llu",l_block->header.difficulty);
-            log_it(L_INFO, "  **    nonce           %llu",l_block->header.nonce);
-            log_it(L_INFO, "  **    prev_block      %s",l_prev_hash_str);
-            log_it(L_INFO, "  **    root_sections   %s",l_root_sections_str  );
-            log_it(L_INFO, "  **    size           %u",l_block->header.size);
-            log_it(L_INFO, "  **    sections[]");
-            DAP_DELETE(l_hash_str);
-            DAP_DELETE(l_prev_hash_str);
-
-            size_t i, l_sections_size = l_block->header.size - sizeof(l_block->header);
-            for( i = 0; i< l_sections_size; i++ ){
-                dap_chain_datum_t * l_datum = (dap_chain_datum_t *) (l_block->datums + i);
-                switch ( l_datum->header.type_id  ) {
-                    case DAP_CHAIN_DATUM_TX:{
-                        dap_chain_datum_tx_t * l_tx = (dap_chain_datum_tx_t *) l_datum->data;
-                        log_it(L_INFO, "  **      tx");
-                        log_it(L_INFO, "  **          lock_time       %s", l_tx->header.lock_time?
-                                   ctime( (time_t *) &l_tx->header.lock_time ) : "0x0000000000000000" );
-                        log_it(L_INFO, "  **          tx_items_size   %u ",l_tx->header.tx_items_size);
-                        /*uint32_t l_data_offset;
-                        for ( l_data_offset = 0; l_data_offset < l_tx->header.tx_items_size; ++l_data_offset  ){
-
-                        }*/
-                        i += sizeof (l_tx->header);
-                        i += l_tx->header.tx_items_size ;
-                    }break;
-                    default:
-                        i = l_sections_size;
-                }
-            }
-        }else{
-            log_it(L_ERROR,"block in block cache for dump is NULL");
-        }
-    }else{
-        log_it(L_ERROR,"block cache for dump is NULL");
-    }
-
-}
-
-/**
- * @brief dap_chain_block_cache_sections_size_grow
- * @param a_block_cache
- * @param a_sections_size_grow
- */
-dap_chain_block_t* dap_chain_block_cache_sections_size_grow(dap_chain_block_cache_t * a_block_cache,size_t a_sections_size_grow )
-{
-    log_it(L_DEBUG,"Block section size reallocation: grow up +%lu",a_sections_size_grow);
-    a_block_cache->block->header.size += a_sections_size_grow;
-    a_block_cache->block=(dap_chain_block_t *) realloc(a_block_cache->block,a_block_cache->block->header.size );
-    if( a_block_cache->block ){
-        a_block_cache->sections_size += a_sections_size_grow;
-        return a_block_cache->block;
-    }else{
-        log_it(L_ERROR, "Can't reallocate block!");
-        return NULL;
-    }
-}
-
diff --git a/modules/type/block/dap_chain_cs_blocks.c b/modules/type/block/dap_chain_cs_blocks.c
deleted file mode 100644
index d997e54ae2604dd7a60794f5c9cfa5454908da60..0000000000000000000000000000000000000000
--- a/modules/type/block/dap_chain_cs_blocks.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Authors:
- * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net>
- * DeM Labs Inc.   https://demlabs.net
- * Kelvin Project https://github.com/kelvinblockchain
- * Copyright  (c) 2017-2018
- * All rights reserved.
-
- This file is part of DAP (Deus Applications Prototypes) the open source project
-
-    DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    DAP is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
-*/
-#include "dap_common.h"
-#include "dap_chain_cs_blocks.h"
-#include "dap_chain_block.h"
-#include "dap_chain_block_cache.h"
-
-#define LOG_TAG "dap_chain_cs_blocks"
-
-typedef struct dap_chain_cs_blocks_pvt
-{
-    dap_chain_cs_blocks_t * blocks;
-
-    dap_chain_block_cache_t * block_cache_first; // Mapped area start
-    dap_chain_block_cache_t * block_cache_last; // Last block in mapped area
-    uint64_t blocks_count;
-    uint64_t difficulty;
-
-} dap_chain_cs_blocks_pvt_t;
-
-
-#define PVT(a) ((dap_chain_cs_blocks_pvt_t *) a->_pvt )
-
-
-/**
- * @brief dap_chain_cs_blocks_init
- * @return
- */
-int dap_chain_cs_blocks_init()
-{
-    return 0;
-}
-
-/**
- * @brief dap_chain_cs_blocks_deinit
- */
-void dap_chain_cs_blocks_deinit()
-{
-
-}
-
-dap_chain_block_cache_t* dap_chain_cs_blocks_allocate_next_block(dap_chain_cs_blocks_t * a_cs_blocks)
-{
-    dap_chain_block_t* l_block = NULL;
-    dap_chain_block_cache_t* l_block_cache = NULL;
-    if ( PVT(a_cs_blocks)->block_cache_last )
-        l_block = dap_chain_block_new( &PVT(a_cs_blocks)->block_cache_last->block_hash );
-    else
-        l_block = dap_chain_block_new( NULL );
-
-    if( l_block ){
-        l_block->header.difficulty = PVT(a_cs_blocks)->difficulty;
-        l_block_cache = dap_chain_block_cache_new(l_block);
-        return l_block_cache;
-    }else{
-        log_it(L_ERROR, "Can't allocate next block!");
-        return NULL;
-    }
-}
-
-
-
diff --git a/modules/type/block/include/dap_chain_block.h b/modules/type/block/include/dap_chain_block.h
deleted file mode 100644
index 18a81cc2cb2016ab2d7b4252fbdc6d7201540163..0000000000000000000000000000000000000000
--- a/modules/type/block/include/dap_chain_block.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Authors:
- * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net>
- * DeM Labs Inc.   https://demlabs.net
- * Kelvin Project https://github.com/kelvinblockchain
- * Copyright  (c) 2017-2018
- * All rights reserved.
-
- This file is part of DAP (Deus Applications Prototypes) the open source project
-
-    DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    DAP is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
-*/
-#pragma once
-#include <stdalign.h>
-#include <stdint.h>
-#include <stddef.h>
-#include "dap_common.h"
-#include "dap_math_ops.h"
-#include "dap_hash.h"
-#include "dap_chain_common.h"
-#include "dap_chain_datum.h"
-#include "dap_chain_datum_hashtree_roots.h"
-
-#define DAP_CHAIN_BLOCK_SIGNATURE 0xDA05BF8E
-
-#define DAP_CHAIN_BLOCK_ID_SIZE 4
-
-typedef union dap_chain_block_typeid{
-    uint8_t data[DAP_CHAIN_BLOCK_ID_SIZE];
-} DAP_ALIGN_PACKED dap_chain_block_typeid_t;
-
-/**
- * @brief The dap_chain_block struct
- */
-typedef struct  dap_chain_block{
-     struct block_header{
-        uint32_t signature; /// @param signature @brief Magic number, always equels to DAP_CHAIN_BLOCK_SIGNATURE
-        int32_t version; /// @param version @brief block version (be carefull, signed value, as Bitcoin has)
-        uint32_t size; /// @param size of the whole block
-        uint64_t timestamp; /// @param timestamp @brief Block create time timestamp
-        uint64_t difficulty; /// difficulty level
-        uint64_t nonce; /// Nonce value to allow header variation for mining
-        union{
-            struct{ // Zero-level block without sharding
-                dap_chain_hash_t prev_block; /// @param prev_block Hash of the previous block
-                dap_chain_hash_t padding0; //
-            uint32_t padding1; //
-            uint64_t padding2; // Always zero (should be well compresed)
-            };
-            struct{
-                dap_chain_hash_t prev_block_0lvl; /// @param prev_block Hash of the previous block
-                dap_chain_hash_t prev_block_shard; /// @param prev_block Hash of the previous block
-            uint32_t shard_id; // Shard id
-            uint64_t nonce2; // Second NonCE for block mining inside the shard
-            };
-        };
-        dap_chain_hash_t root_sections;/// @param root_main Main tree's root for all sections's hashes
-    } DAP_ALIGN_PACKED header;
-    uint8_t datums[]; // Sections
-} DAP_ALIGN_PACKED dap_chain_block_t;
-
-int dap_chain_block_init();
-void dap_chain_block_deinit();
-
-dap_chain_block_t * dap_chain_block_new(dap_chain_hash_t * a_prev_block );
-
-dap_chain_datum_t * dap_chain_block_create_section(dap_chain_block_t * a_block, uint32_t a_section_offset
-                                                     , uint16_t a_section_type, uint32_t a_section_data_size );
-
-
-/**
- * @brief dap_chain_block_calc_hash
- * @param a_block
- * @return
- */
-static inline void dap_chain_block_hash_calc(dap_chain_block_t * a_block, dap_chain_hash_t * a_hash){
-    dap_hash(a_block,a_block->header.size,a_hash->raw,
-             sizeof(a_hash->raw),DAP_HASH_TYPE_SLOW_0);
-}
-
diff --git a/modules/type/block/CMakeLists.txt b/modules/type/blocks/CMakeLists.txt
similarity index 62%
rename from modules/type/block/CMakeLists.txt
rename to modules/type/blocks/CMakeLists.txt
index d5b23c531ad189a996f19a98e6ecd220c96be294..38bae326446f2e224c1259f28dbcfffcadae35ba 100644
--- a/modules/type/block/CMakeLists.txt
+++ b/modules/type/blocks/CMakeLists.txt
@@ -1,5 +1,5 @@
 cmake_minimum_required(VERSION 2.8)
-project (dap_chain_cs_block)
+project (dap_chain_cs_blocks)
   
 file(GLOB DAP_CHAIN_BLOCK_SRCS *.c)
 file(GLOB DAP_CHAIN_BLOCK_HEADERS include/*.h)
@@ -7,6 +7,6 @@ file(GLOB DAP_CHAIN_BLOCK_HEADERS include/*.h)
 add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_BLOCK_SRCS} ${DAP_CHAIN_BLOCK_HEADERS})
 
 
-target_link_libraries(dap_chain_cs_block dap_core dap_crypto dap_chain )
-target_include_directories(dap_chain_cs_block INTERFACE .)
+target_link_libraries(dap_chain_cs_blocks dap_core dap_crypto dap_chain )
+target_include_directories(dap_chain_cs_blocks INTERFACE .)
 target_include_directories(${PROJECT_NAME} PUBLIC include)
diff --git a/modules/type/blocks/dap_chain_block.c b/modules/type/blocks/dap_chain_block.c
new file mode 100644
index 0000000000000000000000000000000000000000..daee181c47d5df5cd523fd53a34bc77176c9ea57
--- /dev/null
+++ b/modules/type/blocks/dap_chain_block.c
@@ -0,0 +1,99 @@
+/*
+ * Authors:
+ * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net>
+ * DeM Labs Ltd   https://demlabs.net
+ * Copyright  (c) 2017-2020
+ * All rights reserved.
+
+ This file is part of DAP SDK the open source project
+
+    DAP SDK is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    DAP SDK is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with any DAP SDK based project.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#include <stddef.h>
+#include "string.h"
+#include "dap_common.h"
+#include "dap_hash.h"
+
+#include "dap_chain_block.h"
+#include "dap_chain_block_cache.h"
+
+#define LOG_TAG "dap_chain_block"
+
+/**
+ * @brief dap_chain_block_init
+ * @return
+ */
+int dap_chain_block_init()
+{
+    return 0;
+}
+
+/**
+ * @brief dap_chain_block_deinit
+ */
+void dap_chain_block_deinit()
+{
+
+}
+
+
+/**
+ * @brief dap_chain_block_new
+ * @param a_prev_block
+ * @return
+ */
+dap_chain_block_t * dap_chain_block_new(dap_chain_hash_fast_t * a_prev_block )
+{
+    dap_chain_block_t * l_block = DAP_NEW_Z_SIZE (dap_chain_block_t,sizeof(l_block->hdr));
+    if( l_block == NULL){
+        log_it(L_CRITICAL, "Can't allocate memory for the new block");
+        return NULL;
+    }else{
+        l_block->hdr.signature = DAP_CHAIN_BLOCK_SIGNATURE;
+        l_block->hdr.version = 1;
+        l_block->hdr.ts_created = time(NULL);
+        size_t l_block_size = sizeof (l_block->hdr);
+        if( a_prev_block ){
+            l_block_size = dap_chain_block_meta_add(l_block, l_block_size, DAP_CHAIN_BLOCK_META_PREV,a_prev_block,sizeof (*a_prev_block) );
+        }else{
+            log_it(L_INFO, "Genesis block produced");
+        }
+        return l_block;
+    }
+
+
+}
+
+// Add metadata in block
+size_t dap_chain_block_meta_add(dap_chain_block_t * a_block, size_t a_block_size, uint8_t a_meta_type, const void * a_data, size_t a_data_size)
+{
+    return a_block_size;
+}
+
+
+size_t dap_chain_block_datum_add(dap_chain_block_t * a_block, size_t a_block_size, dap_chain_datum_t * a_datum, size_t a_datum_size)
+{
+    if ( a_block) {
+        //
+    }else{
+        log_it(L_ERROR, "Block is NULL");
+        return a_block_size;
+    }
+}
+
+size_t dap_chain_block_datum_del_by_hash(dap_chain_block_t * a_block, size_t a_block_size, dap_chain_hash_fast_t* a_datum_hash)
+{
+    return a_block_size;
+}
+
diff --git a/modules/type/blocks/dap_chain_block_cache.c b/modules/type/blocks/dap_chain_block_cache.c
new file mode 100644
index 0000000000000000000000000000000000000000..cf55de237f9d06df99bf004acd6d4d90800b9a0c
--- /dev/null
+++ b/modules/type/blocks/dap_chain_block_cache.c
@@ -0,0 +1,99 @@
+/*
+ * Authors:
+ * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net>
+ * DeM Labs Ltd   https://demlabs.net
+ * Copyright  (c) 2017-2020
+ * All rights reserved.
+
+ This file is part of DAP SDK the open source project
+
+    DAP SDK is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    DAP SDK is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with any DAP SDK based project.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#include <stdlib.h>
+#include <time.h>
+#include "dap_common.h"
+#include "dap_chain_block_cache.h"
+#include "dap_chain_datum_tx.h"
+#include "dap_chain_datum_tx_in.h"
+#include "dap_chain_datum_tx_out.h"
+
+#define LOG_TAG "dap_chain_block_cache"
+
+/**
+ * @brief dap_chain_block_cache_init
+ * @return
+ */
+int dap_chain_block_cache_init()
+{
+    return 0;
+}
+
+/**
+ * @brief dap_chain_block_cache_deinit
+ */
+void dap_chain_block_cache_deinit()
+{
+
+}
+
+/**
+ * @brief dap_chain_block_cache_new
+ * @param a_block
+ * @param a_block_size
+ * @return
+ */
+dap_chain_block_cache_t * dap_chain_block_cache_new(dap_chain_block_t * a_block, size_t a_block_size)
+{
+    if (! a_block)
+        return NULL;
+
+    dap_chain_block_cache_t * l_block_cache = DAP_NEW_Z(dap_chain_block_cache_t);
+    l_block_cache->block = a_block;
+    l_block_cache->block_size= a_block_size;
+    dap_chain_block_cache_update(l_block_cache);
+
+    log_it(L_DEBUG,"Block cache created");
+    return l_block_cache;
+}
+
+/**
+ * @brief dap_chain_block_cache_get_by_hash
+ * @param a_block_hash
+ * @return
+ */
+dap_chain_block_cache_t * dap_chain_block_cache_get_by_hash(dap_chain_hash_fast_t a_block_hash)
+{
+    return NULL;
+}
+
+/**
+ * @brief dap_chain_block_cache_update
+ * @param a_block_cache
+ */
+void dap_chain_block_cache_update(dap_chain_block_cache_t * a_block_cache)
+{
+    assert(a_block_cache);
+    assert(a_block_cache->block);
+    dap_hash_fast(a_block_cache->block, a_block_cache->block_size, &a_block_cache->block_hash);
+}
+
+/**
+ * @brief dap_chain_block_cache_delete
+ * @param a_block
+ */
+void dap_chain_block_cache_delete(dap_chain_block_cache_t * a_block_cache)
+{
+    DAP_DELETE(a_block_cache);
+    log_it(L_DEBUG,"Block cache deleted");
+}
diff --git a/modules/type/blocks/dap_chain_cs_blocks.c b/modules/type/blocks/dap_chain_cs_blocks.c
new file mode 100644
index 0000000000000000000000000000000000000000..62869d706cd5e3053c59c592977dd143dd11ef8c
--- /dev/null
+++ b/modules/type/blocks/dap_chain_cs_blocks.c
@@ -0,0 +1,686 @@
+/*
+ * Authors:
+ * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net>
+ * DeM Labs Ltd   https://demlabs.net
+ * Copyright  (c) 2017-2020
+ * All rights reserved.
+
+ This file is part of DAP SDK the open source project
+
+    DAP SDK is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    DAP SDK is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with any DAP SDK based project.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <pthread.h>
+#include "dap_common.h"
+#include "dap_enc_base58.h"
+#include "dap_chain.h"
+#include "dap_chain_net.h"
+#include "dap_chain_cs.h"
+#include "dap_chain_cs_blocks.h"
+#include "dap_chain_block.h"
+#include "dap_chain_block_cache.h"
+#include "dap_chain_node_cli.h"
+#include "dap_chain_node_cli_cmd.h"
+#define LOG_TAG "dap_chain_cs_blocks"
+
+typedef struct dap_chain_cs_blocks_pvt
+{
+    pthread_rwlock_t rwlock;
+    dap_chain_cs_blocks_t * blocks;
+
+    dap_chain_block_cache_t * block_cache_first; // Mapped area start
+    dap_chain_block_cache_t * block_cache_last; // Last block in mapped area
+
+
+    uint64_t blocks_count;
+    uint64_t difficulty;
+
+    dap_chain_block_t * block_new;
+    size_t block_new_size;
+} dap_chain_cs_blocks_pvt_t;
+
+#define PVT(a) ((dap_chain_cs_blocks_pvt_t *) a->_pvt )
+
+static int s_cli_parse_cmd_hash(char ** a_argv, int a_arg_index, int a_argc, char **a_str_reply,const char * a_param, dap_chain_hash_fast_t * a_datum_hash);
+static void s_cli_meta_hash_print(  dap_string_t * a_str_tmp, const char * a_meta_title, dap_chain_block_meta_t * a_meta);
+static int s_cli_blocks(int a_argc, char ** a_argv, void *a_arg_func, char **a_str_reply);
+
+// Callbacks
+static void s_callback_delete(dap_chain_t * a_chain);
+// Accept new block
+static dap_chain_atom_verify_res_t s_callback_atom_add(dap_chain_t * a_chain, dap_chain_atom_ptr_t , size_t);
+//    Verify new block
+static dap_chain_atom_verify_res_t s_callback_atom_verify(dap_chain_t * a_chain, dap_chain_atom_ptr_t , size_t);
+
+//    Get block header size
+static size_t s_callback_atom_get_static_hdr_size(void);
+
+static dap_chain_atom_iter_t* s_callback_atom_iter_create(dap_chain_t * a_chain );
+static dap_chain_atom_iter_t* s_callback_atom_iter_create_from(dap_chain_t *  ,
+                                                                     dap_chain_atom_ptr_t , size_t);
+
+
+static dap_chain_atom_ptr_t s_callback_atom_iter_find_by_hash(dap_chain_atom_iter_t * a_atom_iter ,
+                                                                       dap_chain_hash_fast_t * a_atom_hash, size_t * a_atom_size);
+static dap_chain_datum_tx_t* s_callback_atom_iter_find_by_tx_hash(dap_chain_t * a_chain ,
+                                                                       dap_chain_hash_fast_t * a_atom_hash);
+
+static dap_chain_datum_t* s_callback_atom_get_datum(dap_chain_atom_ptr_t a_event, size_t a_atom_size);
+//    Get blocks
+static dap_chain_atom_ptr_t s_callback_atom_iter_get_first( dap_chain_atom_iter_t * a_atom_iter, size_t *a_atom_size ); //    Get the fisrt block
+static dap_chain_atom_ptr_t s_callback_atom_iter_get_next( dap_chain_atom_iter_t * a_atom_iter,size_t *a_atom_size );  //    Get the next block
+static dap_chain_atom_ptr_t *s_callback_atom_iter_get_links( dap_chain_atom_iter_t * a_atom_iter , size_t *a_links_size,
+                                                                  size_t ** a_links_size_ptr );  //    Get list of linked blocks
+static dap_chain_atom_ptr_t *s_callback_atom_iter_get_lasts( dap_chain_atom_iter_t * a_atom_iter ,size_t *a_links_size,
+                                                                  size_t ** a_lasts_size_ptr );  //    Get list of linked blocks
+
+// Delete iterator
+static void s_callback_atom_iter_delete(dap_chain_atom_iter_t * a_atom_iter );                  //    Get the fisrt block
+
+static size_t s_callback_add_datums(dap_chain_t * a_chain, dap_chain_datum_t ** a_datums, size_t a_datums_size);
+
+bool s_seed_mode=false;
+
+
+/**
+ * @brief dap_chain_cs_blocks_init
+ * @return
+ */
+int dap_chain_cs_blocks_init()
+{
+    dap_chain_cs_type_add("blocks", dap_chain_cs_blocks_new );
+    s_seed_mode = dap_config_get_item_bool_default(g_config,"general","seed_mode",false);
+    dap_chain_node_cli_cmd_item_create ("block", s_cli_blocks, NULL, "Create and explore blockchains",
+        "New block create, fill and complete commands:"
+            "\tblock -net <chain net name> -chain <chain name> new\n"
+                "\t\tCreate new block and flush memory if was smth formed before\n\n"
+
+            "\tblock -net <chain net name> -chain <chain name> new_datum_add <datum hash>\n"
+                "\t\tAdd block section from datum <datum hash> taken from the mempool\n\n"
+
+            "\tblock -net <chain net name> -chain <chain name> new_datum_del <datum hash>\n"
+                "\t\tDel block section with datum <datum hash>\n\n"
+
+            "\tblock -net <chain net name> -chain <chain name> new_datum_list\n"
+                "\t\tList block sections and show their datums hashes\n\n"
+
+            "\tblock -net <chain net name> -chain <chain name> new_datum\n\n"
+                "\t\tComplete the current new round, verify it and if everything is ok - publish new events in chain\n\n"
+
+        "Blockchain explorer:"
+            "\tblock -net <chain net name> -chain <chain name> dump <block hash>\n"
+                "\t\tDump block info\n\n"
+
+            "\tblock -net <chain net name> -chain <chain name> list [-from_hash <block hash>] [-to_hash <block hash>]"
+            "\t                                                           [-from_dt <datetime>] [-to_dt <datetime>]"
+                "\t\t List blocks"
+
+                                        );
+    if (dap_chain_block_cache_init() != 0){
+        log_it(L_WARNING, "Can't init blocks cache");
+    }
+    log_it(L_NOTICE,"Initialized blocks chain type");
+
+    return 0;
+}
+
+/**
+ * @brief dap_chain_cs_blocks_deinit
+ */
+void dap_chain_cs_blocks_deinit()
+{
+    dap_chain_block_cache_deinit();
+}
+
+int dap_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);
+    a_chain->_inheritor = l_cs_blocks;
+
+    a_chain->callback_delete = s_callback_delete;
+
+    // Atom element callbacks
+    a_chain->callback_atom_add = s_callback_atom_add ;  // Accept new element in chain
+    a_chain->callback_atom_verify = s_callback_atom_verify ;  // Verify new element in chain
+    a_chain->callback_atom_get_hdr_static_size = s_callback_atom_get_static_hdr_size; // Get block hdr size
+
+    a_chain->callback_atom_iter_create = s_callback_atom_iter_create;
+    a_chain->callback_atom_iter_create_from = s_callback_atom_iter_create_from;
+    a_chain->callback_atom_iter_delete = s_callback_atom_iter_delete;
+
+    // Linear pass through
+    a_chain->callback_atom_iter_get_first = s_callback_atom_iter_get_first; // Get the fisrt element from chain
+    a_chain->callback_atom_iter_get_next = s_callback_atom_iter_get_next; // Get the next element from chain from the current one
+    a_chain->callback_atom_get_datum = s_callback_atom_get_datum;
+
+    a_chain->callback_atom_iter_get_links = s_callback_atom_iter_get_links; // Get the next element from chain from the current one
+    a_chain->callback_atom_iter_get_lasts = s_callback_atom_iter_get_lasts;
+
+    a_chain->callback_atom_find_by_hash = s_callback_atom_iter_find_by_hash;
+    a_chain->callback_tx_find_by_hash = s_callback_atom_iter_find_by_tx_hash;
+
+
+    a_chain->callback_add_datums = s_callback_add_datums;
+
+    dap_chain_cs_blocks_pvt_t *l_cs_blocks_pvt = DAP_NEW_Z(dap_chain_cs_blocks_pvt_t);
+    l_cs_blocks->_pvt = l_cs_blocks_pvt;
+    a_chain->_pvt = l_cs_blocks_pvt;
+    pthread_rwlock_init(&l_cs_blocks_pvt->rwlock,NULL);
+
+//    dap_chain_node_role_t l_net_role= dap_chain_net_get_role( dap_chain_net_by_id(a_chain->net_id) );
+
+    // Datum operations callbacks
+/*
+    a_chain->callback_datum_iter_create = s_chain_callback_datum_iter_create; // Datum iterator create
+    a_chain->callback_datum_iter_delete = s_chain_callback_datum_iter_delete; // Datum iterator delete
+    a_chain->callback_datum_iter_get_first = s_chain_callback_datum_iter_get_first; // Get the fisrt datum from chain
+    a_chain->callback_datum_iter_get_next = s_chain_callback_datum_iter_get_next; // Get the next datum from chain from the current one
+*/
+    return 0;
+}
+
+/**
+ * @brief dap_chain_cs_blocks_delete
+ * @param a_chain
+ */
+void dap_chain_cs_blocks_delete(dap_chain_t * a_chain)
+{
+   pthread_rwlock_destroy(&PVT(a_chain)->rwlock );
+}
+
+
+/**
+ * @brief s_cli_parse_cmd_hash
+ * @param a_argv
+ * @param a_arg_index
+ * @param a_argc
+ * @param a_str_reply
+ * @param a_param
+ * @param a_datum_hash
+ * @return
+ */
+static int s_cli_parse_cmd_hash(char ** a_argv, int a_arg_index, int a_argc, char **a_str_reply,const char * a_param,
+                                dap_chain_hash_fast_t * a_datum_hash)
+{
+    assert(a_datum_hash);
+
+    const char *l_datum_hash_str = NULL;
+    dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, a_param, &l_datum_hash_str);
+
+    return dap_enc_base58_hex_to_hash(l_datum_hash_str, a_datum_hash);
+}
+
+/**
+ * @brief s_cli_meta_hash_print
+ * @param a_str_tmp
+ * @param a_meta_title
+ * @param a_meta
+ */
+static void s_cli_meta_hash_print(  dap_string_t * a_str_tmp, const char * a_meta_title, dap_chain_block_meta_t * a_meta)
+{
+    if(a_meta->hdr.size == sizeof (dap_chain_hash_fast_t) ){
+        char * l_hash_str = dap_chain_hash_fast_to_str_new( (dap_chain_hash_fast_t *) a_meta->data);
+        dap_string_append_printf(a_str_tmp,"\t\tPREV: \"%s\"\n", a_meta_title,l_hash_str);
+        DAP_DELETE(l_hash_str);
+    }else{
+        char * l_data_hex = DAP_NEW_Z_SIZE(char,a_meta->hdr.size*2+3);
+        dap_bin2hex(l_data_hex, a_meta->data, a_meta->hdr.size);
+        dap_string_append_printf(a_str_tmp,"\t\t\%s: 0x%s\n", a_meta_title, l_data_hex );
+    }
+}
+
+/**
+ * @brief s_cli_meta_hex_print
+ * @param a_str_tmp
+ * @param a_meta_title
+ * @param a_meta
+ */
+static void s_cli_meta_hex_print(  dap_string_t * a_str_tmp, const char * a_meta_title, dap_chain_block_meta_t * a_meta)
+{
+    char * l_data_hex = DAP_NEW_Z_SIZE(char,a_meta->hdr.size*2+3);
+    dap_bin2hex(l_data_hex, a_meta->data, a_meta->hdr.size);
+    dap_string_append_printf(a_str_tmp,"\t\t\%s: 0x%s\n", a_meta_title, l_data_hex );
+}
+
+/**
+ * @brief s_cli_blocks
+ * @param argc
+ * @param argv
+ * @param arg_func
+ * @param a_str_reply
+ * @return
+ */
+static int s_cli_blocks(int a_argc, char ** a_argv, void *a_arg_func, char **a_str_reply)
+{
+    (void) a_arg_func;
+    enum {
+        SUBCMD_UNDEFINED =0,
+        SUBCMD_NEW_FLUSH,
+        SUBCMD_NEW_DATUM_ADD,
+        SUBCMD_NEW_DATUM_DEL,
+        SUBCMD_NEW_DATUM_LIST,
+        SUBCMD_NEW_COMPLETE,
+        SUBCMD_DUMP,
+        SUBCMD_LIST,
+        SUBCMD_DROP
+    } l_subcmd={0};
+
+    const char* l_subcmd_strs[]={
+        [SUBCMD_NEW_FLUSH]="new",
+        [SUBCMD_NEW_DATUM_ADD]="new_datum_add",
+        [SUBCMD_NEW_DATUM_DEL]="new_datum_del",
+        [SUBCMD_NEW_DATUM_LIST]="new_datum_del",
+        [SUBCMD_NEW_COMPLETE]="new_complete",
+        [SUBCMD_DUMP]="dump",
+        [SUBCMD_LIST]="list",
+        [SUBCMD_DROP]="drop",
+        [SUBCMD_UNDEFINED]=NULL
+    };
+    const size_t l_subcmd_str_count=sizeof(l_subcmd_strs)/sizeof(*l_subcmd_strs)-1;
+    const char* l_subcmd_str_args[l_subcmd_str_count];
+    const char* l_subcmd_str_arg;
+    const char* l_subcmd_str;
+
+
+    int arg_index = 1;
+
+    const char * l_net_name = NULL;
+    const char * l_chain_name = NULL;
+
+    dap_chain_t * l_chain = NULL;
+    dap_chain_cs_blocks_t * l_blocks = NULL;
+    dap_chain_net_t * l_net = NULL;
+
+    // Parse default values
+    if(dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index, a_argc, a_argv, a_str_reply, &l_chain, &l_net) < 0)
+        return -11;
+
+    l_blocks = DAP_CHAIN_CS_BLOCKS(l_chain);
+
+    // Parse commands
+    for (size_t i=0; i<l_subcmd_str_count; i++){
+        int l_opt_idx = dap_chain_node_cli_check_option(a_argv, arg_index,a_argc, l_subcmd_strs[i]);
+        if( l_opt_idx >= 0 ){
+            dap_chain_node_cli_find_option_val(a_argv, l_opt_idx, a_argc, l_subcmd_strs[i], &l_subcmd_str_args[i] );
+            l_subcmd = i;
+            l_subcmd_str = l_subcmd_strs[i];
+            l_subcmd_str_arg = l_subcmd_str_args[i];
+        }
+    }
+    int ret=-1000;
+    // Do subcommand action
+    switch ( l_subcmd ){
+        // Flush memory for the new block
+        case SUBCMD_NEW_FLUSH:{
+            if ( PVT(l_blocks)->block_new )
+                DAP_DELETE( PVT(l_blocks)->block_new );
+            PVT(l_blocks)->block_new = dap_chain_block_new( PVT(l_blocks)->block_cache_last? &PVT(l_blocks)->block_cache_last->block_hash: NULL );
+            PVT(l_blocks)->block_new_size = sizeof (PVT(l_blocks)->block_new->hdr);
+        } break;
+
+        // Add datum to the forming new block
+        case SUBCMD_NEW_DATUM_LIST:{
+
+        }break;
+        case SUBCMD_NEW_DATUM_DEL:{
+            if ( PVT(l_blocks)->block_new ){
+                dap_chain_hash_fast_t l_datum_hash;
+                s_cli_parse_cmd_hash(a_argv,arg_index,a_argc,a_str_reply,"-datum", &l_datum_hash );
+                PVT(l_blocks)->block_new_size=dap_chain_block_datum_del_by_hash( PVT(l_blocks)->block_new, PVT(l_blocks)->block_new_size, &l_datum_hash );
+            }else {
+                dap_chain_node_cli_set_reply_text(a_str_reply,
+                          "Error! Can't delete datum from hash because no forming new block! Check pls you role, it must be MASTER NODE or greater");
+                ret = -12;
+            }
+        }break;
+        case SUBCMD_NEW_DATUM_ADD:{
+            size_t l_datums_count=1;
+            char * l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool(l_chain);
+            dap_chain_datum_t ** l_datums = DAP_NEW_Z_SIZE(dap_chain_datum_t*,
+                                                           sizeof(dap_chain_datum_t*)*l_datums_count);
+            size_t l_datum_size = 0;
+
+            dap_chain_datum_t * l_datum = (dap_chain_datum_t*) dap_chain_global_db_gr_get( l_subcmd_str_arg ,
+                                                                                              &l_datum_size,
+                                                               l_gdb_group_mempool);
+            l_datums[0] = l_datum;
+            if ( s_callback_add_datums(l_chain,l_datums,l_datums_count ) == l_datums_count ){
+                for ( size_t i = 0; i <l_datums_count; i++){
+                   dap_chain_hash_fast_t l_datum_hash;
+                   dap_hash_fast(l_datums[i],dap_chain_datum_size(l_datums[i]),&l_datum_hash);
+                   char * l_datums_datum_hash_str = dap_chain_hash_fast_to_str_new(&l_datum_hash);
+
+                   if ( dap_chain_global_db_gr_del( dap_strdup(l_datums_datum_hash_str),l_gdb_group_mempool ) ){
+                       dap_chain_node_cli_set_reply_text(a_str_reply,
+                                                         "Converted datum %s from mempool to event in the new forming round ",
+                                                         l_datums_datum_hash_str);
+                       DAP_DELETE(l_datums_datum_hash_str);
+                       ret = 0;
+                   }else {
+                       dap_chain_node_cli_set_reply_text(a_str_reply,
+                                                         "Warning! Can't delete datum %s from mempool after conversion to event in the new forming round ",
+                                                         l_datums_datum_hash_str);
+                       ret = 1;
+                   }
+                }
+            }else {
+                dap_chain_node_cli_set_reply_text(a_str_reply,
+                        "Warning! Can't convert datum %s from mempool to the new forming block's section  ", l_subcmd_str_arg);
+                ret = -13;
+            }
+
+            DAP_DELETE(l_gdb_group_mempool);
+        }break;
+
+        case SUBCMD_NEW_COMPLETE:{
+            dap_chain_net_sync_all(l_net);
+        } break;
+
+        case SUBCMD_DROP:{
+            dap_chain_net_sync_all(l_net);
+        }break;
+        case SUBCMD_DUMP:{
+            dap_chain_block_t  * l_block;
+            size_t l_block_size = 0;
+            dap_chain_hash_fast_t l_block_hash={0};
+            dap_enc_base58_hex_to_hash( l_subcmd_str_arg, &l_block_hash); // Convert argument to hash
+            l_block = (dap_chain_block_t*) dap_chain_get_atom_by_hash( l_chain, &l_block_hash, &l_block_size);
+            if ( l_block){
+                dap_chain_block_cache_t *l_block_cache = dap_chain_block_cache_get(l_block, l_block_size);
+                if ( l_block_cache ){
+                    dap_string_t * l_str_tmp = dap_string_new(NULL);
+                    char buf[50];
+                    time_t l_ts_reated = (time_t) l_block->hdr.ts_created;
+                     // Header
+                    dap_string_append_printf(l_str_tmp,"Block %s:\n", l_subcmd_str_arg);
+                    dap_string_append_printf(l_str_tmp,"\t\t\tversion: 0x%04sX\n",l_block->hdr.version);
+                    dap_string_append_printf(l_str_tmp,"\t\t\tcell_id: 0x%016llX\n",l_block->hdr.cell_id.uint64);
+                    dap_string_append_printf(l_str_tmp,"\t\t\tchain_id: 0x%016llX\n",l_block->hdr.chain_id.uint64);
+                    dap_string_append_printf(l_str_tmp,"\t\t\tts_created: %s\n",ctime_r(&l_ts_reated, buf) );
+
+                    // Dump Metadata
+                    dap_string_append_printf(l_str_tmp,"\tMetadata. Count: %us\n",l_block->hdr.meta_count );
+                    for (uint32_t i=0; i < l_block_cache->meta_count; i++){
+                        dap_chain_block_meta_t * l_meta = l_block_cache->meta[i];
+                        switch (l_meta->hdr.type) {
+                            case DAP_CHAIN_BLOCK_META_GENESIS:{
+                                dap_string_append_printf(l_str_tmp,"\t\tGENESIS\n");
+                            }break;
+                            case DAP_CHAIN_BLOCK_META_PREV:{
+                                s_cli_meta_hash_print(l_str_tmp, "PREV", l_meta);
+                            }break;
+                            case DAP_CHAIN_BLOCK_META_ANCHOR:{
+                                s_cli_meta_hash_print(l_str_tmp, "ANCHOR", l_meta);
+                            }break;
+                            case DAP_CHAIN_BLOCK_META_LINK:{
+                                s_cli_meta_hash_print(l_str_tmp, "LINK", l_meta);
+                            }break;
+                            case DAP_CHAIN_BLOCK_META_NONCE:{
+                                s_cli_meta_hex_print(l_str_tmp,"NONCE", l_meta);
+                            }break;
+                            case DAP_CHAIN_BLOCK_META_NONCE2:{
+                                s_cli_meta_hex_print(l_str_tmp,"NONCE2", l_meta);
+                            }break;
+                            default:{
+                                char * l_data_hex = DAP_NEW_Z_SIZE(char,l_meta->hdr.size*2+3);
+                                dap_bin2hex(l_data_hex, l_meta->data, l_meta->hdr.size);
+                                dap_string_append_printf(l_str_tmp,"\t\t\0x%0X: 0x%s\n", l_data_hex );
+                            }
+                        }
+                    }
+                    dap_string_append_printf(l_str_tmp,"\t\tdatums:\tcount: %uz\n",l_block_cache->datum_count);
+                    for (uint32_t i=0; i < l_block_cache->datum_count ; i++){
+                        dap_chain_datum_t * l_datum = l_block_cache->datum[i];
+                        size_t l_datum_size =  dap_chain_datum_size(l_datum);
+                        dap_string_append_printf(l_str_tmp,"\t\t\tdatum:\tdatum_size: %u\n",l_datum_size);
+                        if (l_datum_size < sizeof (l_datum->header) ){
+                            dap_string_append_printf(l_str_tmp,"\t\t\tERROR: datum size %zd is smaller than header size %zd \n",l_datum_size,
+                                                     sizeof (l_datum->header));
+                            break;
+                        }
+                        time_t l_datum_ts_create = (time_t) l_datum->header.ts_create;
+                        // Nested datums
+                        dap_string_append_printf(l_str_tmp,"\t\t\t\tversion:=0x%02X\n", l_datum->header.version_id);
+                        dap_string_append_printf(l_str_tmp,"\t\t\t\ttype_id:=%s\n", c_datum_type_str[l_datum->header.type_id]);
+                        dap_string_append_printf(l_str_tmp,"\t\t\t\tts_create=%s\n",ctime_r( &l_datum_ts_create,buf ));
+                        dap_string_append_printf(l_str_tmp,"\t\t\t\tdata_size=%u\n", l_datum->header.data_size);
+                        dap_chain_net_dump_datum(l_str_tmp, l_datum, "hex" );
+                    }
+                    // Signatures
+                    dap_string_append_printf(l_str_tmp,"\t\tsignatures:\tcount: %u\n",l_block_cache->sign_count );
+                    for (uint32_t i=0; i < l_block_cache->sign_count ; i++){
+                        dap_sign_t * l_sign =l_block_cache->sign[i];
+                        size_t l_sign_size = dap_sign_get_size(l_sign);
+                        dap_chain_addr_t l_addr = {0};
+                        dap_chain_hash_fast_t l_pkey_hash;
+                        dap_sign_get_pkey_hash(l_sign, &l_pkey_hash);
+                        dap_chain_addr_fill(&l_addr, l_sign->header.type, &l_pkey_hash, l_net->pub.id);
+                        char * l_pkey_hash_str = dap_chain_hash_fast_to_str_new(&l_pkey_hash);
+                        dap_string_append_printf(l_str_tmp,"\t\t\t: type:%s size: %zd pkey_hash: %s data_hash: "
+                                                           "n", dap_sign_type_to_str( l_sign->header.type ), l_sign_size, l_pkey_hash_str );
+                        DAP_DELETE( l_pkey_hash_str );
+                    }
+                    dap_chain_node_cli_set_reply_text(a_str_reply, l_str_tmp->str);
+                    dap_string_free(l_str_tmp,false);
+                    ret=0;
+                }
+            }else {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Can't find block %s ", l_subcmd_str_arg);
+                ret=-10;
+            }
+        }break;
+        case SUBCMD_LIST:{
+
+                dap_string_t * l_str_tmp = dap_string_new(NULL);
+                dap_string_append_printf(l_str_tmp,"%s.%s: Have %u blocks :\n",
+                                         l_net->pub.name,l_chain->name,PVT(l_blocks)->blocks_count);
+                dap_chain_block_cache_t * l_block_cache = NULL,*l_block_cache_tmp = NULL;
+
+                pthread_rwlock_rdlock(&PVT(l_blocks)->rwlock);
+                HASH_ITER(hh,PVT(l_blocks)->block_cache_first,l_block_cache, l_block_cache_tmp ) {
+                    char  l_buf[50];
+                    dap_string_append_printf(l_str_tmp,"\t%s: ts_create=%s",
+                                             l_block_cache->block_hash_str, ctime_r( &l_block_cache->ts_created,l_buf ) );
+                }
+                pthread_rwlock_unlock(&PVT(l_blocks)->rwlock);
+
+                dap_chain_node_cli_set_reply_text(a_str_reply, l_str_tmp->str);
+                dap_string_free(l_str_tmp,false);
+
+        }break;
+
+        case SUBCMD_UNDEFINED: {
+            dap_chain_node_cli_set_reply_text(a_str_reply,
+                                              "Undefined block subcommand \"%s\" ",
+                                              l_subcmd_str);
+            ret=-11;
+        }
+    }
+    return ret;
+}
+
+
+/**
+ * @brief s_callback_delete
+ * @details Destructor for blocks consensus chain
+ * @param a_chain
+ */
+static void s_callback_delete(dap_chain_t * a_chain)
+{
+    dap_chain_cs_blocks_t * l_blocks = DAP_CHAIN_CS_BLOCKS ( a_chain );
+    if(l_blocks->callback_delete )
+        l_blocks->callback_delete(l_blocks);
+    if(l_blocks->_inheritor)
+        DAP_DELETE(l_blocks->_inheritor);
+    if(l_blocks->_pvt)
+        DAP_DELETE(l_blocks->_pvt);
+}
+
+/**
+ * @brief s_callback_atom_add
+ * @details Accept new atom in blockchain
+ * @param a_chain
+ * @param a_atom
+ * @param a_atom_size
+ * @return
+ */
+static dap_chain_atom_verify_res_t s_callback_atom_add(dap_chain_t * a_chain, dap_chain_atom_ptr_t a_atom , size_t a_atom_size)
+{
+
+}
+
+/**
+ * @brief s_callback_atom_verify
+ * @param a_chain
+ * @param a_atom
+ * @param a_atom_size
+ * @return
+ */
+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)
+{
+
+}
+
+/**
+ * @brief s_callback_atom_get_static_hdr_size
+ * @return
+ */
+static size_t s_callback_atom_get_static_hdr_size(void)
+{
+
+}
+
+/**
+ * @brief s_callback_atom_iter_create
+ * @param a_chain
+ * @return
+ */
+static dap_chain_atom_iter_t* s_callback_atom_iter_create(dap_chain_t * a_chain )
+{
+
+}
+
+/**
+ * @brief s_callback_atom_iter_create_from
+ * @param a_chain
+ * @param a_atom
+ * @param a_atom_size
+ * @return
+ */
+static dap_chain_atom_iter_t* s_callback_atom_iter_create_from(dap_chain_t * a_chain, dap_chain_atom_ptr_t a_atom, size_t a_atom_size)
+{
+
+}
+
+/**
+ * @brief s_callback_atom_iter_find_by_hash
+ * @param a_atom_iter
+ * @param a_atom_hash
+ * @param a_atom_size
+ * @return
+ */
+static dap_chain_atom_ptr_t s_callback_atom_iter_find_by_hash(dap_chain_atom_iter_t * a_atom_iter, dap_chain_hash_fast_t * a_atom_hash,
+                                                              size_t * a_atom_size)
+{
+
+}
+
+/**
+ * @brief s_callback_atom_iter_find_by_tx_hash
+ * @param a_chain
+ * @param a_atom_hash
+ * @return
+ */
+static dap_chain_datum_tx_t* s_callback_atom_iter_find_by_tx_hash(dap_chain_t * a_chain, dap_chain_hash_fast_t * a_atom_hash)
+{
+
+}
+
+/**
+ * @brief s_callback_atom_get_datum
+ * @param a_event
+ * @param a_atom_size
+ * @return
+ */
+static dap_chain_datum_t* s_callback_atom_get_datum(dap_chain_atom_ptr_t a_event, size_t a_atom_size)
+{
+
+}
+
+/**
+ * @brief s_callback_atom_iter_get_first
+ * @param a_atom_iter
+ * @param a_atom_size
+ * @return
+ */
+static dap_chain_atom_ptr_t s_callback_atom_iter_get_first( dap_chain_atom_iter_t * a_atom_iter, size_t *a_atom_size )
+{
+
+}
+
+/**
+ * @brief s_callback_atom_iter_get_next
+ * @param a_atom_iter
+ * @param a_atom_size
+ * @return
+ */
+static dap_chain_atom_ptr_t s_callback_atom_iter_get_next( dap_chain_atom_iter_t * a_atom_iter,size_t *a_atom_size )
+{
+
+}
+
+/**
+ * @brief s_callback_atom_iter_get_links
+ * @param a_atom_iter
+ * @param a_links_size
+ * @param a_links_size_ptr
+ * @return
+ */
+static dap_chain_atom_ptr_t *s_callback_atom_iter_get_links( dap_chain_atom_iter_t * a_atom_iter , size_t *a_links_size, size_t ** a_links_size_ptr )
+{
+
+}
+
+/**
+ * @brief s_callback_atom_iter_get_lasts
+ * @param a_atom_iter
+ * @param a_links_size
+ * @param a_lasts_size_ptr
+ * @return
+ */
+static dap_chain_atom_ptr_t *s_callback_atom_iter_get_lasts( dap_chain_atom_iter_t * a_atom_iter ,size_t *a_links_size, size_t ** a_lasts_size_ptr )
+{
+
+}
+
+/**
+ * @brief s_callback_atom_iter_delete
+ * @param a_atom_iter
+ */
+static void s_callback_atom_iter_delete(dap_chain_atom_iter_t * a_atom_iter )
+{
+
+}
+
+/**
+ * @brief s_callback_datums_pool_proc
+ * @param a_chain
+ * @param a_datums
+ * @param a_datums_size
+ * @return
+ */
+static size_t s_callback_add_datums(dap_chain_t * a_chain, dap_chain_datum_t ** a_datums, size_t a_datums_size)
+{
+
+}
diff --git a/modules/type/blocks/include/dap_chain_block.h b/modules/type/blocks/include/dap_chain_block.h
new file mode 100644
index 0000000000000000000000000000000000000000..cad3a151794549465eacedaa0f9d8239a1efd284
--- /dev/null
+++ b/modules/type/blocks/include/dap_chain_block.h
@@ -0,0 +1,95 @@
+/*
+ * Authors:
+ * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net>
+ * DeM Labs Ltd   https://demlabs.net
+ * Copyright  (c) 2017-2020
+ * All rights reserved.
+
+ This file is part of DAP SDK the open source project
+
+    DAP SDK is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    DAP SDK is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with any DAP SDK based project.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#pragma once
+#include "dap_common.h"
+#include "dap_math_ops.h"
+#include "dap_hash.h"
+#include "dap_chain_common.h"
+#include "dap_chain_datum.h"
+#include "dap_chain_datum_hashtree_roots.h"
+
+#define DAP_CHAIN_BLOCK_SIGNATURE 0xDA05BF8E
+#define DAP_CHAIN_BLOCK_ID_SIZE 4
+
+
+typedef union dap_chain_block_typeid{
+    uint8_t data[DAP_CHAIN_BLOCK_ID_SIZE];
+} DAP_ALIGN_PACKED dap_chain_block_typeid_t;
+
+/**
+  * @struct dap_chain_block_hdr
+  * @brief Block header
+  */
+typedef struct dap_chain_block_hdr{
+   uint32_t signature; /// @param signature @brief Magic number, always equels to DAP_CHAIN_BLOCK_SIGNATURE
+   int32_t version; /// @param version @brief block version (be carefull, signed value, as Bitcoin has)
+   dap_chain_cell_id_t cell_id; /// Cell id
+   dap_chain_cell_id_t chain_id; /// Chain id
+   uint32_t meta_n_datums_size; /// @param size of the whole block except signatures meta
+   dap_chain_time_t ts_created; /// @param timestamp @brief Block create time timestamp
+   uint16_t meta_count; // Meta values number
+   uint16_t datum_count; // Datums's count
+} DAP_ALIGN_PACKED dap_chain_block_hdr_t;
+
+// Metadata item
+typedef struct dap_chain_block_meta{
+    struct {
+        uint8_t type; /// Meta type
+        uint16_t size;   /// Data size trailing the section
+    } DAP_ALIGN_PACKED hdr;
+    byte_t data[]; /// Section's data
+} DAP_ALIGN_PACKED dap_chain_block_meta_t;
+
+// Block metadata types
+
+#define DAP_CHAIN_BLOCK_META_GENESIS           0x01
+#define DAP_CHAIN_BLOCK_META_PREV              0x10
+#define DAP_CHAIN_BLOCK_META_ANCHOR            0x11
+#define DAP_CHAIN_BLOCK_META_LINK              0x12
+#define DAP_CHAIN_BLOCK_META_NONCE             0x20
+#define DAP_CHAIN_BLOCK_META_NONCE2            0x21
+
+
+/**
+ * @struct dap_chain_block
+ * @brief The dap_chain_block struct
+ */
+typedef struct  dap_chain_block{
+    dap_chain_block_hdr_t hdr;
+    uint8_t meta_n_datum_n_sign[]; // Here are: metadata, datum sections and verificator signatures
+} DAP_ALIGN_PACKED dap_chain_block_t;
+
+// Init module
+int dap_chain_block_init();
+// Deinit module
+void dap_chain_block_deinit();
+
+// Create new block
+dap_chain_block_t * dap_chain_block_new(dap_chain_hash_fast_t * a_prev_block );
+
+// Add metadata in block
+size_t dap_chain_block_meta_add(dap_chain_block_t * a_block, size_t a_block_size, uint8_t a_meta_type, const void * a_data, size_t a_data_size);
+
+// Add datum in block
+size_t dap_chain_block_datum_add(dap_chain_block_t * a_block, size_t a_block_size, dap_chain_datum_t * a_datum, size_t a_datum_size);
+size_t dap_chain_block_datum_del_by_hash(dap_chain_block_t * a_block, size_t a_block_size, dap_chain_hash_fast_t* a_datum_hash);
diff --git a/modules/type/blocks/include/dap_chain_block_cache.h b/modules/type/blocks/include/dap_chain_block_cache.h
new file mode 100644
index 0000000000000000000000000000000000000000..35f115cdd34656b7c041077e80b42177a12fb8ea
--- /dev/null
+++ b/modules/type/blocks/include/dap_chain_block_cache.h
@@ -0,0 +1,66 @@
+/*
+ * Authors:
+ * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net>
+ * DeM Labs Ltd   https://demlabs.net
+ * Copyright  (c) 2017-2020
+ * All rights reserved.
+
+ This file is part of DAP SDK the open source project
+
+    DAP SDK is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    DAP SDK is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with any DAP SDK based project.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#pragma once
+#include "dap_chain_block.h"
+#include "dap_sign.h"
+#include "dap_hash.h"
+#include "uthash.h"
+
+typedef struct dap_chain_block_cache{
+    // Block's general non-nested attributes
+    dap_chain_hash_fast_t block_hash;
+    char* block_hash_str;
+    size_t block_size;
+
+    // Local platform values representation
+    time_t ts_created;
+
+    // Block's datums
+    uint32_t datum_count;
+    dap_chain_datum_t ** datum;
+
+    // Block's metadatas
+    uint32_t meta_count;
+    dap_chain_block_meta_t** meta;
+
+    // Block's signatures
+    size_t sign_count; // Number of signatures in block's tail
+    dap_sign_t ** sign; // Pointer to signatures in block
+
+    // Pointer to block itself
+    dap_chain_block_t * block;
+
+    // Inhertied nested data
+    void * _inheritor;
+
+    // uthash handle
+    UT_hash_handle hh;
+} dap_chain_block_cache_t;
+
+int dap_chain_block_cache_init();
+void dap_chain_block_cache_deinit();
+
+dap_chain_block_cache_t * dap_chain_block_cache_get_by_hash(dap_chain_hash_fast_t a_block_hash);
+dap_chain_block_cache_t * dap_chain_block_cache_new(dap_chain_block_t * a_block, size_t a_block_size);
+void dap_chain_block_cache_update(dap_chain_block_cache_t * a_block_cache);
+void dap_chain_block_cache_delete(dap_chain_block_cache_t * a_block_cache);
diff --git a/modules/type/blocks/include/dap_chain_cs_blocks.h b/modules/type/blocks/include/dap_chain_cs_blocks.h
new file mode 100644
index 0000000000000000000000000000000000000000..f2be5e7fa63f0b63d87dd0a8f2e3ab24e3414ae7
--- /dev/null
+++ b/modules/type/blocks/include/dap_chain_cs_blocks.h
@@ -0,0 +1,61 @@
+/*
+ * Authors:
+ * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net>
+ * DeM Labs Inc.   https://demlabs.net
+ * Copyright  (c) 2017-2020
+ * All rights reserved.
+
+ This file is part of DAP (Deus Applications Prototypes) the open source project
+
+    DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    DAP is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#pragma once
+
+#include "dap_chain.h"
+#include "dap_chain_block.h"
+#include "dap_chain_block_cache.h"
+
+
+typedef struct dap_chain_cs_blocks dap_chain_cs_blocks_t;
+
+typedef void (*dap_chain_cs_blocks_callback_t)(dap_chain_cs_blocks_t *);
+typedef int (*dap_chain_cs_blocks_callback_block_t)(dap_chain_cs_blocks_t *, dap_chain_block_t *,size_t);
+
+
+
+typedef dap_chain_block_t * (*dap_chain_cs_blocks_callback_block_create_t)(dap_chain_cs_blocks_t *,
+                                                                               dap_chain_datum_t *,
+                                                                               dap_chain_hash_fast_t *,
+                                                                               size_t, size_t*);
+
+
+typedef struct dap_chain_cs_blocks
+{
+    dap_chain_t * chain;
+
+    dap_chain_cs_blocks_callback_t callback_delete;
+    dap_chain_cs_blocks_callback_block_create_t callback_block_create;
+    dap_chain_cs_blocks_callback_block_t callback_block_verify;
+    void * _pvt;
+    void * _inheritor;
+} dap_chain_cs_blocks_t;
+
+#define DAP_CHAIN_CS_BLOCKS(a) ((dap_chain_cs_blocks_t*) a->_inheritor)
+typedef int (*dap_chain_blocks_block_callback_ptr_t)(dap_chain_cs_blocks_t *, dap_chain_block_t *);
+
+int dap_chain_cs_blocks_init();
+void dap_chain_cs_blocks_deinit();
+
+int dap_chain_cs_blocks_new(dap_chain_t * a_chain, dap_config_t * a_chain_config);
+void dap_chain_cs_blocks_delete(dap_chain_t * a_chain);
diff --git a/modules/type/dag/dap_chain_cs_dag.c b/modules/type/dag/dap_chain_cs_dag.c
index 15da786b6919f505b3c36663535ed4c593d8da56..69e50b3968bee1cc102c902ec75dc5b5039fa99b 100644
--- a/modules/type/dag/dap_chain_cs_dag.c
+++ b/modules/type/dag/dap_chain_cs_dag.c
@@ -78,6 +78,7 @@ typedef struct dap_chain_cs_dag_pvt {
 
 #define PVT(a) ((dap_chain_cs_dag_pvt_t *) a->_pvt )
 
+static void s_dap_chain_cs_dag_purge(dap_chain_t *a_chain);
 dap_chain_cs_dag_event_item_t* dap_chain_cs_dag_proc_treshold(dap_chain_cs_dag_t * a_dag, dap_ledger_t * a_ledger);
 
 // Atomic element organization callbacks
@@ -128,7 +129,7 @@ static bool s_seed_mode = false;
 int dap_chain_cs_dag_init(void)
 {
     srand((unsigned int) time(NULL));
-    dap_chain_class_add( "dag", dap_chain_cs_dag_new );
+    dap_chain_cs_type_add( "dag", dap_chain_cs_dag_new );
     s_seed_mode = dap_config_get_item_bool_default(g_config,"general","seed_mode",false);
     dap_chain_node_cli_cmd_item_create ("dag", s_cli_dag, NULL, "DAG commands",
         "dag -net <chain net name> -chain <chain name> event create -datum <datum hash> [-H hex|base58(default)]\n"
@@ -171,6 +172,7 @@ int dap_chain_cs_dag_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg)
     pthread_rwlock_init(& PVT(l_dag)->events_rwlock,NULL);
 
     a_chain->callback_delete = dap_chain_cs_dag_delete;
+    a_chain->callback_purge = s_dap_chain_cs_dag_purge;
 
     // Atom element callbacks
     a_chain->callback_atom_add = s_chain_callback_atom_add ;  // Accept new element in chain
@@ -194,7 +196,7 @@ int dap_chain_cs_dag_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg)
     a_chain->callback_tx_find_by_hash = s_chain_callback_atom_iter_find_by_tx_hash;
 
 
-    a_chain->callback_datums_pool_proc = s_chain_callback_datums_pool_proc;
+    a_chain->callback_add_datums = s_chain_callback_datums_pool_proc;
 
     // Datum operations callbacks
 /*
@@ -231,6 +233,34 @@ int dap_chain_cs_dag_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg)
     return 0;
 }
 
+static void s_dap_chain_cs_dag_purge(dap_chain_t *a_chain)
+{
+    dap_chain_cs_dag_pvt_t *l_dag_pvt = PVT(DAP_CHAIN_CS_DAG(a_chain));
+    pthread_rwlock_wrlock(&l_dag_pvt->events_rwlock);
+    dap_chain_cs_dag_event_item_t *l_event_current, *l_event_tmp;
+    HASH_ITER(hh, l_dag_pvt->events, l_event_current, l_event_tmp) {
+        HASH_DEL(l_dag_pvt->events, l_event_current);
+        DAP_DELETE(l_event_current);
+    }
+    HASH_ITER(hh, l_dag_pvt->events_lasts_unlinked, l_event_current, l_event_tmp) {
+        HASH_DEL(l_dag_pvt->events_lasts_unlinked, l_event_current);
+        DAP_DELETE(l_event_current);
+    }
+    HASH_ITER(hh, l_dag_pvt->events_treshold, l_event_current, l_event_tmp) {
+        HASH_DEL(l_dag_pvt->events_treshold, l_event_current);
+        DAP_DELETE(l_event_current);
+    }
+    HASH_ITER(hh, l_dag_pvt->events_treshold_conflicted, l_event_current, l_event_tmp) {
+        HASH_DEL(l_dag_pvt->events_treshold_conflicted, l_event_current);
+        DAP_DELETE(l_event_current);
+    }
+    HASH_ITER(hh, l_dag_pvt->tx_events, l_event_current, l_event_tmp) {
+        HASH_DEL(l_dag_pvt->tx_events, l_event_current);
+        DAP_DELETE(l_event_current);
+    }
+    pthread_rwlock_unlock(&l_dag_pvt->events_rwlock);
+}
+
 /**
  * @brief dap_chain_cs_dag_delete
  * @param a_dag
@@ -238,6 +268,7 @@ int dap_chain_cs_dag_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg)
  */
 void dap_chain_cs_dag_delete(dap_chain_t * a_chain)
 {
+    s_dap_chain_cs_dag_purge(a_chain);
     dap_chain_cs_dag_t * l_dag = DAP_CHAIN_CS_DAG ( a_chain );
     pthread_rwlock_destroy(& PVT(l_dag)->events_rwlock);
 
@@ -255,12 +286,12 @@ static int s_dap_chain_add_atom_to_ledger(dap_chain_cs_dag_t * a_dag, dap_ledger
   switch (l_datum->header.type_id) {
     case DAP_CHAIN_DATUM_TOKEN_DECL: {
       dap_chain_datum_token_t *l_token = (dap_chain_datum_token_t*) l_datum->data;
-      return dap_chain_ledger_token_add(a_ledger, l_token, l_datum->header.data_size);
+      return dap_chain_ledger_token_load(a_ledger, l_token, l_datum->header.data_size);
     }
       break;
     case DAP_CHAIN_DATUM_TOKEN_EMISSION: {
       dap_chain_datum_token_emission_t *l_token_emission = (dap_chain_datum_token_emission_t*) l_datum->data;
-      return dap_chain_ledger_token_emission_add(a_ledger, l_token_emission, l_datum->header.data_size);
+      return dap_chain_ledger_token_emission_load(a_ledger, l_token_emission, l_datum->header.data_size);
     }
       break;
     case DAP_CHAIN_DATUM_TX: {
@@ -274,7 +305,7 @@ static int s_dap_chain_add_atom_to_ledger(dap_chain_cs_dag_t * a_dag, dap_ledger
       HASH_ADD(hh,PVT(a_dag)->tx_events,hash,sizeof (l_tx_event->hash),l_tx_event);
 
       // don't save bad transactions to base
-      if(dap_chain_ledger_tx_add(a_ledger, l_tx) != 1) {
+      if(dap_chain_ledger_tx_load(a_ledger, l_tx) != 1) {
         return -1;
       }
     }