diff --git a/dap_chain_global_db.c b/dap_chain_global_db.c
index 591e8bd500e49efd595a6e02a1c682c95e008547..71b053b8efe5176800210862335b751b3b2565aa 100755
--- a/dap_chain_global_db.c
+++ b/dap_chain_global_db.c
@@ -10,7 +10,6 @@
 #include "dap_chain_common.h"
 #include "dap_strfuncs.h"
 //#include "dap_chain_global_db_pvt.h"
-#include "dap_chain_global_db_driver.h"
 #include "dap_chain_global_db_hist.h"
 #include "dap_chain_global_db.h"
 
@@ -334,6 +333,41 @@ bool dap_chain_global_db_del(const char *a_key)
 {
     return dap_chain_global_db_gr_del(a_key, GROUP_LOCAL_GENERAL);
 }
+
+
+/**
+ * Read last item in global_db
+ *
+ * @param data_size[out] size of output array
+ * @return array (note:not Null-terminated string) on NULL in case of an error
+ */
+dap_store_obj_t* dap_chain_global_db_get_last(const char *a_group)
+{
+    // Read data
+    lock();
+    dap_store_obj_t *l_store_obj = dap_chain_global_db_driver_read_last(a_group);
+    unlock();
+    return l_store_obj;
+}
+
+
+
+
+/**
+ * Read the entire database with condition into an array of size bytes
+ *
+ * @param data_size[out] size of output array
+ * @return array (note:not Null-terminated string) on NULL in case of an error
+ */
+dap_store_obj_t* dap_chain_global_db_cond_load(const char *a_group, uint64_t a_first_id, size_t *a_data_size_out)
+{
+    // Read data
+    lock();
+    dap_store_obj_t *l_store_obj = dap_chain_global_db_driver_cond_read(a_group, a_first_id, a_data_size_out);
+    unlock();
+    return l_store_obj;
+}
+
 /**
  * Read the entire database into an array of size bytes
  *
diff --git a/dap_chain_global_db.h b/dap_chain_global_db.h
index e80ba73d3031015a5628d806e23921c9cde8b350..17a9aae76976d9e63ec4e63ad74dc89e060fa155 100755
--- a/dap_chain_global_db.h
+++ b/dap_chain_global_db.h
@@ -7,6 +7,8 @@
 #include "dap_common.h"
 #include "dap_config.h"
 #include "dap_list.h"
+#include "dap_chain_global_db_driver.h"
+
 
 #define GROUP_LOCAL_HISTORY "global.history"
 #define GROUP_LOCAL_NODE_LAST_TS "local.node.last_ts"
@@ -73,6 +75,8 @@ bool dap_chain_global_db_del(const char *a_key);
  * @param data_size[out] size of output array
  * @return array (note:not Null-terminated string) on NULL in case of an error
  */
+dap_store_obj_t* dap_chain_global_db_get_last(const char *a_group);
+dap_store_obj_t* dap_chain_global_db_cond_load(const char *a_group, uint64_t a_first_id, size_t *a_data_size_out);
 dap_global_db_obj_t** dap_chain_global_db_gr_load(const char *a_group, size_t *a_data_size_out);
 dap_global_db_obj_t** dap_chain_global_db_load(size_t *a_data_size_out);
 
@@ -98,7 +102,7 @@ uint8_t* dap_db_log_pack(dap_global_db_obj_t *a_obj, size_t *a_data_size_out);
 // Parse data from dap_db_log_pack()
 void* dap_db_log_unpack(const void *a_data, size_t a_data_size, size_t *a_store_obj_count);
 // Get timestamp from dap_db_log_pack()
-time_t dap_db_log_unpack_get_timestamp(uint8_t *a_data, size_t a_data_size);
+//time_t dap_db_log_unpack_get_timestamp(uint8_t *a_data, size_t a_data_size);
 
 // Get last timestamp in log
 time_t dap_db_log_get_last_timestamp(void);
diff --git a/dap_chain_global_db_driver.c b/dap_chain_global_db_driver.c
old mode 100644
new mode 100755
index 9e67016b43b565101c7d94e2facff7933c06e4aa..bb456a1f4595abc27f16b436d07fa2fb7d9fd605
--- a/dap_chain_global_db_driver.c
+++ b/dap_chain_global_db_driver.c
@@ -398,7 +398,7 @@ static int save_write_buf(void)
         }
         if(s_drv_callback.transaction_end)
             s_drv_callback.transaction_end();
