From d9ff56f1d0bef0182243a0e0f2146dddaf1c8c65 Mon Sep 17 00:00:00 2001
From: cellframe <roman.khlopkov@demlabs.net>
Date: Mon, 12 Dec 2022 17:55:54 +0300
Subject: [PATCH] [*] Chains swelling fix

---
 modules/chain/dap_chain_cell.c             | 157 ++++++++++++---------
 modules/chain/dap_chain_ledger.c           |   2 +-
 modules/chain/include/dap_chain.h          |   2 +-
 modules/chain/include/dap_chain_cell.h     |  12 +-
 modules/consensus/none/dap_chain_cs_none.c |   2 +-
 modules/net/dap_chain_node_cli_cmd.c       |  12 +-
 modules/type/blocks/dap_chain_cs_blocks.c  |   6 +-
 modules/type/dag/dap_chain_cs_dag.c        |   2 +-
 8 files changed, 110 insertions(+), 85 deletions(-)

diff --git a/modules/chain/dap_chain_cell.c b/modules/chain/dap_chain_cell.c
index ff45cc9fb8..5cb49c37e9 100644
--- a/modules/chain/dap_chain_cell.c
+++ b/modules/chain/dap_chain_cell.c
@@ -156,7 +156,7 @@ void dap_chain_cell_delete(dap_chain_cell_t *a_cell)
         pthread_rwlock_unlock(&a_cell->chain->cell_rwlock);
     }
     a_cell->chain = NULL;
-    DAP_DEL_Z(a_cell->file_storage_path)
+    DAP_DEL_Z(a_cell->file_storage_path);
     pthread_rwlock_destroy(&a_cell->storage_rwlock);
     DAP_DEL_Z(a_cell);
 }
@@ -210,7 +210,7 @@ int dap_chain_cell_load(dap_chain_t * a_chain, const char * a_cell_file_path)
             ret = -5;
             break;
         }
