From 85bdb316550b071bf6eac4020de4042fe12c5f5a Mon Sep 17 00:00:00 2001
From: "daniil.frolov" <daniil.frolov@demlabs.net>
Date: Tue, 21 May 2024 17:26:09 +0700
Subject: [PATCH] [+] Chain unit tests in area forks handling is added [*] Fork
 handling is debugged

---
 modules/type/blocks/dap_chain_cs_blocks.c     |  36 +++---
 .../type/blocks/tests/dap_chain_blocks_test.c | 116 ++++++++++++------
 2 files changed, 98 insertions(+), 54 deletions(-)

diff --git a/modules/type/blocks/dap_chain_cs_blocks.c b/modules/type/blocks/dap_chain_cs_blocks.c
index c5db0ec1f3..c96dc2a2c0 100644
--- a/modules/type/blocks/dap_chain_cs_blocks.c
+++ b/modules/type/blocks/dap_chain_cs_blocks.c
@@ -1471,28 +1471,32 @@ static void s_select_longest_branch(dap_chain_cs_blocks_t * a_blocks, dap_chain_
     // Find longest forked branch 
     dap_list_t *l_branch = a_bcache->forked_branches;
     dap_list_t *l_longest_branch_ptr = l_branch ? (dap_list_t *)l_branch->data : NULL;
-    uint64_t l_longest_branch_length = (HASH_CNT(hh, a_bcache) - current_block_idx + 1);
+    uint64_t l_longest_branch_length = current_block_idx;
     while (l_branch){
-        if (dap_list_length((dap_list_t *)l_branch->data) > l_longest_branch_length){
-            l_longest_branch_length = dap_list_length((dap_list_t *)l_branch->data);
+        uint64_t l_branch_length = dap_list_length((dap_list_t *)l_branch->data);
+        if (l_branch_length > l_longest_branch_length){
+            l_longest_branch_length = l_branch_length;
             l_longest_branch_ptr = (dap_list_t *)l_branch->data;
         }
         l_branch = l_branch->next;
     }
 
-    // pthread_rwlock_wrlock(& PVT(l_blocks)->rwlock);
-    if ((HASH_CNT(hh, a_bcache) - current_block_idx + 1) < l_longest_branch_length){
+    if (current_block_idx < l_longest_branch_length){
         // Switch branches
         dap_list_t *l_new_forked_branch = NULL;
         // First we must to remove all blocks from main branch to forked 
         // branch and delete all datums in this atoms from storages
-        dap_chain_block_cache_t *l_atom, *l_tmp;
-        HASH_ITER(hh, (dap_chain_block_cache_t *)a_bcache->hh.next, l_atom, l_tmp){
-            l_new_forked_branch = dap_list_append(l_new_forked_branch, l_atom);
-            HASH_DEL(a_bcache, l_atom);
-            --PVT(l_blocks)->blocks_count;
-            s_delete_atom_datums(l_blocks, l_atom);
-        }
+        dap_chain_block_cache_t *l_atom = (dap_chain_block_cache_t *)a_bcache->hh.tbl->tail->prev, 
+                                *l_tmp = (dap_chain_block_cache_t *)a_bcache;
+        unsigned l_curr_index;
+        for (l_atom = l_atom->hh.next, l_curr_index = 0; 
+            current_block_idx > l_curr_index; l_atom = l_atom->hh.prev, l_curr_index++){
+                l_new_forked_branch = dap_list_prepend(l_new_forked_branch, l_atom);
+                HASH_DEL(a_bcache, l_atom);
+                --PVT(l_blocks)->blocks_count;
+                s_delete_atom_datums(l_blocks, l_atom);
+            }
+
         a_bcache->forked_branches = dap_list_append(a_bcache->forked_branches, l_new_forked_branch);
         // Next we add all atoms into HT and their datums into storages
         dap_list_t * new_main_branch = l_longest_branch_ptr;
@@ -1505,8 +1509,9 @@ static void s_select_longest_branch(dap_chain_cs_blocks_t * a_blocks, dap_chain_
             new_main_branch = new_main_branch->next;
         }
         dap_list_free(l_longest_branch_ptr);
+        a_bcache->forked_branches = dap_list_remove(a_bcache->forked_branches, l_longest_branch_ptr);
+        
     }
-    // pthread_rwlock_unlock(& PVT(l_blocks)->rwlock);
 }
 
 /**
@@ -1545,7 +1550,9 @@ static dap_chain_atom_verify_res_t s_callback_atom_add(dap_chain_t * a_chain, da
         pthread_rwlock_wrlock(& PVT(l_blocks)->rwlock);
         l_prev_bcache = l_block_pvt->blocks ? l_block_pvt->blocks->hh.tbl->tail->prev : NULL;
         if (l_prev_bcache){
-            for (l_prev_bcache = l_prev_bcache ? l_prev_bcache->hh.next : PVT(l_blocks)->blocks; l_prev_bcache && l_current_item_index < DAP_FORK_MAX_DEPTH; l_current_item_index++, l_prev_bcache = l_prev_bcache->hh.prev){
+            for (l_prev_bcache = l_prev_bcache->hh.next; 
+                l_prev_bcache && l_current_item_index < DAP_FORK_MAX_DEPTH; 
+                l_current_item_index++, l_prev_bcache = l_prev_bcache->hh.prev){
                 if (l_prev_bcache && dap_hash_fast_compare(&l_prev_bcache->block_hash, &l_block_prev_hash)){
                     ++PVT(l_blocks)->blocks_count;
                     HASH_ADD(hh, PVT(l_blocks)->blocks, block_hash, sizeof(l_block_cache->block_hash), l_block_cache);
@@ -1570,7 +1577,6 @@ static dap_chain_atom_verify_res_t s_callback_atom_add(dap_chain_t * a_chain, da
                         l_forked_branches = l_forked_branches->next;
                     }
                 }
-                l_current_item_index++;
             }
         } else {
             HASH_ADD(hh, PVT(l_blocks)->blocks, block_hash, sizeof(l_block_cache->block_hash), l_block_cache);
diff --git a/modules/type/blocks/tests/dap_chain_blocks_test.c b/modules/type/blocks/tests/dap_chain_blocks_test.c
index 3913392f60..5c844ba163 100644
--- a/modules/type/blocks/tests/dap_chain_blocks_test.c
+++ b/modules/type/blocks/tests/dap_chain_blocks_test.c
@@ -32,19 +32,19 @@ void dap_chain_blocks_test()
     dap_list_t *l_second_branch_atoms_list = NULL;
 
     l_block = dap_chain_block_new(NULL, &l_block_size);
-    dap_assert(l_block != NULL, "Creating of genesis block:");
+    dap_assert_PIF(l_block != NULL, "Creating of genesis block:");
     dap_hash_fast(l_block, l_block_size, &l_block_hash);
-    dap_test_msg("Created block %s", dap_chain_hash_fast_to_str_static(&l_block_hash));
-    dap_assert(l_chain->callback_atom_add(l_chain, (dap_chain_atom_ptr_t)l_block, l_block_size, &l_block_hash) == ATOM_ACCEPT, "Adding of genesis block: ");
+    // dap_test_msg("Created genesis block %s", dap_chain_hash_fast_to_str_static(&l_block_hash));
+    dap_assert_PIF(l_chain->callback_atom_add(l_chain, (dap_chain_atom_ptr_t)l_block, l_block_size, &l_block_hash) == ATOM_ACCEPT, "Adding of genesis block: ");
     dap_hash_fast_t *l_block_hash_copy = DAP_DUP_SIZE(&l_block_hash, sizeof(dap_hash_fast_t));
     l_first_branch_atoms_list = dap_list_append(l_first_branch_atoms_list, l_block_hash_copy);
     l_second_branch_atoms_list = dap_list_append(l_second_branch_atoms_list, l_block_hash_copy);
 
     l_block = dap_chain_block_new(&l_block_hash, &l_block_size);
-    dap_assert(l_block != NULL, "Creating of second block:");
+    dap_assert_PIF(l_block != NULL, "Creating of second block:");
     dap_hash_fast(l_block, l_block_size, &l_block_hash);
-    dap_test_msg("Created block %s", dap_chain_hash_fast_to_str_static(&l_block_hash));
-    dap_assert(l_chain->callback_atom_add(l_chain, (dap_chain_atom_ptr_t)l_block, l_block_size, &l_block_hash) == ATOM_ACCEPT, "Adding of second block: ");
+    // dap_test_msg("Created second block %s", dap_chain_hash_fast_to_str_static(&l_block_hash));
+    dap_assert_PIF(l_chain->callback_atom_add(l_chain, (dap_chain_atom_ptr_t)l_block, l_block_size, &l_block_hash) == ATOM_ACCEPT, "Adding of second block: ");
     l_block_hash_copy = DAP_DUP_SIZE(&l_block_hash, sizeof(dap_hash_fast_t));
     l_first_branch_atoms_list = dap_list_append(l_first_branch_atoms_list, l_block_hash_copy);
     l_second_branch_atoms_list = dap_list_append(l_second_branch_atoms_list, l_block_hash_copy);
@@ -52,10 +52,10 @@ void dap_chain_blocks_test()
 
     for (int i = 0; i < 2; i++){
         l_block = dap_chain_block_new(&l_block_hash, &l_block_size);
-        dap_assert(l_block != NULL, "Creating of block:");
+        // dap_assert_PIF(l_block != NULL, "Creating of block:");
         dap_hash_fast(l_block, l_block_size, &l_block_hash);
-        dap_test_msg("Created block %s", dap_chain_hash_fast_to_str_static(&l_block_hash));
-        dap_assert(l_chain->callback_atom_add(l_chain, (dap_chain_atom_ptr_t)l_block, l_block_size, &l_block_hash) == ATOM_ACCEPT, "Adding of block: ");
+        // dap_test_msg("Created block %s", dap_chain_hash_fast_to_str_static(&l_block_hash));
+        dap_assert_PIF(l_chain->callback_atom_add(l_chain, (dap_chain_atom_ptr_t)l_block, l_block_size, &l_block_hash) == ATOM_ACCEPT, "Adding of block: ");
         dap_hash_fast_t *l_block_hash_copy = DAP_DUP_SIZE(&l_block_hash, sizeof(dap_hash_fast_t));
         l_first_branch_atoms_list = dap_list_append(l_first_branch_atoms_list, l_block_hash_copy);
     }
@@ -64,67 +64,105 @@ void dap_chain_blocks_test()
     dap_test_msg("Add forked block from %s", dap_chain_hash_fast_to_str_static(&l_forked_block_hash)); 
     l_block_size = 0;
     l_block = dap_chain_block_new(&l_forked_block_hash, &l_block_size);
-    dap_assert(l_block != NULL, "Creating of forked block:");
+    // dap_assert_PIF(l_block != NULL, "Creating of forked block:");
     dap_hash_fast(l_block, l_block_size, &l_block_hash);
-    dap_test_msg("Created block %s", dap_chain_hash_fast_to_str_static(&l_block_hash));
-    dap_assert(l_chain->callback_atom_add(l_chain, (dap_chain_atom_ptr_t)l_block, l_block_size, &l_block_hash) == ATOM_ACCEPT, "Adding of forked block: ");
+    // dap_test_msg("Created block %s", dap_chain_hash_fast_to_str_static(&l_block_hash));
+    dap_assert_PIF(l_chain->callback_atom_add(l_chain, (dap_chain_atom_ptr_t)l_block, l_block_size, &l_block_hash) == ATOM_ACCEPT, "Adding of forked block: ");
     l_block_hash_copy = DAP_DUP_SIZE(&l_block_hash, sizeof(dap_hash_fast_t));
     l_second_branch_atoms_list = dap_list_append(l_second_branch_atoms_list, l_block_hash_copy);
 
     dap_chain_cell_id_t l_cell_id = {.uint64 = 1};
     size_t l_atom_size_from_iter = 0;
     dap_chain_atom_iter_t *l_iter = l_chain->callback_atom_iter_create(l_chain, l_cell_id, NULL);
-    l_chain->callback_atom_iter_get(l_iter, DAP_CHAIN_ITER_OP_FIRST, &l_atom_size_from_iter);
-    dap_list_t *l_branch_temp = l_first_branch_atoms_list;
-    dap_assert_PIF(dap_hash_fast_compare(l_iter->cur_hash, (dap_hash_fast_t*)l_branch_temp->data), "Check adding block into forked branch: ");
-    l_branch_temp = l_branch_temp->next;
-    while (l_branch_temp && l_chain->callback_atom_iter_get(l_iter, DAP_CHAIN_ITER_OP_NEXT, &l_atom_size_from_iter)){
-        dap_test_msg("Check block %s", dap_chain_hash_fast_to_str_static(l_iter->cur_hash));
+    dap_list_t *l_branch_temp = NULL;
+    dap_chain_atom_ptr_t l_atom = l_chain->callback_atom_iter_get(l_iter, DAP_CHAIN_ITER_OP_FIRST, &l_atom_size_from_iter);
+    for (dap_list_t *l_branch_temp = l_first_branch_atoms_list; l_branch_temp && l_atom; 
+        l_branch_temp = l_branch_temp->next, l_atom = l_chain->callback_atom_iter_get(l_iter, DAP_CHAIN_ITER_OP_NEXT, &l_atom_size_from_iter)){
+        dap_test_msg("Check block %s and %s", dap_chain_hash_fast_to_str_static(l_iter->cur_hash), 
+                                            dap_chain_hash_fast_to_str_static((dap_hash_fast_t*)l_branch_temp->data));
         dap_assert_PIF(dap_hash_fast_compare(l_iter->cur_hash, (dap_hash_fast_t*)l_branch_temp->data), "Check adding block into forked branch: ");
-        l_branch_temp = l_branch_temp->next;
     }
 
 
     dap_test_msg("Add block to forked branch"); 
     l_block_size = 0;
     l_block = dap_chain_block_new(&l_block_hash, &l_block_size);
-    dap_assert(l_block != NULL, "Creating of forked block:");
+    // dap_assert_PIF(l_block != NULL, "Creating of forked block:");
     dap_hash_fast(l_block, l_block_size, &l_block_hash);
-    dap_test_msg("Created block %s", dap_chain_hash_fast_to_str_static(&l_block_hash));
-    dap_assert(l_chain->callback_atom_add(l_chain, (dap_chain_atom_ptr_t)l_block, l_block_size, &l_block_hash) == ATOM_ACCEPT, "Adding of forked block: ");
+    // dap_test_msg("Created block %s", dap_chain_hash_fast_to_str_static(&l_block_hash));
+    dap_assert_PIF(l_chain->callback_atom_add(l_chain, (dap_chain_atom_ptr_t)l_block, l_block_size, &l_block_hash) == ATOM_ACCEPT, "Adding of forked block: ");
     l_block_hash_copy = DAP_DUP_SIZE(&l_block_hash, sizeof(dap_hash_fast_t));
     l_second_branch_atoms_list = dap_list_append(l_second_branch_atoms_list, l_block_hash_copy);
 
-    l_chain->callback_atom_iter_get(l_iter, DAP_CHAIN_ITER_OP_FIRST, &l_atom_size_from_iter);
-    l_branch_temp = l_first_branch_atoms_list;
-    dap_assert_PIF(dap_hash_fast_compare(l_iter->cur_hash, (dap_hash_fast_t*)l_branch_temp->data), "Check adding block into forked branch: ");
-    l_branch_temp = l_branch_temp->next;
-    while (l_branch_temp && l_chain->callback_atom_iter_get(l_iter, DAP_CHAIN_ITER_OP_NEXT, &l_atom_size_from_iter)){
-        dap_test_msg("Check block %s", dap_chain_hash_fast_to_str_static(l_iter->cur_hash));
+    l_atom = l_chain->callback_atom_iter_get(l_iter, DAP_CHAIN_ITER_OP_FIRST, &l_atom_size_from_iter);
+    for (dap_list_t *l_branch_temp = l_first_branch_atoms_list; l_branch_temp && l_atom; 
+        l_branch_temp = l_branch_temp->next, l_atom = l_chain->callback_atom_iter_get(l_iter, DAP_CHAIN_ITER_OP_NEXT, &l_atom_size_from_iter)){
+        dap_test_msg("Check block %s and %s", dap_chain_hash_fast_to_str_static(l_iter->cur_hash), 
+                                            dap_chain_hash_fast_to_str_static((dap_hash_fast_t*)l_branch_temp->data));
         dap_assert_PIF(dap_hash_fast_compare(l_iter->cur_hash, (dap_hash_fast_t*)l_branch_temp->data), "Check adding block into forked branch: ");
-        l_branch_temp = l_branch_temp->next;
     }
 
+    dap_test_msg("Add block to forked branch");
     l_block_size = 0;
     l_block = dap_chain_block_new(&l_block_hash, &l_block_size);
-    dap_assert(l_block != NULL, "Creating of forked block:");
+    // dap_assert_PIF(l_block != NULL, "Creating of forked block:");
     dap_hash_fast(l_block, l_block_size, &l_block_hash);
-    dap_test_msg("Created block %s", dap_chain_hash_fast_to_str_static(&l_block_hash));
-    dap_assert(l_chain->callback_atom_add(l_chain, (dap_chain_atom_ptr_t)l_block, l_block_size, &l_block_hash) == ATOM_ACCEPT, "Adding of forked block: ");
+    // dap_test_msg("Created block %s", dap_chain_hash_fast_to_str_static(&l_block_hash));
+    dap_assert_PIF(l_chain->callback_atom_add(l_chain, (dap_chain_atom_ptr_t)l_block, l_block_size, &l_block_hash) == ATOM_ACCEPT, "Adding of forked block: ");
     l_block_hash_copy = DAP_DUP_SIZE(&l_block_hash, sizeof(dap_hash_fast_t));
     l_second_branch_atoms_list = dap_list_append(l_second_branch_atoms_list, l_block_hash_copy);
 
-    l_chain->callback_atom_iter_get(l_iter, DAP_CHAIN_ITER_OP_FIRST, &l_atom_size_from_iter);
-    l_branch_temp = l_second_branch_atoms_list;
-    dap_assert_PIF(dap_hash_fast_compare(l_iter->cur_hash, (dap_hash_fast_t*)l_branch_temp->data), "Check adding block into forked branch: ");
-    l_branch_temp = l_branch_temp->next;
-    while (l_branch_temp && l_chain->callback_atom_iter_get(l_iter, DAP_CHAIN_ITER_OP_NEXT, &l_atom_size_from_iter)){
-        dap_test_msg("Check block %s", dap_chain_hash_fast_to_str_static(l_iter->cur_hash));
+    l_atom = l_chain->callback_atom_iter_get(l_iter, DAP_CHAIN_ITER_OP_FIRST, &l_atom_size_from_iter);
+    for (dap_list_t *l_branch_temp = l_second_branch_atoms_list; l_branch_temp && l_atom; 
+        l_branch_temp = l_branch_temp->next, l_atom = l_chain->callback_atom_iter_get(l_iter, DAP_CHAIN_ITER_OP_NEXT, &l_atom_size_from_iter)){
+        dap_test_msg("Check block %s and %s", dap_chain_hash_fast_to_str_static(l_iter->cur_hash), 
+                                            dap_chain_hash_fast_to_str_static((dap_hash_fast_t*)l_branch_temp->data));
         dap_assert_PIF(dap_hash_fast_compare(l_iter->cur_hash, (dap_hash_fast_t*)l_branch_temp->data), "Check adding block into forked branch: ");
-        l_branch_temp = l_branch_temp->next;
     }
 
+    dap_test_msg("Add block to former main branch");
+    l_block_size = 0;
+    l_block = dap_chain_block_new((dap_hash_fast_t*)dap_list_last(l_first_branch_atoms_list)->data, &l_block_size);
+    // dap_assert_PIF(l_block != NULL, "Creating of forked block:");
+    dap_hash_fast(l_block, l_block_size, &l_block_hash);
+    // dap_test_msg("Created block %s", dap_chain_hash_fast_to_str_static(&l_block_hash));
+    dap_assert_PIF(l_chain->callback_atom_add(l_chain, (dap_chain_atom_ptr_t)l_block, l_block_size, &l_block_hash) == ATOM_ACCEPT, "Adding of forked block: ");
+    l_block_hash_copy = DAP_DUP_SIZE(&l_block_hash, sizeof(dap_hash_fast_t));
+    l_first_branch_atoms_list = dap_list_append(l_first_branch_atoms_list, l_block_hash_copy);
+
+    l_atom = l_chain->callback_atom_iter_get(l_iter, DAP_CHAIN_ITER_OP_FIRST, &l_atom_size_from_iter);
+    for (dap_list_t *l_branch_temp = l_second_branch_atoms_list; l_branch_temp && l_atom; 
+        l_branch_temp = l_branch_temp->next, l_atom = l_chain->callback_atom_iter_get(l_iter, DAP_CHAIN_ITER_OP_NEXT, &l_atom_size_from_iter)){
+        dap_test_msg("Check block %s and %s", dap_chain_hash_fast_to_str_static(l_iter->cur_hash), 
+                                            dap_chain_hash_fast_to_str_static((dap_hash_fast_t*)l_branch_temp->data));
+        dap_assert_PIF(dap_hash_fast_compare(l_iter->cur_hash, (dap_hash_fast_t*)l_branch_temp->data), "Check adding block into forked branch: ");
+    }
+
+    dap_test_msg("Add block to former main branch");
+    l_block_size = 0;
+    l_block = dap_chain_block_new((dap_hash_fast_t*)dap_list_last(l_first_branch_atoms_list)->data, &l_block_size);
+    // dap_assert_PIF(l_block != NULL, "Creating of forked block:");
+    dap_hash_fast(l_block, l_block_size, &l_block_hash);
+    // dap_test_msg("Created block %s", dap_chain_hash_fast_to_str_static(&l_block_hash));
+    dap_assert_PIF(l_chain->callback_atom_add(l_chain, (dap_chain_atom_ptr_t)l_block, l_block_size, &l_block_hash) == ATOM_ACCEPT, "Adding of forked block: ");
+    l_block_hash_copy = DAP_DUP_SIZE(&l_block_hash, sizeof(dap_hash_fast_t));
+    l_first_branch_atoms_list = dap_list_append(l_first_branch_atoms_list, l_block_hash_copy);
+
+    l_atom = l_chain->callback_atom_iter_get(l_iter, DAP_CHAIN_ITER_OP_FIRST, &l_atom_size_from_iter);
+    for (dap_list_t *l_branch_temp = l_first_branch_atoms_list; l_branch_temp && l_atom; 
+        l_branch_temp = l_branch_temp->next, l_atom = l_chain->callback_atom_iter_get(l_iter, DAP_CHAIN_ITER_OP_NEXT, &l_atom_size_from_iter)){
+        dap_test_msg("Check block %s and %s", dap_chain_hash_fast_to_str_static(l_iter->cur_hash), 
+                                            dap_chain_hash_fast_to_str_static((dap_hash_fast_t*)l_branch_temp->data));
+        dap_assert_PIF(dap_hash_fast_compare(l_iter->cur_hash, (dap_hash_fast_t*)l_branch_temp->data), "Check adding block into forked branch: ");
+    }
+
+    dap_pass_msg("Test of one forked branch ")
+
     l_chain->callback_atom_iter_delete(l_iter);
 
+    
+
+    
+
 
 }
\ No newline at end of file
-- 
GitLab