-        printf("** writing ended cnt=%d\n", cnt);
+        //printf("** writing ended cnt=%d\n", cnt);
         // writing ended
         pthread_mutex_lock(&s_mutex_write_end);
         pthread_cond_broadcast(&s_cond_write_end);
@@ -430,7 +430,6 @@ int dap_chain_global_db_driver_appy(pdap_store_obj_t a_store_obj, size_t a_store
     //dap_store_obj_t *l_store_obj = dap_store_obj_copy(a_store_obj, a_store_count);
     if(!a_store_obj || !a_store_count)
         return -1;
-    a_store_obj->type = 'a';
     // add all records into write buffer
     pthread_mutex_lock(&s_mutex_add_end);
     for(size_t i = 0; i < a_store_count; i++) {
@@ -460,7 +459,7 @@ int dap_chain_global_db_driver_appy(pdap_store_obj_t a_store_obj, size_t a_store
 
 int dap_chain_global_db_driver_add(pdap_store_obj_t a_store_obj, size_t a_store_count)
 {
-    a_store_obj->type = 'd';
+    a_store_obj->type = 'a';
     return dap_chain_global_db_driver_appy(a_store_obj, a_store_count);
 }
 
@@ -470,6 +469,42 @@ int dap_chain_global_db_driver_delete(pdap_store_obj_t a_store_obj, size_t a_sto
     return dap_chain_global_db_driver_appy(a_store_obj, a_store_count);
 }
 
+/**
+ * Read last items
+ *
+ * a_group - group name
+ */
+dap_store_obj_t* dap_chain_global_db_driver_read_last(const char *a_group)
+{
+    dap_store_obj_t *l_ret = NULL;
+    // wait apply write buffer
+    wait_write_buf();
+    // read records using the selected database engine
+    if(s_drv_callback.read_last_store_obj)
+        l_ret = s_drv_callback.read_last_store_obj(a_group);
+    return l_ret;
+}
+
+/**
+ * Read several items
+ *
+ * a_group - group name
+ * a_key - key name, may by NULL, it means reading the whole group
+ * a_id - from this id
+ * 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_cond_read(const char *a_group, uint64_t id, size_t *a_count_out)
+{
+    dap_store_obj_t *l_ret = NULL;
+    // wait apply write buffer
+    wait_write_buf();
+    // read records using the selected database engine
+    if(s_drv_callback.read_cond_store_obj)
+        l_ret = s_drv_callback.read_cond_store_obj(a_group, id, a_count_out);
+    return l_ret;
+}
+
 /**
  * Read several items
  *
diff --git a/dap_chain_global_db_driver.h b/dap_chain_global_db_driver.h
old mode 100644
new mode 100755
index efd2631763ae086f76531870362e8b32af1cb684..b0e099d41408ceea3d77ba7eab03cedfdb525a5b
--- a/dap_chain_global_db_driver.h
+++ b/dap_chain_global_db_driver.h
@@ -27,13 +27,12 @@
 
 #include <stddef.h>
 #include <stdint.h>
-//#include <ctime>
 #include "dap_common.h"
 
 typedef struct dap_store_obj {
-	time_t timestamp;
+	uint64_t id;
+    time_t timestamp;
 	uint8_t type;
-//	char *section;
 	char *group;
 	char *key;
 	uint8_t *value;
@@ -48,11 +47,15 @@ typedef struct dap_store_obj_pkt {
 
 typedef int (*dap_db_driver_write_callback_t)(dap_store_obj_t*);
 typedef dap_store_obj_t* (*dap_db_driver_read_callback_t)(const char *,const char *, size_t *);
+typedef dap_store_obj_t* (*dap_db_driver_read_cond_callback_t)(const char *,uint64_t , size_t *);
+typedef dap_store_obj_t* (*dap_db_driver_read_last_callback_t)(const char *);
 typedef int (*dap_db_driver_callback_t)(void);
 
 typedef struct dap_db_driver_callbacks {
     dap_db_driver_write_callback_t apply_store_obj;
     dap_db_driver_read_callback_t read_store_obj;
+    dap_db_driver_read_last_callback_t read_last_store_obj;
+    dap_db_driver_read_cond_callback_t read_cond_store_obj;
     dap_db_driver_callback_t transaction_start;
     dap_db_driver_callback_t transaction_end;
     dap_db_driver_callback_t deinit;
@@ -70,6 +73,8 @@ char* dap_chain_global_db_driver_hash(const uint8_t *data, size_t data_size);
 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_last(const char *a_group);
+dap_store_obj_t* dap_chain_global_db_driver_cond_read(const char *a_group, uint64_t id, size_t *a_count_out);
 dap_store_obj_t* dap_chain_global_db_driver_read(const char *a_group, const char *a_key, size_t *count_out);
 
 dap_store_obj_pkt_t *dap_store_packet_multiple(pdap_store_obj_t a_store_obj,
diff --git a/dap_chain_global_db_driver_sqlite.c b/dap_chain_global_db_driver_sqlite.c
old mode 100644
new mode 100755
index e3ec3ef143f9c7ca3b0fae1f0f3e3b1a5696f61e..0a9ad3e311ce13940db012729df929fc44b02048
--- a/dap_chain_global_db_driver_sqlite.c
+++ b/dap_chain_global_db_driver_sqlite.c
@@ -97,6 +97,8 @@ int dap_db_driver_sqlite_init(const char *a_filename_db, dap_db_driver_callbacks
 //
         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;
+        a_drv_callback->read_cond_store_obj = dap_db_driver_sqlite_read_cond_store_obj;
+        a_drv_callback->read_last_store_obj = dap_db_driver_sqlite_read_last_store_obj;
         a_drv_callback->transaction_start = dap_db_driver_sqlite_start_transaction;
         a_drv_callback->transaction_end = dap_db_driver_sqlite_end_transaction;
         a_drv_callback->deinit = dap_db_driver_sqlite_deinit;
@@ -245,8 +247,8 @@ static int dap_db_driver_sqlite_create_group_table(const char *a_table_name)
         return -1;
     }
     DAP_DELETE(l_query);
-    // create unique index - hash
-    l_query = dap_strdup_printf("create unique index if not exists 'idx_hash_%s' ON '%s' (hash)", a_table_name,
+    // create unique index - key
+    l_query = dap_strdup_printf("create unique index if not exists 'idx_key_%s' ON '%s' (key)", a_table_name,
             a_table_name);
     if(dap_db_driver_sqlite_exec(s_db, (const char*) l_query, &l_error_message) != SQLITE_OK) {
         log_it(L_ERROR, "Create unique index : %s\n", l_error_message);
@@ -442,22 +444,32 @@ int dap_db_driver_sqlite_end_transaction(void)
  */
 int dap_db_driver_sqlite_apply_store_obj(dap_store_obj_t *a_store_obj)
 {
-    if(!a_store_obj || !a_store_obj->group || !a_store_obj->key || !a_store_obj->value || !a_store_obj->value_len)
+    if(!a_store_obj || !a_store_obj->group)
         return -1;
     char *l_query = NULL;
     char *l_error_message = NULL;
     if(a_store_obj->type == 'a') {
+        if(!a_store_obj->key || !a_store_obj->value || !a_store_obj->value_len)
+                return -1;
         dap_chain_hash_fast_t l_hash;
         dap_hash_fast(a_store_obj->value, a_store_obj->value_len, &l_hash);
 
         char *l_blob_hash = dap_db_driver_get_string_from_blob((uint8_t*) &l_hash, sizeof(dap_chain_hash_fast_t));
         char *l_blob_value = dap_db_driver_get_string_from_blob(a_store_obj->value, a_store_obj->value_len);
+        //add one record
         l_query = sqlite3_mprintf("insert into '%s' values(NULL, '%s', x'%s', '%lld', x'%s')",
                 a_store_obj->group, a_store_obj->key, l_blob_hash, a_store_obj->timestamp, l_blob_value);
         dap_db_driver_sqlite_free(l_blob_hash);
         dap_db_driver_sqlite_free(l_blob_value);
     }
     else if(a_store_obj->type == 'd') {
+        //delete one record
+        if(a_store_obj->key)
+            l_query = sqlite3_mprintf("delete from '%s' where key = '%s'",
+                    a_store_obj->group, a_store_obj->key);
+        // remove all group
+        else
+            l_query = sqlite3_mprintf("drop table if exists '%s'", a_store_obj->group);
     }
     else {
         log_it(L_ERROR, "Unknown store_obj type '0x%x'", a_store_obj->type);
@@ -473,7 +485,7 @@ int dap_db_driver_sqlite_apply_store_obj(dap_store_obj_t *a_store_obj)
     dap_db_driver_sqlite_free(l_query);
     // entry with the same hash is already present
     if(l_ret == SQLITE_CONSTRAINT) {
-        log_it(L_INFO, "Entry with the same hash is already present, %s", l_error_message);
+        log_it(L_INFO, "Entry with the same key is already present, %s", l_error_message);
         dap_db_driver_sqlite_free(l_error_message);
         return 0;
     }
@@ -486,6 +498,141 @@ int dap_db_driver_sqlite_apply_store_obj(dap_store_obj_t *a_store_obj)
     return 0;
 }
 
+static void fill_one_item(const char *a_group, dap_store_obj_t *a_obj, SQLITE_ROW_VALUE *a_row)
+{
+    a_obj->group = dap_strdup(a_group);
+
+    for(int l_iCol = 0; l_iCol < a_row->count; l_iCol++) {
+        SQLITE_VALUE *l_cur_val = a_row->val + l_iCol;
+        switch (l_iCol) {
+        case 0:
+            if(l_cur_val->type == SQLITE_INTEGER)
+                a_obj->id = l_cur_val->val.val_int64;
+            break; // id
+        case 1:
+            if(l_cur_val->type == SQLITE_INTEGER)
+                a_obj->timestamp = l_cur_val->val.val_int64;
+            break; // ts
+        case 2:
+            if(l_cur_val->type == SQLITE_TEXT)
+                a_obj->key = dap_strdup(l_cur_val->val.val_str);
+            break; // key
+        case 3:
+            if(l_cur_val->type == SQLITE_BLOB)
+            {
+                a_obj->value_len = (size_t) l_cur_val->len;
+                a_obj->value = DAP_NEW_SIZE(uint8_t, a_obj->value_len);
+                memcpy(a_obj->value, l_cur_val->val.val_blob, a_obj->value_len);
+            }
+            break; // value
+        }
+    }
+
+}
+
+/**
+ * Read last items
+ *
+ * a_group - group name
+ */
+dap_store_obj_t* dap_db_driver_sqlite_read_last_store_obj(const char *a_group)
+{
+    dap_store_obj_t *l_obj = NULL;
+    char *l_error_message = NULL;
+    sqlite3_stmt *l_res;
+    if(!a_group)
+        return NULL;
+    char *l_str_query = sqlite3_mprintf("SELECT id,ts,key,value FROM '%s' ORDER BY id DESC LIMIT 1", a_group);
+    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) {
+        log_it(L_ERROR, "read last l_ret=%d, %s\n", sqlite3_errcode(s_db), sqlite3_errmsg(s_db));
+        dap_db_driver_sqlite_free(l_error_message);
+        return NULL;
+    }
+
+    SQLITE_ROW_VALUE *l_row = NULL;
+    l_ret = dap_db_driver_sqlite_fetch_array(l_res, &l_row);
+    if(l_ret != SQLITE_ROW && l_ret != SQLITE_DONE)
+    {
+        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);
+        fill_one_item(a_group, l_obj, l_row);
+    }
+    dap_db_driver_sqlite_row_free(l_row);
+    dap_db_driver_sqlite_query_free(l_res);
+
+    return l_obj;
+}
+
+/**
+ * Read several items with conditoin
+ *
+ * a_group - group name
+ * a_id - read from this id
+ * 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_cond_store_obj(const char *a_group, uint64_t a_id, size_t *a_count_out)
+{
+    dap_store_obj_t *l_obj = NULL;
+    char *l_error_message = NULL;
+    sqlite3_stmt *l_res;
+    if(!a_group)
+        return NULL;
+    // no limit
+    int l_count_out = 0;
+    if(a_count_out)
+        l_count_out = *a_count_out;
+    char *l_str_query;
+    if(l_count_out)
+        l_str_query = sqlite3_mprintf("SELECT id,ts,key,value FROM '%s' WHERE id>'%lld' ORDER BY id ASC LIMIT %d",
+                a_group, a_id, l_count_out);
+    else
+        l_str_query = sqlite3_mprintf("SELECT id,ts,key,value FROM '%s' WHERE id>'%lld' ORDER BY id ASC",
+                a_group, a_id);
+    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) {
+        log_it(L_ERROR, "read l_ret=%d, %s\n", sqlite3_errcode(s_db), sqlite3_errmsg(s_db));
+        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)
+        {
+            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) {
+            // realloc memory
+            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));
+            }
+            // fill current item
+            dap_store_obj_t *l_obj_cur = l_obj + l_count_out;
+            fill_one_item(a_group, l_obj_cur, l_row);
+            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;
+}
+
 /**
  * Read several items
  *
@@ -508,18 +655,18 @@ dap_store_obj_t* dap_db_driver_sqlite_read_store_obj(const char *a_group, const
     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",
+            l_str_query = sqlite3_mprintf("SELECT id,ts,key,value FROM '%s' WHERE key='%s' ORDER BY id ASC LIMIT %d",
                     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);
+            l_str_query = sqlite3_mprintf("SELECT id,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);
+            l_str_query = sqlite3_mprintf("SELECT id,ts,key,value FROM '%s' ORDER BY id ASC LIMIT %d",
+                    a_group, l_count_out);
         else
-            l_str_query = sqlite3_mprintf("SELECT ts,key,value FROM '%s' ORDER BY id ASC", a_group, a_key);
+            l_str_query = sqlite3_mprintf("SELECT id,ts,key,value FROM '%s' ORDER BY id ASC", a_group);
     }
     int l_ret = dap_db_driver_sqlite_query(s_db, l_str_query, &l_res, &l_error_message);
     sqlite3_free(l_str_query);
@@ -540,37 +687,15 @@ 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) {
+            // realloc memory
             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));
             }
+            // fill currrent item
             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_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_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
-                }
-            }
+            fill_one_item(a_group, l_obj_cur, l_row);
             l_count_out++;
         }
         dap_db_driver_sqlite_row_free(l_row);
diff --git a/dap_chain_global_db_driver_sqlite.h b/dap_chain_global_db_driver_sqlite.h
old mode 100644
new mode 100755
index bb33f18a8d7abe5facb2e3e6ae056dd714aaa9db..202bf7fc0e2ca50c45bea2bb8ddbf9d9d8b118b9
--- a/dap_chain_global_db_driver_sqlite.h
+++ b/dap_chain_global_db_driver_sqlite.h
@@ -44,4 +44,6 @@ 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_last_store_obj(const char *a_group);
+dap_store_obj_t* dap_db_driver_sqlite_read_cond_store_obj(const char *a_group, uint64_t a_id, size_t *a_count_out);
 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 345858e202beac3a4d1a174a6a086d5fa5c02011..b3704aa2c6f29b8ddeb944bf9e0afa5d79823b27 100755
--- a/dap_chain_global_db_hist.c
+++ b/dap_chain_global_db_hist.c
@@ -24,7 +24,7 @@ static int dap_db_history_unpack_hist(char *l_str_in, dap_global_db_hist_t *a_re
     if(l_count != 4)
         return -1;
     a_rec_out->type = l_strv[0][0];
-    a_rec_out->keys_count = strtoul(l_strv[1], NULL,10);
+    a_rec_out->keys_count = strtoul(l_strv[1], NULL, 10);
     a_rec_out->group = dap_strdup(l_strv[2]);
     a_rec_out->keys = dap_strdup(l_strv[3]);
     dap_strfreev(l_strv);
@@ -73,15 +73,15 @@ uint8_t* dap_db_log_pack(dap_global_db_obj_t *a_obj, size_t *a_data_size_out)
     while(l_keys[i]) {
         dap_store_obj_t *l_obj = NULL;
         // add record - read record
-        if(l_rec.type=='a')
+        if(l_rec.type == 'a')
             l_obj = (dap_store_obj_t*) dap_chain_global_db_obj_get(l_keys[i], l_rec.group);
         // delete record - save only key for record
-        else if(l_rec.type=='d'){// //section=strdup("kelvin_nodes");
-            l_obj = (dap_store_obj_t*)DAP_NEW_Z(dap_store_obj_t);
+        else if(l_rec.type == 'd') { // //section=strdup("kelvin_nodes");
+            l_obj = (dap_store_obj_t*) DAP_NEW_Z(dap_store_obj_t);
             l_obj->group = dap_strdup(l_rec.group);
             l_obj->key = dap_strdup(l_keys[i]);
         }
-        if (l_obj == NULL){
+        if(l_obj == NULL) {
             dap_store_obj_free(l_store_obj, l_count);
             dap_strfreev(l_keys);
             return NULL;
@@ -106,8 +106,6 @@ uint8_t* dap_db_log_pack(dap_global_db_obj_t *a_obj, size_t *a_data_size_out)
 
 }
 
-
-
 /**
  * Add data to the history log
  */
@@ -125,7 +123,7 @@ bool dap_db_history_add(char a_type, pdap_store_obj_t a_store_obj, size_t a_dap_
         l_rec.keys = a_store_obj->key;
     else {
         // make keys vector
-        char **l_keys = DAP_NEW_Z_SIZE(char*, sizeof(char*) * ( ((size_t) a_dap_store_count) + 1));
+        char **l_keys = DAP_NEW_Z_SIZE(char*, sizeof(char*) * (((size_t ) a_dap_store_count) + 1));
         size_t i;
         for(i = 0; i < a_dap_store_count; i++) {
             // if it is marked, the data has not been saved
@@ -144,8 +142,8 @@ bool dap_db_history_add(char a_type, pdap_store_obj_t a_store_obj, size_t a_dap_
     // key - timestamp
     // value - keys of added/deleted data
     l_store_data.key = dap_db_new_history_timestamp();
-    l_store_data.value = (uint8_t*) strdup(l_str) ;
-    l_store_data.value_len = l_str_len+1;
+    l_store_data.value = (uint8_t*) strdup(l_str);
+    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_chain_global_db_driver_add(&l_store_data, 1);
@@ -171,22 +169,27 @@ bool dap_db_history_truncate(void)
  */
 time_t dap_db_log_get_last_timestamp(void)
 {
-    char *last_key = NULL;
-    size_t l_data_size_out = 0;
-    dap_global_db_obj_t **l_objs = dap_chain_global_db_gr_load(GROUP_LOCAL_HISTORY, &l_data_size_out);
-    if(l_data_size_out > 0)
-        last_key = l_objs[0]->key;
-    for(size_t i = 1; i < l_data_size_out; i++) {
-        dap_global_db_obj_t *l_obj_cur = l_objs[i];
-        if(strcmp(last_key, l_obj_cur->key) < 0) {
-            last_key = l_obj_cur->key;
-            //printf("l_obj_cur->key=%s last_key\n", l_obj_cur->key);
-        }
-        //printf("l_obj_cur->key=%s\n", l_obj_cur->key);
+    //dap_store_obj_t *l_last_obj = dap_chain_global_db_driver_read_last(
+    dap_store_obj_t *l_last_obj = dap_chain_global_db_get_last(GROUP_LOCAL_HISTORY);
+    if(l_last_obj) {
+        return l_last_obj->id;
     }
-    time_t l_ret_time = last_key? strtoll(last_key, NULL, 10): 0;
-    dap_chain_global_db_objs_delete(l_objs);
-    return l_ret_time;
+    /*    char *last_key = NULL;
+     size_t l_data_size_out = 0;
+     dap_global_db_obj_t **l_objs = dap_chain_global_db_gr_load(GROUP_LOCAL_HISTORY, &l_data_size_out);
+     if(l_data_size_out > 0)
+     last_key = l_objs[0]->key;
+     for(size_t i = 1; i < l_data_size_out; i++) {
+     dap_global_db_obj_t *l_obj_cur = l_objs[i];
+     if(strcmp(last_key, l_obj_cur->key) < 0) {
+     last_key = l_obj_cur->key;
+     //printf("l_obj_cur->key=%s last_key\n", l_obj_cur->key);
+     }
+     //printf("l_obj_cur->key=%s\n", l_obj_cur->key);
+     }
+     time_t l_ret_time = last_key? strtoll(last_key, NULL, 10): 0;
+     dap_chain_global_db_objs_delete(l_objs);
+     return l_ret_time;*/
 }
 
 static int compare_items(const void * l_a, const void * l_b)
@@ -203,24 +206,41 @@ static int compare_items(const void * l_a, const void * l_b)
 dap_list_t* dap_db_log_get_list(time_t first_timestamp)
 {
     dap_list_t *l_list = NULL;
-    size_t l_list_count = 0;
-    char *l_first_key_str = dap_strdup_printf("%lld", (int64_t) first_timestamp);
     size_t l_data_size_out = 0;
-    dap_global_db_obj_t **l_objs = dap_chain_global_db_gr_load(GROUP_LOCAL_HISTORY, &l_data_size_out);
+    dap_store_obj_t *l_objs = dap_chain_global_db_cond_load(GROUP_LOCAL_HISTORY, first_timestamp, &l_data_size_out);
+    //dap_global_db_obj_t **l_objs = dap_chain_global_db_gr_load(GROUP_LOCAL_HISTORY, first_timestamp, &l_data_size_out);
     for(size_t i = 0; i < l_data_size_out; i++) {
-        dap_global_db_obj_t *l_obj_cur = l_objs[i];
-//        log_it(L_DEBUG,"%lld and %lld tr",strtoll(l_obj_cur->key,NULL,10), first_timestamp );
-        if( strtoll(l_obj_cur->key,NULL,10) > (long long) first_timestamp  ) {
-            dap_global_db_obj_t *l_item = DAP_NEW(dap_global_db_obj_t);
-            l_item->key = dap_strdup(l_obj_cur->key);
-            l_item->value =(uint8_t*) dap_strdup((char*) l_obj_cur->value);
-            l_list = dap_list_append(l_list, l_item);
-            l_list_count++;
-        }
+        dap_store_obj_t *l_obj_cur = l_objs + i;
+        dap_global_db_obj_t *l_item = DAP_NEW(dap_global_db_obj_t);
+        l_item->key = dap_strdup(l_obj_cur->key);
+        l_item->value = (uint8_t*) dap_strdup((char*) l_obj_cur->value);
+        l_list = dap_list_append(l_list, l_item);
     }
-    // sort list by key (time str)
-    //dap_list_sort(l_list, (dap_callback_compare_t) compare_items);
-    log_it(L_DEBUG,"Prepared %u items (list size %u)", l_list_count, dap_list_length(l_list));
+    dap_store_obj_free(l_objs, l_data_size_out);
+
+    return l_list;
+    /*
+     size_t l_list_count = 0;
+     char *l_first_key_str = dap_strdup_printf("%lld", (int64_t) first_timestamp);
+     size_t l_data_size_out = 0;
+
+     for(size_t i = 0; i < l_data_size_out; i++) {
+     dap_global_db_obj_t *l_obj_cur = l_objs[i];
+     //        log_it(L_DEBUG,"%lld and %lld tr",strtoll(l_obj_cur->key,NULL,10), first_timestamp );
+     if( strtoll(l_obj_cur->key,NULL,10) > (long long) first_timestamp  ) {
+     dap_global_db_obj_t *l_item = DAP_NEW(dap_global_db_obj_t);
+     l_item->key = dap_strdup(l_obj_cur->key);
+     l_item->value =(uint8_t*) dap_strdup((char*) l_obj_cur->value);
+     l_list = dap_list_append(l_list, l_item);
+     l_list_count++;
+     }
+     }
+     // sort list by key (time str)
+     //dap_list_sort(l_list, (dap_callback_compare_t) compare_items);
+     log_it(L_DEBUG,"Prepared %u items (list size %u)", l_list_count, dap_list_length(l_list));
+     DAP_DELETE(l_first_key_str);
+     dap_chain_global_db_objs_delete(l_objs);
+     */
     /*/ dbg - sort result
      l_data_size_out = dap_list_length(l_list);
      for(size_t i = 0; i < l_data_size_out; i++) {
@@ -229,9 +249,6 @@ dap_list_t* dap_db_log_get_list(time_t first_timestamp)
      printf("2 %d %s\n", i, l_item->key);
      }*/
 
-    DAP_DELETE(l_first_key_str);
-    dap_chain_global_db_objs_delete(l_objs);
-    return l_list;
 }
 
 /**