diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c index a0f31fdb383784bce3e325ee8b2f0c31ab770ee6..ab659d337739a8be2e142fd3e4023b59d0fc4a0d 100644 --- a/modules/net/dap_chain_net.c +++ b/modules/net/dap_chain_net.c @@ -186,6 +186,7 @@ typedef struct dap_chain_net_pvt{ struct block_reward *rewards; dap_chain_net_decree_t *decree; decree_table_t *decrees; + anchor_table_t *anchors; } dap_chain_net_pvt_t; typedef struct dap_chain_net_item{ @@ -3158,7 +3159,7 @@ int dap_chain_datum_add(dap_chain_t *a_chain, dap_chain_datum_t *a_datum, size_t log_it(L_WARNING, "Corrupted anchor, datum size %zd is not equal to size of anchor %zd", l_datum_data_size, l_anchor_size); return -102; } - return dap_chain_net_anchor_load(l_anchor, a_chain); + return dap_chain_net_anchor_load(l_anchor, a_chain, a_datum_hash); } case DAP_CHAIN_DATUM_TOKEN_DECL: return dap_ledger_token_load(l_ledger, a_datum->data, a_datum->header.data_size); @@ -3205,32 +3206,22 @@ int dap_chain_datum_remove(dap_chain_t *a_chain, dap_chain_datum_t *a_datum, siz dap_ledger_t *l_ledger = dap_chain_net_by_id(a_chain->net_id)->pub.ledger; switch (a_datum->header.type_id) { case DAP_CHAIN_DATUM_DECREE: { - /*dap_chain_datum_decree_t *l_decree = (dap_chain_datum_decree_t *)a_datum->data; - size_t l_decree_size = dap_chain_datum_decree_get_size(l_decree); - if (l_decree_size != l_datum_data_size) { - log_it(L_WARNING, "Corrupted decree, datum size %zd is not equal to size of decree %zd", l_datum_data_size, l_decree_size); - return -102; - }*/ - return 0; //dap_chain_net_decree_load(l_decree, a_chain, a_datum_hash); + return 0; } case DAP_CHAIN_DATUM_ANCHOR: { dap_chain_datum_anchor_t *l_anchor = (dap_chain_datum_anchor_t *)a_datum->data; - - - size_t l_anchor_size = dap_chain_datum_anchor_get_size(l_anchor); if (l_anchor_size != l_datum_data_size) { log_it(L_WARNING, "Corrupted anchor, datum size %zd is not equal to size of anchor %zd", l_datum_data_size, l_anchor_size); return -102; } - return dap_chain_net_anchor_unload(l_anchor, a_chain); + return dap_chain_net_anchor_unload(l_anchor, a_chain, a_datum_hash); } case DAP_CHAIN_DATUM_TOKEN_DECL: - return 0;//dap_ledger_token_load(l_ledger, a_datum->data, a_datum->header.data_size); + return 0; case DAP_CHAIN_DATUM_TOKEN_EMISSION: - return 0;//dap_ledger_token_emission_load(l_ledger, a_datum->data, a_datum->header.data_size, a_datum_hash); - + return 0; case DAP_CHAIN_DATUM_TX: { dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t *)a_datum->data; size_t l_tx_size = dap_chain_datum_tx_get_size(l_tx); @@ -3318,4 +3309,8 @@ void dap_chain_net_set_net_decree(dap_chain_net_t *a_net, dap_chain_net_decree_t decree_table_t **dap_chain_net_get_decrees(dap_chain_net_t *a_net) { return a_net ? &(PVT(a_net)->decrees) : NULL; +} + +anchor_table_t **dap_chain_net_get_anchors(dap_chain_net_t *a_net) { + return a_net ? &(PVT(a_net)->anchors) : NULL; } \ No newline at end of file diff --git a/modules/net/dap_chain_net_anchor.c b/modules/net/dap_chain_net_anchor.c index 2fab9b011989ffbf390aae33f44aa85aee285014..dde964b2d4481c500b626c1d207c35fb8059f107 100644 --- a/modules/net/dap_chain_net_anchor.c +++ b/modules/net/dap_chain_net_anchor.c @@ -40,6 +40,12 @@ #define LOG_TAG "chain_net_anchor" +typedef struct anchor_table{ + dap_hash_fast_t anchor_hash; + dap_chain_datum_anchor_t *anchor; + UT_hash_handle hh; +} anchor_table_t; + // private function prototypes static bool s_verify_pubkeys(dap_sign_t *a_sign, dap_sign_t **a_decree_signs, size_t a_num_of_decree_sign); static inline dap_sign_t *s_concate_all_signs_in_array(dap_sign_t *a_in_signs, size_t a_signs_size, size_t *a_sings_count, size_t *a_signs_arr_size); @@ -134,7 +140,7 @@ int dap_chain_net_anchor_verify(dap_chain_net_t *a_net, dap_chain_datum_anchor_t return s_anchor_verify(a_net, a_anchor, a_data_size, false); } -int dap_chain_net_anchor_load(dap_chain_datum_anchor_t * a_anchor, dap_chain_t *a_chain) +int dap_chain_net_anchor_load(dap_chain_datum_anchor_t * a_anchor, dap_chain_t *a_chain, dap_hash_fast_t *a_anchor_hash) { int ret_val = 0; @@ -165,90 +171,106 @@ int dap_chain_net_anchor_load(dap_chain_datum_anchor_t * a_anchor, dap_chain_t * return -109; } - if ((ret_val = dap_chain_net_decree_apply(&l_hash, NULL, a_chain)) != 0) + if ((ret_val = dap_chain_net_decree_apply(&l_hash, NULL, a_chain)) != 0){ log_it(L_WARNING, "Decree applying failed"); + return ret_val; + } + + + anchor_table_t **l_anchors = dap_chain_net_get_anchors(l_net); + anchor_table_t *l_new_anchor = DAP_NEW_Z(anchor_table_t); + l_new_anchor->anchor_hash = *a_anchor_hash; + l_new_anchor->anchor = a_anchor; + HASH_ADD(hh, *l_anchors, anchor_hash, sizeof(l_new_anchor->anchor_hash), l_new_anchor); return ret_val; } -dap_chain_datum_anchor_t * s_find_previous_anchor(dap_chain_datum_anchor_t * a_anchor, dap_chain_t *a_chain) +dap_chain_datum_anchor_t * s_find_previous_anchor(dap_hash_fast_t *a_old_anchor_hash, dap_chain_net_t *a_net) { - if (!a_anchor || !a_chain){ + if (!a_old_anchor_hash || !a_net){ log_it(L_ERROR,"Params are NULL"); return NULL; } - dap_chain_net_t *l_net = dap_chain_net_by_id(a_chain->net_id); + + dap_chain_net_t *l_net = a_net; dap_chain_datum_anchor_t * l_ret_anchor = NULL; + dap_chain_datum_anchor_t *l_old_anchor = NULL; + + anchor_table_t **l_anchors_ptr = dap_chain_net_get_anchors(l_net); + anchor_table_t *l_anchor = NULL; + HASH_FIND(hh, *l_anchors_ptr, a_old_anchor_hash, sizeof(*a_old_anchor_hash), l_anchor); + if (!l_old_anchor){ + log_it(L_WARNING,"Can not find anchor"); + return NULL; + } + + l_old_anchor = l_anchor->anchor; dap_hash_fast_t l_old_decrere_hash = {}; - if (dap_chain_datum_anchor_get_hash_from_data(a_anchor, &l_old_decrere_hash) != 0) + if (dap_chain_datum_anchor_get_hash_from_data(l_old_anchor, &l_old_decrere_hash) != 0) return NULL; dap_chain_datum_decree_t *l_old_decree = dap_chain_net_decree_get_by_hash(l_net, &l_old_decrere_hash, NULL); uint16_t l_old_decree_type = l_old_decree->header.type; uint16_t l_old_decree_subtype = l_old_decree->header.sub_type; - dap_chain_cell_t *l_cell = a_chain->cells; - size_t l_atom_size = 0; - dap_chain_atom_iter_t *l_atom_iter = a_chain->callback_atom_iter_create(a_chain, l_cell->id, 0); - dap_chain_atom_ptr_t l_atom = a_chain->callback_atom_iter_get(l_atom_iter, DAP_CHAIN_ITER_OP_LAST, &l_atom_size); - while(l_atom && l_atom_size){ + anchor_table_t *l_anchors = HASH_LAST(*l_anchors_ptr); + for(; l_anchors; l_anchors = l_anchors->hh.prev){ size_t l_datums_count = 0; - dap_chain_datum_t **l_datums = a_chain->callback_atom_get_datums(l_atom, l_atom_size, &l_datums_count); - dap_chain_datum_t *l_datum, *l_datum2; - for(size_t l_datum_n = 0; l_datum_n < l_datums_count; l_datum_n++) { - if ( ! (l_datum = l_datums[l_datum_n]) ) - continue; - - if (l_datum->header.type_id != DAP_CHAIN_DATUM_ANCHOR || a_anchor == (dap_chain_datum_anchor_t *)l_datum->data) - continue; - dap_chain_datum_anchor_t *l_curr_anchor = (dap_chain_datum_anchor_t *)l_datum->data; - dap_hash_fast_t l_hash = {}; - if (dap_chain_datum_anchor_get_hash_from_data(l_curr_anchor, &l_hash) != 0) - continue; + dap_chain_datum_anchor_t *l_curr_anchor = l_anchors->anchor; + dap_hash_fast_t l_hash = {}; + if (dap_chain_datum_anchor_get_hash_from_data(l_curr_anchor, &l_hash) != 0) + continue; + + bool l_is_applied = false; + dap_chain_datum_decree_t *l_decree = dap_chain_net_decree_get_by_hash(l_net, &l_hash, &l_is_applied); + if (!l_decree) + continue; + + if (l_decree->header.type == l_old_decree_type && l_old_decree_type == DAP_CHAIN_DATUM_DECREE_TYPE_COMMON && + l_old_decree_subtype == DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_INVALIDATE && + l_decree->header.sub_type == DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_APPROVE){ - bool l_is_applied = false; - dap_chain_datum_decree_t *l_decree = dap_chain_net_decree_get_by_hash(l_net, &l_hash, &l_is_applied); - if (!l_decree) + dap_chain_addr_t l_addr_old, l_addr_new = {}; + if (dap_chain_datum_decree_get_stake_signing_addr(l_old_decree, &l_addr_old)){ continue; + } - if (l_decree->header.type == l_old_decree_type && l_old_decree_type == DAP_CHAIN_DATUM_DECREE_TYPE_COMMON && - l_old_decree_subtype == DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_INVALIDATE && - l_decree->header.sub_type == DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_APPROVE){ - - dap_chain_addr_t l_addr_old, l_addr_new = {}; - if (dap_chain_datum_decree_get_stake_signing_addr(l_old_decree, &l_addr_old)){ - continue; - } - - if (dap_chain_datum_decree_get_stake_signing_addr(l_decree, &l_addr_new)){ - continue; - } + if (dap_chain_datum_decree_get_stake_signing_addr(l_decree, &l_addr_new)){ + continue; + } - if(dap_chain_addr_compare(&l_addr_old, &l_addr_new)){ - l_ret_anchor = l_curr_anchor; - dap_chain_net_decree_reset_applied(l_net, &l_hash); - break; - } - } else if (l_decree->header.type == l_old_decree_type && l_decree->header.sub_type == l_old_decree_subtype){ - // check addr if l_decree type is stake approve + if(dap_chain_addr_compare(&l_addr_old, &l_addr_new)){ l_ret_anchor = l_curr_anchor; dap_chain_net_decree_reset_applied(l_net, &l_hash); - break; + break; } + } else if (l_decree->header.type == l_old_decree_type && l_decree->header.sub_type == l_old_decree_subtype){ + // check addr if l_decree type is stake approve + l_ret_anchor = l_curr_anchor; + dap_chain_net_decree_reset_applied(l_net, &l_hash); + break; } - DAP_DEL_Z(l_datums); if (l_ret_anchor) break; - // go to previous atom - l_atom = a_chain->callback_atom_iter_get(l_atom_iter, DAP_CHAIN_ITER_OP_PREV, &l_atom_size); } - a_chain->callback_atom_iter_delete(l_atom_iter); return l_ret_anchor; } -int dap_chain_net_anchor_unload(dap_chain_datum_anchor_t * a_anchor, dap_chain_t *a_chain) +void s_delete_anchor(dap_chain_net_t *a_net, dap_hash_fast_t *a_anchor_hash) +{ + anchor_table_t **l_anchors_ptr = dap_chain_net_get_anchors(a_net); + anchor_table_t *l_anchor = NULL; + HASH_FIND(hh, *l_anchors_ptr, a_anchor_hash, sizeof(*a_anchor_hash), l_anchor); + if(l_anchor){ + HASH_DEL(*l_anchors_ptr, l_anchor); + DAP_DEL_Z(l_anchor); + } +} + +int dap_chain_net_anchor_unload(dap_chain_datum_anchor_t * a_anchor, dap_chain_t *a_chain, dap_hash_fast_t *a_anchor_hash) { int ret_val = 0; @@ -287,7 +309,8 @@ int dap_chain_net_anchor_unload(dap_chain_datum_anchor_t * a_anchor, dap_chain_t { case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_FEE:{ dap_chain_net_decree_reset_applied(l_net, &l_hash); - dap_chain_datum_anchor_t * l_new_anchor = s_find_previous_anchor(a_anchor, a_chain); + dap_chain_datum_anchor_t * l_new_anchor = s_find_previous_anchor(a_anchor_hash, l_net); + s_delete_anchor(l_net, a_anchor_hash); if (l_new_anchor){// if previous anchor is founded apply it dap_chain_hash_fast_t l_hash = {0}; if ((ret_val = dap_chain_datum_anchor_get_hash_from_data(l_new_anchor, &l_hash)) != 0){ @@ -317,12 +340,14 @@ int dap_chain_net_anchor_unload(dap_chain_datum_anchor_t * a_anchor, dap_chain_t } dap_chain_net_srv_stake_key_invalidate(&l_signing_addr); dap_chain_net_decree_reset_applied(l_net, &l_hash); + s_delete_anchor(l_net, a_anchor_hash); } break; case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_INVALIDATE:{ // Find previous anchor with this stake approve and apply it dap_chain_net_decree_reset_applied(l_net, &l_hash); dap_chain_datum_anchor_t * l_new_anchor = s_find_previous_anchor(a_anchor, a_chain); + s_delete_anchor(l_net, a_anchor_hash); if (l_new_anchor){// if previous anchor is founded apply it dap_chain_hash_fast_t l_hash = {0}; if ((ret_val = dap_chain_datum_anchor_get_hash_from_data(l_new_anchor, &l_hash)) != 0){ @@ -339,6 +364,7 @@ int dap_chain_net_anchor_unload(dap_chain_datum_anchor_t * a_anchor, dap_chain_t case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_MIN_VALUE:{ dap_chain_net_decree_reset_applied(l_net, &l_hash); dap_chain_datum_anchor_t * l_new_anchor = s_find_previous_anchor(a_anchor, a_chain); + s_delete_anchor(l_net, a_anchor_hash); if (l_new_anchor){// if previous anchor is founded apply it dap_chain_hash_fast_t l_hash = {0}; if ((ret_val = dap_chain_datum_anchor_get_hash_from_data(l_new_anchor, &l_hash)) != 0){ @@ -358,6 +384,7 @@ int dap_chain_net_anchor_unload(dap_chain_datum_anchor_t * a_anchor, dap_chain_t case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_MIN_VALIDATORS_COUNT:{ dap_chain_net_decree_reset_applied(l_net, &l_hash); dap_chain_datum_anchor_t * l_new_anchor = s_find_previous_anchor(a_anchor, a_chain); + s_delete_anchor(l_net, a_anchor_hash); if (l_new_anchor){// if previous anchor is founded apply it dap_chain_hash_fast_t l_hash = {0}; if ((ret_val = dap_chain_datum_anchor_get_hash_from_data(l_new_anchor, &l_hash)) != 0){ @@ -378,6 +405,7 @@ int dap_chain_net_anchor_unload(dap_chain_datum_anchor_t * a_anchor, dap_chain_t // find previous anchor with rewarrd and apply it dap_chain_net_decree_reset_applied(l_net, &l_hash); dap_chain_net_remove_last_reward(dap_chain_net_by_id(a_chain->net_id)); + s_delete_anchor(l_net, a_anchor_hash); } break; case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_OWNERS: diff --git a/modules/net/dap_chain_net_decree.c b/modules/net/dap_chain_net_decree.c index 9433256eb788451facee26a448f68c9b9409c27d..46d6c126472ff3e5c110872b348a772d2e4116d5 100644 --- a/modules/net/dap_chain_net_decree.c +++ b/modules/net/dap_chain_net_decree.c @@ -245,7 +245,6 @@ int dap_chain_net_decree_apply(dap_hash_fast_t *a_decree_hash, dap_chain_datum_d decree_table_t **l_decrees = dap_chain_net_get_decrees(l_net), *l_new_decree; HASH_FIND(hh, *l_decrees, a_decree_hash, sizeof(dap_hash_fast_t), l_new_decree); - if (!l_new_decree) { l_new_decree = DAP_NEW_Z(decree_table_t); if (!l_new_decree) { diff --git a/modules/net/include/dap_chain_net.h b/modules/net/include/dap_chain_net.h index 6e9f139a5223f361a849eda5c49a5c7c1f25c485..6e62d461f70fb3948bcfad59038a16bd2368dedb 100644 --- a/modules/net/include/dap_chain_net.h +++ b/modules/net/include/dap_chain_net.h @@ -44,6 +44,7 @@ typedef struct dap_chain_node_client dap_chain_node_client_t; typedef struct dap_ledger dap_ledger_t; typedef struct dap_chain_net_decree dap_chain_net_decree_t; typedef struct decree_table decree_table_t; +typedef struct anchor_table anchor_table_t; typedef enum dap_chain_net_state { NET_STATE_OFFLINE = 0, NET_STATE_LINKS_PREPARE, @@ -233,4 +234,5 @@ enum dap_chain_net_json_rpc_error_list{ }; dap_chain_net_decree_t *dap_chain_net_get_net_decree(dap_chain_net_t *a_net); void dap_chain_net_set_net_decree(dap_chain_net_t *a_net, dap_chain_net_decree_t *a_decree); -decree_table_t **dap_chain_net_get_decrees(dap_chain_net_t *a_net); \ No newline at end of file +decree_table_t **dap_chain_net_get_decrees(dap_chain_net_t *a_net); +anchor_table_t **dap_chain_net_get_anchors(dap_chain_net_t *a_net); \ No newline at end of file diff --git a/modules/net/include/dap_chain_net_anchor.h b/modules/net/include/dap_chain_net_anchor.h index 1a44cab2a1f10439cd03d4c91b355c78d3380355..7275e2c2b3ca0e4143c30f692de3f471b72a9dc4 100644 --- a/modules/net/include/dap_chain_net_anchor.h +++ b/modules/net/include/dap_chain_net_anchor.h @@ -24,6 +24,8 @@ #include "dap_chain_datum_anchor.h" #include "dap_chain_net.h" +int dap_chain_net_anchor_init(dap_chain_net_t *a_net); + int dap_chain_net_anchor_verify(dap_chain_net_t *a_net, dap_chain_datum_anchor_t * a_anchor, size_t a_data_size); -int dap_chain_net_anchor_load(dap_chain_datum_anchor_t * a_anchor, dap_chain_t *a_chain); -int dap_chain_net_anchor_unload(dap_chain_datum_anchor_t * a_anchor, dap_chain_t *a_chain); \ No newline at end of file +int dap_chain_net_anchor_load(dap_chain_datum_anchor_t * a_anchor, dap_chain_t *a_chain, dap_hash_fast_t *a_anchor_hash); +int dap_chain_net_anchor_unload(dap_chain_datum_anchor_t * a_anchor, dap_chain_t *a_chain, dap_hash_fast_t *a_anchor_hash); \ No newline at end of file diff --git a/modules/type/blocks/dap_chain_cs_blocks.c b/modules/type/blocks/dap_chain_cs_blocks.c index 01a2468ff55625627c71735f8a5129ec0dd21d83..66041b7d628e1ded6b362070e01e0f537e599927 100644 --- a/modules/type/blocks/dap_chain_cs_blocks.c +++ b/modules/type/blocks/dap_chain_cs_blocks.c @@ -62,10 +62,12 @@ typedef struct dap_chain_cs_blocks_pvt size_t forked_br_cnt; dap_chain_block_forked_branch_t **forked_branches; // list of lists with atoms in side branches + pthread_rwlock_t forked_branches_rwlock; // Chunks treshold dap_chain_block_chunks_t * chunks; dap_chain_block_datum_index_t *datum_index; // To find datum in blocks + pthread_rwlock_t datums_rwlock; dap_chain_hash_fast_t genesis_block_hash; dap_chain_hash_fast_t static_genesis_block_hash; @@ -78,12 +80,24 @@ typedef struct dap_chain_cs_blocks_pvt dap_timerfd_t *fill_timer; uint64_t fill_timeout; - pthread_rwlock_t rwlock, datums_rwlock; + pthread_rwlock_t rwlock; struct cs_blocks_hal_item *hal; } dap_chain_cs_blocks_pvt_t; #define PVT(a) ((dap_chain_cs_blocks_pvt_t *)(a)->_pvt ) +#define print_rdlock(blocks) log_it(L_DEBUG, "Try to rdlock, %s, %d, thread_id=%u", __FUNCTION__, __LINE__, dap_gettid());\ + pthread_rwlock_rdlock(& PVT(blocks)->rwlock);\ + log_it(L_DEBUG, "Locked rdlock, %s, %d, thread_id=%u", __FUNCTION__, __LINE__, dap_gettid()); + +#define print_wrlock(blocks) log_it(L_DEBUG, "Try to wrlock, %s, %d, thread_id=%u", __FUNCTION__, __LINE__, dap_gettid());\ + pthread_rwlock_wrlock(& PVT(blocks)->rwlock);\ + log_it(L_DEBUG, "Locked wrlock, %s, %d, thread_id=%u", __FUNCTION__, __LINE__, dap_gettid()); + +#define print_unlock(blocks) log_it(L_DEBUG, "Try to unlock, %s, %d, thread_id=%u", __FUNCTION__, __LINE__, dap_gettid());\ + pthread_rwlock_unlock(& PVT(blocks)->rwlock);\ + log_it(L_DEBUG, "Unlocked rwqlock, %s, %d, thread_id=%u", __FUNCTION__, __LINE__, dap_gettid()); + static int s_cli_parse_cmd_hash(char ** a_argv, int a_arg_index, int a_argc, void **a_str_reply,const char * a_param, dap_chain_hash_fast_t * a_datum_hash); static void s_cli_meta_hash_print( json_object* json_obj_a, const char * a_meta_title, dap_chain_block_meta_t * a_meta); static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply); @@ -155,7 +169,7 @@ int dap_chain_cs_blocks_init() { dap_chain_cs_type_add("blocks", s_chain_cs_blocks_new); s_seed_mode = dap_config_get_item_bool_default(g_config,"general","seed_mode",false); - s_debug_more = true; //dap_config_get_item_bool_default(g_config, "blocks", "debug_more", false); + s_debug_more = dap_config_get_item_bool_default(g_config, "blocks", "debug_more", false); dap_cli_server_cmd_add ("block", s_cli_blocks, "Create and explore blockchains", "New block create, fill and complete commands:\n" "block -net <net_name> -chain <chain_name> new\n" @@ -286,6 +300,7 @@ static int s_chain_cs_blocks_new(dap_chain_t *a_chain, dap_config_t *a_chain_con l_cs_blocks->_pvt = l_cs_blocks_pvt; pthread_rwlock_init(&l_cs_blocks_pvt->rwlock,NULL); pthread_rwlock_init(&l_cs_blocks_pvt->datums_rwlock, NULL); + pthread_rwlock_init(&l_cs_blocks_pvt->forked_branches_rwlock, NULL); const char * l_genesis_blocks_hash_str = dap_config_get_item_str_default(a_chain_config,"blocks","genesis_block",NULL); if ( l_genesis_blocks_hash_str ){ @@ -1339,6 +1354,7 @@ 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_rwlock); + pthread_rwlock_destroy(&PVT(l_blocks)->forked_branches_rwlock); dap_chain_block_chunks_delete(PVT(l_blocks)->chunks); DAP_DEL_Z(l_blocks->_inheritor); DAP_DEL_Z(l_blocks->_pvt); @@ -1348,6 +1364,19 @@ static void s_callback_delete(dap_chain_t * a_chain) static void s_callback_cs_blocks_purge(dap_chain_t *a_chain) { dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(a_chain); + + pthread_rwlock_wrlock(&PVT(l_blocks)->forked_branches_rwlock); + for (size_t i = 0; i < PVT(l_blocks)->forked_br_cnt; i++){ + dap_chain_block_forked_branch_atoms_table_t *l_atom_tmp, *l_atom; + HASH_ITER(hh, PVT(l_blocks)->forked_branches[i]->forked_branch_atoms, l_atom, l_atom_tmp) { + HASH_DEL(PVT(l_blocks)->forked_branches[i]->forked_branch_atoms, l_atom); + l_atom = NULL; + } + DAP_DEL_Z(PVT(l_blocks)->forked_branches[i]); + } + DAP_DEL_Z(PVT(l_blocks)->forked_branches); + pthread_rwlock_unlock(&PVT(l_blocks)->forked_branches_rwlock); + pthread_rwlock_wrlock(&PVT(l_blocks)->rwlock); dap_chain_block_cache_t *l_block = NULL, *l_block_tmp = NULL; HASH_ITER(hh, PVT(l_blocks)->blocks, l_block, l_block_tmp) { @@ -1467,73 +1496,6 @@ static void s_add_atom_to_blocks(dap_chain_cs_blocks_t *a_blocks, dap_chain_bloc } -/** - * @brief s_bft_consensus_setup - * @param a_blocks - */ -static void s_bft_consensus_setup(dap_chain_cs_blocks_t * a_blocks) -{ - bool l_was_chunks_changed = false; - // Compare all chunks with chain's tail - for (dap_chain_block_chunk_t *l_chunk = PVT(a_blocks)->chunks->chunks_last ; l_chunk; l_chunk=l_chunk->prev ){ - size_t l_chunk_length = HASH_COUNT(l_chunk->block_cache_hash); - dap_chain_block_cache_t * l_block_cache_chunk_top_prev = dap_chain_block_cache_get_by_hash(a_blocks,&l_chunk->block_cache_top->prev_hash); - dap_chain_block_cache_t * l_block_cache= l_block_cache_chunk_top_prev; - if ( l_block_cache ){ // we found prev block in main chain - size_t l_tail_length = 0; - // Now lets calc tail length - for( ;l_block_cache; l_block_cache=l_block_cache->prev){ - l_tail_length++; - if(l_tail_length>l_chunk_length) - break; - } - if(l_tail_length<l_chunk_length ){ // This generals consensus is bigger than the current one - // Cutoff current chank from the list - if( l_chunk->next) - l_chunk->next->prev = l_chunk->prev; - if( l_chunk->prev) - l_chunk->prev->next = l_chunk->next; - - // Pass through all the tail and move it to chunks - for(l_block_cache= l_block_cache_chunk_top_prev ;l_block_cache; l_block_cache=l_block_cache->prev){ - pthread_rwlock_wrlock(& PVT(a_blocks)->rwlock); - if(l_block_cache->prev) - l_block_cache->prev->next = l_block_cache->next; - if(l_block_cache->next) - l_block_cache->next->prev = l_block_cache->prev; - HASH_DEL(PVT(a_blocks)->blocks,l_block_cache); - --PVT(a_blocks)->blocks_count; - pthread_rwlock_unlock(& PVT(a_blocks)->rwlock); - dap_chain_block_chunks_add(PVT(a_blocks)->chunks,l_block_cache); - } - // Pass through all the chunk and add it to main chain - for(l_block_cache= l_chunk->block_cache_top ;l_block_cache; l_block_cache=l_block_cache->prev){ - int l_check_res = 0; - if (a_blocks->callback_block_verify) - l_check_res = a_blocks->callback_block_verify(a_blocks, l_block_cache->block, l_block_cache->block_size); - if (!l_check_res) { - log_it(L_WARNING,"Can't move block %s from chunk to main chain - data inside wasn't verified: code %d", - l_block_cache->block_hash_str, l_check_res); - dap_chain_block_chunks_add(PVT(a_blocks)->chunks,l_block_cache); - } - // TODO Rework blocks rwlock usage for this code - HASH_ADD(hh, PVT(a_blocks)->blocks, block_hash, sizeof(l_block_cache->block_hash), l_block_cache); - ++PVT(a_blocks)->blocks_count; - s_add_atom_datums(a_blocks, l_block_cache); - } - dap_chain_block_chunk_delete(l_chunk ); - l_was_chunks_changed = true; - } - } - - } - if(l_was_chunks_changed){ - dap_chain_block_chunks_sort( PVT(a_blocks)->chunks); - log_it(L_INFO,"Recursive BFT stage additional check..."); - s_bft_consensus_setup(a_blocks); - } -} - static void s_select_longest_branch(dap_chain_cs_blocks_t * a_blocks, dap_chain_block_cache_t * a_bcache, uint64_t a_main_branch_length, dap_chain_cell_t *a_cell) { dap_chain_cs_blocks_t * l_blocks = a_blocks;