diff --git a/dap_chain_global_db.c b/dap_chain_global_db.c
index 20d00b59c7721f76396e3e0599ae3812691db123..591e8bd500e49efd595a6e02a1c682c95e008547 100755
--- a/dap_chain_global_db.c
+++ b/dap_chain_global_db.c
@@ -17,16 +17,16 @@
 #define LOG_TAG "dap_global_db"
 
 // for access from several streams
-static pthread_mutex_t ldb_mutex_ = PTHREAD_MUTEX_INITIALIZER;
+//static pthread_mutex_t ldb_mutex_ = PTHREAD_MUTEX_INITIALIZER;
 
 static inline void lock()
 {
-    pthread_mutex_lock(&ldb_mutex_);
+    //pthread_mutex_lock(&ldb_mutex_);
 }
 
 static inline void unlock()
 {
-    pthread_mutex_unlock(&ldb_mutex_);
+    //pthread_mutex_unlock(&ldb_mutex_);
 }
 
 // Callback table item
@@ -43,28 +43,27 @@ typedef struct history_group_item
 // Tacked group callbacks
 static history_group_item_t * s_history_group_items = NULL;
 
-char * extract_group_prefix (const char * a_group);
-
+char * extract_group_prefix(const char * a_group);
 
 /**
  * @brief extract_group_prefix
  * @param a_group
  * @return
  */
-char * extract_group_prefix (const char * a_group)
+char * extract_group_prefix(const char * a_group)
 {
-    char * l_group_prefix = NULL, *l_delimeter ;
+    char * l_group_prefix = NULL, *l_delimeter;
     size_t l_group_prefix_size;
-    l_delimeter = index (a_group,'.');
-    if ( l_delimeter == NULL ){
-        l_group_prefix = strdup(a_group);
-        l_group_prefix_size = strlen( l_group_prefix)+1;
+    l_delimeter = index(a_group, '.');
+    if(l_delimeter == NULL) {
+        l_group_prefix = dap_strdup(a_group);
+        l_group_prefix_size = dap_strlen(l_group_prefix) + 1;
     } else {
-        l_group_prefix_size = (size_t)l_delimeter- (size_t) a_group;
-        if ( l_group_prefix_size > 1 )
+        l_group_prefix_size = (size_t) l_delimeter - (size_t) a_group;
+        if(l_group_prefix_size > 1)
             l_group_prefix = strndup(a_group, l_group_prefix_size);
     }
-    return  l_group_prefix;
+    return l_group_prefix;
 }
 
 /**
@@ -75,9 +74,9 @@ char * extract_group_prefix (const char * a_group)
 void dap_chain_global_db_add_history_group_prefix(const char * a_group_prefix)
 {
     history_group_item_t * l_item = DAP_NEW_Z(history_group_item_t);
-    snprintf(l_item->prefix,sizeof (l_item->prefix),"%s",a_group_prefix);
+    snprintf(l_item->prefix, sizeof(l_item->prefix), "%s", a_group_prefix);
     l_item->auto_track = true;
-    HASH_ADD_STR(s_history_group_items , prefix, l_item );
+    HASH_ADD_STR(s_history_group_items, prefix, l_item);
 }
 
 /**
@@ -85,18 +84,19 @@ void dap_chain_global_db_add_history_group_prefix(const char * a_group_prefix)
  * @param a_group_prefix
  * @param a_callback
  */
-void dap_chain_global_db_add_history_callback_notify(const char * a_group_prefix, dap_global_db_obj_callback_notify_t a_callback, void * a_arg)
+void dap_chain_global_db_add_history_callback_notify(const char * a_group_prefix,
+        dap_global_db_obj_callback_notify_t a_callback, void * a_arg)
 {
     history_group_item_t * l_item = NULL;
     HASH_FIND_STR(s_history_group_items, a_group_prefix, l_item);
-    if ( l_item ){
+    if(l_item) {
         l_item->callback_notify = a_callback;
         l_item->callback_arg = a_arg;
-    }else
-        log_it(L_WARNING, "Can't setup notify callback for groups with prefix %s. Possible not in history track state", a_group_prefix);
+    } else
+        log_it(L_WARNING, "Can't setup notify callback for groups with prefix %s. Possible not in history track state",
+                a_group_prefix);
 }
 
-
 /**
  * Clean struct dap_global_db_obj_t
  */
@@ -159,7 +159,8 @@ void dap_chain_global_db_deinit(void)
     //dap_db_deinit();
     unlock();
     history_group_item_t * l_item = NULL, *l_item_tmp = NULL;
-    HASH_ITER(hh, s_history_group_items, l_item, l_item_tmp){
+    HASH_ITER(hh, s_history_group_items, l_item, l_item_tmp)
+    {
         DAP_DELETE(l_item);
     }
     s_history_group_items = NULL;
@@ -173,21 +174,23 @@ void dap_chain_global_db_deinit(void)
  */
 void* dap_chain_global_db_obj_get(const char *a_key, const char *a_group)
 {
-    dap_store_obj_t *l_store_data = dap_db_read_data(a_group, a_key, NULL);
+    size_t l_count = 1;
+    // read one item
+    dap_store_obj_t *l_store_data = dap_chain_global_db_driver_read(a_group, a_key, &l_count);
     return l_store_data;
 
-/*    size_t count = 0;
-    if(!a_key)
-        return NULL;
-    size_t query_len = (size_t) snprintf(NULL, 0, "(&(cn=%s)(objectClass=%s))", a_key, a_group);
-    char *query = DAP_NEW_Z_SIZE(char, query_len + 1); //char query[32 + strlen(a_key)];
-    snprintf(query, query_len + 1, "(&(cn=%s)(objectClass=%s))", a_key, a_group); // objectClass != ou
-    lock();
-    dap_store_obj_t *store_data = dap_db_read_data(query, &count);
-    unlock();
-    assert(count <= 1);
-    DAP_DELETE(query);
-    return store_data;*/
+    /*    size_t count = 0;
+     if(!a_key)
+     return NULL;
+     size_t query_len = (size_t) snprintf(NULL, 0, "(&(cn=%s)(objectClass=%s))", a_key, a_group);
+     char *query = DAP_NEW_Z_SIZE(char, query_len + 1); //char query[32 + strlen(a_key)];
+     snprintf(query, query_len + 1, "(&(cn=%s)(objectClass=%s))", a_key, a_group); // objectClass != ou
+     lock();
+     dap_store_obj_t *store_data = dap_db_read_data(query, &count);
+     unlock();
+     assert(count <= 1);
+     DAP_DELETE(query);
+     return store_data;*/
 }
 
 /**
@@ -200,7 +203,10 @@ void* dap_chain_global_db_obj_get(const char *a_key, const char *a_group)
 uint8_t * dap_chain_global_db_gr_get(const char *a_key, size_t *a_data_len_out, const char *a_group)
 {
     uint8_t *l_ret_value = NULL;
-    dap_store_obj_t *l_store_data = dap_db_read_data(a_group, a_key, a_data_len_out);
+    // read several items, 0 - no limits
+    if(a_data_len_out)
+        *a_data_len_out = 0;
+    dap_store_obj_t *l_store_data = dap_chain_global_db_driver_read(a_group, a_key, a_data_len_out);
     if(l_store_data) {
         l_ret_value = (l_store_data->value) ? DAP_NEW_SIZE(uint8_t, l_store_data->value_len) : NULL; //ret_value = (store_data->value) ? strdup(store_data->value) : NULL;
         memcpy(l_ret_value, l_store_data->value, l_store_data->value_len);
@@ -209,27 +215,27 @@ uint8_t * dap_chain_global_db_gr_get(const char *a_key, size_t *a_data_len_out,
     }
     return l_ret_value;
 
-/*ldb
- *     uint8_t *l_ret_value = NULL;
-    size_t l_count = 0;
-    if(!a_key)
-        return NULL;
-    size_t l_query_len =(size_t) snprintf(NULL, 0, "(&(cn=%s)(objectClass=%s))", a_key, a_group);
-
-    char *l_query = DAP_NEW_Z_SIZE(char, l_query_len + 1); //char query[32 + strlen(a_key)];
-    snprintf(l_query, l_query_len + 1, "(&(cn=%s)(objectClass=%s))", a_key, a_group); // objectClass != ou
-    lock();
-    pdap_store_obj_t store_data = dap_db_read_data(l_query, &l_count);
-    unlock();
-    if(l_count == 1 && store_data && !strcmp(store_data->key, a_key)) {
-        l_ret_value = (store_data->value) ? DAP_NEW_SIZE(uint8_t, store_data->value_len) : NULL; //ret_value = (store_data->value) ? strdup(store_data->value) : NULL;
-        memcpy(l_ret_value, store_data->value, store_data->value_len);
-        if(a_data_out)
-            *a_data_out = store_data->value_len;
-    }
-    dab_db_free_pdap_store_obj_t(store_data, l_count);
-    DAP_DELETE(l_query);
-    return l_ret_value;*/
+    /*ldb
+     *     uint8_t *l_ret_value = NULL;
+     size_t l_count = 0;
+     if(!a_key)
+     return NULL;
+     size_t l_query_len =(size_t) snprintf(NULL, 0, "(&(cn=%s)(objectClass=%s))", a_key, a_group);
+
+     char *l_query = DAP_NEW_Z_SIZE(char, l_query_len + 1); //char query[32 + strlen(a_key)];
+     snprintf(l_query, l_query_len + 1, "(&(cn=%s)(objectClass=%s))", a_key, a_group); // objectClass != ou
+     lock();
+     pdap_store_obj_t store_data = dap_db_read_data(l_query, &l_count);
+     unlock();
+     if(l_count == 1 && store_data && !strcmp(store_data->key, a_key)) {
+     l_ret_value = (store_data->value) ? DAP_NEW_SIZE(uint8_t, store_data->value_len) : NULL; //ret_value = (store_data->value) ? strdup(store_data->value) : NULL;
+     memcpy(l_ret_value, store_data->value, store_data->value_len);
+     if(a_data_out)
+     *a_data_out = store_data->value_len;
+     }
+     dap_store_obj_free(store_data, l_count);
+     DAP_DELETE(l_query);
+     return l_ret_value;*/
 }
 
 uint8_t * dap_chain_global_db_get(const char *a_key, size_t *a_data_out)
@@ -237,7 +243,6 @@ uint8_t * dap_chain_global_db_get(const char *a_key, size_t *a_data_out)
     return dap_chain_global_db_gr_get(a_key, a_data_out, GROUP_LOCAL_GENERAL);
 }
 