-        unsigned long l_read = fread(l_element, 1, l_el_size, l_f);
+        unsigned long l_read = fread((void *)l_element, 1, l_el_size, l_f);
         if(l_read == l_el_size) {
             dap_chain_atom_verify_res_t l_res = a_chain->callback_atom_add(a_chain, l_element, l_el_size); // !!! blocking GDB call !!!
             if (l_res == ATOM_PASS || l_res == ATOM_REJECT) {
@@ -236,6 +236,50 @@ int dap_chain_cell_load(dap_chain_t * a_chain, const char * a_cell_file_path)
 
 }
 
+static bool s_file_write_header(dap_chain_cell_t *a_cell)
+{
+    fseek(a_cell->file_storage, 0L, SEEK_SET);
+    dap_chain_cell_file_header_t l_hdr = {
+        .signature = DAP_CHAIN_CELL_FILE_SIGNATURE,
+        .version = DAP_CHAIN_CELL_FILE_VERSION,
+        .type = DAP_CHAIN_CELL_FILE_TYPE_RAW,
+        .chain_id = { .uint64 = a_cell->id.uint64 },
+        .chain_net_id = a_cell->chain->net_id
+    };
+    if(fwrite(&l_hdr, 1, sizeof(l_hdr), a_cell->file_storage) == sizeof(l_hdr)) {
+        log_it(L_NOTICE, "Initialized file storage for cell 0x%016"DAP_UINT64_FORMAT_X" ( %s )",
+                a_cell->id.uint64, a_cell->file_storage_path);
+    } else {
+        log_it(L_ERROR, "Can't init file storage for cell 0x%016"DAP_UINT64_FORMAT_X" ( %s )",
+                a_cell->id.uint64, a_cell->file_storage_path);
+        return false;
+    }
+    return true;
+}
+
+static ssize_t s_file_atom_add(dap_chain_cell_t *a_cell, dap_chain_atom_ptr_t a_atom, size_t a_atom_size)
+{
+    if (fwrite(&a_atom_size, 1, sizeof(a_atom_size), a_cell->file_storage) != sizeof(a_atom_size)) {
+        log_it (L_ERROR,"Can't write atom data size from cell 0x%016"DAP_UINT64_FORMAT_X" in \"%s\"",
+                a_cell->id.uint64,
+                a_cell->file_storage_path);
+        return -2;
+    }
+    if (fwrite(a_atom, 1, a_atom_size, a_cell->file_storage) != a_atom_size) {
+        log_it (L_ERROR, "Can't write data from cell 0x%016"DAP_UINT64_FORMAT_X" to the file \"%s\"",
+                        a_cell->id.uint64,
+                        a_cell->file_storage_path);
+        return -3;
+    }
+    if(a_cell->chain && a_cell->chain->atom_notifiers ){
+        for( dap_list_t * l_iter = a_cell->chain->atom_notifiers;l_iter; l_iter = dap_list_next(l_iter) ){
+            dap_chain_atom_notifier_t * i = (dap_chain_atom_notifier_t *) l_iter->data;
+            i->callback(i->arg, a_cell->chain, a_cell->id, (void *)a_atom, a_atom_size);
+        }
+    }
+    return a_atom_size + sizeof(a_atom_size);
+}
+
 /**
  * @brief s_cell_file_append
  * add atoms to selected chain
@@ -248,7 +292,7 @@ int dap_chain_cell_load(dap_chain_t * a_chain, const char * a_cell_file_path)
  * @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)
+int dap_chain_cell_file_append(dap_chain_cell_t *a_cell, const void *a_atom, size_t a_atom_size)
 {
     if(!a_cell)
         return -1;
@@ -257,7 +301,9 @@ int dap_chain_cell_file_append( dap_chain_cell_t * a_cell, const void* a_atom, s
                                a_cell->id.uint64, a_cell->file_storage_path);
         return -1;
     }
-    if(!a_cell->file_storage) {
+
+    pthread_rwlock_wrlock(&a_cell->storage_rwlock);
+    if (!a_cell->file_storage) {
         char l_file_path[MAX_PATH] = {'\0'};
         dap_snprintf(l_file_path, MAX_PATH, "%s/%s", DAP_CHAIN_PVT(a_cell->chain)->file_storage_dir,
                      a_cell->file_storage_path);
@@ -265,86 +311,61 @@ int dap_chain_cell_file_append( dap_chain_cell_t * a_cell, const void* a_atom, s
         if (!a_cell->file_storage) {
             log_it(L_INFO, "Create chain cell");
             a_cell->file_storage = fopen(l_file_path, "w+b");
-        }
-        if (!a_cell->file_storage) {
-            log_it(L_ERROR, "Chain cell \"%s\" cannot be opened 0x%016"DAP_UINT64_FORMAT_X,
-                    a_cell->file_storage_path,
-                    a_cell->id.uint64);
-            return -3;
+            if (!a_cell->file_storage) {
+                log_it(L_ERROR, "Chain cell \"%s\" (0x%016"DAP_UINT64_FORMAT_X") cannot be created",
+                        a_cell->file_storage_path,
+                        a_cell->id.uint64);
+                pthread_rwlock_unlock(&a_cell->storage_rwlock);
+                return -3;
+            } else if (s_file_write_header(a_cell)) {// fill the header
+                pthread_rwlock_unlock(&a_cell->storage_rwlock);
+                return -4;
+            }
         }
     }
-    pthread_rwlock_wrlock(&a_cell->storage_rwlock);
+
     fseek(a_cell->file_storage, 0L, SEEK_END);
-    if (ftell(a_cell->file_storage) < (long)sizeof(dap_chain_cell_file_header_t)) { // fill the header
-        fseek(a_cell->file_storage, 0L, SEEK_SET);
-        dap_chain_cell_file_header_t l_hdr = {
-            .signature = DAP_CHAIN_CELL_FILE_SIGNATURE,
-            .version = DAP_CHAIN_CELL_FILE_VERSION,
-            .type = DAP_CHAIN_CELL_FILE_TYPE_RAW,
-            .chain_id = { .uint64 = a_cell->id.uint64 },
-            .chain_net_id = a_cell->chain->net_id
-        };
-        if(fwrite(&l_hdr, 1, sizeof(l_hdr), a_cell->file_storage) == sizeof(l_hdr)) {
-            log_it(L_NOTICE, "Initialized file storage for cell 0x%016"DAP_UINT64_FORMAT_X" ( %s )",
-                    a_cell->id.uint64, a_cell->file_storage_path);
-        } else {
-            log_it(L_ERROR, "Can't init file storage for cell 0x%016"DAP_UINT64_FORMAT_X" ( %s )",
-                    a_cell->id.uint64, a_cell->file_storage_path);
-            dap_chain_cell_close(a_cell);
-            return -4;
+    if (ftell(a_cell->file_storage) < (long)sizeof(dap_chain_cell_file_header_t)) {
+        log_it(L_WARNING, "Corrupted chain file header, rewrite it");
+        if (!s_file_write_header(a_cell)) {
+            pthread_rwlock_unlock(&a_cell->storage_rwlock);
+            return -5;
         }
     }
-    // if no atom provided in arguments, we flush all the atoms in given chain
-    size_t l_atom_size = a_atom_size ? a_atom_size : 0;
+
     size_t l_total_wrote_bytes = 0, l_count = 0;
-    dap_chain_atom_iter_t *l_atom_iter = a_atom ? NULL : a_cell->chain->callback_atom_iter_create(a_cell->chain, a_cell->id, 0);
-    if (!a_atom) {
+    if (a_atom && a_atom_size)
+        l_total_wrote_bytes = s_file_atom_add(a_cell, a_atom, a_atom_size);
+    else { // if no atom provided in arguments, we flush all the atoms in given chain
+        size_t l_atom_size = 0;
         fseek(a_cell->file_storage, sizeof(dap_chain_cell_file_header_t), SEEK_SET);
-    }
-    for (dap_chain_atom_ptr_t l_atom = a_atom ? (dap_chain_atom_ptr_t)a_atom : a_cell->chain->callback_atom_iter_get_first(l_atom_iter, &l_atom_size);
-         l_atom;
-         l_atom = a_atom ? NULL : a_cell->chain->callback_atom_iter_get_next(l_atom_iter, &l_atom_size), l_count++)
-    {
-        if (fwrite(&l_atom_size, 1, sizeof(l_atom_size), a_cell->file_storage) != sizeof(l_atom_size)) {
-            log_it (L_ERROR,"Can't write atom data size from cell 0x%016"DAP_UINT64_FORMAT_X" in \"%s\"",
-                    a_cell->id.uint64,
-                    a_cell->file_storage_path);
-            dap_chain_cell_close(a_cell);
-            l_total_wrote_bytes = -2;
-            break;
-        }
-        l_total_wrote_bytes += sizeof(l_atom_size);
-        if (fwrite(l_atom, 1, l_atom_size, a_cell->file_storage) != l_atom_size) {
-            log_it (L_ERROR, "Can't write data from cell 0x%016"DAP_UINT64_FORMAT_X" to the file \"%s\"",
-                            a_cell->id.uint64,
-                            a_cell->file_storage_path);
-            dap_chain_cell_close(a_cell);
-            l_total_wrote_bytes = -3;
-            break;
-        }
-        l_total_wrote_bytes += l_atom_size;
-
-        if(a_cell->chain && a_cell->chain->atom_notifiers ){
-            for( dap_list_t * l_iter = a_cell->chain->atom_notifiers;l_iter; l_iter = dap_list_next(l_iter) ){
-                dap_chain_atom_notifier_t * i = (dap_chain_atom_notifier_t *) l_iter->data;
-                i->callback(i->arg, a_cell->chain, a_cell->id, (void *)l_atom, l_atom_size);
+        dap_chain_atom_iter_t *l_atom_iter = a_cell->chain->callback_atom_iter_create(a_cell->chain, a_cell->id, 0);
+        dap_chain_atom_ptr_t l_atom = a_cell->chain->callback_atom_iter_get_first(l_atom_iter, &l_atom_size);
+        while (l_atom && l_atom_size && ++l_count) {
+            ssize_t l_atom_added_size = s_file_atom_add(a_cell, a_atom, a_atom_size);
+            if (l_atom_added_size < 0) {
+                l_total_wrote_bytes = l_atom_added_size;
+                break;
             }
+            l_total_wrote_bytes += l_atom_added_size;
+            l_atom = a_cell->chain->callback_atom_iter_get_next(l_atom_iter, &l_atom_size);
         }
+        a_cell->chain->callback_atom_iter_delete(l_atom_iter);
     }
-    if (l_total_wrote_bytes > 0) {
+
+    if (l_total_wrote_bytes > 0)
         fflush(a_cell->file_storage);
-        if (!a_atom) {
+    if (!a_atom) {
+        if (l_total_wrote_bytes > 0) {
             ftruncate(fileno(a_cell->file_storage), l_total_wrote_bytes + sizeof(dap_chain_cell_file_header_t));
             log_it(L_DEBUG, "Saved %zu atoms (total %zu bytes", l_count, l_total_wrote_bytes);
+        } else {
+            ftruncate(fileno(a_cell->file_storage), sizeof(dap_chain_cell_file_header_t));
+            s_file_write_header(a_cell);
+            log_it(L_WARNING, "Nothing to save, event table is empty. Rewrite the file header");
         }
-    } else if (!a_atom) {
-        log_it(L_WARNING, "Nothing to save, event table is empty");
     }
-
     pthread_rwlock_unlock(&a_cell->storage_rwlock);
-    if (l_atom_iter) {
-        a_cell->chain->callback_atom_iter_delete(l_atom_iter);
-    }
     return (int)l_total_wrote_bytes;
 }
 
diff --git a/modules/chain/dap_chain_ledger.c b/modules/chain/dap_chain_ledger.c
index 8e0ccceda4..68692f66be 100644
--- a/modules/chain/dap_chain_ledger.c
+++ b/modules/chain/dap_chain_ledger.c
@@ -1189,7 +1189,7 @@ static int s_token_tsd_parse(dap_ledger_t * a_ledger, dap_chain_ledger_token_ite
                                        l_addr_str);
                                 DAP_DELETE(l_addr_str);
                                 DAP_DELETE(l_addrs);
-                                DAP_DEL_Z(a_token_item->tx_recv_allow)
+                                DAP_DEL_Z(a_token_item->tx_recv_allow);
                                 return -11;
                             }
                         }
diff --git a/modules/chain/include/dap_chain.h b/modules/chain/include/dap_chain.h
index 89d344a732..87567372f6 100644
--- a/modules/chain/include/dap_chain.h
+++ b/modules/chain/include/dap_chain.h
@@ -41,7 +41,7 @@ typedef struct dap_chain_cell dap_chain_cell_t;
 typedef struct dap_ledger dap_ledger_t;
 
 // Atomic element
-typedef void * dap_chain_atom_ptr_t;
+typedef const void * dap_chain_atom_ptr_t;
 
 // Atomic element iterator
 typedef struct dap_chain_atom_iter{
diff --git a/modules/chain/include/dap_chain_cell.h b/modules/chain/include/dap_chain_cell.h
index 8ca6a758cb..693090f310 100644
--- a/modules/chain/include/dap_chain_cell.h
+++ b/modules/chain/include/dap_chain_cell.h
@@ -74,11 +74,11 @@ typedef struct dap_chain_cell_decl{
 
 
 int dap_chain_cell_init(void);
-dap_chain_cell_t * dap_chain_cell_create_fill(dap_chain_t * a_chain, dap_chain_cell_id_t a_cell_id);
-dap_chain_cell_t * dap_chain_cell_create_fill2(dap_chain_t * a_chain, const char *a_filename);
-dap_chain_cell_t * dap_chain_cell_find_by_id(dap_chain_t * a_chain, dap_chain_cell_id_t a_cell_id);
+dap_chain_cell_t *dap_chain_cell_create_fill(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id);
+dap_chain_cell_t *dap_chain_cell_create_fill2(dap_chain_t *a_chain, const char *a_filename);
+dap_chain_cell_t *dap_chain_cell_find_by_id(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id);
 void dap_chain_cell_close(dap_chain_cell_t *a_cell);
 void dap_chain_cell_delete(dap_chain_cell_t *a_cell);
-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);
+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/modules/consensus/none/dap_chain_cs_none.c b/modules/consensus/none/dap_chain_cs_none.c
index 80faa8c738..38a53b26a5 100644
--- a/modules/consensus/none/dap_chain_cs_none.c
+++ b/modules/consensus/none/dap_chain_cs_none.c
@@ -596,7 +596,7 @@ static dap_chain_datum_t **s_chain_callback_atom_get_datum(dap_chain_atom_ptr_t
 {
     UNUSED(a_atom_size);
     if (a_atom){
-        dap_chain_datum_t * l_datum = a_atom;
+        dap_chain_datum_t *l_datum = (dap_chain_datum_t *)a_atom;
         if (l_datum){
             dap_chain_datum_t **l_datums = DAP_NEW(dap_chain_datum_t *);
             if (a_datums_count)
diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c
index 60fa016796..43861b7d3c 100644
--- a/modules/net/dap_chain_node_cli_cmd.c
+++ b/modules/net/dap_chain_node_cli_cmd.c
@@ -5552,12 +5552,14 @@ static int s_check_cmd(int a_arg_index, int a_argc, char **a_argv, char **a_str_
     dap_chain_atom_iter_t *l_iter = NULL;
     dap_chain_cell_t *l_cell_tmp = NULL;
     dap_chain_cell_t *l_cell = NULL;
-    size_t l_size = 0;
+    size_t l_atom_size = 0, l_datums_count = 0;
 
     HASH_ITER(hh, l_chain->cells, l_cell, l_cell_tmp) {
         l_iter = l_cell->chain->callback_atom_iter_create(l_cell->chain, l_cell->id, 0);
-        dap_chain_datum_t *l_datum = l_cell->chain->callback_atom_find_by_hash(l_iter, &l_hash_tmp, &l_size);
-        if (l_datum) {
+        dap_chain_atom_ptr_t l_atom = l_cell->chain->callback_atom_find_by_hash(l_iter, &l_hash_tmp, &l_atom_size);
+        dap_chain_datum_t **l_datums = l_cell->chain->callback_atom_get_datums(l_atom, l_atom_size, &l_datums_count);
+        for (size_t i = 0; i < l_datums_count; i++) {
+            dap_chain_datum_t *l_datum = l_datums[i];
             dap_hash_fast_t l_hash;
             dap_hash_fast(l_datum->data, l_datum->header.data_size, &l_hash);
             if (!memcmp(l_hash_tmp.raw, l_hash.raw, DAP_CHAIN_HASH_FAST_SIZE)) {
@@ -5566,11 +5568,13 @@ static int s_check_cmd(int a_arg_index, int a_argc, char **a_argv, char **a_str_
                 break;
             }
         }
+        DAP_DEL_Z(l_datums);
+        l_cell->chain->callback_atom_iter_delete(l_iter);
     }
 
 end:
 
-    if (l_gdb_group) DAP_FREE(l_gdb_group);
+    DAP_DEL_Z(l_gdb_group);
 
     if (!found) {
         dap_cli_server_cmd_set_reply_text(a_str_reply, "not found!");
diff --git a/modules/type/blocks/dap_chain_cs_blocks.c b/modules/type/blocks/dap_chain_cs_blocks.c
index 54c65b26dd..3952e6674d 100644
--- a/modules/type/blocks/dap_chain_cs_blocks.c
+++ b/modules/type/blocks/dap_chain_cs_blocks.c
@@ -623,8 +623,8 @@ static void s_callback_delete(dap_chain_t * a_chain)
     pthread_rwlock_unlock(&PVT(l_blocks)->rwlock);
     pthread_rwlock_destroy(&PVT(l_blocks)->rwlock);
     pthread_rwlock_destroy(&PVT(l_blocks)->datums_lock);
-    DAP_DEL_Z(l_blocks->_inheritor)
-    DAP_DEL_Z(l_blocks->_pvt)
+    DAP_DEL_Z(l_blocks->_inheritor);
+    DAP_DEL_Z(l_blocks->_pvt);
     log_it(L_INFO, "Block destructed");
 }
 
@@ -1029,7 +1029,7 @@ static dap_chain_datum_tx_t* s_callback_atom_iter_find_by_tx_hash(dap_chain_t *
 static dap_chain_datum_t** s_callback_atom_get_datums(dap_chain_atom_ptr_t a_atom, size_t a_atom_size, size_t * a_datums_count)
 {
     assert(a_datums_count);
-    dap_chain_datum_t ** l_ret = dap_chain_block_get_datums(a_atom, a_atom_size,a_datums_count);
+    dap_chain_datum_t ** l_ret = dap_chain_block_get_datums((dap_chain_block_t *)a_atom, a_atom_size,a_datums_count);
     return l_ret;
 }
 
diff --git a/modules/type/dag/dap_chain_cs_dag.c b/modules/type/dag/dap_chain_cs_dag.c
index f5316eea35..3ee05d0ec7 100644
--- a/modules/type/dag/dap_chain_cs_dag.c
+++ b/modules/type/dag/dap_chain_cs_dag.c
@@ -1353,7 +1353,7 @@ static int s_cli_dag(int argc, char ** argv, char **a_str_reply)
                     // If not verify only mode we add
                     if ( ! l_verify_only ){
                         dap_chain_atom_ptr_t l_new_atom = DAP_DUP_SIZE(l_event, l_event_size); // produce deep copy of event;
-                        memcpy(l_new_atom, l_event, l_event_size);
+                        memcpy((void *)l_new_atom, l_event, l_event_size);
                         if(s_chain_callback_atom_add(l_chain, l_new_atom,l_event_size) < 0) { // Add new atom in chain
                             DAP_DELETE(l_new_atom);
                             dap_string_append_printf(l_str_ret_tmp, "Event %s not added in chain\n", l_objs[i].key);
-- 
GitLab