From 6cb10a5457e549b8d4dbb902005475182f218bcc Mon Sep 17 00:00:00 2001
From: Dmitriy Gerasimov <naeper@demlabs.net>
Date: Tue, 21 May 2019 19:37:36 +0700
Subject: [PATCH] [*] Lot of fixes for teh proper ledger work

---
 dap_chain.c        |  27 ++++++++----
 dap_chain.h        |  10 +++--
 dap_chain_cell.c   |  48 +++++++++++++--------
 dap_chain_cell.h   |   2 +-
 dap_chain_ledger.c | 101 ++++++++++++++++++++++++++++++---------------
 dap_chain_ledger.h |   2 +-
 6 files changed, 127 insertions(+), 63 deletions(-)

diff --git a/dap_chain.c b/dap_chain.c
index 264f945..2d00c75 100755
--- a/dap_chain.c
+++ b/dap_chain.c
@@ -117,7 +117,7 @@ dap_chain_t * dap_chain_load_net_cfg_name(const char * a_chan_net_cfg_name)
  * @param a_chain_id
  * @return
  */
-dap_chain_t * dap_chain_create(const char * a_chain_net_name, const char * a_chain_name, dap_chain_net_id_t a_chain_net_id, dap_chain_id_t a_chain_id )
+dap_chain_t * dap_chain_create(dap_ledger_t* a_ledger, const char * a_chain_net_name, const char * a_chain_name, dap_chain_net_id_t a_chain_net_id, dap_chain_id_t a_chain_id )
 {
     dap_chain_t * l_ret = DAP_NEW_Z(dap_chain_t);
     DAP_CHAIN_PVT_LOCAL_NEW(l_ret);
@@ -125,6 +125,7 @@ dap_chain_t * dap_chain_create(const char * a_chain_net_name, const char * a_cha
     memcpy(l_ret->net_id.raw,a_chain_net_id.raw,sizeof(a_chain_net_id));
     l_ret->name = strdup (a_chain_name);
     l_ret->net_name = strdup (a_chain_net_name);
+    l_ret->ledger = a_ledger;
 
     dap_chain_item_t * l_ret_item = DAP_NEW_Z(dap_chain_item_t);
     l_ret_item->chain = l_ret;
@@ -202,7 +203,7 @@ dap_chain_t * dap_chain_find_by_id(dap_chain_net_id_t a_chain_net_id,dap_chain_i
  * @param a_chain_cfg_path
  * @return
  */
-dap_chain_t * dap_chain_load_from_cfg(const char * a_chain_net_name,dap_chain_net_id_t a_chain_net_id, const char * a_chain_cfg_name)
+dap_chain_t * dap_chain_load_from_cfg(dap_ledger_t* a_ledger, const char * a_chain_net_name,dap_chain_net_id_t a_chain_net_id, const char * a_chain_cfg_name)
 {
     log_it (L_DEBUG, "Loading chain from config \"%s\"", a_chain_cfg_name);
     if ( a_chain_net_name){
@@ -242,12 +243,12 @@ dap_chain_t * dap_chain_load_from_cfg(const char * a_chain_net_name,dap_chain_ne
                 return NULL;
             }
 
-            l_chain =  dap_chain_create(a_chain_net_name,l_chain_name, a_chain_net_id,l_chain_id);
+            l_chain =  dap_chain_create(a_ledger,a_chain_net_name,l_chain_name, a_chain_net_id,l_chain_id);
             if ( dap_chain_cs_create(l_chain, l_cfg) == 0 ) {
                 log_it (L_NOTICE,"Consensus initialized for chain id 0x%016llX",
                         l_chain_id.uint64 );
 
-                if ( dap_config_get_item_str( l_cfg , "files","storage_dir" ) ) {
+                if ( dap_config_get_item_str_default(l_cfg , "files","storage_dir",NULL ) ) {
                     DAP_CHAIN_PVT ( l_chain)->file_storage_dir = strdup (
                                 dap_config_get_item_str( l_cfg , "files","storage_dir" ) ) ;
                     if ( dap_chain_load_all( l_chain ) != 0 ){
@@ -257,9 +258,9 @@ dap_chain_t * dap_chain_load_from_cfg(const char * a_chain_net_name,dap_chain_ne
                         log_it (L_NOTICE, "Initialized chain files");
                     }
                 } else{
-                    log_it (L_ERROR, "Not set file storage path");
-                    dap_chain_delete(l_chain);
-                    l_chain = NULL;
+                    log_it (L_INFO, "Not set file storage path, will not stored in files");
+                    //dap_chain_delete(l_chain);
+                    //l_chain = NULL;
                 }
 
             }else{
@@ -279,6 +280,18 @@ dap_chain_t * dap_chain_load_from_cfg(const char * a_chain_net_name,dap_chain_ne
     }
 }
 
+
+/**
+ * @brief dap_chain_has_file_store
+ * @param a_chain
+ * @return
+ */
+bool dap_chain_has_file_store(dap_chain_t * a_chain)
+{
+    return  DAP_CHAIN_PVT(a_chain)->file_storage_dir != NULL;
+}
+
+
 /**
  * @brief dap_chain_save_all
  * @param l_chain
diff --git a/dap_chain.h b/dap_chain.h
index 503bd74..9d1ab57 100755
--- a/dap_chain.h
+++ b/dap_chain.h
@@ -46,6 +46,7 @@ typedef struct dap_chain_atom_iter{
     dap_chain_t * chain;
     dap_chain_atom_ptr_t cur;
     void * cur_item;
+    void * _inheritor;
 } dap_chain_atom_iter_t;
 
 
@@ -126,16 +127,17 @@ int dap_chain_init(void);
 void dap_chain_deinit(void);
 
 
-dap_chain_t * dap_chain_create(const char * a_chain_net_name, const char * a_chain_name, dap_chain_net_id_t a_chain_net_id, dap_chain_id_t a_chain_id );
+dap_chain_t * dap_chain_create(dap_ledger_t* a_ledger,const char * a_chain_net_name, const char * a_chain_name, dap_chain_net_id_t a_chain_net_id, dap_chain_id_t a_chain_id );
 
-int dap_chain_load_all (dap_chain_t * l_chain);
-int dap_chain_save_all (dap_chain_t * l_chain);
+int dap_chain_load_all (dap_chain_t * a_chain);
+int dap_chain_save_all (dap_chain_t * a_chain);
+bool dap_chain_has_file_store(dap_chain_t * a_chain);
 
 //dap_chain_t * dap_chain_open(const char * a_file_storage,const char * a_file_cache);
 void dap_chain_info_dump_log(dap_chain_t * a_chain);
 
 dap_chain_t * dap_chain_find_by_id(dap_chain_net_id_t a_chain_net_id,dap_chain_id_t a_chain_id);
-dap_chain_t * dap_chain_load_from_cfg(const char * a_chain_net_name, dap_chain_net_id_t a_chain_net_id, const char * a_chain_cfg_name);
+dap_chain_t * dap_chain_load_from_cfg(dap_ledger_t* a_ledger,const char * a_chain_net_name, dap_chain_net_id_t a_chain_net_id, const char * a_chain_cfg_name);
 
 void dap_chain_delete(dap_chain_t * a_chain);
 
diff --git a/dap_chain_cell.c b/dap_chain_cell.c
index 37111aa..2193232 100755
--- a/dap_chain_cell.c
+++ b/dap_chain_cell.c
@@ -125,6 +125,35 @@ int dap_chain_cell_load(dap_chain_t * a_chain, const char * a_cell_file_path)
 
 }
 
+/**
+ * @brief s_cell_file_append
+ * @param a_cell
+ * @param a_atom
+ * @param a_atom_size
+ * @return
+ */
+int dap_chain_cell_file_append( dap_chain_cell_t * a_cell, const void* a_atom, size_t a_atom_size)
+{
+    size_t l_total_wrote_bytes = 0;
+    if ( fwrite(&a_atom_size,1,sizeof(a_atom_size),a_cell->file_storage) == sizeof(a_atom_size) ){
+        l_total_wrote_bytes += sizeof (a_atom_size);
+        if ( fwrite(&a_atom,1,a_atom_size,a_cell->file_storage) == a_atom_size ){
+            l_total_wrote_bytes += a_atom_size;
+        } else {
+            log_it (L_ERROR, "Can't write data from cell 0x%016X to the file \"%s\"",
+                            a_cell->id.uint64,
+                            a_cell->file_storage_path);
+            return -1;
+        }
+    } else {
+        log_it (L_ERROR,"Can't write atom data size from cell 0x%016X in \"%s\"",
+                a_cell->id.uint64,
+                a_cell->file_storage_path);
+        return -2;
+    }
+    return (int)  l_total_wrote_bytes;
+}
+
 /**
  * @brief dap_chain_cell_file_update
  * @param a_cell
@@ -158,24 +187,9 @@ int dap_chain_cell_file_update( dap_chain_cell_t * a_cell)
         dap_chain_atom_iter_t *l_atom_iter = l_chain->callback_atom_iter_create (l_chain);
         dap_chain_atom_ptr_t *l_atom = l_chain->callback_atom_iter_get_first(l_atom_iter);
         size_t l_atom_size = l_chain->callback_atom_get_size(l_atom);
-        size_t l_total_wrote_bytes = 0;
         while ( l_atom  && l_atom_size){
-            if ( fwrite(&l_atom_size,1,sizeof(l_atom_size),a_cell->file_storage) == sizeof(l_atom_size) ){
-                l_total_wrote_bytes += sizeof (l_atom_size);
-                if ( fwrite(&l_atom,1,l_atom_size,a_cell->file_storage) == l_atom_size ){
-                    l_total_wrote_bytes += l_atom_size;
-                } else {
-                    log_it (L_ERROR, "Can't write data from cell 0x%016X to the file \"%s\"",
-                                    a_cell->id.uint64,
-                                    a_cell->file_storage_path);
-                    break;
-                }
-            } else {
-                log_it (L_ERROR,"Can't write atom data size from cell 0x%016X in \"%s\"",
-                        a_cell->id.uint64,
-                        a_cell->file_storage_path);
-                return -2;
-            }
+            if ( dap_chain_cell_file_append (a_cell,l_atom, l_atom_size) <0 )
+                break;
             l_atom = l_chain->callback_atom_iter_get_next( l_atom_iter );
             l_atom_size = l_chain->callback_atom_get_size(l_atom);
         }
diff --git a/dap_chain_cell.h b/dap_chain_cell.h
index 67577cd..eb42534 100755
--- a/dap_chain_cell.h
+++ b/dap_chain_cell.h
@@ -28,7 +28,6 @@
 #include "dap_chain_common.h"
 
 typedef struct dap_chain dap_chain_t;
-
 typedef struct dap_chain_cell dap_chain_cell_t;
 
 typedef struct dap_chain_cell {
@@ -75,3 +74,4 @@ typedef struct dap_chain_cell_decl{
 int dap_chain_cell_init(void);
 int dap_chain_cell_load(dap_chain_t * a_chain, const char * a_cell_file_path);
 int dap_chain_cell_file_update( dap_chain_cell_t * a_cell);
+int dap_chain_cell_file_append( dap_chain_cell_t * a_cell,const void* a_atom, size_t a_atom_size);
diff --git a/dap_chain_ledger.c b/dap_chain_ledger.c
index 29de718..ab6e414 100755
--- a/dap_chain_ledger.c
+++ b/dap_chain_ledger.c
@@ -55,12 +55,12 @@ typedef struct dap_chain_ledger_token_emission_item {
 } dap_chain_ledger_token_emission_item_t;
 
 typedef struct dap_chain_ledger_token_item {
-    char tiker[10];
+    char ticker[10];
     dap_chain_hash_fast_t datum_token_hash;
     uint8_t padding[6];
     dap_chain_datum_token_t * datum_token;
-    uint64_t emission_total;
-    pthread_rwlock_t *token_emissions_rwlock;
+    uint64_t total_supply;
+    pthread_rwlock_t token_emissions_rwlock;
     dap_chain_ledger_token_emission_item_t * token_emissions;
     UT_hash_handle hh;
 } dap_chain_ledger_token_item_t;
@@ -101,7 +101,7 @@ typedef struct dap_ledger_private {
     bool check_token_emission;
     dap_chain_cell_id_t local_cell_id;
 } dap_ledger_private_t;
-#define LEDGER_INTERNAL(a) ( (dap_ledger_private_t* ) a->_internal )
+#define PVT(a) ( (dap_ledger_private_t* ) a->_internal )
 
 static const dap_chain_ledger_tx_item_t* tx_item_find_by_addr(dap_ledger_t *a_ledger,
         const dap_chain_addr_t *a_addr, dap_chain_hash_fast_t *a_tx_first_hash);
@@ -115,8 +115,8 @@ static dap_ledger_t * dap_chain_ledger_handle_new(void)
     l_ledger->_internal = (void*)DAP_NEW_Z(dap_ledger_private_t);
 
     // Initialize Read/Write Lock Attribute
-    pthread_rwlock_init(&LEDGER_INTERNAL(l_ledger)->ledger_rwlock, NULL); // PTHREAD_RWLOCK_INITIALIZER;
-    pthread_rwlock_init(&LEDGER_INTERNAL(l_ledger)->tokens_rwlock, NULL);
+    pthread_rwlock_init(&PVT(l_ledger)->ledger_rwlock, NULL); // PTHREAD_RWLOCK_INITIALIZER;
+    pthread_rwlock_init(&PVT(l_ledger)->tokens_rwlock, NULL);
 
     return l_ledger;
 }
@@ -129,9 +129,9 @@ void dap_chain_ledger_handle_free(dap_ledger_t *a_ledger)
     if(!a_ledger)
         return;
     // Destroy Read/Write Lock
-    pthread_rwlock_destroy(&LEDGER_INTERNAL(a_ledger)->ledger_rwlock);
-    pthread_rwlock_destroy(&LEDGER_INTERNAL(a_ledger)->tokens_rwlock);
-    DAP_DELETE(LEDGER_INTERNAL(a_ledger));
+    pthread_rwlock_destroy(&PVT(a_ledger)->ledger_rwlock);
+    pthread_rwlock_destroy(&PVT(a_ledger)->tokens_rwlock);
+    DAP_DELETE(PVT(a_ledger));
     DAP_DELETE(a_ledger);
 }
 
@@ -147,6 +147,29 @@ static int compare_datum_items(const void * l_a, const void * l_b)
     return 1;
 }
 
+/**
+ * @brief dap_chain_ledger_token_add
+ * @param a_token
+ * @param a_token_size
+ * @return
+ */
+int dap_chain_ledger_token_add(dap_ledger_t * a_ledger,  dap_chain_datum_token_t *a_token, size_t a_token_size)
+{
+    if ( !a_ledger)
+        return  -1;
+
+    dap_chain_ledger_token_item_t * l_token_item = DAP_NEW_Z(dap_chain_ledger_token_item_t);
+    snprintf(l_token_item->ticker,sizeof (l_token_item->ticker),"%s",a_token->header.ticker);
+    l_token_item->datum_token = DAP_NEW_Z_SIZE(dap_chain_datum_token_t, a_token_size);
+    memcpy(l_token_item->datum_token, a_token,a_token_size);
+    l_token_item->total_supply = a_token->header.total_supply;
+    pthread_rwlock_init(&l_token_item->token_emissions_rwlock,NULL);
+    dap_hash_fast(a_token,a_token_size, &l_token_item->datum_token_hash);
+
+    HASH_ADD_STR(PVT(a_ledger)->tokens, ticker, l_token_item) ;
+    return  0;
+}
+
 /**
  * @brief dap_chain_ledger_create
  * @param a_check_flags
@@ -155,7 +178,7 @@ static int compare_datum_items(const void * l_a, const void * l_b)
 dap_ledger_t* dap_chain_ledger_create(uint16_t a_check_flags)
 {
     dap_ledger_t *l_ledger = dap_chain_ledger_handle_new();
-    dap_ledger_private_t *l_ledger_priv = LEDGER_INTERNAL(l_ledger);
+    dap_ledger_private_t *l_ledger_priv = PVT(l_ledger);
     l_ledger_priv->check_flags = a_check_flags;
     l_ledger_priv->check_ds = a_check_flags & DAP_CHAIN_LEDGER_CHECK_LOCAL_DS;
     l_ledger_priv->check_cells_ds = a_check_flags & DAP_CHAIN_LEDGER_CHECK_CELLS_DS;
@@ -174,7 +197,7 @@ int dap_chain_ledger_token_emission_add(dap_ledger_t *a_ledger,
         const dap_chain_datum_token_emission_t *a_token_emission, size_t a_token_emission_size)
 {
     int ret = 0;
-    dap_ledger_private_t *l_ledger_priv = LEDGER_INTERNAL(a_ledger);
+    dap_ledger_private_t *l_ledger_priv = PVT(a_ledger);
 
     const char * c_token_ticker = a_token_emission->hdr.ticker;
     dap_chain_ledger_token_item_t * l_token_item = NULL;
@@ -189,7 +212,7 @@ int dap_chain_ledger_token_emission_add(dap_ledger_t *a_ledger,
         dap_hash_fast(a_token_emission, a_token_emission_size, &l_token_emission_hash);
         char * l_hash_str = dap_chain_hash_fast_to_str_new(&l_token_emission_hash);
 
-        pthread_rwlock_wrlock(l_token_item->token_emissions_rwlock);
+        pthread_rwlock_wrlock( &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);
         if(l_token_emission_item == NULL) {
@@ -209,7 +232,7 @@ int dap_chain_ledger_token_emission_add(dap_ledger_t *a_ledger,
                     a_token_emission->hdr.value, c_token_ticker, l_hash_str);
             ret = -1;
         }
-        pthread_rwlock_unlock(l_token_item->token_emissions_rwlock);
+        pthread_rwlock_unlock( &l_token_item->token_emissions_rwlock);
         DAP_DELETE(l_hash_str);
     }
     pthread_rwlock_unlock(&l_ledger_priv->tokens_rwlock);
@@ -225,7 +248,7 @@ int dap_chain_ledger_token_emission_add(dap_ledger_t *a_ledger,
 dap_chain_datum_token_emission_t * dap_chain_ledger_token_emission_find(dap_ledger_t *a_ledger,
         const char *a_token_ticker, const dap_chain_hash_fast_t *a_token_emission_hash)
 {
-    dap_ledger_private_t *l_ledger_priv = LEDGER_INTERNAL(a_ledger);
+    dap_ledger_private_t *l_ledger_priv = PVT(a_ledger);
     dap_chain_datum_token_emission_t * l_token_emission = NULL;
     dap_chain_ledger_token_item_t * l_token_item = NULL;
     pthread_rwlock_rdlock(&l_ledger_priv->tokens_rwlock);
@@ -233,11 +256,11 @@ dap_chain_datum_token_emission_t * dap_chain_ledger_token_emission_find(dap_ledg
 
     if(l_token_item) {
         dap_chain_ledger_token_emission_item_t * l_token_emission_item = NULL;
-        pthread_rwlock_rdlock(l_token_item->token_emissions_rwlock);
+        pthread_rwlock_rdlock( &l_token_item->token_emissions_rwlock);
         HASH_FIND(hh, l_token_item->token_emissions, a_token_emission_hash, sizeof(*a_token_emission_hash),
                 l_token_emission_item);
         l_token_emission = l_token_emission_item->datum_token_emission;
-        pthread_rwlock_unlock(l_token_item->token_emissions_rwlock);
+        pthread_rwlock_unlock( &l_token_item->token_emissions_rwlock);
     }
     pthread_rwlock_unlock(&l_ledger_priv->tokens_rwlock);
     return l_token_emission;
@@ -249,7 +272,7 @@ dap_chain_datum_token_emission_t * dap_chain_ledger_token_emission_find(dap_ledg
  */
 void dap_chain_ledger_set_local_cell_id(dap_ledger_t *a_ledger, dap_chain_cell_id_t a_local_cell_id)
 {
-    LEDGER_INTERNAL(a_ledger)->local_cell_id.uint64 = a_local_cell_id.uint64;
+    PVT(a_ledger)->local_cell_id.uint64 = a_local_cell_id.uint64;
 }
 
 /**
@@ -317,7 +340,7 @@ static dap_chain_datum_tx_t* s_find_datum_tx_by_hash(dap_ledger_t *a_ledger,
 {
     if(!a_tx_hash)
         return NULL;
-    dap_ledger_private_t *l_ledger_priv = LEDGER_INTERNAL(a_ledger);
+    dap_ledger_private_t *l_ledger_priv = PVT(a_ledger);
     dap_chain_datum_tx_t *l_tx_ret = NULL;
     dap_chain_ledger_tx_item_t *l_tx_item;
     pthread_rwlock_rdlock(&l_ledger_priv->ledger_rwlock);
@@ -363,7 +386,7 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
      5. sum(  find (tx2.input.tx_prev_hash).output[tx2.input_tx_prev_idx].value )  ==  sum (tx2.outputs.value)
      */
 
-    dap_ledger_private_t *l_ledger_priv = LEDGER_INTERNAL(a_ledger);
+    dap_ledger_private_t *l_ledger_priv = PVT(a_ledger);
     if(!a_tx)
         return -1;
 
@@ -572,7 +595,7 @@ int dap_chain_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx)
     if(!a_tx)
         return -1;
     int ret = 1;
-    dap_ledger_private_t *l_ledger_priv = LEDGER_INTERNAL(a_ledger);
+    dap_ledger_private_t *l_ledger_priv = PVT(a_ledger);
     dap_list_t *l_list_bound_items = NULL;
     if(dap_chain_ledger_tx_cache_check(a_ledger, a_tx, &l_list_bound_items) < 0)
         return -1;
@@ -581,12 +604,14 @@ int dap_chain_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx)
     // Mark 'out' items in cache if they were used & delete previous transactions from cache if it need
     // find all bound pairs 'in' and 'out'
     dap_list_t *l_list_tmp = l_list_bound_items;
+    char * l_token_ticker = NULL;
 //    int l_list_tmp_num = 0;
     while(l_list_tmp) {
         dap_chain_ledger_tx_bound_t *bound_item = l_list_tmp->data;
         dap_chain_tx_in_t *l_tx_in = bound_item->tx_cur_in;
         dap_chain_ledger_tx_item_t *l_prev_item_out = bound_item->item_out;
-
+        if ( l_token_ticker == NULL)
+            l_token_ticker = dap_strdup (l_prev_item_out->token_tiker);
         /// Mark 'out' item in cache because it used
         dap_chain_hash_fast_t *l_tx_prev_hash =
                 &(l_prev_item_out->tx_hash_spent_fast[l_tx_in->header.tx_out_prev_idx]);
@@ -602,11 +627,11 @@ int dap_chain_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx)
             int res = dap_chain_ledger_tx_remove(a_ledger, &l_tx_prev_hash_to_del);
             if(res == -2) {
                 log_it(L_ERROR, "Can't delete previous transactions because hash=0x%x not found", l_tx_prev_hash_str);
-                assert(0);
+                return -2;
             }
             else if(res != 1) {
                 log_it(L_ERROR, "Can't delete previous transactions with hash=0x%x", l_tx_prev_hash_str);
-                assert(0);
+                return -3;
             }
             // TODO restore when the blockchain appears
             // remove from mempool ledger
@@ -633,11 +658,9 @@ int dap_chain_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx)
         // there should be no duplication
         log_it(L_WARNING, "Transaction (hash=0x%x) deleted from cache because there is an attempt to add it to cache",
                 l_tx_hash);
-        assert(0);
     }
     // add transaction to the cache list
-    if(ret == 1)
-            {
+    if(ret == 1){
         l_item_tmp = DAP_NEW_Z(dap_chain_ledger_tx_item_t);
         memcpy(&l_item_tmp->tx_hash_fast, l_tx_hash, sizeof(dap_chain_hash_fast_t));
         l_item_tmp->tx = DAP_NEW_SIZE(dap_chain_datum_tx_t, dap_chain_datum_tx_get_size(a_tx));
@@ -647,6 +670,18 @@ int dap_chain_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx)
             dap_list_t *l_tist_tmp = dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_OUT, &l_item_tmp->n_outs);
             dap_list_free(l_tist_tmp);
         }
+        if ( l_token_ticker == NULL) { //No token ticker in previous txs
+            size_t l_tokens_count = 0;
+            dap_list_t *l_tokens_list = dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_TOKEN, &l_tokens_count );
+            if ( l_tokens_count>0 ){
+                dap_chain_tx_token_t * l_token = (dap_chain_tx_token_t*) l_tokens_list->data;
+                l_token_ticker = dap_strdup (l_token->header.ticker);
+                dap_list_free(l_tokens_list);
+            }
+        }
+        if (l_token_ticker)
+            strncpy(l_item_tmp->token_tiker,l_token_ticker,sizeof (l_item_tmp->token_tiker));
+
         memcpy(l_item_tmp->tx, a_tx, dap_chain_datum_tx_get_size(a_tx));
         HASH_ADD(hh, l_ledger_priv->ledger, tx_hash_fast, sizeof(dap_chain_hash_fast_t), l_item_tmp); // tx_hash_fast: name of key field
         ret = 1;
@@ -666,7 +701,7 @@ int dap_chain_ledger_tx_remove(dap_ledger_t *a_ledger, dap_chain_hash_fast_t *a_
     if(!a_tx_hash)
         return -1;
     int l_ret = -1;
-    dap_ledger_private_t *l_ledger_priv = LEDGER_INTERNAL(a_ledger);
+    dap_ledger_private_t *l_ledger_priv = PVT(a_ledger);
     dap_chain_ledger_tx_item_t *l_item_tmp;
     pthread_rwlock_wrlock(&l_ledger_priv->ledger_rwlock);
     HASH_FIND(hh, l_ledger_priv->ledger, a_tx_hash, sizeof(dap_chain_hash_fast_t), l_item_tmp);
@@ -692,7 +727,7 @@ int dap_chain_ledger_tx_remove(dap_ledger_t *a_ledger, dap_chain_hash_fast_t *a_
  */
 void dap_chain_ledger_purge(dap_ledger_t *a_ledger)
 {
-    dap_ledger_private_t *l_ledger_priv = LEDGER_INTERNAL(a_ledger);
+    dap_ledger_private_t *l_ledger_priv = PVT(a_ledger);
     dap_chain_ledger_tx_item_t *l_iter_current, *l_item_tmp;
     pthread_rwlock_wrlock(&l_ledger_priv->ledger_rwlock);
     HASH_ITER(hh, l_ledger_priv->ledger , l_iter_current, l_item_tmp)
@@ -711,7 +746,7 @@ void dap_chain_ledger_purge(dap_ledger_t *a_ledger)
 _dap_int128_t dap_chain_ledger_count(dap_ledger_t *a_ledger)
 {
     _dap_int128_t l_ret = 0;
-    dap_ledger_private_t *l_ledger_priv = LEDGER_INTERNAL(a_ledger);
+    dap_ledger_private_t *l_ledger_priv = PVT(a_ledger);
     dap_chain_ledger_tx_item_t *l_iter_current, *l_item_tmp;
     pthread_rwlock_rdlock(&l_ledger_priv->ledger_rwlock);
     HASH_ITER(hh, l_ledger_priv->ledger , l_iter_current, l_item_tmp)
@@ -765,7 +800,7 @@ uint64_t dap_chain_ledger_calc_balance(dap_ledger_t *a_ledger, const dap_chain_a
     uint64_t balance = 0;
     if(!a_addr || !dap_chain_addr_check_sum(a_addr))
         return 0;
-    dap_ledger_private_t *l_ledger_priv = LEDGER_INTERNAL(a_ledger);
+    dap_ledger_private_t *l_ledger_priv = PVT(a_ledger);
     dap_chain_ledger_tx_item_t *l_iter_current, *l_item_tmp;
     pthread_rwlock_rdlock(&l_ledger_priv->ledger_rwlock);
     HASH_ITER(hh, l_ledger_priv->ledger , l_iter_current, l_item_tmp)
@@ -822,7 +857,7 @@ static const dap_chain_ledger_tx_item_t* tx_item_find_by_addr(dap_ledger_t *a_le
 {
     if(!a_addr || !a_tx_first_hash)
         return NULL;
-    dap_ledger_private_t *l_ledger_priv = LEDGER_INTERNAL(a_ledger);
+    dap_ledger_private_t *l_ledger_priv = PVT(a_ledger);
     bool is_tx_found = false;
     bool is_null_hash = dap_hash_fast_is_blank(a_tx_first_hash);
     bool is_search_enable = is_null_hash;
@@ -892,7 +927,7 @@ const dap_chain_datum_tx_t* dap_chain_ledger_tx_find_by_pkey(dap_ledger_t *a_led
 {
     if(!a_public_key || !a_tx_first_hash)
         return NULL;
-    dap_ledger_private_t *l_ledger_priv = LEDGER_INTERNAL(a_ledger);
+    dap_ledger_private_t *l_ledger_priv = PVT(a_ledger);
     dap_chain_datum_tx_t *l_cur_tx = NULL;
     bool is_null_hash = dap_hash_fast_is_blank(a_tx_first_hash);
     bool is_search_enable = is_null_hash;
@@ -938,7 +973,7 @@ const dap_chain_datum_tx_t* dap_chain_ledger_tx_cache_find_out_cond(dap_ledger_t
     if(!a_addr || !a_tx_first_hash)
         return NULL;
     int l_ret = -1;
-    dap_ledger_private_t *l_ledger_priv = LEDGER_INTERNAL(a_ledger);
+    dap_ledger_private_t *l_ledger_priv = PVT(a_ledger);
     dap_chain_datum_tx_t *l_cur_tx = NULL;
     bool is_null_hash = dap_hash_fast_is_blank(a_tx_first_hash);
     bool is_search_enable = is_null_hash;
diff --git a/dap_chain_ledger.h b/dap_chain_ledger.h
index 494c27c..40eaa96 100755
--- a/dap_chain_ledger.h
+++ b/dap_chain_ledger.h
@@ -74,7 +74,7 @@ int dap_chain_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx);
  *
  */
 
-int dap_chain_ledger_token_add(dap_chain_datum_token_t *a_token, size_t a_token_size);
+int dap_chain_ledger_token_add(dap_ledger_t * a_ledger,dap_chain_datum_token_t *a_token, size_t a_token_size);
 
 /**
  * Add token emission datum
-- 
GitLab