From d98f387635b8e4e536e42fca78745a2c5ef61255 Mon Sep 17 00:00:00 2001
From: Roman Khlopkov <roman.khlopkov@demlabs.net>
Date: Thu, 20 Jan 2022 11:22:30 +0000
Subject: [PATCH] hotfix-5489

---
 modules/chain/dap_chain_ledger.c              | 175 +++++++++---------
 modules/channel/chain/dap_stream_ch_chain.c   |   3 +-
 modules/common/dap_chain_datum_tx_items.c     |   3 +-
 .../common/include/dap_chain_datum_tx_items.h |   2 +-
 .../consensus/dag-poa/dap_chain_cs_dag_poa.c  |   4 +-
 modules/global-db/dap_chain_global_db.c       |  26 +--
 .../global-db/dap_chain_global_db_driver.c    |   2 +-
 .../dap_chain_global_db_driver_cdb.c          |   9 +-
 modules/net/dap_chain_net.c                   |   5 +
 modules/net/dap_chain_node_cli_cmd.c          |  11 +-
 modules/type/dag/dap_chain_cs_dag.c           |   7 +-
 modules/type/dag/dap_chain_cs_dag_event.c     |   2 +-
 modules/type/dag/include/dap_chain_cs_dag.h   |   4 +-
 .../type/dag/include/dap_chain_cs_dag_event.h |   2 +-
 14 files changed, 129 insertions(+), 126 deletions(-)

diff --git a/modules/chain/dap_chain_ledger.c b/modules/chain/dap_chain_ledger.c
index 753c0e6278..13bed27174 100644
--- a/modules/chain/dap_chain_ledger.c
+++ b/modules/chain/dap_chain_ledger.c
@@ -191,11 +191,8 @@ typedef struct dap_ledger_private {
     bool check_cells_ds;
     bool check_token_emission;
     dap_chain_cell_id_t local_cell_id;
-    /* Cache section */
-    dap_ledger_cache_item_t last_tx;
-    dap_ledger_cache_item_t last_spent_tx;
-    dap_ledger_cache_item_t last_emit;
-    dap_ledger_cache_str_item_t last_ticker;
+
+    bool load_mode;
 } dap_ledger_private_t;
 #define PVT(a) ( (dap_ledger_private_t* ) a->_internal )
 
@@ -279,10 +276,7 @@ void dap_chain_ledger_handle_free(dap_ledger_t *a_ledger)
 
 void dap_chain_ledger_load_end(dap_ledger_t *a_ledger)
 {
-    PVT(a_ledger)->last_tx.found = true;
-    PVT(a_ledger)->last_spent_tx.found = true;
-    PVT(a_ledger)->last_emit.found = true;
-    PVT(a_ledger)->last_ticker.found = true;
+    PVT(a_ledger)->load_mode = false;
 }
 
 
@@ -868,10 +862,15 @@ static int s_token_tsd_parse(dap_ledger_t * a_ledger, dap_chain_ledger_token_ite
 
 int dap_chain_ledger_token_load(dap_ledger_t *a_ledger,  dap_chain_datum_token_t *a_token, size_t a_token_size)
 {
-    if (PVT(a_ledger)->last_ticker.found) {
+    if (!PVT(a_ledger)->load_mode) {
         return dap_chain_ledger_token_add(a_ledger, a_token, a_token_size);
-    } else if (!strncmp(PVT(a_ledger)->last_ticker.key, a_token->ticker, DAP_CHAIN_TICKER_SIZE_MAX)) {
-        PVT(a_ledger)->last_ticker.found = true;
+    } else {
+        dap_chain_ledger_token_item_t *l_token_item;
+        pthread_rwlock_rdlock(&PVT(a_ledger)->tokens_rwlock);
+        HASH_FIND_STR(PVT(a_ledger)->tokens, a_token->ticker, l_token_item);
+        pthread_rwlock_unlock(&PVT(a_ledger)->tokens_rwlock);
+        if (!l_token_item)
+            return dap_chain_ledger_token_add(a_ledger, a_token, a_token_size);
     }
     return 0;
 }
@@ -999,15 +998,9 @@ void dap_chain_ledger_load_cache(dap_ledger_t *a_ledger)
             }
         }
         HASH_ADD_STR(l_ledger_pvt->tokens, ticker, l_token_item);
-        if (i == l_objs_count - 1) {
-            l_ledger_pvt->last_ticker.key = l_token_item->ticker;
-        }
     }
     dap_chain_global_db_objs_delete(l_objs, l_objs_count);
     DAP_DELETE(l_gdb_group);
-    if (l_objs_count == 0 || l_ledger_pvt->last_ticker.key == NULL) {
-        l_ledger_pvt->last_ticker.found = true;
-    }
 
     l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, DAP_CHAIN_LEDGER_EMISSIONS_STR);
     l_objs_count = 0;
@@ -1032,15 +1025,9 @@ void dap_chain_ledger_load_cache(dap_ledger_t *a_ledger)
             HASH_ADD(hh, l_ledger_pvt->treshold_emissions, datum_token_emission_hash,
                      sizeof(dap_chain_hash_fast_t), l_emission_item);
         }