-
 /**
  * Set one entry to base
  */
@@ -245,38 +250,39 @@ bool dap_chain_global_db_gr_set(const char *a_key, const void *a_value, size_t a
 {
     pdap_store_obj_t store_data = DAP_NEW_Z_SIZE(dap_store_obj_t, sizeof(struct dap_store_obj));
     store_data->type = 'a';
-    store_data->key = strdup(a_key );
-    store_data->value = DAP_NEW_Z_SIZE(uint8_t,a_value_len);
+    store_data->key = dap_strdup(a_key);
+    store_data->value = DAP_NEW_Z_SIZE(uint8_t, a_value_len);
 
     memcpy(store_data->value, a_value, a_value_len);
 
-    store_data->value_len = (a_value_len == (size_t) -1) ? strlen((const char* ) a_value) : a_value_len;
-    store_data->group = strdup(a_group);
+    store_data->value_len = (a_value_len == (size_t) -1) ? dap_strlen((const char*) a_value) : a_value_len;
+    store_data->group = dap_strdup(a_group);
     store_data->timestamp = time(NULL);
     lock();
-    int l_res = dap_db_add(store_data, 1);
+    int l_res = dap_chain_global_db_driver_add(store_data, 1);
     unlock();
 
     // Extract prefix if added successfuly, add history log and call notify callback if present
-    if (!l_res ){
-        char * l_group_prefix = extract_group_prefix (a_group);
+    if(!l_res) {
+        char * l_group_prefix = extract_group_prefix(a_group);
         history_group_item_t * l_history_group_item = NULL;
-        if ( l_group_prefix )
+        if(l_group_prefix)
             HASH_FIND_STR(s_history_group_items, l_group_prefix, l_history_group_item);
 
-        if ( l_history_group_item ){
-            if ( l_history_group_item->auto_track ){
+        if(l_history_group_item) {
+            if(l_history_group_item->auto_track) {
                 lock();
                 dap_db_history_add('a', store_data, 1);
                 unlock();
             }
-            if ( l_history_group_item->callback_notify )
-                l_history_group_item->callback_notify(l_history_group_item->callback_arg, 'a',l_group_prefix,a_group,a_key,a_value,a_value_len);
+            if(l_history_group_item->callback_notify)
+                l_history_group_item->callback_notify(l_history_group_item->callback_arg, 'a', l_group_prefix, a_group,
+                        a_key, a_value, a_value_len);
         }
-        if ( l_group_prefix)
-            DAP_DELETE( l_group_prefix);
-    }else {
-        log_it(L_ERROR,"Save error: %d",l_res);
+        if(l_group_prefix)
+            DAP_DELETE(l_group_prefix);
+    } else {
+        log_it(L_ERROR, "Save error: %d", l_res);
     }
     DAP_DELETE(store_data);
 
@@ -295,27 +301,28 @@ bool dap_chain_global_db_gr_del(const char *a_key, const char *a_group)
     if(!a_key)
         return NULL;
     pdap_store_obj_t store_data = DAP_NEW_Z_SIZE(dap_store_obj_t, sizeof(struct dap_store_obj));
-    store_data->key = strdup( a_key);
-    store_data->group = strdup( a_group);
+    store_data->key = dap_strdup(a_key);
+    store_data->group = dap_strdup(a_group);
     lock();
-    int l_res = dap_db_delete(store_data, 1);
+    int l_res = dap_chain_global_db_driver_delete(store_data, 1);
     unlock();
-    if (!l_res){
+    if(!l_res) {
         // Extract prefix
-        char * l_group_prefix = extract_group_prefix (a_group);
+        char * l_group_prefix = extract_group_prefix(a_group);
         history_group_item_t * l_history_group_item = NULL;
-        if ( l_group_prefix )
+        if(l_group_prefix)
             HASH_FIND_STR(s_history_group_items, l_group_prefix, l_history_group_item);
-        if (l_history_group_item ){
+        if(l_history_group_item) {
             if(l_history_group_item->auto_track) {
                 lock();
                 dap_db_history_add('d', store_data, 1);
                 unlock();
             }
-            if ( l_history_group_item->callback_notify )
-                l_history_group_item->callback_notify(l_history_group_item->callback_arg,'d',l_group_prefix,a_group, a_key, NULL, 0);
+            if(l_history_group_item->callback_notify)
+                l_history_group_item->callback_notify(l_history_group_item->callback_arg, 'd', l_group_prefix, a_group,
+                        a_key, NULL, 0);
         }
-        if ( l_group_prefix )
+        if(l_group_prefix)
             DAP_DELETE(l_group_prefix);
     }
     DAP_DELETE(store_data);
@@ -335,45 +342,65 @@ bool dap_chain_global_db_del(const char *a_key)
  */
 dap_global_db_obj_t** dap_chain_global_db_gr_load(const char *a_group, size_t *a_data_size_out)
 {
-    size_t l_query_len = (size_t) snprintf(NULL, 0, "(objectClass=%s)", a_group);
-    char *l_query = DAP_NEW_Z_SIZE(char, l_query_len + 1);
-    //const char *query = "(objectClass=addr_leased)";
-    snprintf(l_query, l_query_len + 1, "(objectClass=%s)", a_group);
     size_t count = 0;
     // Read data
     lock();
-    pdap_store_obj_t store_obj = dap_db_read_data(a_group, NULL, &count);
+    dap_store_obj_t *l_store_obj = dap_chain_global_db_driver_read(a_group, NULL, &count);
     unlock();
-    DAP_DELETE(l_query);
-    // Serialization data
-    dap_store_obj_pkt_t *pkt = dap_store_packet_multiple(store_obj, 0, count);
-    dab_db_free_pdap_store_obj_t(store_obj, count);
-    if(pkt)
-    {
-        size_t count_new = 0;
-        pdap_store_obj_t store_data = dap_store_unpacket(pkt, &count_new);
-        assert(count_new == count);
-        //char **data = DAP_NEW_SIZE(char*, (count_new + 1) * sizeof(char*));
-        dap_global_db_obj_t **data = DAP_NEW_Z_SIZE(dap_global_db_obj_t*,
-                (count_new + 1) * sizeof(dap_global_db_obj_t*)); // last item in mass must be zero
-        for(size_t i = 0; i < count_new; i++) {
-            pdap_store_obj_t store_data_cur = store_data + i;
-            assert(store_data_cur);
-            data[i] = DAP_NEW(dap_global_db_obj_t);
-            data[i]->key = strdup(store_data_cur->key);
-            data[i]->value_len = store_data_cur->value_len;
-            data[i]->value = DAP_NEW_Z_SIZE(uint8_t, store_data_cur->value_len + 1);
-            memcpy(data[i]->value, store_data_cur->value, store_data_cur->value_len);
-        }
-        DAP_DELETE(store_data);
-        DAP_DELETE(pkt);
-        if(a_data_size_out)
-            *a_data_size_out = count_new;
-        return data;
+    if(!l_store_obj || !count)
+        return NULL;
+    dap_global_db_obj_t **l_data = DAP_NEW_Z_SIZE(dap_global_db_obj_t*,
+            (count + 1) * sizeof(dap_global_db_obj_t*)); // last item in mass must be zero
+    for(size_t i = 0; i < count; i++) {
+        dap_store_obj_t *l_store_obj_cur = l_store_obj + i;
+        assert(l_store_obj_cur);
+        l_data[i] = DAP_NEW(dap_global_db_obj_t);
+        l_data[i]->key = dap_strdup(l_store_obj_cur->key);
+        l_data[i]->value_len = l_store_obj_cur->value_len;
+        l_data[i]->value = DAP_NEW_Z_SIZE(uint8_t, l_store_obj_cur->value_len + 1);
+        memcpy(l_data[i]->value, l_store_obj_cur->value, l_store_obj_cur->value_len);
     }
+    dap_store_obj_free(l_store_obj, count);
     if(a_data_size_out)
-        *a_data_size_out = 0;
-    return NULL;
+        *a_data_size_out = count;
+    return l_data;
+    /*size_t l_query_len = (size_t) snprintf(NULL, 0, "(objectClass=%s)", a_group);
+     char *l_query = DAP_NEW_Z_SIZE(char, l_query_len + 1);
+     //const char *query = "(objectClass=addr_leased)";
+     snprintf(l_query, l_query_len + 1, "(objectClass=%s)", a_group);
+     size_t count = 0;
+     // Read data
+     lock();
+     pdap_store_obj_t store_obj = dap_chain_global_db_driver_read(a_group, NULL, &count);
+     unlock();
+     DAP_DELETE(l_query);
+     // Serialization data
+     dap_store_obj_pkt_t *pkt = dap_store_packet_multiple(store_obj, 0, count);
+     dap_store_obj_free(store_obj, count);
+     if(pkt)
+     {
+     size_t count_new = 0;
+     pdap_store_obj_t store_data = dap_store_unpacket_multiple(pkt, &count_new);
+     assert(count_new == count);
+     //char **data = DAP_NEW_SIZE(char*, (count_new + 1) * sizeof(char*));
+     dap_global_db_obj_t **data = DAP_NEW_Z_SIZE(dap_global_db_obj_t*,
+     (count_new + 1) * sizeof(dap_global_db_obj_t*)); // last item in mass must be zero
+     for(size_t i = 0; i < count_new; i++) {
+     pdap_store_obj_t store_data_cur = store_data + i;
+     assert(store_data_cur);
+     data[i] = DAP_NEW(dap_global_db_obj_t);
+     data[i]->key = strdup(store_data_cur->key);
+     data[i]->value_len = store_data_cur->value_len;
+     data[i]->value = DAP_NEW_Z_SIZE(uint8_t, store_data_cur->value_len + 1);
+     memcpy(data[i]->value, store_data_cur->value, store_data_cur->value_len);
+     }
+     DAP_DELETE(store_data);
+     DAP_DELETE(pkt);
+     if(a_data_size_out)
+     *a_data_size_out = count_new;
+     return data;
+     }*/
+
 }
 
 dap_global_db_obj_t** dap_chain_global_db_load(size_t *a_data_size_out)
@@ -387,7 +414,7 @@ dap_global_db_obj_t** dap_chain_global_db_load(size_t *a_data_size_out)
  */
 bool dap_chain_global_db_obj_save(void* a_store_data, size_t a_objs_count)
 {
-    dap_store_obj_t* l_store_data = (dap_store_obj_t*) a_store_data;
+/*    dap_store_obj_t* l_store_data = (dap_store_obj_t*) a_store_data;
     if(l_store_data && a_objs_count > 0) {
         // real records
         size_t l_objs_count = a_objs_count;
@@ -399,7 +426,7 @@ bool dap_chain_global_db_obj_save(void* a_store_data, size_t a_objs_count)
             size_t l_count = 0;
             char *l_query = dap_strdup_printf("(&(cn=%s)(objectClass=%s))", l_obj->key, l_obj->group);
             lock();
-            dap_store_obj_t *l_read_store_data = dap_db_read_data(l_query,NULL, &l_count);
+            dap_store_obj_t *l_read_store_data = dap_chain_global_db_driver_read(l_query, NULL, &l_count);
             unlock();
             // whether to add a record
             if(l_obj->type == 'a' && l_read_store_data) {
@@ -419,57 +446,50 @@ bool dap_chain_global_db_obj_save(void* a_store_data, size_t a_objs_count)
                 // reduce the number of real records
                 l_objs_count--;
             }
-            dab_db_free_pdap_store_obj_t(l_read_store_data, l_count);
+            dap_store_obj_free(l_read_store_data, l_count);
             DAP_DELETE(l_query);
-        }
+        }*/
 
-        // save/delete data
-        if(l_objs_count > 0) {
+    // save/delete data
+    if(!a_objs_count)
+        return true;
 
-            lock();
-            int l_res = -1;
-            //add a record
-            if(l_store_data->type == 'a')
-                l_res = dap_db_add(l_store_data, a_objs_count);
-            //delete a record
-            if(l_store_data->type == 'd')
-                l_res = dap_db_delete(l_store_data, a_objs_count);
-            unlock();
-            // Extract prefix if added successfuly, add history log and call notify callback if present
-            if (!l_res){
-                for (size_t i =0; i< l_objs_count; i++ ){
-                    history_group_item_t * l_history_group_item = NULL;
-                    dap_store_obj_t* l_obj = l_store_data + i;
-                    char * l_group_prefix = extract_group_prefix (l_obj->group );
-                    if ( l_group_prefix )
-                        HASH_FIND_STR(s_history_group_items, l_group_prefix, l_history_group_item);
-
-                    if ( l_history_group_item ){
-                        if ( l_history_group_item->auto_track ){
-                            lock();
-                            dap_db_history_add(l_store_data->type, l_store_data, 1);
-                            unlock();
-                        }
-                        if ( l_history_group_item->callback_notify ){
-                                if (l_obj){
-                                    l_history_group_item->callback_notify( l_history_group_item->callback_arg, l_store_data->type,
-                                                                          l_group_prefix, l_obj->group , l_obj->key,
-                                                                          l_obj->value, l_obj->value_len );
-                                }else {
-                                    break;
-                                }
-                        }
+    lock();
+    int l_res = dap_chain_global_db_driver_appy(a_store_data, a_objs_count);
+    unlock();
+
+    // Extract prefix if added successfuly, add history log and call notify callback if present
+    if(!l_res) {
+        for(size_t i = 0; i < a_objs_count; i++) {
+            history_group_item_t * l_history_group_item = NULL;
+            dap_store_obj_t* l_obj = a_store_data + i;
+            char * l_group_prefix = extract_group_prefix(l_obj->group);
+            if(l_group_prefix)
+                HASH_FIND_STR(s_history_group_items, l_group_prefix, l_history_group_item);
+
+            if(l_history_group_item) {
+                if(l_history_group_item->auto_track) {
+                    lock();
+                    dap_db_history_add(l_obj->type, l_obj, 1);
+                    unlock();
+                }
+                if(l_history_group_item->callback_notify) {
+                    if(l_obj) {
+                        l_history_group_item->callback_notify(l_history_group_item->callback_arg,
+                                l_obj->type,
+                                l_group_prefix, l_obj->group, l_obj->key,
+                                l_obj->value, l_obj->value_len);
+                    } else {
+                        break;
                     }
-                    DAP_DELETE( l_group_prefix);
                 }
-
             }
-            if(!l_res)
-                return true;
+            DAP_DELETE(l_group_prefix);
         }
-        else
-            return true;
+
     }
+    if(!l_res)
+        return true;
     return false;
 }
 
@@ -477,51 +497,56 @@ bool dap_chain_global_db_gr_save(dap_global_db_obj_t* a_objs, size_t a_objs_coun
 {
     dap_store_obj_t *l_store_data = DAP_NEW_Z_SIZE(dap_store_obj_t, a_objs_count * sizeof(struct dap_store_obj));
     time_t l_timestamp = time(NULL);
+    char *l_group = dap_strdup(a_group);
     for(size_t q = 0; q < a_objs_count; ++q) {
         dap_store_obj_t *store_data_cur = l_store_data + q;
         dap_global_db_obj_t *a_obj_cur = a_objs + q;
         store_data_cur->key = a_obj_cur->key;
-        store_data_cur->group = strdup(a_group);
+        store_data_cur->group = l_group;
         store_data_cur->value = a_obj_cur->value;
         store_data_cur->value_len = a_obj_cur->value_len;
         store_data_cur->timestamp = l_timestamp;
     }
     if(l_store_data) {
         lock();
-        int l_res = dap_db_add(l_store_data, a_objs_count);
+        int l_res = dap_chain_global_db_driver_add(l_store_data, a_objs_count);
         unlock();
-        if (!l_res){
-            for (size_t i =0; i< a_objs_count; i++ ){
+        if(!l_res) {
+            for(size_t i = 0; i < a_objs_count; i++) {
                 history_group_item_t * l_history_group_item = NULL;
                 dap_store_obj_t *l_obj = l_store_data + i;
 
-                char * l_group_prefix = extract_group_prefix (l_obj->group );
-                if ( l_group_prefix )
+                char * l_group_prefix = extract_group_prefix(l_obj->group);
+                if(l_group_prefix)
                     HASH_FIND_STR(s_history_group_items, l_group_prefix, l_history_group_item);
 
-                if ( l_history_group_item ){
-                    if ( l_history_group_item->auto_track ){
+                if(l_history_group_item) {
+                    if(l_history_group_item->auto_track) {
                         lock();
                         dap_db_history_add('a', l_store_data, 1);
                         unlock();
                     }
-                    if ( l_history_group_item->callback_notify ){
-                            if (l_obj){
-                                l_history_group_item->callback_notify(l_history_group_item->callback_arg,'a',l_group_prefix, l_obj->group , l_obj->key,
-                                               l_obj->value, l_obj->value_len );
-                            }else {
-                                break;
-                            }
+                    if(l_history_group_item->callback_notify) {
+                        if(l_obj) {
+                            l_history_group_item->callback_notify(l_history_group_item->callback_arg, 'a',
+                                    l_group_prefix, l_obj->group, l_obj->key,
+                                    l_obj->value, l_obj->value_len);
+                        } else {
+                            break;
+                        }
                     }
                 }
-                DAP_DELETE( l_group_prefix);
+                DAP_DELETE(l_group_prefix);
             }
 
         }
-        DAP_DELETE(l_store_data); //dab_db_free_pdap_store_obj_t(store_data, a_objs_count);
-        if(!l_res)
+        DAP_DELETE(l_store_data); //dap_store_obj_free(store_data, a_objs_count);
+        if(!l_res){
+            DAP_DELETE(l_group);
             return true;
+        }
     }
+    DAP_DELETE(l_group);
     return false;
 }
 
@@ -537,21 +562,21 @@ bool dap_chain_global_db_save(dap_global_db_obj_t* a_objs, size_t a_objs_count)
  */
 char* dap_chain_global_db_hash(const uint8_t *data, size_t data_size)
 {
-    return dap_db_driver_db_hash(data,data_size);
+    return dap_chain_global_db_driver_hash(data, data_size);
 }
 
 /**
-* Parse data from dap_db_log_pack()
-*
-* return dap_store_obj_t*
-*/
+ * Parse data from dap_db_log_pack()
+ *
+ * return dap_store_obj_t*
+ */
 void* dap_db_log_unpack(const void *a_data, size_t a_data_size, size_t *a_store_obj_count)
 {
     const dap_store_obj_pkt_t *l_pkt = (const dap_store_obj_pkt_t*) a_data;
-    if(!l_pkt || l_pkt->data_size != ( (size_t ) a_data_size - sizeof(dap_store_obj_pkt_t)))
+    if(!l_pkt || l_pkt->data_size != ((size_t) a_data_size - sizeof(dap_store_obj_pkt_t)))
         return NULL;
     size_t l_store_obj_count = 0;
-    dap_store_obj_t *l_obj = dap_store_unpacket(l_pkt, &l_store_obj_count);
+    dap_store_obj_t *l_obj = dap_store_unpacket_multiple(l_pkt, &l_store_obj_count);
     if(a_store_obj_count)
         *a_store_obj_count = l_store_obj_count;
 
@@ -588,7 +613,7 @@ char* dap_db_log_get_diff(size_t *a_data_size_out)
         l_keys_vals[i] = l_obj_cur->key;
         l_keys_vals[i + l_data_size_out] = (char*) l_obj_cur->value;
     }
-    if (a_data_size_out)
+    if(a_data_size_out)
         *a_data_size_out = l_data_size_out;
     // last element - NULL (marker)
     l_keys_vals[l_data_size_out * 2] = NULL;
diff --git a/dap_chain_global_db_driver.c b/dap_chain_global_db_driver.c
index 2cd50549fd13c860a2db31f1099c330acbdc1298..9e67016b43b565101c7d94e2facff7933c06e4aa 100644
--- a/dap_chain_global_db_driver.c
+++ b/dap_chain_global_db_driver.c
@@ -160,12 +160,126 @@ void dap_store_obj_free(dap_store_obj_t *a_store_obj, size_t a_store_count)
     DAP_DELETE(a_store_obj);
 }
 
+static size_t dap_db_get_size_pdap_store_obj_t(pdap_store_obj_t store_obj)
+{
+    size_t size = sizeof(uint32_t) + 2 * sizeof(uint16_t) + sizeof(size_t) + sizeof(time_t) + dap_strlen(store_obj->group) +
+            dap_strlen(store_obj->key) + store_obj->value_len;
+    return size;
+}
+
+/**
+ * serialization
+ * @param a_store_obj_count count of structures store_obj
+ * @param a_timestamp create data time
+ * @param a_size_out[out] size of output structure
+ * @return NULL in case of an error
+ */
+dap_store_obj_pkt_t *dap_store_packet_multiple(pdap_store_obj_t a_store_obj, time_t a_timestamp, size_t a_store_obj_count)
+{
+    if(!a_store_obj || a_store_obj_count < 1)
+        return NULL;
+    size_t l_data_size_out = sizeof(uint32_t); // size of output data
+    // calculate output structure size
+    for(size_t l_q = 0; l_q < a_store_obj_count; ++l_q)
+        l_data_size_out += dap_db_get_size_pdap_store_obj_t(&a_store_obj[l_q]);
+
+    dap_store_obj_pkt_t *l_pkt = DAP_NEW_Z_SIZE(dap_store_obj_pkt_t, sizeof(dap_store_obj_pkt_t) + l_data_size_out);
+    l_pkt->data_size = l_data_size_out;
+    l_pkt->timestamp = a_timestamp;
+    uint64_t l_offset = 0;
+    uint32_t l_count = (uint32_t) a_store_obj_count;
+    memcpy(l_pkt->data + l_offset, &l_count, sizeof(uint32_t));
+    l_offset += sizeof(uint32_t);
+    for( size_t l_q = 0; l_q < a_store_obj_count; ++l_q) {
+        dap_store_obj_t obj = a_store_obj[l_q];
+        //uint16_t section_size = (uint16_t) dap_strlen(obj.section);
+        uint16_t group_size = (uint16_t) dap_strlen(obj.group);
+        uint16_t key_size = (uint16_t) dap_strlen(obj.key);
+        memcpy(l_pkt->data + l_offset, &obj.type, sizeof(int));
+        l_offset += sizeof(int);
+        //memcpy(l_pkt->data + l_offset, &section_size, sizeof(uint16_t));
+        //l_offset += sizeof(uint16_t);
+        //memcpy(l_pkt->data + l_offset, obj.section, section_size);
+        //l_offset += section_size;
+        memcpy(l_pkt->data + l_offset, &group_size, sizeof(uint16_t));
+        l_offset += sizeof(uint16_t);
+        memcpy(l_pkt->data + l_offset, obj.group, group_size);
+        l_offset += group_size;
+        memcpy(l_pkt->data + l_offset, &obj.timestamp, sizeof(time_t));
+        l_offset += sizeof(time_t);
+        memcpy(l_pkt->data + l_offset, &key_size, sizeof(uint16_t));
+        l_offset += sizeof(uint16_t);
+        memcpy(l_pkt->data + l_offset, obj.key, key_size);
+        l_offset += key_size;
+        memcpy(l_pkt->data + l_offset, &obj.value_len, sizeof(size_t));
+        l_offset += sizeof(size_t);
+        memcpy(l_pkt->data + l_offset, obj.value, obj.value_len);
+        l_offset += obj.value_len;
+    }
+    assert(l_data_size_out == l_offset);
+    return l_pkt;
+}
+/**
+ * deserialization
+ * @param store_obj_count[out] count of the output structures store_obj
+ * @return NULL in case of an error*
+ */
+
+dap_store_obj_t *dap_store_unpacket_multiple(const dap_store_obj_pkt_t *pkt, size_t *store_obj_count)
+{
+    if(!pkt || pkt->data_size < 1)
+        return NULL;
+    uint64_t offset = 0;
+    uint32_t count;
+    memcpy(&count, pkt->data, sizeof(uint32_t));
+    offset += sizeof(uint32_t);
+    dap_store_obj_t *store_obj = DAP_NEW_Z_SIZE(dap_store_obj_t, count * sizeof(struct dap_store_obj));
+    for(size_t q = 0; q < count; ++q) {
+        dap_store_obj_t *obj = store_obj + q;
+        uint16_t str_size;
+        memcpy(&obj->type, pkt->data + offset, sizeof(int));
+        offset += sizeof(int);
+
+        //memcpy(&str_size, pkt->data + offset, sizeof(uint16_t));
+        //offset += sizeof(uint16_t);
+        //obj->section = DAP_NEW_Z_SIZE(char, str_size + 1);
+        //memcpy(obj->section, pkt->data + offset, str_size);
+        //offset += str_size;
+
+        memcpy(&str_size, pkt->data + offset, sizeof(uint16_t));
+        offset += sizeof(uint16_t);
+        obj->group = DAP_NEW_Z_SIZE(char, str_size + 1);
+        memcpy(obj->group, pkt->data + offset, str_size);
+        offset += str_size;
+
+        memcpy(&obj->timestamp, pkt->data + offset, sizeof(time_t));
+        offset += sizeof(time_t);
+
+        memcpy(&str_size, pkt->data + offset, sizeof(uint16_t));
+        offset += sizeof(uint16_t);
+        obj->key = DAP_NEW_Z_SIZE(char, str_size + 1);
+        memcpy(obj->key, pkt->data + offset, str_size);
+        offset += str_size;
+
+        memcpy(&obj->value_len, pkt->data + offset, sizeof(size_t));
+        offset += sizeof(size_t);
+
+        obj->value = DAP_NEW_Z_SIZE(uint8_t, obj->value_len + 1);
+        memcpy(obj->value, pkt->data + offset, obj->value_len);
+        offset += obj->value_len;
+    }
+    assert(pkt->data_size == offset);
+    if(store_obj_count)
+        *store_obj_count = count;
+    return store_obj;
+}
+
 /**
  * Calc hash for data
  *
  * return hash or NULL
  */
-char* dap_db_driver_db_hash(const uint8_t *data, size_t data_size)
+char* dap_chain_global_db_driver_hash(const uint8_t *data, size_t data_size)
 {
     if(!data || data_size <= 0)
         return NULL;
@@ -311,7 +425,7 @@ static void* func_write_buf(void * arg)
     pthread_exit(0);
 }
 
-int dap_db_add(pdap_store_obj_t a_store_obj, size_t a_store_count)
+int dap_chain_global_db_driver_appy(pdap_store_obj_t a_store_obj, size_t a_store_count)
 {
     //dap_store_obj_t *l_store_obj = dap_store_obj_copy(a_store_obj, a_store_count);
     if(!a_store_obj || !a_store_count)
@@ -344,19 +458,33 @@ int dap_db_add(pdap_store_obj_t a_store_obj, size_t a_store_count)
     return 0;
 }
 
-int dap_db_delete(pdap_store_obj_t a_store_obj, size_t a_store_count)
+int dap_chain_global_db_driver_add(pdap_store_obj_t a_store_obj, size_t a_store_count)
+{
+    a_store_obj->type = 'd';
+    return dap_chain_global_db_driver_appy(a_store_obj, a_store_count);
+}
+
+int dap_chain_global_db_driver_delete(pdap_store_obj_t a_store_obj, size_t a_store_count)
 {
     a_store_obj->type = 'd';
-    return dap_db_add(a_store_obj, a_store_count);
+    return dap_chain_global_db_driver_appy(a_store_obj, a_store_count);
 }
 
-dap_store_obj_t* dap_db_read_data(const char *a_group, const char *a_key, size_t *count_out)
+/**
+ * Read several items
+ *
+ * a_group - group name
+ * a_key - key name, may by NULL, it means reading the whole group
+ * a_count_out[in], how many items to read, 0 - no limits
+ * a_count_out[out], how many items was read
+ */
+dap_store_obj_t* dap_chain_global_db_driver_read(const char *a_group, const char *a_key, size_t *a_count_out)
 {
     dap_store_obj_t *l_ret = NULL;
     // wait apply write buffer
     wait_write_buf();
-    // read record
+    // read records using the selected database engine
     if(s_drv_callback.read_store_obj)
-        l_ret = s_drv_callback.read_store_obj(a_group, a_key, count_out);
+        l_ret = s_drv_callback.read_store_obj(a_group, a_key, a_count_out);
     return l_ret;
 }
diff --git a/dap_chain_global_db_driver.h b/dap_chain_global_db_driver.h
index 9d819aac2198e3a05af11c3d24c4cbc1d80963a7..efd2631763ae086f76531870362e8b32af1cb684 100644
--- a/dap_chain_global_db_driver.h
+++ b/dap_chain_global_db_driver.h
@@ -65,20 +65,17 @@ void dap_db_driver_deinit(void);
 dap_store_obj_t* dap_store_obj_copy(dap_store_obj_t *a_store_obj, size_t a_store_count);
 void dap_store_obj_free(dap_store_obj_t *a_store_obj, size_t a_store_count);
 
-char* dap_db_driver_db_hash(const uint8_t *data, size_t data_size);
+char* dap_chain_global_db_driver_hash(const uint8_t *data, size_t data_size);
 
-int dap_db_add(pdap_store_obj_t a_store_obj, size_t a_store_count);
-int dap_db_delete(pdap_store_obj_t a_store_obj, size_t a_store_count);
-dap_store_obj_t* dap_db_read_data(const char *a_group, const char *a_key, size_t *count_out);
+int dap_chain_global_db_driver_appy(pdap_store_obj_t a_store_obj, size_t a_store_count);
+int dap_chain_global_db_driver_add(pdap_store_obj_t a_store_obj, size_t a_store_count);
+int dap_chain_global_db_driver_delete(pdap_store_obj_t a_store_obj, size_t a_store_count);
+dap_store_obj_t* dap_chain_global_db_driver_read(const char *a_group, const char *a_key, size_t *count_out);
 
-pdap_store_obj_t dap_db_read_file_data(const char *a_path, const char *a_group); // state of emergency only, if LDB database is inaccessible
-dap_store_obj_pkt_t *dap_store_packet_single(pdap_store_obj_t a_store_obj);
 dap_store_obj_pkt_t *dap_store_packet_multiple(pdap_store_obj_t a_store_obj,
 		time_t a_timestamp, size_t a_store_obj_count);
-dap_store_obj_t *dap_store_unpacket(const dap_store_obj_pkt_t *a_pkt,
+dap_store_obj_t *dap_store_unpacket_multiple(const dap_store_obj_pkt_t *a_pkt,
 		size_t *a_store_obj_count);
 
-void dab_db_free_pdap_store_obj_t(pdap_store_obj_t a_store_data,
-		size_t a_count);
 
 #endif //_GLOBAL_DB_DRIVER_H_
diff --git a/dap_chain_global_db_driver_sqlite.c b/dap_chain_global_db_driver_sqlite.c
index ef8984ba5981c5b33498f785a8e7803af63c0a7d..e3ec3ef143f9c7ca3b0fae1f0f3e3b1a5696f61e 100644
--- a/dap_chain_global_db_driver_sqlite.c
+++ b/dap_chain_global_db_driver_sqlite.c
@@ -91,9 +91,9 @@ int dap_db_driver_sqlite_init(const char *a_filename_db, dap_db_driver_callbacks
             printf("can't set new journal mode\n");
 
         if(!dap_db_driver_sqlite_set_pragma(s_db, "page_size", "1024")) // DELETE | TRUNCATE | PERSIST | MEMORY | WAL | OFF
-                    printf("can't set page_size\n");
-  //      *PRAGMA page_size = bytes; // page size DB; it is reasonable to make it equal to the size of the disk cluster 4096
-    //     *PRAGMA cache_size = -kibibytes; // by default it is equal to 2000 pages of database
+            printf("can't set page_size\n");
+        //      *PRAGMA page_size = bytes; // page size DB; it is reasonable to make it equal to the size of the disk cluster 4096
+        //     *PRAGMA cache_size = -kibibytes; // by default it is equal to 2000 pages of database
 //
         a_drv_callback->apply_store_obj = dap_db_driver_sqlite_apply_store_obj;
         a_drv_callback->read_store_obj = dap_db_driver_sqlite_read_store_obj;
@@ -268,16 +268,10 @@ static int dap_db_driver_sqlite_create_group_table(const char *a_table_name)
  * SELECT * FROM data WHERE hex(sd) LIKE '%370%'
  * hex(x'0806') -> '08f6' или quote(sd) -> X'08f6'
  * substr(x'031407301210361320690000',3,2) -> x'0730'
- * преобразование типов:
+ *
  * CAST(substr(sd,5,2) as TEXT)
  * additional function of line to number _uint8
  * byte_to_bin(x'ff') -> 255
- * логические операции:
- // [out] res - идентификатор запроса, память нужно будет удалять через dap_db_driver_sqlite_query_free()
- // "SELECT name FROM sqlite_master WHERE type='table' ORDER BY name"
- // [out] error_message - сюда будет записано текстовое сообщение об ошибке (память требует удаления через sqlite_free())
- // return: возвращает код ошибки SQL (если не равно SQLITE_OK(0) то ошибка)
- * return 0 if Ok, else error code >0
  */
 static int dap_db_driver_sqlite_query(sqlite3 *db, char *query, sqlite3_stmt **l_res, char **l_error_message)
 {
@@ -493,17 +487,40 @@ int dap_db_driver_sqlite_apply_store_obj(dap_store_obj_t *a_store_obj)
 }
 
 /**
- * Read data
- * a_key may be NULL
+ * Read several items
+ *
+ * a_group - group name
+ * a_key - key name, may by NULL, it means reading the whole group
+ * a_count_out[in], how many items to read, 0 - no limits
+ * a_count_out[out], how many items was read
  */
-dap_store_obj_t* dap_db_driver_sqlite_read_store_obj(const char *a_group, const char *a_key)
+dap_store_obj_t* dap_db_driver_sqlite_read_store_obj(const char *a_group, const char *a_key, size_t *a_count_out)
 {
     dap_store_obj_t *l_obj = NULL;
     char *l_error_message = NULL;
     sqlite3_stmt *l_res;
-    if(!a_group || !a_key)
+    if(!a_group)
         return NULL;
-    char *l_str_query = sqlite3_mprintf("SELECT ts,value FROM '%s' WHERE key='%s' LIMIT 1", a_group, a_key);
+    // no limit
+    int l_count_out = 0;
+    if(a_count_out)
+        l_count_out = *a_count_out;
+    char *l_str_query;
+    if(a_key) {
+        if(l_count_out)
+            l_str_query = sqlite3_mprintf("SELECT ts,key,value FROM '%s' WHERE key='%s' LIMIT %d ORDER BY id ASC",
+                    a_group, a_key, l_count_out);
+        else
+            l_str_query = sqlite3_mprintf("SELECT ts,key,value FROM '%s' WHERE key='%s' ORDER BY id ASC", a_group,
+                    a_key);
+    }
+    else {
+        if(l_count_out)
+            l_str_query = sqlite3_mprintf("SELECT ts,key,value FROM '%s' LIMIT %d ORDER BY id ASC",
+                    a_group, a_key, l_count_out);
+        else
+            l_str_query = sqlite3_mprintf("SELECT ts,key,value FROM '%s' ORDER BY id ASC", a_group, a_key);
+    }
     int l_ret = dap_db_driver_sqlite_query(s_db, l_str_query, &l_res, &l_error_message);
     sqlite3_free(l_str_query);
     if(l_ret != SQLITE_OK) {
@@ -511,7 +528,11 @@ dap_store_obj_t* dap_db_driver_sqlite_read_store_obj(const char *a_group, const
         dap_db_driver_sqlite_free(l_error_message);
         return NULL;
     }
+
+    //int b = qlite3_column_count(s_db);
     SQLITE_ROW_VALUE *l_row = NULL;
+    l_count_out = 0;
+    int l_count_sized = 0;
     do {
         l_ret = dap_db_driver_sqlite_fetch_array(l_res, &l_row);
         if(l_ret != SQLITE_ROW && l_ret != SQLITE_DONE)
@@ -519,31 +540,45 @@ dap_store_obj_t* dap_db_driver_sqlite_read_store_obj(const char *a_group, const
             log_it(L_ERROR, "read l_ret=%d, %s\n", sqlite3_errcode(s_db), sqlite3_errmsg(s_db));
         }
         if(l_ret == SQLITE_ROW && l_row) {
-            l_obj = DAP_NEW_Z(dap_store_obj_t);
-            l_obj->group = dap_strdup(a_group);
-            l_obj->key = dap_strdup(a_key);
+            if(l_count_out >= l_count_sized) {
+                l_count_sized += 10;
+                l_obj = DAP_REALLOC(l_obj, sizeof(dap_store_obj_t) * l_count_sized);
+                memset(l_obj + l_count_out, 0, sizeof(dap_store_obj_t) * (l_count_sized - l_count_out));
+            }
+            dap_store_obj_t *l_obj_cur = l_obj + l_count_out;
+
+            l_obj_cur->group = dap_strdup(a_group);
+            l_obj_cur->key = dap_strdup(a_key);
 
             for(int l_iCol = 0; l_iCol < l_row->count; l_iCol++) {
                 SQLITE_VALUE *cur_val = l_row->val + l_iCol;
                 switch (l_iCol) {
                 case 0:
                     if(cur_val->type == SQLITE_INTEGER)
-                        l_obj->timestamp = cur_val->val.val_int64;
-                    break; // id
+                        l_obj_cur->timestamp = cur_val->val.val_int64;
+                    break; // ts
                 case 1:
+                    if(cur_val->type == SQLITE_TEXT)
+                        l_obj_cur->key = dap_strdup(cur_val->val.val_str);
+                    break; // key
+                case 2:
                     if(cur_val->type == SQLITE_BLOB)
                     {
-                        l_obj->value_len = (size_t) cur_val->len;
-                        l_obj->value = DAP_NEW_SIZE(uint8_t, l_obj->value_len);
-                        memcpy(l_obj->value, cur_val->val.val_blob, l_obj->value_len);
+                        l_obj_cur->value_len = (size_t) cur_val->len;
+                        l_obj_cur->value = DAP_NEW_SIZE(uint8_t, l_obj_cur->value_len);
+                        memcpy(l_obj_cur->value, cur_val->val.val_blob, l_obj_cur->value_len);
                     }
+                    break;// value
                 }
             }
+            l_count_out++;
         }
         dap_db_driver_sqlite_row_free(l_row);
     } while(l_row);
 
     dap_db_driver_sqlite_query_free(l_res);
 
+    if(a_count_out)
+        *a_count_out = l_count_out;
     return l_obj;
 }
diff --git a/dap_chain_global_db_driver_sqlite.h b/dap_chain_global_db_driver_sqlite.h
index f75b770103443a4ebddb6c9fcbd325074976e6f1..bb33f18a8d7abe5facb2e3e6ae056dd714aaa9db 100644
--- a/dap_chain_global_db_driver_sqlite.h
+++ b/dap_chain_global_db_driver_sqlite.h
@@ -44,4 +44,4 @@ int dap_db_driver_sqlite_end_transaction(void);
 // Apply data (write or delete)
 int dap_db_driver_sqlite_apply_store_obj(dap_store_obj_t *a_store_obj);
 // Read data
-dap_store_obj_t* dap_db_driver_sqlite_read_store_obj(const char *a_group, const char *a_key);
+dap_store_obj_t* dap_db_driver_sqlite_read_store_obj(const char *a_group, const char *a_key, size_t *a_count_out);
diff --git a/dap_chain_global_db_hist.c b/dap_chain_global_db_hist.c
index f95ce13c8b0288c34d3fb6599604f0ce60abf160..345858e202beac3a4d1a174a6a086d5fa5c02011 100755
--- a/dap_chain_global_db_hist.c
+++ b/dap_chain_global_db_hist.c
@@ -82,7 +82,7 @@ uint8_t* dap_db_log_pack(dap_global_db_obj_t *a_obj, size_t *a_data_size_out)
             l_obj->key = dap_strdup(l_keys[i]);
         }
         if (l_obj == NULL){
-            dab_db_free_pdap_store_obj_t(l_store_obj, l_count);
+            dap_store_obj_free(l_store_obj, l_count);
             dap_strfreev(l_keys);
             return NULL;
         }
@@ -96,7 +96,7 @@ uint8_t* dap_db_log_pack(dap_global_db_obj_t *a_obj, size_t *a_data_size_out)
     // serialize data
     dap_store_obj_pkt_t *l_data_out = dap_store_packet_multiple(l_store_obj, l_timestamp, l_count);
 
-    dab_db_free_pdap_store_obj_t(l_store_obj, l_count);
+    dap_store_obj_free(l_store_obj, l_count);
     dap_strfreev(l_keys);
 
     if(l_data_out && a_data_size_out) {
@@ -148,8 +148,7 @@ bool dap_db_history_add(char a_type, pdap_store_obj_t a_store_obj, size_t a_dap_
     l_store_data.value_len = l_str_len+1;
     l_store_data.group = GROUP_LOCAL_HISTORY;
     l_store_data.timestamp = time(NULL);
-    int l_res = dap_db_add(&l_store_data, 1);
-    //printf("!!!\n!!!HISTORY store save l_res=%d ts=%lld text=%s\n!!!\n",l_res,l_store_data.timestamp,l_str);
+    int l_res = dap_chain_global_db_driver_add(&l_store_data, 1);
     if(l_rec.keys_count > 1)
         DAP_DELETE(l_rec.keys);
     DAP_DELETE(l_str);
diff --git a/dap_chain_global_db_hist.h b/dap_chain_global_db_hist.h
index b21d6341919d89f021b6384cebf05151db39e041..62e98c5844bf6cc84f79563db42850d416a41761 100755
--- a/dap_chain_global_db_hist.h
+++ b/dap_chain_global_db_hist.h
@@ -1,7 +1,7 @@
 #pragma once
 
 #include <stdbool.h>
-#include "dap_chain_global_db_pvt.h"
+#include "dap_chain_global_db_driver.h"
 
 #define GLOBAL_DB_HIST_REC_SEPARATOR "\r;"
 #define GLOBAL_DB_HIST_KEY_SEPARATOR "\a;"
diff --git a/dap_chain_global_db_pvt.c b/dap_chain_global_db_pvt.c
deleted file mode 100755
index 52a0028bc0980d618dae92bd682b4b5337832ada..0000000000000000000000000000000000000000
--- a/dap_chain_global_db_pvt.c
+++ /dev/null
@@ -1,575 +0,0 @@
-#include <string.h>
-#include <stdio.h>
-#include <assert.h>
-#include <time.h>
-
-#include "dap_chain_global_db.h"
-#include "dap_chain_global_db_pvt.h"
-#include "dap_strfuncs.h"
-#include "dap_list.h"
-
-#define LOG_TAG "dap_global_db"
-#define TDB_PREFIX_LEN 7
-
-static struct ldb_context *s_ldb = NULL;
-static TALLOC_CTX *s_mem_ctx = NULL;
-
-//static int dap_store_len = 0; // initialized only when reading from local db
-static char *dap_db_path = NULL;
-
-#define CALL2(a, b, ...) (a), (b)
-#define dap_db_add_record(...) dap_db_merge(CALL2(__VA_ARGS__, 0))
-
-static int dap_db_add_msg(struct ldb_message *a_msg)
-{
-    if(ldb_msg_sanity_check(s_ldb, a_msg) != LDB_SUCCESS) {
-        log_it(L_ERROR, "LDB message is inconsistent: %s", ldb_errstring(s_ldb));
-        return -1;
-    }
-    ldb_transaction_start(s_ldb);
-    int status = ldb_add(s_ldb, a_msg);
-    // Delete the entry if it already exist and add again
-    if(status == LDB_ERR_ENTRY_ALREADY_EXISTS) {
-        ldb_delete(s_ldb, a_msg->dn);
-        status = ldb_add(s_ldb, a_msg);
-    }
-    if(status != LDB_SUCCESS) {
-        if(status == LDB_ERR_ENTRY_ALREADY_EXISTS) {
-            log_it(L_INFO, "Entry %s already present, skipped", ldb_dn_get_linearized(a_msg->dn));
-        }
-        else {
-            log_it(L_ERROR, "LDB adding error: %s", ldb_errstring(s_ldb));
-        }
-        ldb_transaction_cancel(s_ldb);
-        return -2;
-    }
-    else {
-        ldb_transaction_commit(s_ldb);
-        //log_it(L_INFO, "Entry %s added", ldb_dn_get_linearized(a_msg->dn));
-        return 0;
-    }
-}
-
-/**
- * @brief dap_db_group_create
- * @param a_group
- */
-void dap_db_group_create(const char * a_group)
-{
-    struct ldb_message *msg;
-
-    // level 2: group record
-    msg = ldb_msg_new(s_ldb);
-    msg->dn = ldb_dn_new(s_mem_ctx, s_ldb, "ou=addrs_leased,dc=kelvin_nodes");
-    ldb_msg_add_string(msg, "ou", a_group );
-    ldb_msg_add_string(msg, "objectClass", "group");
-    ldb_msg_add_string(msg, "section", "kelvin_nodes");
-    ldb_msg_add_string(msg, "description", "Whitelist of Kelvin blockchain nodes");
-    dap_db_add_msg(msg);
-    talloc_free(msg->dn);
-    talloc_free(msg);
-
-}
-
-/**
- * @brief dap_db_init
- * @param path
- * @return
- */
-int dap_db_init(const char *path)
-{
-    s_mem_ctx = talloc_new(NULL);
-    if(ldb_global_init() != 0) {
-        log_it(L_ERROR, "Couldn't initialize LDB's global information");
-        return -1;
-    };
-    if((s_ldb = ldb_init(s_mem_ctx, NULL)) != LDB_SUCCESS) {
-        log_it(L_INFO, "ldb context initialized");
-        char *l_tdb_path = DAP_NEW_Z_SIZE(char,strlen(path) + TDB_PREFIX_LEN );
-        memset(l_tdb_path, '\0', strlen(path) + TDB_PREFIX_LEN);
-        strcat(l_tdb_path, "tdb://"); // using tdb for simplicity, no need for separate LDAP server
-        strcat(l_tdb_path, path);
-        struct ldb_result *data_message;
-        if(ldb_connect(s_ldb, l_tdb_path, 0, NULL) != LDB_SUCCESS) {
-            log_it(L_ERROR, "Couldn't connect to database");
-            DAP_DELETE(l_tdb_path);
-            return 1;
-        }
-        dap_db_path = strdup(l_tdb_path);
-        const char *query = "(dn=*)";
-        if(ldb_search(s_ldb, s_mem_ctx, &data_message, NULL, LDB_SCOPE_DEFAULT, NULL, "%s", query) != LDB_SUCCESS) {
-            log_it(L_ERROR, "Database querying failed");
-            DAP_DELETE(l_tdb_path);
-            return 2;
-        }
-        struct ldb_message *msg;
-        if(data_message->count == 0) {
-            // level 1: section record
-            msg = ldb_msg_new(s_ldb);
-            msg->dn = ldb_dn_new(s_mem_ctx, s_ldb, "dc=kelvin_nodes");
-            ldb_msg_add_string(msg, "dc", "kelvin_nodes");
-            ldb_msg_add_string(msg, "objectClass", "top");
-            ldb_msg_add_string(msg, "objectClass", "section");
-            dap_db_add_msg(msg);
-
-            // level 2: groups
-            dap_db_group_create( GROUP_LOCAL_HISTORY);
-            dap_db_group_create( GROUP_LOCAL_GENERAL );
-            dap_db_group_create( GROUP_LOCAL_NODE_LAST_TS);
-
-        }
-        talloc_free(data_message);
-        DAP_DELETE(l_tdb_path);
-        return 0;
-    }
-    else {
-        log_it(L_ERROR, "Couldn't initialize LDB context");
-        return -2;
-    }
-}
-
-int dap_db_del_msg(struct ldb_dn *ldn)
-{
-    ldb_transaction_start(s_ldb);
-    int status = ldb_delete(s_ldb, ldn);
-    if(status != LDB_SUCCESS) {
-        log_it(L_ERROR, "LDB deleting error: %s", ldb_errstring(s_ldb));
-        ldb_transaction_cancel(s_ldb);
-        return -2;
-    }
-    else {
-        ldb_transaction_commit(s_ldb);
-        //log_it(L_INFO, "Entry %s deleted", ldb_dn_get_linearized(ldn));
-        return 0;
-    }
-}
-
-static int compare_message_items(const void * l_a, const void * l_b)
-{
-    const struct ldb_message *l_item_a = (const struct ldb_message*) l_a;
-    const struct ldb_message *l_item_b = (const struct ldb_message*) l_b;
-    const struct ldb_val *l_val_a = ldb_msg_find_ldb_val(l_item_a, "time");
-    const struct ldb_val *l_val_b = ldb_msg_find_ldb_val(l_item_b, "time");
-    time_t timestamp_a = 0;
-    time_t timestamp_b = 0;
-    if(l_val_a)
-        memcpy(&timestamp_a, l_val_a->data, min(sizeof(time_t), l_val_a->length));
-    if(l_val_b)
-        memcpy(&timestamp_b, l_val_b->data, min(sizeof(time_t), l_val_b->length));
-    if(timestamp_a == timestamp_b)
-        return 0;
-    if(timestamp_a < timestamp_b)
-        return -1;
-    return 1;
-}
-
-/**
- * Get data from base
- *
- * query RFC2254 (The String Representation of LDAP Search Filters)
- * sample:
- * (uid=testuser)    Matches to all users that have exactly the value testuser for the attribute uid.
- * (uid=test*)    Matches to all users that have values for the attribute uid that start with test.
- * (!(uid=test*))    Matches to all users that have values for the attribute uid that do not start with test.
- * (&(department=1234)(city=Paris)) Matches to all users that have exactly the value 1234 for the attribute department and exactly the value Paris for the attribute city .
- *
- */
-pdap_store_obj_t dap_db_read_data_ldb(const char *a_query, size_t *a_count)
-{
-    struct ldb_result *data_message;
-    /*
-     CN      commonName (2.5.4.3)
-     L       localityName (2.5.4.7)
-     ST      stateOrProvinceName (2.5.4.8)
-     O       organizationName (2.5.4.10)
-     OU      organizationalUnitName (2.5.4.11)
-     C       countryName (2.5.4.6)
-     STREET  streetAddress (2.5.4.9)
-     DC      domainComponent (0.9.2342.19200300.100.1.25)
-     UID     userId (0.9.2342.19200300.100.1.1)
-     */
-    if(ldb_connect(s_ldb, dap_db_path, LDB_FLG_RDONLY, NULL) != LDB_SUCCESS) {
-        log_it(L_ERROR, "Couldn't connect to database");
-        return NULL;
-    }
-    //sample: query = "(objectClass=addr_leased)";
-    if(ldb_search(s_ldb, NULL, &data_message, NULL, LDB_SCOPE_DEFAULT, NULL, a_query) != LDB_SUCCESS) {
-        log_it(L_ERROR, "Database querying failed");
-        return NULL;
-    }
-    //log_it(L_INFO, "Obtained binary data, %d entries", data_message->count);
-
-    // not found data
-    if(!data_message->count ) {
-        talloc_free(data_message);
-        return NULL;
-    }
-
-    pdap_store_obj_t store_data = DAP_NEW_Z_SIZE(dap_store_obj_t, data_message->count * sizeof(struct dap_store_obj));
-    if(!store_data) {
-        log_it(L_ERROR, "Couldn't allocate memory, store objects unobtained");
-        talloc_free(data_message);
-        return NULL;
-    }
-
-    dap_list_t *l_list_items = NULL;
-    // fill list
-    for(size_t i = 0; i < data_message->count; i++) {
-        l_list_items = dap_list_prepend(l_list_items, data_message->msgs[i]);
-    }
-    // sort list by time
-    l_list_items = dap_list_sort(l_list_items, (dap_callback_compare_t) compare_message_items);
-
-    dap_list_t *l_list = l_list_items;
-    size_t q = 0;
-    while(l_list) {
-        const struct ldb_message *l_msgs = l_list->data;
-        store_data[q].section = strdup(ldb_msg_find_attr_as_string(l_msgs, "section", "")); //strdup("kelvin_nodes");
-        store_data[q].group = strdup(ldb_msg_find_attr_as_string(l_msgs, "objectClass", "")); //strdup(group);
-        store_data[q].type = 1;
-        store_data[q].key = strdup(ldb_msg_find_attr_as_string(l_msgs, "cn", ""));
-        // get timestamp
-        const struct ldb_val *l_val = ldb_msg_find_ldb_val(l_msgs, "time");
-        if(l_val) {
-            memcpy(&store_data[q].timestamp, l_val->data, min(sizeof(time_t), l_val->length));
-        }
-        // get value
-        l_val = ldb_msg_find_ldb_val(l_msgs, "val");
-        if(l_val) {
-            store_data[q].value_len = l_val->length;
-            store_data[q].value = DAP_NEW_SIZE(uint8_t, l_val->length);
-            memcpy(store_data[q].value, l_val->data, l_val->length);
-        }
-        q++;
-        l_list = dap_list_next(l_list);
-        //log_it(L_INFO, "Record %s read successfully", ldb_dn_get_linearized(data_message->msgs[q]->dn));
-    }
-    size_t dap_store_len = data_message->count;
-    /*for(size_t q = 0; q < dap_store_len; ++q) {
-        store_data[q].section = strdup(ldb_msg_find_attr_as_string(data_message->msgs[q], "section", "")); //strdup("kelvin_nodes");
-        store_data[q].group = strdup(ldb_msg_find_attr_as_string(data_message->msgs[q], "objectClass", "")); //strdup(group);
-        store_data[q].type = 1;
-        store_data[q].key = strdup(ldb_msg_find_attr_as_string(data_message->msgs[q], "cn", ""));
-        // get timestamp
-        const struct ldb_val *l_val = ldb_msg_find_ldb_val(data_message->msgs[q], "time");
-        if(l_val) {
-            memcpy(&store_data[q].timestamp, l_val->data, min(sizeof(time_t), l_val->length));
-        }
-        // get value
-        l_val = ldb_msg_find_ldb_val(data_message->msgs[q], "val");
-        if(l_val) {
-            store_data[q].value_len = l_val->length;
-            store_data[q].value = DAP_NEW_SIZE(uint8_t, l_val->length);
-            memcpy(store_data[q].value, l_val->data, l_val->length);
-        }
-        //log_it(L_INFO, "Record %s read successfully", ldb_dn_get_linearized(data_message->msgs[q]->dn));
-    }*/
-    talloc_free(data_message);
-    dap_list_free(l_list_items);
-    if(a_count)
-        *a_count = dap_store_len;
-    return store_data;
-}
-
-/**
- * clean memory
- */
-void dab_db_free_pdap_store_obj_t(pdap_store_obj_t store_data, size_t count)
-{
-    if(!store_data)
-        return;
-    for(size_t i = 0; i < count; i++) {
-        pdap_store_obj_t store_one = store_data + i;
-        DAP_DELETE(store_one->section);
-        DAP_DELETE(store_one->group);
-        DAP_DELETE(store_one->key);
-        DAP_DELETE(store_one->value);
-    }
-    DAP_DELETE(store_data);
-}
-
-/* Get the entire content without using query expression
- * This function is highly dissuaded from being used
- * */
-pdap_store_obj_t dap_db_read_file_data(const char *path, const char *group)
-{
-    struct ldb_ldif *ldif_msg;
-    FILE *fs = fopen(path, "r");
-    if(!fs) {
-        log_it(L_ERROR, "Can't open file %s", path);
-        return NULL;
-    }
-    pdap_store_obj_t store_data = (pdap_store_obj_t) malloc(256 * sizeof(dap_store_obj_t));
-    if(store_data != NULL) {
-        log_it(L_INFO, "We're about to put entries in store objects");
-    }
-    else {
-        log_it(L_ERROR, "Couldn't allocate memory, store objects unobtained");
-        fclose(fs);
-        return NULL;
-    }
-
-    size_t q = 0;
-    for(ldif_msg = ldb_ldif_read_file(s_ldb, fs); ldif_msg; ldif_msg = ldb_ldif_read_file(s_ldb, fs), q++) {
-        if(q % 256 == 0) {
-            store_data = (pdap_store_obj_t) realloc(store_data, (q + 256) * sizeof(dap_store_obj_t));
-        }
-        /* if (ldif_msg->changetype == LDB_CHANGETYPE_ADD) {
-         / ... /
-         } */ // in case we gonna use extra LDIF functionality
-        const char *key = ldb_msg_find_attr_as_string(ldif_msg->msg, "cn", NULL);
-        if(key != NULL) {
-            store_data[q].section = strdup("kelvin-testnet");
-            store_data[q].group = strdup(group);
-            store_data[q].type = 1;
-            store_data[q].key = strdup(key);
-            store_data[q].value =(uint8_t*) strdup( ldb_msg_find_attr_as_string(ldif_msg->msg, "time", NULL));
-            store_data[q].value_len = strlen ( (char*) store_data[q].value) +1;
-            log_it(L_INFO, "Record %s stored successfully", ldb_dn_get_linearized(ldif_msg->msg->dn));
-        }
-        ldb_ldif_read_free(s_ldb, ldif_msg);
-    }
-    fclose(fs);
-    return store_data;
-}
-
-/*
- * Add multiple entries received from remote node to local database.
- * Since we don't know the size, it must be supplied too
- *
- * dap_store_size the count records
- * return 0 if Ok, <0 if errors
- */
-int dap_db_add_ldb(pdap_store_obj_t a_store_obj, size_t a_store_count)
-{
-    int l_ret = 0;
-    if(a_store_obj == NULL) {
-        log_it(L_ERROR, "Invalid Dap store objects passed");
-        return -1;
-    }
-    if(ldb_connect(s_ldb, dap_db_path, 0, NULL) != LDB_SUCCESS) {
-        log_it(L_ERROR, "Couldn't connect to database");
-        return -2;
-    }
-    //log_it(L_INFO, "We're about to put %d records into database", a_store_count);
-    struct ldb_message *l_msg;
-    if(a_store_count == 0) {
-        a_store_count = 1;
-    }
-    for(size_t q = 0; q < a_store_count; q++) {
-        // level 3: leased address, single whitelist entity
-
-        // if it is marked, don't save
-        if(a_store_obj[q].timestamp == (time_t) -1)
-            continue;
-
-        l_msg = ldb_msg_new(s_ldb);
-        char dn[256];
-        memset(dn, '\0', 256);
-        strcat(dn, "cn=");
-        strcat(dn, a_store_obj[q].key);
-        //strcat(dn, ",ou=addrs_leased,dc=kelvin_nodes");
-        strcat(dn, ",ou=");
-        strcat(dn, a_store_obj[q].group);
-        strcat(dn, ",dc=kelvin_nodes");
-        l_msg->dn = ldb_dn_new(s_mem_ctx, s_ldb, dn);
-        int l_res = ldb_msg_add_string(l_msg, "cn", a_store_obj[q].key);
-        ldb_msg_add_string(l_msg, "objectClass", a_store_obj[q].group);
-        ldb_msg_add_string(l_msg, "section", "kelvin_nodes");
-        ldb_msg_add_string(l_msg, "description", "Approved Kelvin node");
-
-        struct ldb_val l_val;
-        struct ldb_message_element *return_el;
-        l_val.data = (uint8_t*) &a_store_obj[q].timestamp;
-        l_val.length = sizeof(time_t);
-        l_res = ldb_msg_add_value(l_msg, "time", &l_val, &return_el);
-
-        l_val.data = a_store_obj[q].value;
-        l_val.length = a_store_obj[q].value_len;
-        l_res = ldb_msg_add_value(l_msg, "val", &l_val, &return_el);
-
-        l_ret += dap_db_add_msg(l_msg); // accumulation error codes
-        talloc_free(l_msg->dn);
-        talloc_free(l_msg);
-    }
-    return l_ret;
-}
-
-/*
- * Delete multiple entries from local database.
- *
- * dap_store_size the count records
- * return 0 if Ok, <0 if errors
- */
-int dap_db_delete_ldb(pdap_store_obj_t store_obj, size_t a_store_count)
-{
-    int ret = 0;
-    if(store_obj == NULL) {
-        log_it(L_ERROR, "Invalid Dap store objects passed");
-        return -1;
-    }
-    if(ldb_connect(s_ldb, dap_db_path, 0, NULL) != LDB_SUCCESS) {
-        log_it(L_ERROR, "Couldn't connect to database");
-        return -2;
-    }
-    //log_it(L_INFO, "We're delete %d records from database", a_store_count);
-    if(a_store_count == 0) {
-        a_store_count = 1;
-    }
-    for(size_t q = 0; q < a_store_count; q++) {
-        char dn[128];
-        memset(dn, '\0', 128);
-        strcat(dn, "cn=");
-        strcat(dn, store_obj[q].key);
-        //strcat(dn, ",ou=addrs_leased,dc=kelvin_nodes");
-        strcat(dn, ",ou=");
-        strcat(dn, store_obj[q].group);
-        strcat(dn, ",dc=kelvin_nodes");
-        struct ldb_dn *ldn = ldb_dn_new(s_mem_ctx, s_ldb, dn);
-        ret += dap_db_del_msg(ldn); // accumulation error codes
-        talloc_free(ldn);
-    }
-    return ret;
-
-}
-
-/* serialization */
-/*dap_store_obj_pkt_t *dap_store_packet_single(pdap_store_obj_t store_obj)
- {
- dap_store_obj_pkt_t *pkt = DAP_NEW_Z_SIZE(dap_store_obj_pkt_t,
- sizeof(int) + 4 + strlen(store_obj->group) + strlen(store_obj->key) + strlen(store_obj->section)
- + strlen(store_obj->value));
- pkt->grp_size = strlen(store_obj->group) + 1;
- pkt->name_size = strlen(store_obj->key) + 1;
- pkt->sec_size = strlen(store_obj->section) + 1;
- pkt->type = store_obj->type;
- memcpy(pkt->data, &store_obj->section, pkt->sec_size);
- memcpy(pkt->data + pkt->sec_size, &store_obj->group, pkt->grp_size);
- memcpy(pkt->data + pkt->sec_size + pkt->grp_size, &store_obj->key, pkt->name_size);
- memcpy(pkt->data + pkt->sec_size + pkt->grp_size + pkt->name_size, &store_obj->value, strlen(store_obj->value) + 1);
- return pkt;
- }*/
-
-static size_t dap_db_get_size_pdap_store_obj_t(pdap_store_obj_t store_obj)
-{
-    size_t size = sizeof(uint32_t) + 3 * sizeof(uint16_t) + sizeof(size_t) + sizeof(time_t) + dap_strlen(store_obj->group) +
-            dap_strlen(store_obj->key) + dap_strlen(store_obj->section) + store_obj->value_len;
-    return size;
-}
-
-/**
- * serialization
- * @param a_store_obj_count count of structures store_obj
- * @param a_timestamp create data time
- * @param a_size_out[out] size of output structure
- * @return NULL in case of an error
- */
-dap_store_obj_pkt_t *dap_store_packet_multiple(pdap_store_obj_t a_store_obj, time_t a_timestamp, size_t a_store_obj_count)
-{
-    if(!a_store_obj || a_store_obj_count < 1)
-        return NULL;
-    size_t l_data_size_out = sizeof(uint32_t); // size of output data
-    // calculate output structure size
-    for(size_t l_q = 0; l_q < a_store_obj_count; ++l_q)
-        l_data_size_out += dap_db_get_size_pdap_store_obj_t(&a_store_obj[l_q]);
-
-    dap_store_obj_pkt_t *l_pkt = DAP_NEW_Z_SIZE(dap_store_obj_pkt_t, sizeof(dap_store_obj_pkt_t) + l_data_size_out);
-    l_pkt->data_size = l_data_size_out;
-    l_pkt->timestamp = a_timestamp;
-    uint64_t l_offset = 0;
-    uint32_t l_count = (uint32_t) a_store_obj_count;
-    memcpy(l_pkt->data + l_offset, &l_count, sizeof(uint32_t));
-    l_offset += sizeof(uint32_t);
-    for( size_t l_q = 0; l_q < a_store_obj_count; ++l_q) {
-        dap_store_obj_t obj = a_store_obj[l_q];
-        uint16_t section_size = (uint16_t) dap_strlen(obj.section);
-        uint16_t group_size = (uint16_t) dap_strlen(obj.group);
-        uint16_t key_size = (uint16_t) dap_strlen(obj.key);
-        memcpy(l_pkt->data + l_offset, &obj.type, sizeof(int));
-        l_offset += sizeof(int);
-        memcpy(l_pkt->data + l_offset, &section_size, sizeof(uint16_t));
-        l_offset += sizeof(uint16_t);
-        memcpy(l_pkt->data + l_offset, obj.section, section_size);
-        l_offset += section_size;
-        memcpy(l_pkt->data + l_offset, &group_size, sizeof(uint16_t));
-        l_offset += sizeof(uint16_t);
-        memcpy(l_pkt->data + l_offset, obj.group, group_size);
-        l_offset += group_size;
-        memcpy(l_pkt->data + l_offset, &obj.timestamp, sizeof(time_t));
-        l_offset += sizeof(time_t);
-        memcpy(l_pkt->data + l_offset, &key_size, sizeof(uint16_t));
-        l_offset += sizeof(uint16_t);
-        memcpy(l_pkt->data + l_offset, obj.key, key_size);
-        l_offset += key_size;
-        memcpy(l_pkt->data + l_offset, &obj.value_len, sizeof(size_t));
-        l_offset += sizeof(size_t);
-        memcpy(l_pkt->data + l_offset, obj.value, obj.value_len);
-        l_offset += obj.value_len;
-    }
-    assert(l_data_size_out == l_offset);
-    return l_pkt;
-}
-/**
- * deserialization
- * @param store_obj_count[out] count of the output structures store_obj
- * @return NULL in case of an error*
- */
-
-dap_store_obj_t *dap_store_unpacket(const dap_store_obj_pkt_t *pkt, size_t *store_obj_count)
-{
-    if(!pkt || pkt->data_size < 1)
-        return NULL;
-    uint64_t offset = 0;
-    uint32_t count;
-    memcpy(&count, pkt->data, sizeof(uint32_t));
-    offset += sizeof(uint32_t);
-    dap_store_obj_t *store_obj = DAP_NEW_Z_SIZE(dap_store_obj_t, count * sizeof(struct dap_store_obj));
-    for(size_t q = 0; q < count; ++q) {
-        dap_store_obj_t *obj = store_obj + q;
-        uint16_t str_size;
-        memcpy(&obj->type, pkt->data + offset, sizeof(int));
-        offset += sizeof(int);
-
-        memcpy(&str_size, pkt->data + offset, sizeof(uint16_t));
-        offset += sizeof(uint16_t);
-        obj->section = DAP_NEW_Z_SIZE(char, str_size + 1);
-        memcpy(obj->section, pkt->data + offset, str_size);
-        offset += str_size;
-
-        memcpy(&str_size, pkt->data + offset, sizeof(uint16_t));
-        offset += sizeof(uint16_t);
-        obj->group = DAP_NEW_Z_SIZE(char, str_size + 1);
-        memcpy(obj->group, pkt->data + offset, str_size);
-        offset += str_size;
-
-        memcpy(&obj->timestamp, pkt->data + offset, sizeof(time_t));
-        offset += sizeof(time_t);
-
-        memcpy(&str_size, pkt->data + offset, sizeof(uint16_t));
-        offset += sizeof(uint16_t);
-        obj->key = DAP_NEW_Z_SIZE(char, str_size + 1);
-        memcpy(obj->key, pkt->data + offset, str_size);
-        offset += str_size;
-
-        memcpy(&obj->value_len, pkt->data + offset, sizeof(size_t));
-        offset += sizeof(size_t);
-
-        obj->value = DAP_NEW_Z_SIZE(uint8_t, obj->value_len + 1);
-        memcpy(obj->value, pkt->data + offset, obj->value_len);
-        offset += obj->value_len;
-    }
-    assert(pkt->data_size == offset);
-    if(store_obj_count)
-        *store_obj_count = count;
-    return store_obj;
-}
-
-void dap_db_deinit()
-{
-    talloc_free(s_ldb);
-    talloc_free(s_mem_ctx);
-    free(dap_db_path);
-    s_ldb = NULL;
-    s_mem_ctx = NULL;
-    dap_db_path = NULL;
-}
diff --git a/dap_chain_global_db_pvt.h b/dap_chain_global_db_pvt.h
deleted file mode 100755
index dacd0eabcf117c0066e74a5f4106f78c4d80ab1f..0000000000000000000000000000000000000000
--- a/dap_chain_global_db_pvt.h
+++ /dev/null
@@ -1,43 +0,0 @@
-#ifndef _GLOBAL_DB_DRIVER_H_
-#define _GLOBAL_DB_DRIVER_H_
-
-#include <stdint.h>
-#include "dap_common.h"
-#include "ldb.h"
-
-typedef struct dap_store_obj {
-    time_t timestamp;
-    uint8_t type;
-    char *section;
-    char *group;
-    char *key;
-    uint8_t *value;
-    size_t value_len;
-}DAP_ALIGN_PACKED dap_store_obj_t, *pdap_store_obj_t;
-
-typedef struct dap_store_obj_pkt {
-    /*uint8_t type;
-     uint8_t sec_size;
-     uint8_t grp_size;
-     uint8_t name_size;*/
-    time_t timestamp;
-    size_t data_size;
-    uint8_t data[];
-}__attribute__((packed)) dap_store_obj_pkt_t;
-
-int dap_db_init(const char*);
-void dap_db_group_create(const char *);
-void dap_db_deinit(void);
-
-int dap_db_add(pdap_store_obj_t a_store_obj, size_t a_store_count);
-int dap_db_delete(pdap_store_obj_t a_store_obj, size_t a_store_count);
-
-pdap_store_obj_t dap_db_read_data_ldb(const char *a_query, size_t *a_count);
-pdap_store_obj_t dap_db_read_file_data(const char *a_path, const char *a_group); // state of emergency only, if LDB database is inaccessible
-dap_store_obj_pkt_t *dap_store_packet_single(pdap_store_obj_t a_store_obj);
-dap_store_obj_pkt_t *dap_store_packet_multiple(pdap_store_obj_t a_store_obj, time_t a_timestamp, size_t a_store_obj_count);
-dap_store_obj_t *dap_store_unpacket(const dap_store_obj_pkt_t *a_pkt, size_t *a_store_obj_count);
-
-void dab_db_free_pdap_store_obj_t(pdap_store_obj_t a_store_data, size_t a_count);
-
-#endif // #ifndef _GLOBAL_DB_DRIVER_H_