diff --git a/modules/chain/dap_chain_ch.c b/modules/chain/dap_chain_ch.c index 2408af9abd05bc29689d681c52ce0cc5aef608da..344e252e3859b870250a42430c332dddda522b6d 100644 --- a/modules/chain/dap_chain_ch.c +++ b/modules/chain/dap_chain_ch.c @@ -645,6 +645,7 @@ static bool s_sync_in_chains_callback(void *a_arg) } case ATOM_FORK: { debug_if(s_debug_more, L_WARNING, "Atom with hash %s for %s:%s added to a fork branch.", l_atom_hash_str, l_chain->net_name, l_chain->name); + l_ack_send = true; break; } default: diff --git a/modules/consensus/esbocs/dap_chain_cs_esbocs.c b/modules/consensus/esbocs/dap_chain_cs_esbocs.c index 4f2d2489069bc7722c9f5d47a45f04be7ce066de..41b5a23e711768a6f353558b87e475f6748fdca0 100644 --- a/modules/consensus/esbocs/dap_chain_cs_esbocs.c +++ b/modules/consensus/esbocs/dap_chain_cs_esbocs.c @@ -78,7 +78,7 @@ static int s_callback_new(dap_chain_t *a_chain, dap_config_t *a_chain_cfg); static void s_callback_delete(dap_chain_cs_blocks_t *a_blocks); static int s_callback_created(dap_chain_t *a_chain, dap_config_t *a_chain_net_cfg); static size_t s_callback_block_sign(dap_chain_cs_blocks_t *a_blocks, dap_chain_block_t **a_block_ptr, size_t a_block_size); -static int s_callback_block_verify(dap_chain_cs_blocks_t *a_blocks, dap_chain_block_t *a_block, size_t a_block_size); +static int s_callback_block_verify(dap_chain_cs_blocks_t *a_blocks, dap_chain_block_t *a_block, dap_hash_fast_t *a_block_hash, size_t a_block_size); static void s_db_change_notifier(dap_store_obj_t *a_obj, void * a_arg); static dap_list_t *s_check_emergency_rights(dap_chain_esbocs_t *a_esbocs, dap_chain_addr_t *a_signing_addr); static int s_cli_esbocs(int a_argc, char **a_argv, void **a_str_reply); @@ -2783,42 +2783,29 @@ static uint64_t s_get_precached_key_hash(struct precached_key **a_precached_keys return 0; } -static int s_callback_block_verify(dap_chain_cs_blocks_t *a_blocks, dap_chain_block_t *a_block, size_t a_block_size) +static int s_callback_block_verify(dap_chain_cs_blocks_t *a_blocks, dap_chain_block_t *a_block, dap_hash_fast_t *a_block_hash, size_t a_block_size) { dap_chain_esbocs_t *l_esbocs = DAP_CHAIN_ESBOCS(a_blocks); dap_chain_esbocs_pvt_t *l_esbocs_pvt = PVT(l_esbocs); - if (sizeof(a_block->hdr) >= a_block_size) { - log_it(L_WARNING, "Incorrect header size with block %p on chain %s", a_block, a_blocks->chain->name); - return -7; - } - size_t l_offset = dap_chain_block_get_sign_offset(a_block, a_block_size); - if (!l_offset) { - log_it(L_WARNING, "Block with size %zu parsing error", a_block_size); - return -5; - } - if ((a_block->hdr.meta_n_datum_n_signs_size > l_offset || a_block->hdr.version == 2) && - a_block->hdr.meta_n_datum_n_signs_size != a_block_size - sizeof(a_block->hdr)) { - log_it(L_WARNING, "Incorrect size with block %p on chain %s", a_block, a_blocks->chain->name); - return -8; - } - if (l_esbocs->session && l_esbocs->session->processing_candidate == a_block) // It's a block candidate, don't check signs - return 0; - + return a_block->hdr.version > 1 ? 0 : -3; + size_t l_block_size = a_block_size; // /* Can't calc it for many old bugged blocks */ dap_chain_block_get_size(a_block); size_t l_signs_count = 0; + size_t l_offset = dap_chain_block_get_sign_offset(a_block, l_block_size); dap_sign_t **l_signs = dap_sign_get_unique_signs(a_block->meta_n_datum_n_sign+l_offset, - a_block_size-sizeof(a_block->hdr)-l_offset, &l_signs_count); + l_block_size-sizeof(a_block->hdr)-l_offset, &l_signs_count); if (!l_signs_count){ - log_it(L_ERROR, "No any signatures at all for block"); + log_it(L_ERROR, "No any signatures at all for block %s", dap_hash_fast_to_str_static(a_block_hash)); DAP_DELETE(l_signs); return -2; } if (l_signs_count < l_esbocs_pvt->min_validators_count) { - log_it(L_ERROR, "Corrupted block: not enough signs: %zu of %hu", l_signs_count, l_esbocs_pvt->min_validators_count); + log_it(L_ERROR, "Corrupted block %s: not enough signs: %zu of %hu", dap_hash_fast_to_str_static(a_block_hash), + l_signs_count, l_esbocs_pvt->min_validators_count); DAP_DELETE(l_signs); return -1; } @@ -2826,60 +2813,73 @@ static int s_callback_block_verify(dap_chain_cs_blocks_t *a_blocks, dap_chain_bl // Parse the rest signs int l_ret = 0; uint16_t l_signs_verified_count = 0; - size_t l_block_excl_sign_size = dap_chain_block_get_sign_offset(a_block, a_block_size) + sizeof(a_block->hdr); - bool l_block_is_emergency = s_block_is_emergency(a_block, a_block_size); + size_t l_block_excl_sign_size = dap_chain_block_get_sign_offset(a_block, l_block_size) + sizeof(a_block->hdr); + bool l_block_is_emergency = s_block_is_emergency(a_block, l_block_size); // Get the header on signing operation time size_t l_block_original = a_block->hdr.meta_n_datum_n_signs_size; a_block->hdr.meta_n_datum_n_signs_size = l_block_excl_sign_size - sizeof(a_block->hdr); for (size_t i = 0; i < l_signs_count; i++) { dap_sign_t *l_sign = l_signs[i]; - if (!dap_sign_verify_size(l_sign, a_block_size - l_block_excl_sign_size + sizeof(a_block->hdr))) { - log_it(L_ERROR, "Corrupted block: sign size is bigger than block size"); - l_ret = -3; - break; - } dap_chain_addr_t l_signing_addr = { .net_id = a_blocks->chain->net_id }; s_get_precached_key_hash(&l_esbocs_pvt->precached_keys, l_sign, &l_signing_addr.data.hash_fast); if (!l_esbocs_pvt->poa_mode) { // Compare signature with delegated keys if (!dap_chain_net_srv_stake_key_delegated(&l_signing_addr)) { - debug_if(l_esbocs_pvt->debug, L_ATT, "Unknown PoS signer %s", - dap_chain_hash_fast_to_str_static(&l_signing_addr.data.hash_fast)); + if (l_esbocs_pvt->debug) { + char l_block_hash_str[DAP_HASH_FAST_STR_SIZE]; + dap_hash_fast_to_str(a_block_hash, l_block_hash_str, DAP_HASH_FAST_STR_SIZE); + log_it(L_ATT, "Unknown PoS signer %s for block %s", dap_hash_fast_to_str_static(&l_signing_addr.data.hash_fast), l_block_hash_str); + } continue; } } else { // Compare signature with auth_certs if (!s_validator_check(&l_signing_addr, l_esbocs_pvt->poa_validators)) { - debug_if(l_esbocs_pvt->debug, L_ATT, "Unknown PoA signer %s", - dap_chain_hash_fast_to_str_static(&l_signing_addr.data.hash_fast)); + if (l_esbocs_pvt->debug) { + char l_block_hash_str[DAP_HASH_FAST_STR_SIZE]; + dap_hash_fast_to_str(a_block_hash, l_block_hash_str, DAP_HASH_FAST_STR_SIZE); + log_it(L_ATT, "Unknown PoA signer %s for block %s", dap_hash_fast_to_str_static(&l_signing_addr.data.hash_fast), l_block_hash_str); + } continue; } } if (i == 0) { if (l_block_is_emergency && !s_check_emergency_rights(l_esbocs, &l_signing_addr)) { - log_it(L_ATT, "Restricted emergency block submitter %s", - dap_chain_hash_fast_to_str_static(&l_signing_addr.data.hash_fast)); + if (l_esbocs_pvt->debug) { + char l_block_hash_str[DAP_HASH_FAST_STR_SIZE]; + dap_hash_fast_to_str(a_block_hash, l_block_hash_str, DAP_HASH_FAST_STR_SIZE); + log_it(L_ATT, "Restricted emergency block submitter %s for block %s", dap_hash_fast_to_str_static(&l_signing_addr.data.hash_fast), l_block_hash_str); + } l_ret = -5; break; } else if (l_esbocs_pvt->check_signs_structure && - !s_check_signing_rights(l_esbocs, a_block, a_block_size, &l_signing_addr, true)) { - log_it(L_ATT, "Restricted block submitter %s", - dap_chain_hash_fast_to_str_static(&l_signing_addr.data.hash_fast)); + !s_check_signing_rights(l_esbocs, a_block, l_block_size, &l_signing_addr, true)) { + if (l_esbocs_pvt->debug) { + char l_block_hash_str[DAP_HASH_FAST_STR_SIZE]; + dap_hash_fast_to_str(a_block_hash, l_block_hash_str, DAP_HASH_FAST_STR_SIZE); + log_it(L_ATT, "Restricted block submitter %s for block %s", dap_hash_fast_to_str_static(&l_signing_addr.data.hash_fast), l_block_hash_str); + } l_ret = -5; break; } } else { if (l_block_is_emergency && !s_check_emergency_rights(l_esbocs, &l_signing_addr) && l_esbocs_pvt->check_signs_structure && - !s_check_signing_rights(l_esbocs, a_block, a_block_size, &l_signing_addr, false)) { - log_it(L_ATT, "Restricted emergency block signer %s", - dap_chain_hash_fast_to_str_static(&l_signing_addr.data.hash_fast)); + !s_check_signing_rights(l_esbocs, a_block, l_block_size, &l_signing_addr, false)) { + if (l_esbocs_pvt->debug) { + char l_block_hash_str[DAP_HASH_FAST_STR_SIZE]; + dap_hash_fast_to_str(a_block_hash, l_block_hash_str, DAP_HASH_FAST_STR_SIZE); + log_it(L_ATT, "Restricted emergency block signer %s for block %s", dap_hash_fast_to_str_static(&l_signing_addr.data.hash_fast), l_block_hash_str); + } l_ret = -5; break; } else if (l_esbocs_pvt->check_signs_structure && - !s_check_signing_rights(l_esbocs, a_block, a_block_size, &l_signing_addr, false)) { - log_it(L_ATT, "Restricted block signer %s", - dap_chain_hash_fast_to_str_static(&l_signing_addr.data.hash_fast)); + !s_check_signing_rights(l_esbocs, a_block, l_block_size, &l_signing_addr, false)) { + if (l_esbocs_pvt->debug) { + char l_block_hash_str[DAP_HASH_FAST_STR_SIZE]; + dap_hash_fast_to_str(a_block_hash, l_block_hash_str, DAP_HASH_FAST_STR_SIZE); + log_it(L_ATT, "Restricted block signer %s for block %s", dap_hash_fast_to_str_static(&l_signing_addr.data.hash_fast), l_block_hash_str); + } l_ret = -5; break; } @@ -2892,12 +2892,8 @@ static int s_callback_block_verify(dap_chain_cs_blocks_t *a_blocks, dap_chain_bl a_block->hdr.meta_n_datum_n_signs_size = l_block_original; if (l_signs_verified_count < l_esbocs_pvt->min_validators_count) { - dap_hash_fast_t l_block_hash; - dap_hash_fast(a_block, a_block_size, &l_block_hash); - char l_block_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE]; - dap_hash_fast_to_str(&l_block_hash, l_block_hash_str, DAP_CHAIN_HASH_FAST_STR_SIZE); debug_if(l_esbocs_pvt->debug, L_ERROR, "Corrupted block %s: not enough authorized signs: %u of %u", - l_block_hash_str, l_signs_verified_count, l_esbocs_pvt->min_validators_count); + dap_hash_fast_to_str_static(a_block_hash), l_signs_verified_count, l_esbocs_pvt->min_validators_count); return l_ret ? l_ret : -4; } return 0; diff --git a/modules/type/blocks/dap_chain_block.c b/modules/type/blocks/dap_chain_block.c index f1c6c7e8dc191cba147f4a8941bbf184e2125020..181a53bf6dc83679a356af312e0fa348937e61dd 100644 --- a/modules/type/blocks/dap_chain_block.c +++ b/modules/type/blocks/dap_chain_block.c @@ -103,23 +103,29 @@ dap_chain_block_t *dap_chain_block_new(dap_chain_hash_fast_t *a_prev_block, size */ size_t s_block_get_datum_offset(const dap_chain_block_t *a_block, size_t a_block_size) { - if( a_block_size < sizeof(a_block->hdr) ){ - log_it(L_ERROR, "Can't get datum offset: corrupted block size %zu / header size %zu", a_block_size, sizeof (a_block->hdr)); + assert(a_block && a_block_size); + if (a_block_size < sizeof(a_block->hdr)) { + log_it(L_ERROR, "Can't get datum offset: corrupted block size %zu / header size %zu", a_block_size, sizeof(a_block->hdr)); return 0; } size_t l_offset = 0; - dap_chain_block_meta_t * l_meta=NULL; - for( size_t i = 0; i< a_block->hdr.meta_count && - l_offset < (a_block_size-sizeof (a_block->hdr)) && - sizeof (l_meta->hdr) <= (a_block_size-sizeof (a_block->hdr)) - l_offset ; i++){ - l_meta =(dap_chain_block_meta_t *) (a_block->meta_n_datum_n_sign +l_offset); + dap_chain_block_meta_t *l_meta = NULL; + for (size_t i = 0; i < a_block->hdr.meta_count; i++) { + if (sizeof(a_block->hdr) + l_offset + sizeof(dap_chain_block_meta_t) > a_block_size) + return 0; + if (l_offset + sizeof(dap_chain_block_meta_t) < l_offset) + return 0; + l_meta = (dap_chain_block_meta_t *)(a_block->meta_n_datum_n_sign + l_offset); + l_offset += sizeof(dap_chain_block_meta_t); size_t l_meta_data_size = l_meta->hdr.data_size; - if (l_meta_data_size + sizeof (l_meta->hdr) + l_offset <= (a_block_size-sizeof (a_block->hdr)) ){ - l_offset += sizeof (l_meta->hdr); - l_offset += l_meta_data_size; - }else - l_offset = (a_block_size-sizeof (a_block->hdr)); + if (sizeof(a_block->hdr) + l_offset + l_meta_data_size > a_block_size) + return 0; + if (l_offset + l_meta_data_size < l_offset) + return 0; + l_offset += l_meta_data_size; } + if (sizeof(a_block->hdr) + l_offset > a_block_size) + return 0; return l_offset; } @@ -133,10 +139,8 @@ size_t s_block_get_datum_offset(const dap_chain_block_t *a_block, size_t a_block */ size_t dap_chain_block_datum_add(dap_chain_block_t ** a_block_ptr, size_t a_block_size, dap_chain_datum_t * a_datum, size_t a_datum_size) { - assert(a_block_ptr); - dap_chain_block_t * l_block = *a_block_ptr; - assert(l_block); - assert(a_datum_size); + dap_chain_block_t *l_block = *a_block_ptr; + dap_return_val_if_fail(l_block && a_block_size && a_datum && a_datum_size, a_block_size); size_t l_offset = s_block_get_datum_offset(l_block,a_block_size); dap_chain_datum_t * l_datum =(dap_chain_datum_t *) (l_block->meta_n_datum_n_sign + l_offset); // Pass all datums to the end @@ -167,7 +171,7 @@ size_t dap_chain_block_datum_add(dap_chain_block_t ** a_block_ptr, size_t a_bloc *a_block_ptr = l_block = DAP_REALLOC(l_block, sizeof(l_block->hdr) + l_offset + a_datum_size); if (!l_block) { log_it(L_CRITICAL, "Memory reallocation error"); - return 0; + return a_block_size; } memcpy(l_block->meta_n_datum_n_sign + l_offset, a_datum, a_datum_size); l_offset += a_datum_size; @@ -248,38 +252,26 @@ size_t dap_chain_block_datum_del_by_hash(dap_chain_block_t ** a_block_ptr, size_ */ size_t dap_chain_block_get_sign_offset(const dap_chain_block_t *a_block, size_t a_block_size) { - assert(a_block); - assert(a_block_size); + dap_return_val_if_fail(a_block && a_block_size, 0); if (a_block_size <= sizeof(a_block->hdr)) { log_it(L_ERROR, "Get sign: corrupted block, block size %zd is lesser than block header size %zd", a_block_size,sizeof (a_block->hdr)); return 0; } - size_t l_offset = s_block_get_datum_offset(a_block, a_block_size); - dap_chain_datum_t * l_datum =(dap_chain_datum_t *) (a_block->meta_n_datum_n_sign + l_offset); // Pass all datums to the end - for(size_t n=0; n<a_block->hdr.datum_count && l_offset< (a_block_size-sizeof (a_block->hdr)) ; n++){ - size_t l_datum_size = dap_chain_datum_size(l_datum); - - // Check if size 0 - if(! l_datum_size){ - log_it(L_ERROR,"Datum size is 0, smth is corrupted in block"); + for (size_t n = 0; n < a_block->hdr.datum_count; n++) { + if (sizeof(a_block->hdr) + l_offset + sizeof(dap_chain_datum_t) > a_block_size) return 0; - } - // Check if size of of block size - if ( (l_datum_size+l_offset) > (a_block_size-sizeof (a_block->hdr)) ){ - log_it(L_ERROR,"Datum size is too big %zu thats with offset %zu is bigger than block size %zu", l_datum_size, l_offset, a_block_size); + dap_chain_datum_t *l_datum =(dap_chain_datum_t *)(a_block->meta_n_datum_n_sign + l_offset); + size_t l_datum_size = dap_chain_datum_size(l_datum); + if (l_offset + l_datum_size <= l_offset) return 0; - } l_offset += l_datum_size; - // Updae current datum pointer, if it was deleted - we also need to update it after realloc - l_datum =(dap_chain_datum_t *) (a_block->meta_n_datum_n_sign + l_offset); } - if (l_offset> (a_block_size-sizeof (a_block->hdr))){ - log_it(L_ERROR,"Offset %zd with block header %zu is bigger than block size %zu", l_offset,sizeof (a_block->hdr),a_block_size); + if (sizeof(a_block->hdr) + l_offset > a_block_size) { + log_it(L_ERROR, "Offset %zd with block header %zu is bigger than block size %zu", l_offset, sizeof(a_block->hdr), a_block_size); return 0; } - return l_offset; } @@ -345,7 +337,7 @@ size_t dap_chain_block_get_signs_count(const dap_chain_block_t * a_block, size_t assert(a_block_size); uint16_t l_sign_count = 0; size_t l_offset = dap_chain_block_get_sign_offset(a_block,a_block_size); - for ( ; l_offset+sizeof(a_block->hdr) < a_block_size; l_sign_count++) { + for ( ; l_offset + sizeof(a_block->hdr) + sizeof(dap_sign_t) < a_block_size; l_sign_count++) { dap_sign_t *l_sign = (dap_sign_t *)(a_block->meta_n_datum_n_sign + l_offset); size_t l_sign_size = dap_sign_get_size(l_sign); if (!l_sign_size){ @@ -356,6 +348,8 @@ size_t dap_chain_block_get_signs_count(const dap_chain_block_t * a_block, size_t log_it(L_ERROR, "Corrupted sign #%hu size %zu", l_sign_count, l_sign_size); return l_sign_count; } + if (l_offset + l_sign_size <= l_offset) + return l_sign_count; l_offset += l_sign_size; } return l_sign_count; @@ -365,15 +359,15 @@ bool dap_chain_block_sign_match_pkey(const dap_chain_block_t *a_block, size_t a_ { dap_return_val_if_fail(a_block && a_block_size, false); size_t l_offset = dap_chain_block_get_sign_offset(a_block, a_block_size); - while (l_offset + sizeof(a_block->hdr) < a_block_size) { + while (l_offset + sizeof(a_block->hdr) + sizeof(dap_sign_t) < a_block_size) { dap_sign_t *l_sign = (dap_sign_t *)(a_block->meta_n_datum_n_sign + l_offset); size_t l_sign_size = dap_sign_get_size(l_sign); - if (!l_sign_size) { - log_it(L_WARNING, "Empty or corrupted sign"); + if (!l_sign_size || l_sign_size + l_offset + sizeof(a_block->hdr) > a_block_size) return false; - } if (dap_pkey_compare_with_sign(a_sign_pkey, l_sign)) return true; + if (l_offset + l_sign_size < l_offset) + return false; l_offset += l_sign_size; } return false; diff --git a/modules/type/blocks/dap_chain_block_chunk.c b/modules/type/blocks/dap_chain_block_chunk.c deleted file mode 100644 index 697a99523b062e6a7c61a392aa4799da611426c7..0000000000000000000000000000000000000000 --- a/modules/type/blocks/dap_chain_block_chunk.c +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Authors: - * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net> - * DeM Labs Ltd https://demlabs.net - * Copyright (c) 2020 - * All rights reserved. - - This file is part of DAP SDK the open source project - - DAP SDK is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - DAP SDK is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with any DAP SDK based project. If not, see <http://www.gnu.org/licenses/>. -*/ -#include "dap_common.h" -#include "dap_strfuncs.h" -#include "dap_global_db.h" -#include "dap_chain_block_chunk.h" - -#define LOG_TAG "dap_chain_block_chunk" - -/** - * @brief dap_chain_block_chunks_create - * @param a_blocks - * @return - */ -dap_chain_block_chunks_t * dap_chain_block_chunks_create(dap_chain_cs_blocks_t * a_blocks) -{ - assert(a_blocks); - assert(a_blocks->chain); - dap_chain_block_chunks_t * l_ret = DAP_NEW_Z(dap_chain_block_chunks_t); - if (!l_ret) { - log_it(L_CRITICAL, "%s", c_error_memory_alloc); - return NULL; - } - l_ret->blocks = a_blocks; - l_ret->gdb_group = dap_strdup_printf("local.%s.%s.block.chunks",a_blocks->chain->net_name, a_blocks->chain->name ); - - size_t l_objs_count =0; - dap_global_db_obj_t * l_objs= dap_global_db_get_all_sync(l_ret->gdb_group, &l_objs_count); - for(size_t n=0; n< l_objs_count; n++){ - dap_hash_fast_t l_block_hash; - dap_chain_hash_fast_from_str(l_objs[n].key, &l_block_hash); - dap_chain_block_cache_t *l_block_cache = dap_chain_block_cache_new(&l_block_hash, (dap_chain_block_t *)l_objs[n].value, l_objs[n].value_len, n + 1, true); - dap_chain_block_chunks_add(l_ret, l_block_cache ); - } - dap_global_db_objs_delete(l_objs,l_objs_count); - return l_ret; -} - -/** - * @brief dap_chain_block_chunks_delete - * @param a_chunks - */ -void dap_chain_block_chunks_delete(dap_chain_block_chunks_t * a_chunks) -{ - dap_chain_block_cache_hash_t *l_block_cache_hash, *l_block_cache_hash_tmp; - for (dap_chain_block_chunk_t *l_chunk = a_chunks->chunks_last; l_chunk; l_chunk = l_chunk->prev) { - HASH_ITER(hh, l_chunk->block_cache_hash , l_block_cache_hash, l_block_cache_hash_tmp){ - HASH_DEL(l_chunk->block_cache_hash, l_block_cache_hash); - DAP_DELETE(l_block_cache_hash); - } - } - dap_chain_block_cache_t* l_block_cache, *l_block_cache_tmp = NULL; - HASH_ITER(hh, a_chunks->cache , l_block_cache, l_block_cache_tmp) { - HASH_DEL(a_chunks->cache, l_block_cache); - dap_chain_block_cache_delete(l_block_cache); - } - DAP_DELETE(a_chunks->gdb_group); - DAP_DELETE(a_chunks); -} - - -/** - * @brief dap_chain_block_chunks_add - * @param a_chunks - * @param a_block_cache - * @return - */ -void dap_chain_block_chunks_add(dap_chain_block_chunks_t * a_chunks,dap_chain_block_cache_t * a_block_cache) -{ - if (!a_block_cache) - return; - dap_chain_block_cache_hash_t * l_chunk_cache_hash = NULL; - dap_chain_block_cache_t * l_chunk_cache = NULL; - // Parse block and produce cache object - // Check if already present - HASH_FIND(hh, a_chunks->cache, &a_block_cache->block_hash, sizeof(dap_chain_hash_fast_t), l_chunk_cache); - if (l_chunk_cache){ - log_it(L_WARNING, "Already present block %s in cache",a_block_cache->block_hash_str); - dap_chain_block_cache_delete(a_block_cache); - return; - } - // Save to GDB - //dap_global_db_set(a_chunks->gdb_group, a_block_cache->block_hash_str, a_block_cache->block, a_block_cache->block_size, - // false, NULL, NULL ); - - // And here we select chunk for the new block cache - bool l_is_chunk_found = false; - for (dap_chain_block_chunk_t * l_chunk = a_chunks->chunks_last; l_chunk; l_chunk = l_chunk->prev ){ - if(dap_hash_fast_compare(&l_chunk->block_cache_top->block_hash, &a_block_cache->prev_hash ) ){ - // Init cache-hash object - l_chunk_cache_hash = DAP_NEW_Z(dap_chain_block_cache_hash_t); - if (!l_chunk_cache_hash) { - log_it(L_CRITICAL, "%s", c_error_memory_alloc); - return; - } - l_chunk_cache_hash->block_cache=a_block_cache; - l_chunk_cache_hash->ts_created = time(NULL); - l_chunk_cache_hash->block_hash = a_block_cache->block_hash; - l_chunk_cache_hash->chunk = l_chunk; - - // Update first block cache from the head - l_chunk->block_cache_top = a_block_cache; - // Add to selected chunk its hash object - HASH_ADD(hh,l_chunk->block_cache_hash , block_hash, sizeof (l_chunk_cache_hash->block_hash), l_chunk_cache_hash); - - // Update chunk id to make it unique - dap_chain_hash_fast_t l_hash_new_data[2]={a_block_cache->block_hash,l_chunk->chunk_id }; - dap_hash_fast(l_hash_new_data,sizeof (l_hash_new_data),&l_chunk->chunk_id); - l_is_chunk_found = true; - } - } - - if ( ! l_is_chunk_found ) { // Don't found anything suitable - if so we create our own chunk - dap_chain_block_chunk_t * l_chunk = dap_chain_block_chunk_create(a_chunks); - - // Init cache-hash object - l_chunk_cache_hash = DAP_NEW_Z(dap_chain_block_cache_hash_t); - if (!l_chunk_cache_hash) { - log_it(L_CRITICAL, "%s", c_error_memory_alloc); - return; - } - l_chunk_cache_hash->block_cache=a_block_cache; - l_chunk_cache_hash->ts_created = time(NULL); - l_chunk_cache_hash->block_hash = a_block_cache->block_hash; - l_chunk_cache_hash->chunk = l_chunk; - - // Update first block cache from the head - l_chunk->block_cache_top = a_block_cache; - // Add to selected chunk its hash object - HASH_ADD(hh,l_chunk->block_cache_hash , block_hash, sizeof (l_chunk_cache_hash->block_hash), l_chunk_cache_hash); - - // Update chunk id to make it unique - dap_chain_hash_fast_t l_hash_new_data[2]={a_block_cache->block_hash,l_chunk->chunk_id }; - dap_hash_fast(l_hash_new_data,sizeof (l_hash_new_data),&l_chunk->chunk_id); - } - - - // Add object itself to all-chunks cache - HASH_ADD(hh,a_chunks->cache ,block_hash ,sizeof (a_block_cache->block_hash), a_block_cache); -} - -/** - * @brief dap_chain_block_chunk_create - * @param a_chunks - * @return - */ -dap_chain_block_chunk_t * dap_chain_block_chunk_create(dap_chain_block_chunks_t * a_chunks) -{ - dap_chain_block_chunk_t * l_chunk = DAP_NEW_Z(dap_chain_block_chunk_t); - if (!l_chunk) { - log_it(L_CRITICAL, "%s", c_error_memory_alloc); - return NULL; - } - // Add in tail - l_chunk->prev = a_chunks->chunks_first; - if (a_chunks->chunks_first){ - l_chunk->next = a_chunks->chunks_first->next; - if (! l_chunk->next) - a_chunks->chunks_last = l_chunk; - else - l_chunk->next->prev = l_chunk; - }else - a_chunks->chunks_last = l_chunk; - a_chunks->chunks_first = l_chunk; - return l_chunk; -} - -/** - * @brief dap_chain_block_chunk_delete - * @param a_chunk - */ -void dap_chain_block_chunk_delete( dap_chain_block_chunk_t * a_chunk) -{ - dap_chain_block_cache_hash_t * l_cache_hash = NULL, *l_tmp = NULL; - HASH_ITER(hh, a_chunk->block_cache_hash, l_cache_hash, l_tmp){ - // Clang bug at this, l_cache_hash should change at every loop cycle - HASH_DEL(a_chunk->block_cache_hash, l_cache_hash); - DAP_DELETE(l_cache_hash); - } - DAP_DELETE(a_chunk); -} - -/** - * @brief dap_chain_block_chunks_sort - * @param a_chunks - */ -void dap_chain_block_chunks_sort(dap_chain_block_chunks_t * a_chunks) -{ - // Sort chunk list beginning from the new one and bubble up the longest one on the top - size_t l_chunk_length_max=0; - //dap_chain_block_chunk_t * l_chunk_max = NULL; - for (dap_chain_block_chunk_t * l_chunk = a_chunks->chunks_first ; l_chunk; l_chunk = l_chunk? l_chunk->next: NULL ){ - if(!l_chunk) - break; - size_t l_chunk_length = HASH_COUNT(l_chunk->block_cache_hash); - if (! l_chunk_length){ - log_it(L_WARNING,"Chunk can't be empty, it must be deleted from chunks treshold"); - } - if (l_chunk_length > l_chunk_length_max ){ - //l_chunk_max = l_chunk; - l_chunk_length_max = l_chunk_length; - }else if (l_chunk_length == l_chunk_length_max ){ - continue; - }else{ - // Prev store - dap_chain_block_chunk_t * l_chunk_prev = l_chunk->prev; - - // Link next with prev - if (l_chunk->next ) - l_chunk->next->prev = l_chunk->prev; - - dap_chain_block_chunk_t * l_chunk_prev_prev = NULL; - - if (l_chunk_prev){ - // Link prev with next - l_chunk_prev->next = l_chunk->next; - l_chunk_prev_prev = l_chunk_prev->prev; - // Link prev with current - l_chunk_prev->prev = l_chunk; - // Update first chunks - if ( ! l_chunk_prev_prev) - a_chunks->chunks_first = l_chunk; - } - - // Link current with prev - l_chunk->next = l_chunk->prev ; - l_chunk->prev = l_chunk_prev_prev; - - // Replace previous with current - l_chunk = l_chunk_prev; - - // Its the last chunk - if (l_chunk && ! l_chunk->next) - a_chunks->chunks_last = l_chunk; - } - } - log_it(L_INFO,"Chunks sorted: max tail %zd", l_chunk_length_max ); - -} diff --git a/modules/type/blocks/dap_chain_cs_blocks.c b/modules/type/blocks/dap_chain_cs_blocks.c index ea48d44a6ae9abfa95c2a993ff7cf133baf866c2..79b7469c6198db17eae8ac0c52ed880590025a31 100644 --- a/modules/type/blocks/dap_chain_cs_blocks.c +++ b/modules/type/blocks/dap_chain_cs_blocks.c @@ -28,8 +28,6 @@ #include "dap_chain_cs_blocks.h" #include "dap_chain_block.h" #include "dap_chain_block_cache.h" -#include "dap_chain_block_chunk.h" -#include "dap_timerfd.h" #include "dap_cli_server.h" #include "dap_chain_node_cli_cmd.h" #include "dap_chain_mempool.h" @@ -52,34 +50,29 @@ struct cs_blocks_hal_item { UT_hash_handle hh; }; -typedef struct dap_chain_cs_blocks_pvt -{ +typedef struct dap_chain_cs_blocks_pvt { // Parent link - dap_chain_cs_blocks_t * cs_blocks; + dap_chain_cs_blocks_t *cs_blocks; - // All the blocks are here. In feature should be limited with 1000 when the rest would be loaded from file when needs them - dap_chain_block_cache_t * blocks; + // All the blocks are here + dap_chain_block_cache_t *blocks; + _Atomic uint64_t blocks_count; + // Brnches and forks 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 + // Datum search in blocks + dap_chain_block_datum_index_t *datum_index; pthread_rwlock_t datums_rwlock; + _Atomic uint64_t tx_count; dap_chain_hash_fast_t genesis_block_hash; dap_chain_hash_fast_t static_genesis_block_hash; - _Atomic uint64_t blocks_count; - - time_t time_between_blocks_minimum; // Minimal time between blocks bool is_celled; - dap_timerfd_t *fill_timer; - uint64_t fill_timeout; - pthread_rwlock_t rwlock; struct cs_blocks_hal_item *hal; } dap_chain_cs_blocks_pvt_t; @@ -154,7 +147,9 @@ static dap_chain_block_t *s_new_block_move(dap_chain_cs_blocks_t *a_blocks, size //Work with atoms static uint64_t s_callback_count_atom(dap_chain_t *a_chain); static dap_list_t *s_callback_get_atoms(dap_chain_t *a_chain, size_t a_count, size_t a_page, bool a_reverse); - +// Get TXs callbacks +static uint64_t s_callback_count_txs(dap_chain_t *a_chain); +static dap_list_t *s_callback_get_txs(dap_chain_t *a_chain, size_t a_count, size_t a_page, bool a_reverse); static int s_chain_cs_blocks_new(dap_chain_t * a_chain, dap_config_t * a_chain_config); static bool s_seed_mode = false; @@ -297,6 +292,9 @@ static int s_chain_cs_blocks_new(dap_chain_t *a_chain, dap_config_t *a_chain_con a_chain->callback_count_atom = s_callback_count_atom; a_chain->callback_get_atoms = s_callback_get_atoms; + a_chain->callback_count_tx = s_callback_count_txs; + a_chain->callback_get_txs = s_callback_get_txs; + l_cs_blocks->callback_new_block_move = s_new_block_move; @@ -317,7 +315,7 @@ static int s_chain_cs_blocks_new(dap_chain_t *a_chain, dap_config_t *a_chain_con log_it( L_ERROR, "Can't read hash from genesis_block \"%s\", ret code %d ", l_genesis_blocks_hash_str, lhr); } } - l_cs_blocks_pvt->is_celled = dap_config_get_item_bool_default(a_chain_config,"blocks","is_celled",false); + l_cs_blocks_pvt->is_celled = dap_config_get_item_bool_default(a_chain_config, "blocks", "is_celled", false); const char * l_static_genesis_blocks_hash_str = dap_config_get_item_str_default(a_chain_config,"blocks","static_genesis_block",NULL); if ( l_static_genesis_blocks_hash_str ){ int lhr; @@ -325,10 +323,6 @@ static int s_chain_cs_blocks_new(dap_chain_t *a_chain, dap_config_t *a_chain_con log_it( L_ERROR, "Can't read hash from static_genesis_block \"%s\", ret code %d ", l_static_genesis_blocks_hash_str, lhr); } } - l_cs_blocks_pvt->chunks = dap_chain_block_chunks_create(l_cs_blocks); - - l_cs_blocks_pvt->fill_timeout = dap_config_get_item_uint64_default(a_chain_config, "blocks", "fill_timeout", 60) * 1000; // 1 min - l_cs_blocks_pvt->blocks_count = 0; uint16_t l_list_len = 0; const char **l_hard_accept_list = dap_config_get_array_str(a_chain_config, "blocks", "hard_accept_list", &l_list_len); @@ -1417,7 +1411,6 @@ static void s_callback_delete(dap_chain_t * a_chain) 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); log_it(L_INFO, "Block destructed"); @@ -1458,11 +1451,7 @@ static void s_callback_cs_blocks_purge(dap_chain_t *a_chain) l_datum_index = NULL; } pthread_rwlock_unlock(&PVT(l_blocks)->datums_rwlock); - - dap_chain_block_chunks_delete(PVT(l_blocks)->chunks); dap_chain_cell_delete_all(a_chain); - //dap_chain_cell_delete_all_and_free_file(a_chain); - PVT(l_blocks)->chunks = dap_chain_block_chunks_create(l_blocks); } /** @@ -1494,6 +1483,8 @@ static int s_add_atom_datums(dap_chain_cs_blocks_t *a_blocks, dap_chain_block_ca dap_hash_fast_t *l_datum_hash = a_block_cache->datum_hash + i; int l_res = dap_chain_datum_add(a_blocks->chain, l_datum, l_datum_size, l_datum_hash); l_ret++; + if (l_datum->header.type_id == DAP_CHAIN_DATUM_TX) + PVT(a_blocks)->tx_count++; // Save datum hash -> block_hash link in hash table dap_chain_block_datum_index_t *l_datum_index = DAP_NEW_Z(dap_chain_block_datum_index_t); if (!l_datum_index) { @@ -1805,135 +1796,165 @@ static dap_chain_atom_verify_res_t s_callback_atom_add(dap_chain_t * a_chain, da * @param a_atom_size * @return */ -static dap_chain_atom_verify_res_t s_callback_atom_verify(dap_chain_t * a_chain, dap_chain_atom_ptr_t a_atom , size_t a_atom_size, dap_chain_hash_fast_t * a_atom_hash) +static dap_chain_atom_verify_res_t s_callback_atom_verify(dap_chain_t *a_chain, dap_chain_atom_ptr_t a_atom, size_t a_atom_size, dap_chain_hash_fast_t *a_atom_hash) { + dap_return_val_if_fail(a_chain && a_atom && a_atom_size && a_atom_hash, ATOM_REJECT); dap_chain_cs_blocks_t * l_blocks = DAP_CHAIN_CS_BLOCKS(a_chain); assert(l_blocks); - dap_chain_cs_blocks_pvt_t * l_blocks_pvt = PVT(l_blocks); + dap_chain_cs_blocks_pvt_t *l_blocks_pvt = PVT(l_blocks); assert(l_blocks_pvt); - dap_chain_block_t * l_block = (dap_chain_block_t *) a_atom; + dap_chain_block_t * l_block = (dap_chain_block_t *)a_atom; dap_chain_hash_fast_t l_block_hash = *a_atom_hash; - if(sizeof (l_block->hdr) >= a_atom_size){ - log_it(L_WARNING,"Size of block is %zd that is equal or less then block's header size %zd",a_atom_size,sizeof (l_block->hdr)); - return ATOM_REJECT; + if (sizeof(l_block->hdr) >= a_atom_size) { + log_it(L_WARNING, "Size of block %s is %zd that is equal or less then block's header size %zd", + dap_hash_fast_to_str_static(a_atom_hash), a_atom_size, sizeof(l_block->hdr)); + return ATOM_REJECT; } - - // Hard accept list - if (l_blocks_pvt->hal) { + size_t l_offset = dap_chain_block_get_sign_offset(l_block, a_atom_size); + if (!l_offset) { + log_it(L_WARNING, "Block %s with size %zu parsing error", dap_hash_fast_to_str_static(a_atom_hash), a_atom_size); + return ATOM_REJECT; + } + if ((l_block->hdr.version >= 2 || /* Old bug, crutch for it */ l_block->hdr.meta_n_datum_n_signs_size != l_offset) && + l_block->hdr.meta_n_datum_n_signs_size + sizeof(l_block->hdr) != a_atom_size) { + // Hard accept list struct cs_blocks_hal_item *l_hash_found = NULL; HASH_FIND(hh, l_blocks_pvt->hal, &l_block_hash, sizeof(l_block_hash), l_hash_found); - if (l_hash_found) { - return ATOM_ACCEPT; + if (!l_hash_found) { + log_it(L_WARNING, "Incorrect size %zu of block %s, expected %zu", l_block->hdr.meta_n_datum_n_signs_size + sizeof(l_block->hdr), + dap_hash_fast_to_str_static(a_atom_hash), a_atom_size); + return ATOM_REJECT; } } - - if (l_block->hdr.ts_created > dap_time_now() + 60) { - log_it(L_WARNING, "Incorrect block timestamp"); - return ATOM_REJECT; + while (sizeof(l_block->hdr) + l_offset + sizeof(dap_sign_t) < a_atom_size) { + dap_sign_t *l_sign = (dap_sign_t *)((byte_t *)a_atom + sizeof(l_block->hdr) + l_offset); + size_t l_sign_size = dap_sign_get_size(l_sign); + if (l_offset + l_sign_size <= l_offset) + break; + l_offset += l_sign_size; + } + if (l_offset + sizeof(l_block->hdr) != a_atom_size) { + log_it(L_WARNING, "Incorrect size %zu of block %s, expected %zu", l_offset + sizeof(l_block->hdr), + dap_hash_fast_to_str_static(a_atom_hash), a_atom_size); + return ATOM_REJECT; } - // 2nd level consensus - if(l_blocks->callback_block_verify) - if (l_blocks->callback_block_verify(l_blocks, l_block, a_atom_size)){ - debug_if(s_debug_more, L_WARNING, "Block rejected by block verificator."); - return ATOM_REJECT; - } + if (!l_block->hdr.ts_created || l_block->hdr.ts_created > dap_time_now() + 600) { + log_it(L_WARNING, "Incorrect block %s timestamp", dap_hash_fast_to_str_static(a_atom_hash)); + return ATOM_REJECT; + } + int ret = ATOM_MOVE_TO_THRESHOLD; // Parse metadata bool l_is_genesis = dap_chain_block_meta_get(l_block, a_atom_size, DAP_CHAIN_BLOCK_META_GENESIS); - dap_hash_t *l_prev_hash_meta_data = (dap_hash_t *)dap_chain_block_meta_get(l_block, a_atom_size, DAP_CHAIN_BLOCK_META_PREV); - dap_hash_t l_block_prev_hash = l_prev_hash_meta_data ? *l_prev_hash_meta_data : (dap_hash_t){}; - - char* l_block_str = dap_chain_hash_fast_to_str_new(&l_block_hash); - char* l_prev_block_str = dap_chain_hash_fast_to_str_new(&l_block_prev_hash); - - debug_if(s_debug_more, L_DEBUG,"Verify new block with hash %s. previous block %s", l_block_str, l_prev_block_str); - DAP_DELETE(l_block_str); - DAP_DELETE(l_prev_block_str); // genesis or seed mode if (l_is_genesis) { - if (!PVT(l_blocks)->blocks) { + if (PVT(l_blocks)->blocks) { + log_it(L_WARNING, "Can't accept genesis block %s: already present data in blockchain", dap_hash_fast_to_str_static(a_atom_hash)); + return ATOM_REJECT; + } #ifndef DAP_CHAIN_BLOCKS_TEST - if (s_seed_mode) - log_it(L_NOTICE, "Accepting new genesis block"); - - else if(dap_hash_fast_compare(&l_block_hash,&PVT(l_blocks)->static_genesis_block_hash) - && !dap_hash_fast_is_blank(&l_block_hash)) - log_it(L_NOTICE, "Accepting static genesis block"); - else{ - char l_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE] = { '\0' }; - dap_hash_fast_to_str(&l_block_hash, l_hash_str, sizeof(l_hash_str)); - log_it(L_WARNING,"Cant accept genesis block: seed mode not enabled or hash mismatch with static genesis block %s in configuration", l_hash_str); - return ATOM_REJECT; - } + if (s_seed_mode) + log_it(L_NOTICE, "Accepting new genesis block %s", dap_hash_fast_to_str_static(a_atom_hash)); + else if(dap_hash_fast_compare(&l_block_hash, &PVT(l_blocks)->static_genesis_block_hash) + && !dap_hash_fast_is_blank(&l_block_hash)) + log_it(L_NOTICE, "Accepting static genesis block %s", dap_hash_fast_to_str_static(a_atom_hash)); + else { + char l_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE]; + dap_hash_fast_to_str(&PVT(l_blocks)->static_genesis_block_hash, l_hash_str, sizeof(l_hash_str)); + log_it(L_WARNING, "Can't accept genesis block %s: seed mode not enabled or hash mismatch with static genesis block %s in configuration", + dap_hash_fast_to_str_static(a_atom_hash), l_hash_str); + return ATOM_REJECT; + } #else - PVT(l_blocks)->genesis_block_hash = *a_atom_hash; + PVT(l_blocks)->genesis_block_hash = *a_atom_hash; #endif - debug_if(s_debug_more,L_DEBUG,"%s","Accepting new genesis block"); - return ATOM_ACCEPT; - } else { - log_it(L_WARNING,"Cant accept genesis block: already present data in blockchain"); + ret = ATOM_ACCEPT; + } else { + dap_hash_t *l_prev_hash_meta_data = (dap_hash_t *)dap_chain_block_meta_get(l_block, a_atom_size, DAP_CHAIN_BLOCK_META_PREV); + if (!l_prev_hash_meta_data) { + log_it(L_WARNING, "Block %s isn't a genesis one but not contains previous block hash in metadata", dap_hash_fast_to_str_static(a_atom_hash)); return ATOM_REJECT; } - } else { - dap_chain_block_cache_t *l_bcache_last = PVT(l_blocks)->blocks ? PVT(l_blocks)->blocks->hh.tbl->tail->prev : NULL; - l_bcache_last = l_bcache_last ? l_bcache_last->hh.next : PVT(l_blocks)->blocks; - + dap_hash_t l_block_prev_hash = *l_prev_hash_meta_data; + if (s_debug_more) { + char l_prev_block_hash_str[DAP_HASH_FAST_STR_SIZE]; + dap_hash_fast_to_str(&l_block_prev_hash, l_prev_block_hash_str, DAP_HASH_FAST_STR_SIZE); + log_it(L_DEBUG, "Verify new block with hash %s. Previous block hash is %s", dap_hash_fast_to_str_static(a_atom_hash), l_prev_block_hash_str); + } + dap_chain_block_cache_t *l_bcache_last = HASH_LAST(PVT(l_blocks)->blocks); if (l_bcache_last && dap_hash_fast_compare(&l_bcache_last->block_hash, &l_block_prev_hash)) - return ATOM_ACCEPT; - - // search block and previous block in forked branch - pthread_rwlock_rdlock(& PVT(l_blocks)->rwlock); - for (size_t i = 0; i < PVT(l_blocks)->forked_br_cnt; i++){ - dap_chain_block_forked_branch_t *l_cur_branch = PVT(l_blocks)->forked_branches[i]; - dap_chain_block_forked_branch_atoms_table_t *l_item = NULL; - // Check block already present in forked branch - HASH_FIND(hh, l_cur_branch->forked_branch_atoms, &l_block_hash, sizeof(dap_hash_fast_t), l_item); - if (l_item && dap_hash_fast_compare(&l_item->block_hash, &l_block_hash)){ - debug_if(s_debug_more,L_DEBUG,"%s","Block already exist in forked branch."); - pthread_rwlock_unlock(& PVT(l_blocks)->rwlock); - return ATOM_PASS; - } - l_item = NULL; - // Find previous block is last block in current branch - HASH_FIND(hh, l_cur_branch->forked_branch_atoms, &l_block_prev_hash, sizeof(dap_hash_fast_t), l_item); - if (l_item && l_item->hh.next != NULL){ - pthread_rwlock_unlock(& PVT(l_blocks)->rwlock); - debug_if(s_debug_more,L_DEBUG,"%s","Found previous block in forked branch. Can't add block into branch because previous block is not last in the branch."); - return ATOM_PASS; - } else if (l_item && l_item->hh.next == NULL) { - pthread_rwlock_unlock(& PVT(l_blocks)->rwlock); - debug_if(s_debug_more,L_DEBUG,"%s","Accept block to a forked branch."); - return ATOM_ACCEPT; + ret = ATOM_ACCEPT; + else { // search block and previous block in forked branch + pthread_rwlock_rdlock(& PVT(l_blocks)->rwlock); + for (size_t i = 0; i < PVT(l_blocks)->forked_br_cnt; i++){ + dap_chain_block_forked_branch_t *l_cur_branch = PVT(l_blocks)->forked_branches[i]; + dap_chain_block_forked_branch_atoms_table_t *l_item = NULL; + // Check block already present in forked branch + HASH_FIND(hh, l_cur_branch->forked_branch_atoms, &l_block_hash, sizeof(dap_hash_fast_t), l_item); + if (l_item) { + debug_if(s_debug_more,L_DEBUG,"%s","Block already exist in forked branch."); + ret = ATOM_PASS; + break; + } + l_item = NULL; + // Find previous block is last block in current branch + HASH_FIND(hh, l_cur_branch->forked_branch_atoms, &l_block_prev_hash, sizeof(dap_hash_fast_t), l_item); + if (!l_item) + continue; + if (l_item->hh.next) { + debug_if(s_debug_more,L_DEBUG,"%s","Found previous block in forked branch. Can't add block into branch because previous block is not last in the branch."); + ret = ATOM_PASS; + break; + } else { + debug_if(s_debug_more,L_DEBUG,"%s","Accept block to a forked branch."); + ret = ATOM_ACCEPT; + break; + } } - } + if (ret == ATOM_MOVE_TO_THRESHOLD) { + // search block and previous block in main branch + unsigned l_checked_atoms_cnt = DAP_FORK_MAX_DEPTH; + for (dap_chain_block_cache_t *l_tmp = l_bcache_last; l_tmp && l_checked_atoms_cnt; l_tmp = l_tmp->hh.prev, l_checked_atoms_cnt--){ + if(dap_hash_fast_compare(&l_tmp->block_hash, &l_block_hash)){ + debug_if(s_debug_more,L_DEBUG,"%s","Block is already exist in main branch."); + ret = ATOM_PASS; + break; + } - // search block and previous block in main branch - unsigned l_checked_atoms_cnt = DAP_FORK_MAX_DEPTH; - for (dap_chain_block_cache_t *l_tmp = l_bcache_last; l_tmp && l_checked_atoms_cnt; l_tmp = l_tmp->hh.prev, l_checked_atoms_cnt--){ - if(dap_hash_fast_compare(&l_tmp->block_hash, &l_block_hash)){ - pthread_rwlock_unlock(& PVT(l_blocks)->rwlock); - debug_if(s_debug_more,L_DEBUG,"%s","Block is already exist in main branch."); - return ATOM_PASS; + if (dap_hash_fast_compare(&l_tmp->block_hash, &l_block_prev_hash)) { + if (l_tmp->hh.next) { + debug_if(s_debug_more,L_DEBUG,"%s","New fork!"); + ret = ATOM_FORK; + break; + } + debug_if(s_debug_more,L_DEBUG,"%s","Accept block to a main branch."); + ret = ATOM_ACCEPT; + break; + } + } } + pthread_rwlock_unlock(&PVT(l_blocks)->rwlock); + } + } - if (dap_hash_fast_compare(&l_tmp->block_hash, &l_block_prev_hash)){ - if (l_tmp->hh.next != NULL){ - pthread_rwlock_unlock(& PVT(l_blocks)->rwlock); - debug_if(s_debug_more,L_DEBUG,"%s","New fork!"); - return ATOM_FORK; - } else { - pthread_rwlock_unlock(& PVT(l_blocks)->rwlock); - debug_if(s_debug_more,L_DEBUG,"%s","Accept block to a main branch."); - return ATOM_ACCEPT; - } + if (ret == ATOM_FORK || ret == ATOM_ACCEPT) { + // 2nd level consensus + if (l_blocks->callback_block_verify && l_blocks->callback_block_verify(l_blocks, l_block, a_atom_hash, /* Old bug, crutch for it */ a_atom_size)) { + // Hard accept list + struct cs_blocks_hal_item *l_hash_found = NULL; + HASH_FIND(hh, l_blocks_pvt->hal, &l_block_hash, sizeof(l_block_hash), l_hash_found); + if (!l_hash_found) { + log_it(L_WARNING, "Block %s rejected by block verificator", dap_hash_fast_to_str_static(a_atom_hash)); + return ATOM_REJECT; } } + } else if (ret == ATOM_MOVE_TO_THRESHOLD) { + debug_if(s_debug_more,L_DEBUG,"%s","Can't find valid previous block in chain or forked branches."); + return ATOM_REJECT; } - debug_if(s_debug_more,L_DEBUG,"%s","Can't find valid previous block in chain or forked branches."); - pthread_rwlock_unlock(& PVT(l_blocks)->rwlock); - return ATOM_REJECT; + return ret; } /** @@ -2415,3 +2436,34 @@ static uint256_t s_callback_calc_reward(dap_chain_t *a_chain, dap_hash_fast_t *a DIV_256(l_ret, GET_256_FROM_64(s_block_timediff_unit_size * l_signs_count), &l_ret); return l_ret; } + +static uint64_t s_callback_count_txs(dap_chain_t *a_chain) +{ + return PVT(DAP_CHAIN_CS_BLOCKS(a_chain))->tx_count; +} + + +static dap_list_t *s_callback_get_txs(dap_chain_t *a_chain, size_t a_count, size_t a_page, bool a_reverse) +{ + UNUSED(a_reverse); // TODO + size_t l_count = s_callback_count_txs(a_chain); + size_t l_offset = a_count * a_page; + if (l_offset > l_count) + return NULL; + if (a_page < 2) + l_offset = 0; + dap_list_t *l_list = NULL; + size_t l_counter = 0; + size_t l_end = l_offset + a_count; + for (dap_chain_block_datum_index_t *it = PVT(DAP_CHAIN_CS_BLOCKS(a_chain))->datum_index; + it && l_counter < l_end; + it = it->hh.next) { + dap_chain_datum_t *l_datum = it->block_cache->datum[it->datum_index]; + if (l_datum->header.type_id == DAP_CHAIN_DATUM_TX && l_counter++ >= l_offset) { + dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t *)l_datum->data; + l_list = dap_list_append(l_list, l_tx); + } + } + return l_list; +} + diff --git a/modules/type/blocks/include/dap_chain_block.h b/modules/type/blocks/include/dap_chain_block.h index 519b655c85ed90f61657cc85543473fcece94e8b..a0407e390a52d9a2a759d96fd0ee9dca63d17271 100644 --- a/modules/type/blocks/include/dap_chain_block.h +++ b/modules/type/blocks/include/dap_chain_block.h @@ -83,6 +83,8 @@ typedef struct dap_chain_block{ uint8_t meta_n_datum_n_sign[]; // Here are: metadata, datum sections and verificator signatures } DAP_ALIGN_PACKED dap_chain_block_t; +DAP_STATIC_INLINE size_t dap_chain_block_get_size(dap_chain_block_t *a_block) { return sizeof(a_block->hdr) + a_block->hdr.meta_n_datum_n_signs_size; } + // Init module int dap_chain_block_init(); // Deinit module diff --git a/modules/type/blocks/include/dap_chain_block_chunk.h b/modules/type/blocks/include/dap_chain_block_chunk.h deleted file mode 100644 index d2e21a898dc82318871b66e1d7791333e75fad91..0000000000000000000000000000000000000000 --- a/modules/type/blocks/include/dap_chain_block_chunk.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Authors: - * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net> - * DeM Labs Ltd https://demlabs.net - * Copyright (c) 2020 - * All rights reserved. - - This file is part of DAP SDK the open source project - - DAP SDK is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - DAP SDK is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with any DAP SDK based project. If not, see <http://www.gnu.org/licenses/>. -*/ -#pragma once -#include "dap_chain_block_cache.h" -#include "dap_chain_cs_blocks.h" - -typedef struct dap_chain_block_chunk dap_chain_block_chunk_t; -typedef struct dap_chain_block_cache_hash{ - dap_chain_block_chunk_t * chunk; - dap_chain_block_cache_t *block_cache; - time_t ts_created; - dap_chain_hash_fast_t block_hash; - UT_hash_handle hh; -} dap_chain_block_cache_hash_t; - - -typedef struct dap_chain_block_chunk{ - dap_chain_hash_fast_t chunk_id; - dap_chain_block_cache_hash_t *block_cache_hash; - dap_chain_block_cache_t *block_cache_top; - struct dap_chain_block_chunk * prev; - struct dap_chain_block_chunk * next; -} dap_chain_block_chunk_t; - - -typedef struct dap_chain_block_chunks{ - dap_chain_cs_blocks_t * blocks; - - dap_chain_block_cache_t *cache; - - dap_chain_block_chunk_t * chunks_last; - dap_chain_block_chunk_t * chunks_first; - char * gdb_group; -} dap_chain_block_chunks_t; - -dap_chain_block_chunks_t * dap_chain_block_chunks_create(dap_chain_cs_blocks_t * a_blocks); - -dap_chain_block_chunk_t * dap_chain_block_chunk_create(dap_chain_block_chunks_t * a_chunks); -void dap_chain_block_chunk_delete( dap_chain_block_chunk_t * a_chunk); - -void dap_chain_block_chunks_delete(dap_chain_block_chunks_t * a_chunks); -void dap_chain_block_chunks_sort(dap_chain_block_chunks_t * a_chunks); - -void dap_chain_block_chunks_add(dap_chain_block_chunks_t * a_chunks, dap_chain_block_cache_t * a_block_cache); - -/** - * @brief dap_chain_block_chunks_get_longest_count - * @param a_chunks - */ -static inline size_t dap_chain_block_chunks_get_longest_count(dap_chain_block_chunks_t * a_chunks) -{ - assert(a_chunks); - return a_chunks->chunks_last? HASH_COUNT(a_chunks->chunks_last->block_cache_hash):0; -} - -/** - * @brief dap_chain_block_chunks_get_longest_top - * @param a_chunks - * @return - */ -static inline dap_chain_block_cache_t* dap_chain_block_chunks_get_longest_top(dap_chain_block_chunks_t * a_chunks) -{ - assert(a_chunks); - return a_chunks->chunks_last?a_chunks->chunks_last->block_cache_top:NULL; -} diff --git a/modules/type/blocks/include/dap_chain_cs_blocks.h b/modules/type/blocks/include/dap_chain_cs_blocks.h index 1cdca941d391f12feb731287fd526a73037b332d..69a25180ca834f2d526d4c402d0445f58b0d1f42 100644 --- a/modules/type/blocks/include/dap_chain_cs_blocks.h +++ b/modules/type/blocks/include/dap_chain_cs_blocks.h @@ -40,7 +40,7 @@ typedef struct dap_chain_cs_blocks dap_chain_cs_blocks_t; typedef void (*dap_chain_cs_blocks_callback_t)(dap_chain_cs_blocks_t *); typedef void (*dap_chain_cs_blocks_callback_op_results_t)(dap_chain_cs_blocks_t * a_cs_blocks, int a_rc, void * a_arg); -typedef int (*dap_chain_cs_blocks_callback_block_t)(dap_chain_cs_blocks_t *, dap_chain_block_t *, size_t); +typedef int (*dap_chain_cs_blocks_callback_block_verify_t)(dap_chain_cs_blocks_t *a_cs_blocks, dap_chain_block_t *a_block, dap_hash_fast_t *a_block_hash, size_t a_block_size); typedef size_t (*dap_chain_cs_blocks_callback_block_sign_t)(dap_chain_cs_blocks_t *, dap_chain_block_t **, size_t); typedef dap_chain_block_t *(*dap_chain_cs_block_move_t)(dap_chain_cs_blocks_t *, size_t *); typedef dap_chain_block_t * (*dap_chain_cs_blocks_callback_block_create_t)(dap_chain_cs_blocks_t *, @@ -56,7 +56,7 @@ typedef struct dap_chain_cs_blocks dap_chain_cs_blocks_callback_t callback_delete; dap_chain_cs_blocks_callback_block_create_t callback_block_create; - dap_chain_cs_blocks_callback_block_t callback_block_verify; + dap_chain_cs_blocks_callback_block_verify_t callback_block_verify; dap_chain_cs_blocks_callback_block_sign_t callback_block_sign; dap_chain_cs_block_move_t callback_new_block_move; diff --git a/modules/type/blocks/tests/dap_chain_blocks_test.c b/modules/type/blocks/tests/dap_chain_blocks_test.c index 1faa1f2e7e92ab83b2d12f607809b0ec39cd3617..74d87da324abff28757fea8a729b4ed5cae6c7a4 100644 --- a/modules/type/blocks/tests/dap_chain_blocks_test.c +++ b/modules/type/blocks/tests/dap_chain_blocks_test.c @@ -35,9 +35,10 @@ bool dap_chain_block_test_compare_chain_hash_lists(dap_chain_t* a_chain, dap_lis dap_list_t *l_branch_temp = NULL; dap_chain_atom_ptr_t l_atom = a_chain->callback_atom_iter_get(l_iter, DAP_CHAIN_ITER_OP_FIRST, &l_atom_size_from_iter); for (dap_list_t *l_branch_temp = a_atoms_hash_list; l_branch_temp && l_atom; - l_branch_temp = l_branch_temp->next, l_atom = a_chain->callback_atom_iter_get(l_iter, DAP_CHAIN_ITER_OP_NEXT, &l_atom_size_from_iter)){ - dap_test_msg("Check block %s : num %" DAP_UINT64_FORMAT_U " and %s", dap_chain_hash_fast_to_str_static(l_iter->cur_hash), l_iter->cur_num, - dap_chain_hash_fast_to_str_static((dap_hash_fast_t*)l_branch_temp->data)); + l_branch_temp = l_branch_temp->next, l_atom = a_chain->callback_atom_iter_get(l_iter, DAP_CHAIN_ITER_OP_NEXT, &l_atom_size_from_iter)) { + char l_branch_hash_str[DAP_HASH_FAST_STR_SIZE]; + dap_hash_fast_to_str((dap_hash_fast_t *)l_branch_temp->data, l_branch_hash_str, DAP_HASH_FAST_STR_SIZE); + dap_test_msg("Check block %s : num %" DAP_UINT64_FORMAT_U " and %s", dap_chain_hash_fast_to_str_static(l_iter->cur_hash), l_iter->cur_num, l_branch_hash_str); if (!dap_hash_fast_compare(l_iter->cur_hash, (dap_hash_fast_t*)l_branch_temp->data)){ a_chain->callback_atom_iter_delete(l_iter); return false; diff --git a/modules/type/dag/dap_chain_cs_dag.c b/modules/type/dag/dap_chain_cs_dag.c index a12a7f690a4022bc30e5fed7ae6839d16f3343e0..c6612bca4e2cdb3ef587c681c4b60544189c6e68 100644 --- a/modules/type/dag/dap_chain_cs_dag.c +++ b/modules/type/dag/dap_chain_cs_dag.c @@ -367,7 +367,6 @@ static void s_dap_chain_cs_dag_purge(dap_chain_t *a_chain) } pthread_mutex_unlock(&l_dag_pvt->events_mutex); dap_chain_cell_delete_all(a_chain); - //dap_chain_cell_delete_all_and_free_file(a_chain); } /**