-        if (i == l_objs_count - 1) {
-            l_ledger_pvt->last_emit.hash = &l_emission_item->datum_token_emission_hash;
-        }
     }
     dap_chain_global_db_objs_delete(l_objs, l_objs_count);
     DAP_DELETE(l_gdb_group);
-    if (l_objs_count == 0 || l_ledger_pvt->last_emit.hash == NULL) {
-        l_ledger_pvt->last_emit.found = true;
-    }
 
     l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, DAP_CHAIN_LEDGER_TXS_STR);
     l_objs_count = 0;
@@ -1052,15 +1039,9 @@ void dap_chain_ledger_load_cache(dap_ledger_t *a_ledger)
         memcpy(l_tx_item->tx, l_objs[i].value + sizeof(l_tx_item->cache_data), l_objs[i].value_len - sizeof(l_tx_item->cache_data));
         memcpy(&l_tx_item->cache_data, l_objs[i].value, sizeof(l_tx_item->cache_data));
         HASH_ADD(hh, l_ledger_pvt->ledger_items, tx_hash_fast, sizeof(dap_chain_hash_fast_t), l_tx_item);
-        if (i == l_objs_count - 1) {
-            l_ledger_pvt->last_tx.hash = &l_tx_item->tx_hash_fast;
-        }
     }
     dap_chain_global_db_objs_delete(l_objs, l_objs_count);
     DAP_DELETE(l_gdb_group);
-    if (l_objs_count == 0 || l_ledger_pvt->last_tx.hash == NULL) {
-        l_ledger_pvt->last_tx.found = true;
-    }
 
     l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, DAP_CHAIN_LEDGER_SPENT_TXS_STR);
     l_objs_count = 0;
@@ -1070,15 +1051,9 @@ void dap_chain_ledger_load_cache(dap_ledger_t *a_ledger)
         dap_chain_hash_fast_from_str(l_objs[i].key, &l_tx_spent_item->tx_hash_fast);
         strncpy(l_tx_spent_item->token_ticker, (char *)l_objs[i].value, DAP_CHAIN_TICKER_SIZE_MAX);
         HASH_ADD(hh, l_ledger_pvt->spent_items, tx_hash_fast, sizeof(dap_chain_hash_fast_t), l_tx_spent_item);
-        if (i == l_objs_count - 1) {
-            l_ledger_pvt->last_spent_tx.hash = &l_tx_spent_item->tx_hash_fast;
-        }
     }
     dap_chain_global_db_objs_delete(l_objs, l_objs_count);
     DAP_DELETE(l_gdb_group);
-    if (l_objs_count == 0 || l_ledger_pvt->last_spent_tx.hash == NULL) {
-        l_ledger_pvt->last_spent_tx.found = true;
-    }
 
     l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, DAP_CHAIN_LEDGER_BALANCES_STR);
     l_objs_count = 0;
@@ -1120,10 +1095,13 @@ dap_ledger_t* dap_chain_ledger_create(uint16_t a_check_flags, char *a_net_name)
     l_ledger_priv->check_cells_ds = a_check_flags & DAP_CHAIN_LEDGER_CHECK_CELLS_DS;
     l_ledger_priv->check_token_emission = a_check_flags & DAP_CHAIN_LEDGER_CHECK_TOKEN_EMISSION;
     l_ledger_priv->net = dap_chain_net_by_name(a_net_name);
+    l_ledger_priv->load_mode = true;
 
     log_it(L_DEBUG,"Created ledger \"%s\"",a_net_name);
-    // load ledger cache from GDB
-    dap_chain_ledger_load_cache(l_ledger);
+    if (dap_config_get_item_bool_default(g_config, "ledger", "cached", true)) {
+        // load ledger cache from GDB
+        dap_chain_ledger_load_cache(l_ledger);
+    }
     return l_ledger;
 }
 
@@ -1307,16 +1285,34 @@ int dap_chain_ledger_token_emission_add(dap_ledger_t *a_ledger, byte_t *a_token_
 
 int dap_chain_ledger_token_emission_load(dap_ledger_t *a_ledger, byte_t *a_token_emission, size_t a_token_emission_size)
 {
-    if (PVT(a_ledger)->last_emit.found) {
+    if (!PVT(a_ledger)->load_mode) {
         return dap_chain_ledger_token_emission_add(a_ledger, a_token_emission, a_token_emission_size);
     } else {
         dap_chain_hash_fast_t l_token_emission_hash = {};
         dap_hash_fast(a_token_emission, a_token_emission_size, &l_token_emission_hash);
-        if (!memcmp(PVT(a_ledger)->last_emit.hash, &l_token_emission_hash, sizeof(dap_chain_hash_fast_t))) {
-            PVT(a_ledger)->last_emit.found = true;
+        dap_chain_ledger_token_emission_item_t *l_token_emission_item;
+        dap_chain_ledger_token_item_t *l_token_item, *l_item_tmp;
+        pthread_rwlock_rdlock(&PVT(a_ledger)->tokens_rwlock);
+        HASH_ITER(hh, PVT(a_ledger)->tokens, l_token_item, l_item_tmp) {
+            pthread_rwlock_rdlock(&l_token_item->token_emissions_rwlock);
+            HASH_FIND(hh, l_token_item->token_emissions, &l_token_emission_hash, sizeof(l_token_emission_hash),
+                    l_token_emission_item);
+            pthread_rwlock_unlock(&l_token_item->token_emissions_rwlock);
+            if (l_token_emission_item) {
+                pthread_rwlock_unlock(&PVT(a_ledger)->tokens_rwlock);
+                return 0;
+            }
+        }
+        pthread_rwlock_unlock(&PVT(a_ledger)->tokens_rwlock);
+        pthread_rwlock_rdlock(&PVT(a_ledger)->treshold_emissions_rwlock);
+        HASH_FIND(hh, PVT(a_ledger)->treshold_emissions, &l_token_emission_hash, sizeof(l_token_emission_hash),
+                l_token_emission_item);
+        pthread_rwlock_unlock(&PVT(a_ledger)->treshold_emissions_rwlock);
+        if (l_token_emission_item) {
+            return DAP_CHAIN_CS_VERIFY_CODE_TX_NO_TOKEN;
         }
     }
-    return 0;
+    return dap_chain_ledger_token_emission_add(a_ledger, a_token_emission, a_token_emission_size);
 }
 
 /**
@@ -2439,21 +2435,30 @@ FIN:
 
 int dap_chain_ledger_tx_load(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx)
 {
-    if (PVT(a_ledger)->last_tx.found && PVT(a_ledger)->last_spent_tx.found) {
+    if (!PVT(a_ledger)->load_mode) {
         return dap_chain_ledger_tx_add(a_ledger, a_tx, false);
     } else {
         dap_chain_hash_fast_t l_tx_hash = {};
         dap_hash_fast(a_tx, dap_chain_datum_tx_get_size(a_tx), &l_tx_hash);
-        if (!PVT(a_ledger)->last_tx.found &&
-                !memcmp(PVT(a_ledger)->last_tx.hash, &l_tx_hash, sizeof(dap_chain_hash_fast_t))) {
-            PVT(a_ledger)->last_tx.found = true;
-        }
-        if (!PVT(a_ledger)->last_spent_tx.found &&
-                !memcmp(PVT(a_ledger)->last_spent_tx.hash, &l_tx_hash, sizeof(dap_chain_hash_fast_t))) {
-            PVT(a_ledger)->last_spent_tx.found = true;
-        }
-    }
-    return 1;
+        dap_chain_ledger_tx_item_t *l_tx_item;
+        pthread_rwlock_rdlock(&PVT(a_ledger)->ledger_rwlock);
+        HASH_FIND(hh, PVT(a_ledger)->ledger_items, &l_tx_hash, sizeof(dap_chain_hash_fast_t), l_tx_item);
+        if (l_tx_item) {
+            pthread_rwlock_unlock(&PVT(a_ledger)->ledger_rwlock);
+            return 1;
+        }
+        HASH_FIND(hh, PVT(a_ledger)->treshold_txs, &l_tx_hash, sizeof(dap_chain_hash_fast_t), l_tx_item);
+        if (l_tx_item) {
+            pthread_rwlock_unlock(&PVT(a_ledger)->ledger_rwlock);
+            return DAP_CHAIN_CS_VERIFY_CODE_TX_NO_PREVIOUS;
+        }
+        dap_chain_ledger_tx_spent_item_t *l_tx_spent_item;
+        HASH_FIND(hh, PVT(a_ledger)->spent_items, &l_tx_hash, sizeof(dap_chain_hash_fast_t), l_tx_spent_item);
+        pthread_rwlock_unlock(&PVT(a_ledger)->ledger_rwlock);
+        if (l_tx_spent_item)
+            return 1;
+    }
+    return dap_chain_ledger_tx_add(a_ledger, a_tx, false);
 }
 
 /**
@@ -2488,7 +2493,8 @@ int dap_chain_ledger_tx_remove(dap_ledger_t *a_ledger, dap_chain_hash_fast_t *a_
             char *l_cache_data = DAP_NEW_Z_SIZE(char, DAP_CHAIN_TICKER_SIZE_MAX);
             strncpy(l_cache_data, l_item_used->token_ticker, DAP_CHAIN_TICKER_SIZE_MAX);
             l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, DAP_CHAIN_LEDGER_SPENT_TXS_STR);
-            if (!dap_chain_global_db_gr_set(dap_hash_fast_to_str_new(a_tx_hash), l_cache_data, -1, l_gdb_group)) {
+            char *l_tx_hash_str = dap_hash_fast_to_str_new(a_tx_hash);
+            if (!dap_chain_global_db_gr_set(l_tx_hash_str, l_cache_data, -1, l_gdb_group)) {
                 if(s_debug_more)
                     log_it(L_WARNING, "Ledger cache mismatch");
                 DAP_DELETE(l_cache_data);
@@ -2512,7 +2518,6 @@ void dap_chain_ledger_purge(dap_ledger_t *a_ledger, bool a_preserve_db)
 {
     dap_ledger_private_t *l_ledger_priv = PVT(a_ledger);
     const int l_hash_str_size = DAP_CHAIN_HASH_FAST_SIZE * 2 + 2;
-    char l_hash_str[l_hash_str_size];
     pthread_rwlock_wrlock(&l_ledger_priv->ledger_rwlock);
     pthread_rwlock_wrlock(&l_ledger_priv->tokens_rwlock);
     pthread_rwlock_wrlock(&l_ledger_priv->treshold_emissions_rwlock);
@@ -2521,69 +2526,66 @@ void dap_chain_ledger_purge(dap_ledger_t *a_ledger, bool a_preserve_db)
 
     // delete transactions
     dap_chain_ledger_tx_item_t *l_item_current, *l_item_tmp;
-    char *l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, DAP_CHAIN_LEDGER_TXS_STR);
+    char *l_gdb_group;
     HASH_ITER(hh, l_ledger_priv->ledger_items , l_item_current, l_item_tmp) {
-        DAP_DELETE(l_item_current->tx);
         HASH_DEL(l_ledger_priv->ledger_items, l_item_current);
-        if (!a_preserve_db) {
-            dap_chain_hash_fast_to_str(&l_item_current->tx_hash_fast, l_hash_str, l_hash_str_size);
-            dap_chain_global_db_gr_del(dap_strdup(l_hash_str), l_gdb_group);
-        }
+        DAP_DELETE(l_item_current->tx);
         DAP_DELETE(l_item_current);
     }
-    DAP_DELETE(l_gdb_group);
+    if (!a_preserve_db) {
+        l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, DAP_CHAIN_LEDGER_TXS_STR);
+        dap_chain_global_db_gr_del(NULL, l_gdb_group);
+        DAP_DELETE(l_gdb_group);
+    }
 
     // delete spent transactions
     dap_chain_ledger_tx_spent_item_t *l_spent_item_current, *l_spent_item_tmp;
-    l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, DAP_CHAIN_LEDGER_SPENT_TXS_STR);
     HASH_ITER(hh, l_ledger_priv->spent_items, l_spent_item_current, l_spent_item_tmp) {
         HASH_DEL(l_ledger_priv->spent_items, l_spent_item_current);
-        if (!a_preserve_db) {
-            dap_chain_hash_fast_to_str(&l_spent_item_current->tx_hash_fast, l_hash_str, l_hash_str_size);
-            dap_chain_global_db_gr_del(dap_strdup(l_hash_str), l_gdb_group);
-        }
         DAP_DELETE(l_item_current);
     }
-    DAP_DELETE(l_gdb_group);
+    if (!a_preserve_db) {
+        l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, DAP_CHAIN_LEDGER_SPENT_TXS_STR);
+        dap_chain_global_db_gr_del(NULL, l_gdb_group);
+        DAP_DELETE(l_gdb_group);
+    }
 
     // delete balances
     dap_ledger_wallet_balance_t *l_balance_current, *l_balance_tmp;
-    l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, DAP_CHAIN_LEDGER_BALANCES_STR);
-    char *l_emissions_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, DAP_CHAIN_LEDGER_EMISSIONS_STR);
     HASH_ITER(hh, l_ledger_priv->balance_accounts, l_balance_current, l_balance_tmp) {
         HASH_DEL(l_ledger_priv->balance_accounts, l_balance_current);
-        if (!a_preserve_db)
-            dap_chain_global_db_gr_del(l_balance_current->key, l_gdb_group);
         DAP_DELETE(l_balance_current);
     }
-    DAP_DELETE(l_gdb_group);
+    if (!a_preserve_db) {
+        l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, DAP_CHAIN_LEDGER_BALANCES_STR);
+        dap_chain_global_db_gr_del(NULL, l_gdb_group);
+        DAP_DELETE(l_gdb_group);
+    }
 
     // delete tokens & its emissions
     dap_chain_ledger_token_item_t *l_token_current, *l_token_tmp;
     dap_chain_ledger_token_emission_item_t *l_emission_current, *l_emission_tmp;
-    l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, DAP_CHAIN_LEDGER_TOKENS_STR);
     HASH_ITER(hh, l_ledger_priv->tokens, l_token_current, l_token_tmp) {
         HASH_DEL(l_ledger_priv->tokens, l_token_current);
         pthread_rwlock_wrlock(&l_token_current->token_emissions_rwlock);
         HASH_ITER(hh, l_token_current->token_emissions, l_emission_current, l_emission_tmp) {
             HASH_DEL(l_token_current->token_emissions, l_emission_current);
-            if (!a_preserve_db) {
-                dap_chain_hash_fast_to_str(&l_emission_current->datum_token_emission_hash, l_hash_str, l_hash_str_size);
-                dap_chain_global_db_gr_del(dap_strdup(l_hash_str), l_emissions_gdb_group);
-            }
             DAP_DELETE(l_emission_current->datum_token_emission);
             DAP_DELETE(l_emission_current);
         }
         pthread_rwlock_unlock(&l_token_current->token_emissions_rwlock);
-        if (!a_preserve_db)
-            dap_chain_global_db_gr_del(dap_strdup(l_token_current->ticker), l_gdb_group);
         DAP_DELETE(l_token_current->datum_token);
         pthread_rwlock_destroy(&l_token_current->token_emissions_rwlock);
         DAP_DELETE(l_token_current);
-    }  
-    DAP_DELETE(l_gdb_group);
-    DAP_DELETE(l_emissions_gdb_group);
-
+    }
+    if (!a_preserve_db) {
+        l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, DAP_CHAIN_LEDGER_TOKENS_STR);
+        dap_chain_global_db_gr_del(NULL, l_gdb_group);
+        DAP_DELETE(l_gdb_group);
+        l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, DAP_CHAIN_LEDGER_EMISSIONS_STR);
+        dap_chain_global_db_gr_del(NULL, l_gdb_group);
+        DAP_DELETE(l_gdb_group);
+    }
 
     // delete threshold emissions
     HASH_ITER(hh, l_ledger_priv->treshold_emissions, l_emission_current, l_emission_tmp) {
@@ -2598,11 +2600,6 @@ void dap_chain_ledger_purge(dap_ledger_t *a_ledger, bool a_preserve_db)
         DAP_DELETE(l_item_current);
     }
 
-    l_ledger_priv->last_tx.found = true;
-    l_ledger_priv->last_spent_tx.found = true;
-    l_ledger_priv->last_emit.found = true;
-    l_ledger_priv->last_ticker.found = true;
-
     pthread_rwlock_unlock(&l_ledger_priv->ledger_rwlock);
     pthread_rwlock_unlock(&l_ledger_priv->tokens_rwlock);
     pthread_rwlock_unlock(&l_ledger_priv->treshold_emissions_rwlock);
diff --git a/modules/channel/chain/dap_stream_ch_chain.c b/modules/channel/chain/dap_stream_ch_chain.c
index daf067c161..79a97dc50e 100644
--- a/modules/channel/chain/dap_stream_ch_chain.c
+++ b/modules/channel/chain/dap_stream_ch_chain.c
@@ -499,7 +499,8 @@ static bool s_sync_in_chains_callback(dap_proc_thread_t *a_thread, void *a_arg)
         if (s_debug_more){
             char l_atom_hash_str[72]={[0]='\0'};
             dap_chain_hash_fast_to_str(&l_atom_hash,l_atom_hash_str,sizeof (l_atom_hash_str)-1 );
-            log_it(L_WARNING,"Atom with hash %s for %s:%s not accepted (code ATOM_PASS, already present)",  l_atom_hash_str, l_chain->net_name, l_chain->name);
+            log_it(L_INFO, "%s atom with hash %s for %s:%s", l_atom_add_res == ATOM_ACCEPT ? "Accepted" : "Thresholded",
+                            l_atom_hash_str, l_chain->net_name, l_chain->name);
         }
         dap_db_set_last_hash_remote(l_sync_request->request.node_addr.uint64, l_chain, &l_atom_hash);
         DAP_DELETE(l_atom_copy);
diff --git a/modules/common/dap_chain_datum_tx_items.c b/modules/common/dap_chain_datum_tx_items.c
index 38cde942ce..8e62f58083 100644
--- a/modules/common/dap_chain_datum_tx_items.c
+++ b/modules/common/dap_chain_datum_tx_items.c
@@ -148,12 +148,13 @@ size_t dap_chain_datum_item_tx_get_size(const uint8_t *a_item)
  *
  * return item, NULL Error
  */
-dap_chain_tx_token_t* dap_chain_datum_tx_item_token_create(dap_chain_hash_fast_t * a_datum_token_hash,const char * a_ticker)
+dap_chain_tx_token_t *dap_chain_datum_tx_item_token_create(dap_chain_id_t a_id, dap_chain_hash_fast_t *a_datum_token_hash,const char *a_ticker)
 {
     if(!a_ticker)
         return NULL;
     dap_chain_tx_token_t *l_item = DAP_NEW_Z(dap_chain_tx_token_t);
     l_item->header.type = TX_ITEM_TYPE_TOKEN;
+    l_item->header.token_emission_chain_id.uint64 = a_id.uint64;
     memcpy (& l_item->header.token_emission_hash, a_datum_token_hash, sizeof ( *a_datum_token_hash ) );
     strncpy(l_item->header.ticker, a_ticker, sizeof(l_item->header.ticker) - 1);
     return l_item;
diff --git a/modules/common/include/dap_chain_datum_tx_items.h b/modules/common/include/dap_chain_datum_tx_items.h
index 3b891bc45c..6fb2f647cd 100644
--- a/modules/common/include/dap_chain_datum_tx_items.h
+++ b/modules/common/include/dap_chain_datum_tx_items.h
@@ -80,7 +80,7 @@ size_t dap_chain_datum_item_tx_get_size(const uint8_t *a_item);
  *
  * return item, NULL Error
  */
-dap_chain_tx_token_t* dap_chain_datum_tx_item_token_create(dap_chain_hash_fast_t * a_datum_token_hash,const char * a_ticker);
+dap_chain_tx_token_t *dap_chain_datum_tx_item_token_create(dap_chain_id_t a_id, dap_chain_hash_fast_t *a_datum_token_hash, const char *a_ticker);
 
 /**
  * Create item dap_chain_tx_out_t
diff --git a/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c b/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c
index c763ede337..c6e4380624 100644
--- a/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c
+++ b/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c
@@ -91,7 +91,7 @@ static bool s_round_event_ready_minimum_check(dap_chain_cs_dag_t * a_dag, dap_ch
                                             dap_chain_cs_dag_event_round_cfg_t * a_event_round_cfg);
 static void s_round_event_cs_done(dap_chain_cs_dag_t * a_dag, dap_chain_cs_dag_event_t * a_event,
                                     char * a_event_hash_hex_str, dap_chain_cs_dag_event_round_cfg_t * a_event_round_cfg);
-static void s_round_event_clean_dup(dap_chain_cs_dag_t * a_dag, char * a_event_hash_hex_str);
+static void s_round_event_clean_dup(dap_chain_cs_dag_t * a_dag, const char *a_event_hash_hex_str);
 
 // CLI commands
 static int s_cli_dag_poa(int argc, char ** argv, char **str_reply);
@@ -346,7 +346,7 @@ typedef struct event_clean_dup_items {
 
 static event_clean_dup_items_t *s_event_clean_dup_items = NULL;
 
-static void s_round_event_clean_dup(dap_chain_cs_dag_t * a_dag, char * a_event_hash_hex_str) {
+static void s_round_event_clean_dup(dap_chain_cs_dag_t * a_dag, const char *a_event_hash_hex_str) {
     char * l_gdb_group_events = a_dag->gdb_group_events_round_new;
     size_t l_event_size = 0;
     dap_chain_cs_dag_event_t * l_event;
diff --git a/modules/global-db/dap_chain_global_db.c b/modules/global-db/dap_chain_global_db.c
index 7d714677cb..325450910b 100644
--- a/modules/global-db/dap_chain_global_db.c
+++ b/modules/global-db/dap_chain_global_db.c
@@ -604,10 +604,8 @@ bool dap_chain_global_db_set( char *a_key,  void *a_value, size_t a_value_len)
  * @param a_group a group name string
  * @return True if object was deleted or false otherwise.
  */
-bool dap_chain_global_db_gr_del(char *a_key,const char *a_group)
+bool dap_chain_global_db_gr_del(char *a_key, const char *a_group)
 {
-    if(!a_key)
-        return NULL;
     dap_store_obj_t store_data;
     memset(&store_data, 0, sizeof(dap_store_obj_t));
     store_data.key = dap_strdup(a_key);
@@ -615,16 +613,18 @@ bool dap_chain_global_db_gr_del(char *a_key,const char *a_group)
     lock();
     int l_res = dap_chain_global_db_driver_delete(&store_data, 1);
     unlock();
-    if(l_res >= 0) {
-        // add to Del group
-        global_db_gr_del_add(dap_strdup(a_key), store_data.group, time(NULL));
-    }
-    // do not add to history if l_res=1 (already deleted)
-    if (!l_res) {
-        store_data.key = a_key;
-        dap_global_db_obj_track_history(&store_data);
-    } else {
-        DAP_DELETE(a_key);
+    if (a_key) {
+        if (l_res >= 0) {
+            // add to Del group
+            global_db_gr_del_add(dap_strdup(a_key), store_data.group, time(NULL));
+        }
+        // do not add to history if l_res=1 (already deleted)
+        if (!l_res) {
+            store_data.key = a_key;
+            dap_global_db_obj_track_history(&store_data);
+        } else {
+            DAP_DELETE(a_key);
+        }
     }
     return !l_res;
 }
diff --git a/modules/global-db/dap_chain_global_db_driver.c b/modules/global-db/dap_chain_global_db_driver.c
index 3e3176a1af..98e9e26cac 100644
--- a/modules/global-db/dap_chain_global_db_driver.c
+++ b/modules/global-db/dap_chain_global_db_driver.c
@@ -458,7 +458,7 @@ int dap_chain_global_db_driver_appy(pdap_store_obj_t a_store_obj, size_t a_store
                 log_it(L_ERROR, "Can't write item %s/%s (code %d)\n", l_store_obj_cur->group, l_cur_key, l_ret_tmp);
                 l_ret -= 1;
             }
-            DAP_DELETE(l_cur_key);
+            DAP_DEL_Z(l_cur_key);
             if (l_ret)
                 break;
         }
diff --git a/modules/global-db/dap_chain_global_db_driver_cdb.c b/modules/global-db/dap_chain_global_db_driver_cdb.c
index 9ad9af43ca..3a237fd47a 100644
--- a/modules/global-db/dap_chain_global_db_driver_cdb.c
+++ b/modules/global-db/dap_chain_global_db_driver_cdb.c
@@ -172,10 +172,11 @@ pcdb_instance dap_cdb_init_group(char *a_group, int a_flags) {
     pthread_mutex_lock(&cdb_mutex);
     char l_cdb_path[strlen(s_cdb_path) + strlen(a_group) + 2];
     HASH_FIND_STR(s_cdb, a_group, l_cdb_i);
-    if (l_cdb_i && !(a_flags & CDB_TRUNC)) {
-        goto FIN;
+    if (!(a_flags & CDB_TRUNC)) {
+        if (l_cdb_i)
+            goto FIN;
+        l_cdb_i = DAP_NEW(cdb_instance);
     }
-    l_cdb_i = DAP_NEW(cdb_instance);
     l_cdb_i->local_group = dap_strdup(a_group);
     l_cdb_i->cdb = cdb_new();
     memset(l_cdb_path, '\0', sizeof(l_cdb_path));
@@ -611,13 +612,13 @@ int dap_db_driver_cdb_apply_store_obj(pdap_store_obj_t a_store_obj) {
         if(a_store_obj->key) {
             if(cdb_del(l_cdb_i->cdb, a_store_obj->key, (int) strlen(a_store_obj->key)) == -3)
                 ret = 1;
+            DAP_DELETE(a_store_obj->key);
         } else {
             cdb_destroy(l_cdb_i->cdb);
             if (!dap_cdb_init_group(a_store_obj->group, CDB_TRUNC | CDB_PAGEWARMUP)) {
                 ret = -1;
             }
         }
-        DAP_DELETE(a_store_obj->key);
     }
     return ret;
 }
diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c
index 700ada9e03..4ee4a41743 100644
--- a/modules/net/dap_chain_net.c
+++ b/modules/net/dap_chain_net.c
@@ -1781,6 +1781,11 @@ static int s_cli_net(int argc, char **argv, char **a_str_reply)
                     dap_chain_gdb_ledger_load((char *)dap_chain_gdb_get_group(l_chain), l_chain);
                 } else {
                     dap_chain_load_all(l_chain);
+                    if (l_chain->callback_atom_add_from_treshold) {
+                        while (l_chain->callback_atom_add_from_treshold(l_chain, NULL)) {
+                            log_it(L_DEBUG, "Added atom from treshold");
+                        }
+                    }
                 }
             }
         } else {
diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c
index ae4fea9b08..21a17895ef 100644
--- a/modules/net/dap_chain_node_cli_cmd.c
+++ b/modules/net/dap_chain_node_cli_cmd.c
@@ -3279,13 +3279,10 @@ int com_token_emit(int a_argc, char ** a_argv, char ** a_str_reply)
     // Create emission datum
     // then create datum in memory
     if(!l_emission){
-        char * l_gdb_group_mempool_emission;
-        if(l_chain_emission) {
-            l_gdb_group_mempool_emission = dap_chain_net_get_gdb_group_mempool(l_chain_emission);
-        }
-        else {
-            l_gdb_group_mempool_emission = dap_chain_net_get_gdb_group_mempool_by_chain_type(l_net, CHAIN_TYPE_EMISSION);
+        if (!l_chain_emission) {
+            l_chain_emission = dap_chain_net_get_chain_by_chain_type(l_net, CHAIN_TYPE_EMISSION);
         }
+        char *l_gdb_group_mempool_emission = dap_chain_net_get_gdb_group_mempool(l_chain_emission);
         size_t l_emission_size = sizeof(l_emission->hdr) +
                 sizeof(l_emission->data.type_auth.signs_count);
 
@@ -3358,7 +3355,7 @@ int com_token_emit(int a_argc, char ** a_argv, char ** a_str_reply)
     l_tx->header.ts_created = time(NULL);
     dap_chain_hash_fast_t l_tx_prev_hash = { 0 };
     // create items
-    dap_chain_tx_token_t *l_tx_token = dap_chain_datum_tx_item_token_create(&l_emission_hash, l_ticker);
+    dap_chain_tx_token_t *l_tx_token = dap_chain_datum_tx_item_token_create(l_chain_emission->id, &l_emission_hash, l_ticker);
     dap_chain_tx_in_t *l_in = dap_chain_datum_tx_item_in_create(&l_tx_prev_hash, 0);
     dap_chain_tx_out_t *l_out = dap_chain_datum_tx_item_out_create(l_addr, l_emission_value);
 
diff --git a/modules/type/dag/dap_chain_cs_dag.c b/modules/type/dag/dap_chain_cs_dag.c
index dca78a4dda..98ce729b20 100644
--- a/modules/type/dag/dap_chain_cs_dag.c
+++ b/modules/type/dag/dap_chain_cs_dag.c
@@ -382,9 +382,10 @@ static int s_dap_chain_add_atom_to_events_table(dap_chain_cs_dag_t * a_dag, dap_
     if (s_debug_more) {
         char l_buf_hash[128] = {'\0'};
         dap_chain_hash_fast_to_str(&a_event_item->hash,l_buf_hash,sizeof(l_buf_hash)-1);
-        log_it(L_DEBUG,"Dag event %s checked, add it to ledger", l_buf_hash);
         if (l_ledger_res != 0)
             log_it(L_WARNING,"Dag event %s checked, but ledger declined: code %d", l_buf_hash, l_ledger_res);
+        else
+            log_it(L_DEBUG,"Dag event %s checked, add it to ledger", l_buf_hash);
     }
     return l_ledger_res;
 }
@@ -1655,11 +1656,11 @@ static int s_cli_dag(int argc, char ** argv, char **a_str_reply)
                         DAP_DELETE(l_hash_str);
                         dap_string_append_printf(l_str_tmp,
                             "\t\t\t\tts_update: %s", 
-                            dap_ctime_r(&l_event_round_cfg.ts_update, buf) );
+                            dap_ctime_r((time_t *)&l_event_round_cfg.ts_update, buf) );
                         if (l_event_round_cfg.ts_confirmations_minimum_completed != 0)
                             dap_string_append_printf(l_str_tmp,
                                 "\t\t\t\tts_confirmations_minimum_completed: %s", 
-                                dap_ctime_r(&l_event_round_cfg.ts_confirmations_minimum_completed, buf) );
+                                dap_ctime_r((time_t *)&l_event_round_cfg.ts_confirmations_minimum_completed, buf) );
                     }
 
                      // Header
diff --git a/modules/type/dag/dap_chain_cs_dag_event.c b/modules/type/dag/dap_chain_cs_dag_event.c
index d0ba2b1354..a9500468df 100644
--- a/modules/type/dag/dap_chain_cs_dag_event.c
+++ b/modules/type/dag/dap_chain_cs_dag_event.c
@@ -204,7 +204,7 @@ bool dap_chain_cs_dag_event_gdb_set(char *a_event_hash_str, dap_chain_cs_dag_eve
     return ret;
 }
 
-dap_chain_cs_dag_event_t* dap_chain_cs_dag_event_gdb_get(char *a_event_hash_str, size_t * a_event_size, const char *a_group,
+dap_chain_cs_dag_event_t* dap_chain_cs_dag_event_gdb_get(const char *a_event_hash_str, size_t * a_event_size, const char *a_group,
                                                             dap_chain_cs_dag_event_round_cfg_t * a_event_round_cfg) {
     size_t l_event_round_item_size = 0;
     dap_chain_cs_dag_event_round_item_t* l_event_round_item = 
diff --git a/modules/type/dag/include/dap_chain_cs_dag.h b/modules/type/dag/include/dap_chain_cs_dag.h
index d11ae746d9..dcfc83dd4c 100644
--- a/modules/type/dag/include/dap_chain_cs_dag.h
+++ b/modules/type/dag/include/dap_chain_cs_dag.h
@@ -36,10 +36,10 @@ typedef dap_chain_cs_dag_event_t * (*dap_chain_cs_dag_callback_event_create_t)(d
                                                                                dap_chain_hash_fast_t *,
                                                                                size_t, size_t*);
 
-typedef int (*dap_chain_cs_dag_callback_get_round_cfg_t)(dap_chain_cs_dag_t *, dap_chain_cs_dag_event_round_cfg_t *);
+typedef void (*dap_chain_cs_dag_callback_get_round_cfg_t)(dap_chain_cs_dag_t *, dap_chain_cs_dag_event_round_cfg_t *);
 typedef void (*dap_chain_cs_dag_callback_set_event_round_cfg_t)(dap_chain_cs_dag_t *, dap_chain_cs_dag_event_round_cfg_t *);
 
-typedef void (*dap_chain_cs_dag_callback_event_round_sync_t)(dap_chain_cs_dag_t * a_dag, const char a_op_code, const char *a_group,
+typedef int (*dap_chain_cs_dag_callback_event_round_sync_t)(dap_chain_cs_dag_t * a_dag, const char a_op_code, const char *a_group,
                                                 const char *a_key, const void *a_value, const size_t a_value_size);
 
 typedef struct dap_chain_cs_dag_hal_item {
diff --git a/modules/type/dag/include/dap_chain_cs_dag_event.h b/modules/type/dag/include/dap_chain_cs_dag_event.h
index 1847092b25..8934d6af0f 100644
--- a/modules/type/dag/include/dap_chain_cs_dag_event.h
+++ b/modules/type/dag/include/dap_chain_cs_dag_event.h
@@ -147,7 +147,7 @@ static inline size_t dap_chain_cs_dag_event_round_item_get_size(dap_chain_cs_dag
 bool dap_chain_cs_dag_event_gdb_set(char *a_event_hash_str, dap_chain_cs_dag_event_t * a_event, size_t a_event_size,
                                         const char *a_group, dap_chain_cs_dag_event_round_cfg_t * a_event_round_cfg);
 
-dap_chain_cs_dag_event_t* dap_chain_cs_dag_event_gdb_get(char *a_event_hash_str, size_t * a_event_size,
+dap_chain_cs_dag_event_t* dap_chain_cs_dag_event_gdb_get(const char *a_event_hash_str, size_t * a_event_size,
                                                         const char *a_group, dap_chain_cs_dag_event_round_cfg_t * a_event_round_cfg);
 
 
-- 
GitLab