diff --git a/CMakeLists.txt b/CMakeLists.txt index eb274c7fb471e5c6bdb7bbda2eb021d4d2aac96d..10e86caa95db39e8486166816f9f48ca91a389c8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -105,6 +105,30 @@ if (CELLFRAME_MODULES MATCHES "cs-dag-pos") set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_chain_cs_dag_pos) endif() +# Blocks based consensus(es) +if (CELLFRAME_MODULES MATCHES "cs-block-" ) + set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_chain_cs_dag) +endif() + +# PoA consensus for blocks +if (CELLFRAME_MODULES MATCHES "cs-block-poa") + message("[+] Module 'cs-block-poa'") + set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_chain_cs_block_poa) +endif() + +# PoS consensus for blocks +if (CELLFRAME_MODULES MATCHES "cs-block-pos") + message("[+] Module 'cs-block-pos'") + set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_chain_cs_block_pos) +endif() + +# PoW consensus for blocks +if (CELLFRAME_MODULES MATCHES "cs-block-pow") + message("[+] Module 'cs-block-pow'") + set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_chain_cs_block_pos) +endif() + + # No-consensus if (CELLFRAME_MODULES MATCHES "cs-none") message("[+] Module 'cs-none'") diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt index b7d35fe8e87786ac29237543471f39bca4f32373..c1e23565f1487b0f4897b1010b3e762a86796143 100644 --- a/modules/CMakeLists.txt +++ b/modules/CMakeLists.txt @@ -38,20 +38,10 @@ if (CELLFRAME_MODULES MATCHES "srv") endif() # Consensus type dag -if (CELLFRAME_MODULES MATCHES "cs-dag") +if (CELLFRAME_MODULES MATCHES "cs-dag-") add_subdirectory(type/dag) endif() -# Consensus type dag -if (CELLFRAME_MODULES MATCHES "cs-blocks") - add_subdirectory(type/blocks) -endif() - -# No consensus -if (CELLFRAME_MODULES MATCHES "cs-none") - add_subdirectory(consensus/none) -endif() - # DAG PoA if (CELLFRAME_MODULES MATCHES "cs-dag-poa") add_subdirectory(consensus/dag-poa) @@ -62,6 +52,31 @@ if (CELLFRAME_MODULES MATCHES "cs-dag-pos") add_subdirectory(consensus/dag-pos) endif() +# Consensus type blocks +if (CELLFRAME_MODULES MATCHES "cs-block-") + add_subdirectory(type/blocks) +endif() + +# Block PoA +if (CELLFRAME_MODULES MATCHES "cs-block-poa") + add_subdirectory(consensus/block-poa) +endif() + +# Block PoS +if (CELLFRAME_MODULES MATCHES "cs-block-pos") + add_subdirectory(consensus/block-pos) +endif() + +# Block PoW +if (CELLFRAME_MODULES MATCHES "cs-block-pow") + add_subdirectory(consensus/block-pow) +endif() + +# No consensus +if (CELLFRAME_MODULES MATCHES "cs-none") + add_subdirectory(consensus/none) +endif() + # Service App if (CELLFRAME_MODULES MATCHES "srv-app") add_subdirectory(service/app) diff --git a/modules/consensus/block-poa/dap_chain_cs_block_poa.c b/modules/consensus/block-poa/dap_chain_cs_block_poa.c index 5aa85e5aa8a02992c9164c9d4f361e7528fd957c..dc7f7b131ef93bb347507153e591afffa95427ad 100644 --- a/modules/consensus/block-poa/dap_chain_cs_block_poa.c +++ b/modules/consensus/block-poa/dap_chain_cs_block_poa.c @@ -44,7 +44,7 @@ typedef struct dap_chain_cs_dag_poa_pvt { - dap_cert_t * sign_cert; + dap_enc_key_t *sign_key; dap_cert_t ** auth_certs; char * auth_certs_prefix; uint16_t auth_certs_count; @@ -59,9 +59,10 @@ static void s_callback_delete(dap_chain_cs_blocks_t* a_blocks); static int s_callback_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg); static int s_callback_created(dap_chain_t * a_chain, dap_config_t *a_chain_cfg); 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 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); // CLI commands -static int s_cli_block_poa(int argc, char ** argv, void *arg_func, char **str_reply); +static int s_cli_block_poa(int argc, char ** argv, char **str_reply); static bool s_seed_mode = false; /** @@ -73,8 +74,8 @@ int dap_chain_cs_block_poa_init(void) // Add consensus constructor dap_chain_cs_add ("block_poa", s_callback_new ); s_seed_mode = dap_config_get_item_bool_default(g_config,"general","seed_mode",false); - dap_chain_node_cli_cmd_item_create ("block_poa", s_cli_block_poa, NULL, "Blockchain PoA commands", - "block_poa -net <chain net name> -chain <chain name> block new_block_sign [-cert <cert name>] \n" + dap_chain_node_cli_cmd_item_create ("block_poa", s_cli_block_poa, "Blockchain PoA commands", + "block_poa -net <chain net name> -chain <chain name> block sign [-cert <cert name>] \n" "\tSign new block with certificate <cert name> or withs own PoA certificate\n\n"); return 0; @@ -98,9 +99,8 @@ void dap_chain_cs_block_poa_deinit(void) * @param str_reply * @return */ -static int s_cli_block_poa(int argc, char ** argv, void *arg_func, char **a_str_reply) +static int s_cli_block_poa(int argc, char ** argv, char **a_str_reply) { - (void) arg_func; int ret = -666; int arg_index = 1; dap_chain_net_t * l_chain_net = NULL; @@ -118,25 +118,28 @@ static int s_cli_block_poa(int argc, char ** argv, void *arg_func, char **a_str_ dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index,argc,argv,a_str_reply,&l_chain,&l_chain_net); dap_chain_cs_blocks_t * l_blocks = DAP_CHAIN_CS_BLOCKS(l_chain); - //dap_chain_cs_dag_poa_t * l_poa = DAP_CHAIN_CS_DAG_POA( l_dag ) ; dap_chain_cs_block_poa_pvt_t * l_poa_pvt = PVT ( DAP_CHAIN_CS_BLOCK_POA( l_blocks ) ); const char * l_block_new_cmd_str = NULL; const char * l_block_hash_str = NULL; const char * l_cert_str = NULL; - dap_cert_t * l_cert = l_poa_pvt->sign_cert; - if ( l_poa_pvt->sign_cert == NULL) { - dap_chain_node_cli_set_reply_text(a_str_reply, "No certificate to sign events\n"); - return -2; - } dap_chain_node_cli_find_option_val(argv, arg_index, argc, "block", &l_block_new_cmd_str); dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-block", &l_block_hash_str); dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-cert", &l_cert_str); + dap_enc_key_t *l_sign_key; // Load cert to sign if its present - if (l_cert_str) - l_cert = dap_cert_find_by_name( l_cert_str); + if (l_cert_str) { + dap_cert_t *l_cert = dap_cert_find_by_name( l_cert_str); + l_sign_key = l_cert->enc_key; + } else { + l_sign_key = l_poa_pvt->sign_key; + } + if (!l_sign_key || !l_sign_key->priv_key_data) { + dap_chain_node_cli_set_reply_text(a_str_reply, "No certificate to sign blocks\n"); + return -2; + } // block hash may be in hex or base58 format char *l_block_hash_hex_str; @@ -150,12 +153,10 @@ static int s_cli_block_poa(int argc, char ** argv, void *arg_func, char **a_str_ l_event_hash_base58_str = dap_strdup(l_block_hash_str); } - // Parse block ccmd + // Parse block cmd if ( l_block_new_cmd_str != NULL ){ - if (l_poa_pvt->sign_cert ) - ret = -1; - if ( strcmp(l_block_new_cmd_str,"new_block_sign") == 0) { // Sign event command - l_blocks->block_new_size = dap_chain_block_sign_add( &l_blocks->block_new,l_blocks->block_new_size, l_cert ); + if ( strcmp(l_block_new_cmd_str,"sign") == 0) { // Sign event command + l_blocks->block_new_size = dap_chain_block_sign_add( &l_blocks->block_new,l_blocks->block_new_size, l_sign_key); //dap_chain_hash_fast_t l_block_new_hash; //dap_hash_fast(l_blocks->block_new, l_blocks->block_new_size,&l_block_new_hash); } @@ -170,14 +171,15 @@ static int s_cli_block_poa(int argc, char ** argv, void *arg_func, char **a_str_ */ static int s_callback_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg) { - dap_chain_cs_create(a_chain,a_chain_cfg); + dap_chain_cs_blocks_new(a_chain, a_chain_cfg); dap_chain_cs_blocks_t * l_blocks = DAP_CHAIN_CS_BLOCKS( a_chain ); dap_chain_cs_block_poa_t * l_poa = DAP_NEW_Z ( dap_chain_cs_block_poa_t); l_blocks->_inheritor = l_poa; l_blocks->callback_delete = s_callback_delete; l_blocks->callback_block_verify = s_callback_block_verify; - l_poa->_pvt = DAP_NEW_Z ( dap_chain_cs_block_poa_pvt_t ); - dap_chain_cs_block_poa_pvt_t * l_poa_pvt = PVT ( l_poa ); + l_blocks->callback_block_sign = s_callback_block_sign; + l_poa->_pvt = DAP_NEW_Z(dap_chain_cs_block_poa_pvt_t); + dap_chain_cs_block_poa_pvt_t *l_poa_pvt = PVT(l_poa); if (dap_config_get_item_str(a_chain_cfg,"block-poa","auth_certs_prefix") ) { l_poa_pvt->auth_certs_count = dap_config_get_item_uint16_default(a_chain_cfg,"block-poa","auth_certs_number",0); @@ -219,14 +221,19 @@ static int s_callback_created(dap_chain_t * a_chain, dap_config_t *a_chain_net_c if (PVT(l_poa)->prev_callback_created ) PVT(l_poa)->prev_callback_created(a_chain,a_chain_net_cfg); - const char * l_sign_cert = NULL; - if ( ( l_sign_cert = dap_config_get_item_str(a_chain_net_cfg,"block-poa","sign-cert") ) != NULL ) { - - if ( ( PVT(l_poa)->sign_cert = dap_cert_find_by_name(l_sign_cert)) == NULL ){ - log_it(L_ERROR,"Can't load sign certificate, name \"%s\" is wrong",l_sign_cert); - }else - log_it(L_NOTICE,"Loaded \"%s\" certificate to sign poa blocks", l_sign_cert); - + const char * l_sign_cert_str = NULL; + if ( ( l_sign_cert_str = dap_config_get_item_str(a_chain_net_cfg,"block-poa","sign-cert") ) != NULL ) { + dap_cert_t *l_sign_cert = dap_cert_find_by_name(l_sign_cert_str); + if (l_sign_cert == NULL) { + log_it(L_ERROR, "Can't load sign certificate, name \"%s\" is wrong", l_sign_cert_str); + } else if (l_sign_cert->enc_key->priv_key_data) { + PVT(l_poa)->sign_key = l_sign_cert->enc_key; + log_it(L_NOTICE, "Loaded \"%s\" certificate to sign poa blocks", l_sign_cert_str); + } else { + log_it(L_ERROR, "Certificate \"%s\" has no private key", l_sign_cert_str); + } + } else { + log_it(L_ERROR, "No sign certificate provided, can't sign any blocks"); } return 0; } @@ -256,6 +263,29 @@ static void s_callback_delete(dap_chain_cs_blocks_t * a_blocks) } } +/** + * @brief + * function makes block singing + * @param a_dag a_blocks dap_chain_cs_blocks_t + * @param a_block dap_chain_block_t + * @param a_block_size size_t size of block object + * @return int + */ +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) +{ + assert(a_blocks); + dap_chain_cs_block_poa_t *l_poa = DAP_CHAIN_CS_BLOCK_POA(a_blocks); + dap_chain_cs_block_poa_pvt_t *l_poa_pvt = PVT(l_poa); + if (!l_poa_pvt->sign_key) { + log_it(L_WARNING, "Can't sign block with sign-cert in [block-poa] section"); + return 0; + } + if (!a_block_ptr || !(*a_block_ptr) || !a_block_size) { + log_it(L_WARNING, "Block size or block pointer is NULL"); + return 0; + } + return dap_chain_block_sign_add(a_block_ptr, a_block_size, l_poa_pvt->sign_key); +} /** * @brief s_callbac_block_verify @@ -276,21 +306,23 @@ static int s_callback_block_verify(dap_chain_cs_blocks_t * a_blocks, dap_chain_b return -2; } // Parse the rest signs - size_t l_offset = (byte_t*)l_sign - (byte_t*) a_block; - while (l_offset < a_block_size - sizeof (a_block->hdr) ){ + size_t l_offset = (byte_t *)l_sign - a_block->meta_n_datum_n_sign; + while (l_offset < a_block_size - sizeof(a_block->hdr)) { + if (!dap_sign_verify_size(l_sign, a_block_size)) { + log_it(L_ERROR, "Corrupted block: sign size is bigger than block size"); + return -3; + } size_t l_sign_size = dap_sign_get_size(l_sign); // Check if sign size 0 if (!l_sign_size){ log_it(L_ERROR, "Corrupted block: sign size got zero"); - return -3; + return -4; } // Check if sign size too big if (l_sign_size > a_block_size- sizeof (a_block->hdr)-l_offset ){ log_it(L_ERROR, "Corrupted block: sign size %zd is too big, out from block size %zd", l_sign_size, a_block_size); - return -3; + return -5; } - l_offset += l_sign_size; - // Compare signature with auth_certs for (uint16_t j = 0; j < l_poa_pvt->auth_certs_count; j++) { if (dap_cert_compare_with_sign ( l_poa_pvt->auth_certs[j], l_sign) == 0){ @@ -298,6 +330,12 @@ static int s_callback_block_verify(dap_chain_cs_blocks_t * a_blocks, dap_chain_b break; } } + l_offset += l_sign_size; + l_sign = (dap_sign_t *)(a_block->meta_n_datum_n_sign + l_offset); + } + if (l_offset != a_block_size - sizeof(a_block->hdr)) { + log_it(L_ERROR, "Corrupted block: sign end exceeded the block bound"); + return -6; } return l_signs_verified_count >= l_poa_pvt->auth_certs_count_verify ? 0 : -1; } diff --git a/modules/consensus/block-pos/CMakeLists.txt b/modules/consensus/block-pos/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..2417e6529e529168867e0f383b60606f07463e1a --- /dev/null +++ b/modules/consensus/block-pos/CMakeLists.txt @@ -0,0 +1,11 @@ +cmake_minimum_required(VERSION 3.0) +project (dap_chain_cs_block_pos) + +file(GLOB DAP_CHAIN_CS_BLOCK_POS_SRCS *.c) +file(GLOB DAP_CHAIN_CS_BLOCK_POS_HEADERS include/*.h) + +add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_CS_BLOCK_POS_SRCS} ${DAP_CHAIN_CS_BLOCK_POS_HEADERS}) + +target_link_libraries(dap_chain_cs_block_pos dap_core dap_crypto dap_chain dap_chain_cs_blocks dap_chain_net_srv_stake) +target_include_directories(dap_chain_cs_block_pos INTERFACE .) +target_include_directories(${PROJECT_NAME} PUBLIC include) diff --git a/modules/consensus/block-pos/dap_chain_cs_block_pos.c b/modules/consensus/block-pos/dap_chain_cs_block_pos.c new file mode 100644 index 0000000000000000000000000000000000000000..7b6d0dfc3b70565d0f7606b784953e2c4e63d2f4 --- /dev/null +++ b/modules/consensus/block-pos/dap_chain_cs_block_pos.c @@ -0,0 +1,303 @@ +/* + * Authors: + * Roman Khlopkov <roman.khlopkov@demlabs.net> + * DeM Labs Inc. https://demlabs.net + * Kelvin Project https://github.com/kelvinblockchain + * Copyright (c) 2017-2021 + * All rights reserved. + + This file is part of DAP (Deus Applications Prototypes) the open source project + + DAP (Deus Applicaions Prototypes) 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 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 based project. If not, see <http://www.gnu.org/licenses/>. +*/ +#include <stdlib.h> + +#include "dap_chain_net.h" +#include "dap_common.h" +#include "dap_string.h" +#include "dap_strfuncs.h" +#include "dap_chain_cs.h" +#include "dap_chain_cs_blocks.h" +#include "dap_chain_cs_block_pos.h" +#include "dap_chain_net_srv_stake.h" +#include "dap_chain_ledger.h" + +#define LOG_TAG "dap_chain_cs_block_pos" + +typedef struct dap_chain_cs_block_pos_pvt +{ + dap_enc_key_t *blocks_sign_key; + char **tokens_hold; + uint64_t *tokens_hold_value; + size_t tokens_hold_size; + uint16_t confirmations_minimum; + dap_chain_callback_new_cfg_t prev_callback_created; +} dap_chain_cs_block_pos_pvt_t; + +#define PVT(a) ((dap_chain_cs_block_pos_pvt_t *)a->_pvt) + +static void s_callback_delete(dap_chain_cs_blocks_t *a_blocks); +static int s_callback_new(dap_chain_t *a_chain, dap_config_t *a_chain_cfg); +static int s_callback_created(dap_chain_t *a_chain, dap_config_t *a_chain_cfg); +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 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); + +/** + * @brief dap_chain_cs_block_pos_init + * @return + */ +int dap_chain_cs_block_pos_init() +{ + dap_chain_cs_add("block_pos", s_callback_new); + return 0; +} + +/** + * @brief dap_chain_cs_block_pos_deinit + */ +void dap_chain_cs_block_pos_deinit(void) +{ + +} + +/** + * @brief s_cs_callback + * @param a_chain + * @param a_chain_cfg + */ +static int s_callback_new(dap_chain_t *a_chain, dap_config_t *a_chain_cfg) +{ + dap_chain_cs_blocks_new(a_chain, a_chain_cfg); + dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(a_chain); + dap_chain_cs_block_pos_t *l_pos = DAP_NEW_Z(dap_chain_cs_block_pos_t); + l_blocks->_inheritor = l_pos; + l_blocks->callback_delete = s_callback_delete; + l_blocks->callback_block_verify = s_callback_block_verify; + l_blocks->callback_block_sign = s_callback_block_sign; + l_pos->_pvt = DAP_NEW_Z(dap_chain_cs_block_pos_pvt_t); + + dap_chain_cs_block_pos_pvt_t *l_pos_pvt = PVT(l_pos); + + char ** l_tokens_hold = NULL; + char ** l_tokens_hold_value_str = NULL; + uint16_t l_tokens_hold_size = 0; + uint16_t l_tokens_hold_value_size = 0; + + l_tokens_hold = dap_config_get_array_str(a_chain_cfg, "block-pos", "stake_tokens", &l_tokens_hold_size); + l_tokens_hold_value_str = dap_config_get_array_str(a_chain_cfg, "block-pos", "stake_tokens_value", &l_tokens_hold_value_size); + + if (l_tokens_hold_size != l_tokens_hold_value_size){ + log_it(L_CRITICAL, "Entries tokens_hold and tokens_hold_value are different size!"); + goto lb_err; + } + l_pos_pvt->confirmations_minimum = dap_config_get_item_uint16_default(a_chain_cfg, "block-pos", "verifications_minimum", 1); + l_pos_pvt->tokens_hold_size = l_tokens_hold_size; + l_pos_pvt->tokens_hold = DAP_NEW_Z_SIZE(char *, sizeof(char *) * l_tokens_hold_size); + l_pos_pvt->tokens_hold_value = DAP_NEW_Z_SIZE(uint64_t, l_tokens_hold_value_size * sizeof(uint64_t)); + + for (size_t i = 0; i < l_tokens_hold_value_size; i++) { + l_pos_pvt->tokens_hold[i] = dap_strdup(l_tokens_hold[i]); + if ((l_pos_pvt->tokens_hold_value[i] = + strtoull(l_tokens_hold_value_str[i],NULL,10)) == 0) { + log_it(L_CRITICAL, "Token %s has inproper hold value %s", + l_pos_pvt->tokens_hold[i], l_tokens_hold_value_str[i]); + goto lb_err; + } + } + // Save old callback if present and set the call of its own (chain callbacks) + l_pos_pvt->prev_callback_created = l_blocks->chain->callback_created; + l_blocks->chain->callback_created = s_callback_created; + return 0; + +lb_err: + for (int i = 0; i < l_tokens_hold_size; i++) + DAP_DELETE(l_tokens_hold[i]); + DAP_DELETE(l_tokens_hold); + DAP_DELETE(l_pos_pvt->tokens_hold_value); + DAP_DELETE(l_pos_pvt); + DAP_DELETE(l_pos ); + l_blocks->_inheritor = NULL; + l_blocks->callback_delete = NULL; + l_blocks->callback_block_verify = NULL; + return -1; + +} + +/** + * @brief s_callback_created + * @param a_chain + * @param a_chain_cfg + * @return + */ +static int s_callback_created(dap_chain_t *a_chain, dap_config_t *a_chain_net_cfg) +{ + dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(a_chain); + dap_chain_cs_block_pos_t *l_pos = DAP_CHAIN_CS_BLOCK_POS(l_blocks); + + const char * l_sign_cert_str = NULL; + if ( ( l_sign_cert_str = dap_config_get_item_str(a_chain_net_cfg,"block-pos","sign-cert") ) != NULL ) { + dap_cert_t *l_sign_cert = dap_cert_find_by_name(l_sign_cert_str); + if (l_sign_cert == NULL) { + log_it(L_ERROR, "Can't load sign certificate, name \"%s\" is wrong", l_sign_cert_str); + } else if (l_sign_cert->enc_key->priv_key_data) { + PVT(l_pos)->blocks_sign_key = l_sign_cert->enc_key; + log_it(L_NOTICE, "Loaded \"%s\" certificate to sign PoS blocks", l_sign_cert_str); + } else { + log_it(L_ERROR, "Certificate \"%s\" has no private key", l_sign_cert_str); + } + } else { + log_it(L_ERROR, "No sign certificate provided, can't sign any blocks"); + } + return 0; +} + + +/** + * @brief s_chain_cs_block_callback_delete + * @param a_block + */ +static void s_callback_delete(dap_chain_cs_blocks_t *a_blocks) +{ + dap_chain_cs_block_pos_t *l_pos = DAP_CHAIN_CS_BLOCK_POS(a_blocks); + if (l_pos->_pvt) + DAP_DELETE(l_pos->_pvt); +} + +/** + * @brief + * function makes block singing + * @param a_block a_blocks dap_chain_cs_blocks_t + * @param a_block dap_chain_block_t + * @param a_block_size size_t size of block object + * @return int + */ +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) +{ + assert(a_blocks); + dap_chain_cs_block_pos_t *l_pos = DAP_CHAIN_CS_BLOCK_POS(a_blocks); + dap_chain_cs_block_pos_pvt_t *l_pos_pvt = PVT(l_pos); + if (!l_pos_pvt->blocks_sign_key) { + log_it(L_WARNING, "Can't sign block with sign-cert in [block-pos] section"); + return 0; + } + if (!a_block_ptr || !(*a_block_ptr) || !a_block_size) { + log_it(L_WARNING, "Block size or block pointer is NULL"); + return 0; + } + return dap_chain_block_sign_add(a_block_ptr, a_block_size, l_pos_pvt->blocks_sign_key); +} + +/** + * @brief + * function makes block singing verification + * @param a_block a_blocks dap_chain_cs_blocks_t + * @param a_block dap_chain_block_t + * @param a_block_size size_t size of block object + * @return int + */ +static int s_callback_block_verify(dap_chain_cs_blocks_t *a_blocks, dap_chain_block_t *a_block, size_t a_block_size) +{ + dap_chain_cs_block_pos_t *l_pos = DAP_CHAIN_CS_BLOCK_POS(a_blocks); + dap_chain_cs_block_pos_pvt_t *l_pos_pvt = PVT(l_pos); + + if (a_blocks->chain->ledger == NULL) { + log_it(L_CRITICAL,"Ledger is NULL can't check PoS on this chain %s", a_blocks->chain->name); + return -3; + } + + if (sizeof(a_block->hdr) >= a_block_size) { + log_it(L_WARNING,"Incorrect size with block %p on chain %s", a_block, a_blocks->chain->name); + return -7; + } + + size_t l_signs_count = dap_chain_block_get_signs_count(a_block, a_block_size); + if (l_signs_count < l_pos_pvt->confirmations_minimum) { + log_it(L_WARNING,"Wrong signature number with block %p on chain %s", a_block, a_blocks->chain->name); + return -2; // Wrong signatures number + } + + uint16_t l_verified_num = 0; + for (size_t l_sig_pos = 0; l_sig_pos < l_signs_count; l_sig_pos++) { + dap_sign_t *l_sign = dap_chain_block_sign_get(a_block, a_block_size, l_sig_pos); + if (l_sign == NULL) { + log_it(L_WARNING, "Block isn't signed with anything: sig pos %zu, event size %zu", l_sig_pos, a_block_size); + return -4; + } + + bool l_sign_size_correct = dap_sign_verify_size(l_sign, a_block_size); + if (!l_sign_size_correct) { + log_it(L_WARNING, "Block's sign #%zu size is incorrect", l_sig_pos); + return -44; + } + size_t l_block_data_size = dap_chain_block_get_sign_offset(a_block, a_block_size); + if (l_block_data_size == a_block_size) { + log_it(L_WARNING,"Block has nothing except sign, nothing to verify so I pass it (who knows why we have it?)"); + return 0; + } + + int l_sign_verified = dap_sign_verify(l_sign, a_block, l_block_data_size); + if (l_sign_verified != 1) { + log_it(L_WARNING, "Block's sign is incorrect: code %d", l_sign_verified); + return -41; + } + + /*dap_chain_hash_fast_t l_pkey_hash; + if (!dap_sign_get_pkey_hash(l_sign, &l_pkey_hash)) { + log_it(L_WARNING, "Block's sign has no any key"); + return -5; + } + dap_chain_addr_t l_addr = {}; + dap_chain_addr_fill(&l_addr, l_sign->header.type, &l_pkey_hash, a_blocks->chain->net_id); + + if (l_sig_pos == 0) { + size_t l_datums_count = 0; + dap_chain_datum_t **l_datums = dap_chain_block_get_datums(a_block, a_block_size, &l_datums_count); + for (unsigned i = 0; i < l_datums_count; i++) { + if (l_datums[i]->header.type_id == DAP_CHAIN_DATUM_TX) { + dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t *)l_datums[i]->data; + if (!dap_chain_net_srv_stake_validator(&l_addr, l_tx)) { + log_it(L_WARNING,"Not passed stake validator with datum %u of block %p on chain %s", i, a_block, a_blocks->chain->name); + return -6; + } + } + } + } + + bool l_is_enough_balance = false; + for (size_t i = 0; i < l_pos_pvt->tokens_hold_size; i++) { + uint128_t l_balance = dap_chain_ledger_calc_balance(a_blocks->chain->ledger, &l_addr, l_pos_pvt->tokens_hold[i]); + uint64_t l_value = dap_chain_uint128_to(l_balance); + if (l_value >= l_pos_pvt->tokens_hold_value[i]) { + l_verified_num++; + l_is_enough_balance = true; + break; + } + } + if (!l_is_enough_balance) { + char *l_addr_str = dap_chain_addr_to_str(&l_addr); + log_it(L_WARNING, "Verify of block is false, because balance is not enough for addr=%s", l_addr_str); + DAP_DELETE(l_addr_str); + return -1; + }*/ // TODO comlete stake validator for all datums in the block + } + + // Check number + if (l_verified_num >= l_pos_pvt->confirmations_minimum) { + // Passed all checks + return 0; + } else { + log_it(L_WARNING, "Wrong block: only %hu/%hu signs are valid", l_verified_num, l_pos_pvt->confirmations_minimum); + return -2; + } +} diff --git a/modules/consensus/block-pos/include/dap_chain_cs_block_pos.h b/modules/consensus/block-pos/include/dap_chain_cs_block_pos.h new file mode 100644 index 0000000000000000000000000000000000000000..368c77a653e87749451b5860d7c1ab5f2addde5d --- /dev/null +++ b/modules/consensus/block-pos/include/dap_chain_cs_block_pos.h @@ -0,0 +1,39 @@ +/* + * Authors: + * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net> + * DeM Labs Inc. https://demlabs.net + * Kelvin Project https://github.com/kelvinblockchain + * Copyright (c) 2017-2018 + * All rights reserved. + + This file is part of DAP (Deus Applications Prototypes) the open source project + + DAP (Deus Applicaions Prototypes) 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 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 based project. If not, see <http://www.gnu.org/licenses/>. +*/ +#pragma once +#include "dap_chain_cs_blocks.h" +#include "dap_cert.h" + +typedef struct dap_chain_cs_block_pos +{ + dap_chain_t *chain; + dap_chain_cs_blocks_t *blocks; + void *_pvt; +} dap_chain_cs_block_pos_t; + +#define DAP_CHAIN_CS_BLOCK_POS(a) ((dap_chain_cs_block_pos_t *)(a)->_inheritor) + + +int dap_chain_cs_block_pos_init(); +void dap_chain_cs_block_pos_deinit(void); diff --git a/modules/net/include/dap_chain_net.h b/modules/net/include/dap_chain_net.h index 98e6ceb0728633ed87e69548183c3e82a818ea72..e7e40be7532b8207727a0bd53802a41410b9b4cc 100644 --- a/modules/net/include/dap_chain_net.h +++ b/modules/net/include/dap_chain_net.h @@ -67,7 +67,7 @@ static const char * g_net_state_str[]={ typedef struct dap_chain_net{ struct { dap_chain_net_id_t id; - dap_chain_cell_id_t cell_id; // Cell where the node is connected to. {{0}} if not celled(sharder) blockchain + dap_chain_cell_id_t cell_id; // Cell where the node is connected to. {{0}} if not celled(sharded) blockchain char * name; char * gdb_groups_prefix; char * gdb_nodes_aliases; diff --git a/modules/type/blocks/dap_chain_block.c b/modules/type/blocks/dap_chain_block.c index e9a6836f5f1f3b59eab751fe1a38c93505be62e4..4bc564e15eb26fe7d0e5691dfaf8902ae829b98a 100644 --- a/modules/type/blocks/dap_chain_block.c +++ b/modules/type/blocks/dap_chain_block.c @@ -25,7 +25,7 @@ #include "dap_common.h" #include "dap_config.h" #include "dap_hash.h" - +#include "dap_chain_net.h" #include "dap_chain_block.h" #include "dap_chain_block_cache.h" @@ -58,7 +58,7 @@ void dap_chain_block_deinit() * @param a_prev_block * @return */ -dap_chain_block_t * dap_chain_block_new(dap_chain_hash_fast_t * a_prev_block ) +dap_chain_block_t *dap_chain_block_new(dap_chain_hash_fast_t *a_prev_block, size_t *a_block_size) { dap_chain_block_t * l_block = DAP_NEW_Z_SIZE (dap_chain_block_t,sizeof(l_block->hdr)); if( l_block == NULL){ @@ -68,16 +68,18 @@ dap_chain_block_t * dap_chain_block_new(dap_chain_hash_fast_t * a_prev_block ) l_block->hdr.signature = DAP_CHAIN_BLOCK_SIGNATURE; l_block->hdr.version = 1; l_block->hdr.ts_created = time(NULL); - size_t l_block_size = sizeof (l_block->hdr); + size_t l_block_size = sizeof(l_block->hdr); if( a_prev_block ){ - l_block_size = dap_chain_block_meta_add(&l_block, l_block_size, DAP_CHAIN_BLOCK_META_PREV,a_prev_block,sizeof (*a_prev_block) ); + l_block_size = dap_chain_block_meta_add(&l_block, l_block_size, DAP_CHAIN_BLOCK_META_PREV, + a_prev_block, sizeof(*a_prev_block)); }else{ + l_block_size = dap_chain_block_meta_add(&l_block, l_block_size, DAP_CHAIN_BLOCK_META_GENESIS, NULL, 0); log_it(L_INFO, "Genesis block produced"); } + if (a_block_size) + *a_block_size = l_block_size; return l_block; } - - } /** @@ -89,7 +91,7 @@ dap_chain_block_t * dap_chain_block_new(dap_chain_hash_fast_t * a_prev_block ) size_t s_block_get_datum_offset (dap_chain_block_t * a_block, size_t a_block_size) { if( a_block_size < sizeof(a_block->hdr) ){ - log_it(L_ERROR,"Meta add: Corrupted block size %zd thats smaller then block header size %zd ", 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)); } size_t l_offset = 0; dap_chain_block_meta_t * l_meta=NULL; @@ -136,28 +138,22 @@ size_t dap_chain_block_meta_add(dap_chain_block_t ** a_block_ptr, size_t a_block return 0; } - size_t l_offset = s_block_get_datum_offset(l_block,a_block_size); - size_t l_datum_n_sign_copy_size = (a_block_size-sizeof (l_block->hdr)) - l_offset; - if (l_datum_n_sign_copy_size){ - byte_t * l_meta_end = l_block->meta_n_datum_n_sign +l_offset; - byte_t * l_datum_n_sign_copy = DAP_NEW_SIZE(byte_t, l_datum_n_sign_copy_size); - memcpy(l_datum_n_sign_copy, l_meta_end,l_datum_n_sign_copy_size); - *a_block_ptr = l_block = DAP_REALLOC(l_block,a_block_size +sizeof (l_meta->hdr) +a_data_size ); - l_meta= (dap_chain_block_meta_t*) (l_block->meta_n_datum_n_sign +l_offset); // Update data end in reallocated block - l_meta->hdr.data_size = a_data_size; - l_meta->hdr.type = a_meta_type; - l_offset += a_data_size; - l_offset += sizeof(l_meta->hdr); - if (a_data_size) - memcpy(l_meta->data, a_data, a_data_size); - l_meta_end= l_block->meta_n_datum_n_sign +l_offset; // Update meta end - memcpy(l_meta_end, l_datum_n_sign_copy, l_datum_n_sign_copy_size); - l_offset += l_datum_n_sign_copy_size; - l_block->hdr.meta_n_datum_n_signs_size = l_offset; - l_block->hdr.meta_count++; - DAP_DELETE(l_datum_n_sign_copy); + size_t l_add_size = sizeof(l_meta->hdr) + a_data_size; + *a_block_ptr = l_block = DAP_REALLOC(l_block, a_block_size + l_add_size); + size_t l_offset = s_block_get_datum_offset(l_block, a_block_size); + size_t l_datum_n_sign_copy_size = a_block_size - sizeof(l_block->hdr) - l_offset; + if (l_datum_n_sign_copy_size) { + byte_t *l_meta_end = l_block->meta_n_datum_n_sign + l_offset; + memmove(l_meta_end + l_add_size, l_meta_end, l_datum_n_sign_copy_size); } - return l_offset+sizeof (l_block->hdr); + l_meta = (dap_chain_block_meta_t *)(l_block->meta_n_datum_n_sign + l_offset); // Update data end in reallocated block + l_meta->hdr.data_size = a_data_size; + l_meta->hdr.type = a_meta_type; + if (a_data_size) + memcpy(l_meta->data, a_data, a_data_size); + l_block->hdr.meta_n_datum_n_signs_size = l_offset + l_datum_n_sign_copy_size; + l_block->hdr.meta_count++; + return a_block_size + l_add_size; } /** @@ -199,14 +195,14 @@ size_t dap_chain_block_datum_add(dap_chain_block_t ** a_block_ptr, size_t a_bloc log_it(L_ERROR,"Offset %zd is bigger than block size %zd (without header)", l_offset, (a_block_size-sizeof (l_block->hdr))); return a_block_size; } - if (UINT32_MAX - l_block->hdr.meta_n_datum_n_signs_size < a_datum_size && l_block->hdr.datum_count<UINT16_MAX ){ + if (a_datum_size + l_block->hdr.meta_n_datum_n_signs_size < UINT32_MAX && l_block->hdr.datum_count < UINT16_MAX) { // If were signs - they would be deleted after because signed should be all the block filled - *a_block_ptr = l_block = DAP_REALLOC(l_block,l_offset +a_datum_size); - memcpy(l_block->meta_n_datum_n_sign + l_offset, a_datum,a_datum_size); + *a_block_ptr = l_block = DAP_REALLOC(l_block, sizeof(l_block->hdr) + l_offset + a_datum_size); + memcpy(l_block->meta_n_datum_n_sign + l_offset, a_datum, a_datum_size); l_offset += a_datum_size; l_block->hdr.datum_count++; l_block->hdr.meta_n_datum_n_signs_size = l_offset; - return l_offset+sizeof (l_block->hdr); + return l_offset + sizeof(l_block->hdr); }else{ //log_it(L_ERROR,""); return a_block_size; @@ -279,12 +275,12 @@ size_t dap_chain_block_datum_del_by_hash(dap_chain_block_t ** a_block_ptr, size_ * @param a_block_size * @return */ -static size_t s_block_get_sign_offset(dap_chain_block_t * a_block, size_t a_block_size) +size_t dap_chain_block_get_sign_offset(dap_chain_block_t *a_block, size_t a_block_size) { assert(a_block); assert(a_block_size); - if(a_block_size>=sizeof (a_block->hdr)){ - log_it(L_ERROR, "Corrupted block, block size %zd is lesser than block header size %zd", a_block_size,sizeof (a_block->hdr)); + 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; } @@ -309,7 +305,7 @@ static size_t s_block_get_sign_offset(dap_chain_block_t * a_block, size_t a_bloc 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 %zd is bigger than block size %zd ", l_offset,sizeof (a_block->hdr),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 a_block_size; } @@ -323,17 +319,19 @@ static size_t s_block_get_sign_offset(dap_chain_block_t * a_block, size_t a_bloc * @param a_cert * @return */ -size_t dap_chain_block_sign_add( dap_chain_block_t ** a_block_ptr, size_t a_block_size, dap_cert_t * a_cert ) +size_t dap_chain_block_sign_add(dap_chain_block_t **a_block_ptr, size_t a_block_size, dap_enc_key_t *a_key) { assert(a_block_ptr); - dap_chain_block_t * l_block = *a_block_ptr; - size_t l_offset = s_block_get_sign_offset(l_block,a_block_size); - dap_sign_t * l_block_sign = dap_cert_sign(a_cert,l_block,l_offset+sizeof (l_block->hdr),0); + dap_chain_block_t *l_block = *a_block_ptr; + size_t l_offset = dap_chain_block_get_sign_offset(l_block, a_block_size); + dap_sign_t *l_block_sign = dap_sign_create(a_key, l_block, l_offset + sizeof(l_block->hdr), 0); size_t l_block_sign_size = dap_sign_get_size(l_block_sign); + if (!l_block_sign_size) + return 0; *a_block_ptr = l_block = DAP_REALLOC(l_block, l_block_sign_size + a_block_size); - memcpy( ((byte_t *)l_block) +a_block_size,l_block_sign, l_block_sign_size ); + memcpy(((byte_t *)l_block) + a_block_size, l_block_sign, l_block_sign_size); DAP_DELETE(l_block_sign); - return a_block_size+l_block_sign_size; + return a_block_size + l_block_sign_size; } /** @@ -346,25 +344,47 @@ size_t dap_chain_block_sign_add( dap_chain_block_t ** a_block_ptr, size_t a_bloc dap_sign_t *dap_chain_block_sign_get ( dap_chain_block_t * a_block, size_t a_block_size, uint16_t a_sign_num ) { assert(a_block); - size_t l_offset = s_block_get_sign_offset(a_block,a_block_size); - uint16_t l_sign_cur=0; - dap_sign_t * l_sign = (dap_sign_t*) a_block->meta_n_datum_n_sign+l_offset; - while( l_sign_cur <a_sign_num){ + size_t l_offset = dap_chain_block_get_sign_offset(a_block, a_block_size); + uint16_t l_sign_cur = 0; + dap_sign_t *l_sign = (dap_sign_t *)(a_block->meta_n_datum_n_sign + l_offset); + while (l_sign_cur < a_sign_num) { size_t l_sign_size = dap_sign_get_size(l_sign); - if (!l_sign){ + if (!l_sign_size){ log_it(L_ERROR, "Empty sign #%u", l_sign_cur ); return NULL; } if (l_sign_size > a_block_size- l_offset - sizeof (a_block->hdr) ){ - log_it(L_ERROR, "Corrupted sign #%u size %zd", l_sign_cur, l_sign_size ); + log_it(L_ERROR, "Corrupted sign #%u size %zu", l_sign_cur, l_sign_size ); return NULL; } l_offset += l_sign_size; l_sign_cur++; l_sign = (dap_sign_t*) a_block->meta_n_datum_n_sign+l_offset; } - return l_sign_cur == a_sign_num? l_sign : NULL; + return l_sign_cur == a_sign_num ? l_sign : NULL; +} + +size_t dap_chain_block_get_signs_count(dap_chain_block_t * a_block, size_t a_block_size) +{ + assert(a_block); + 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 < 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){ + log_it(L_WARNING, "Empty sign #%hu", l_sign_count); + return l_sign_count; + } + if (l_sign_size > a_block_size - l_offset - sizeof(a_block->hdr)) { + log_it(L_ERROR, "Corrupted sign #%hu size %zu", l_sign_count, l_sign_size); + return l_sign_count; + } + l_offset += l_sign_size; + } + return l_sign_count; } /** @@ -379,11 +399,11 @@ dap_chain_datum_t** dap_chain_block_get_datums(dap_chain_block_t * a_block, size assert(a_block); assert(a_block_size); if( a_block_size<sizeof (a_block->hdr)){ - log_it(L_ERROR,"Corrupted block size %zd lesser than block header size %zd", a_block_size, sizeof (a_block->hdr)); + log_it(L_ERROR, "Get datums: corrupted block size %zd lesser than block header size %zd", a_block_size, sizeof (a_block->hdr)); return NULL; } - assert(a_datums_count); - *a_datums_count = a_block->hdr.datum_count; + if (a_datums_count) + *a_datums_count = 0; if (a_block->hdr.datum_count == 0) return NULL; size_t l_offset = s_block_get_datum_offset(a_block,a_block_size); @@ -405,11 +425,11 @@ dap_chain_datum_t** dap_chain_block_get_datums(dap_chain_block_t * a_block, size return l_ret; } l_ret[n] = l_datum; - (*a_datums_count)++; + if (a_datums_count) + (*a_datums_count)++; // Update current datum pointer and offset l_offset += l_datum_size; 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 is bigger than block size %zd (without header)", l_offset, (a_block_size-sizeof (a_block->hdr))); @@ -428,10 +448,11 @@ dap_chain_datum_t** dap_chain_block_get_datums(dap_chain_block_t * a_block, size dap_chain_block_meta_t** dap_chain_block_get_meta(dap_chain_block_t * a_block, size_t a_block_size,size_t * a_meta_count ) { if( a_block_size < sizeof(a_block->hdr) ){ - log_it(L_ERROR,"Meta add: Corrupted block size %zu thats smaller then block header size %zu ", a_block_size, sizeof (a_block->hdr)); + log_it(L_ERROR,"Get meta: corrupted block size %zu thats smaller then block header size %zu", a_block_size, sizeof (a_block->hdr)); } - *a_meta_count = a_block->hdr.meta_count; - if (a_block->hdr.meta_count ==0) // no meta - nothing to return + if (a_meta_count) + *a_meta_count = 0; + if (a_block->hdr.meta_count == 0) // no meta - nothing to return return NULL; size_t l_offset = 0; dap_chain_block_meta_t * l_meta=NULL; @@ -443,11 +464,13 @@ dap_chain_block_meta_t** dap_chain_block_get_meta(dap_chain_block_t * a_block, s 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_ret[i] = l_meta; - (*a_meta_count)++; - l_offset += sizeof (l_meta->hdr); - l_offset += l_meta_data_size; - }else - l_offset = (a_block_size-sizeof (a_block->hdr)); + if (a_meta_count) + (*a_meta_count)++; + l_offset += sizeof(l_meta->hdr) + l_meta_data_size; + }else { + log_it(L_WARNING, "Get meta: corrupted block, can read only %zu from %hu metas", i, a_block->hdr.meta_count); + return l_ret; + } } return l_ret; } @@ -465,6 +488,7 @@ dap_chain_block_meta_t** dap_chain_block_get_meta(dap_chain_block_t * a_block, s void dap_chain_block_meta_extract(dap_chain_block_meta_t ** a_meta, size_t a_meta_count, dap_chain_hash_fast_t * a_block_prev_hash, dap_chain_hash_fast_t * a_block_anchor_hash, + dap_chain_hash_fast_t *a_merkle, dap_chain_hash_fast_t ** a_block_links, size_t *a_block_links_count, bool * a_is_genesis, @@ -472,12 +496,15 @@ void dap_chain_block_meta_extract(dap_chain_block_meta_t ** a_meta, size_t a_met uint64_t *a_nonce2 ) { + if (!a_meta || !a_meta_count) + return; // Check for meta that could be faced only once bool l_was_prev = false; bool l_was_genesis = false; bool l_was_anchor = false; bool l_was_nonce = false; bool l_was_nonce2 = false; + bool l_was_merkle = false; // Init links parsing size_t l_links_count_max = 5; if (a_block_links_count) @@ -563,7 +590,20 @@ void dap_chain_block_meta_extract(dap_chain_block_meta_t ** a_meta, size_t a_met if (l_meta->hdr.data_size == sizeof (*a_nonce2 ) ) memcpy(a_nonce2, l_meta->data, l_meta->hdr.data_size); else - log_it(L_WARNING, "NONCE2 meta #%zd has wrong size %hu when expecting %zu",i, l_meta->hdr.data_size, sizeof (*a_nonce2)); + log_it(L_WARNING, "NONCE2 meta #%zu has wrong size %hu when expecting %zu",i, l_meta->hdr.data_size, sizeof (*a_nonce2)); + } + break; + case DAP_CHAIN_BLOCK_META_MERKLE: + if(l_was_merkle){ + log_it(L_WARNING, "Merckle root could be only one in the block, meta #%zu is ignored ", i); + break; + } + l_was_merkle = true; + if (a_merkle) { + if (l_meta->hdr.data_size == sizeof(*a_merkle)) + memcpy(a_merkle, l_meta->data, l_meta->hdr.data_size); + else + log_it(L_WARNING, "Merkle root meta #%zu has wrong size %hu when expecting %zu", i, l_meta->hdr.data_size, sizeof (*a_nonce2)); } break; default: { log_it(L_WARNING, "Unknown meta #%zu type 0x%02hx (size %hu), possible corrupted block or you need to upgrade your software", diff --git a/modules/type/blocks/dap_chain_block_cache.c b/modules/type/blocks/dap_chain_block_cache.c index 685e736fca54f309a9857a905949908f484545b6..49eaa19c068c53cadb3121d7e915c795889e453a 100644 --- a/modules/type/blocks/dap_chain_block_cache.c +++ b/modules/type/blocks/dap_chain_block_cache.c @@ -53,7 +53,7 @@ void dap_chain_block_cache_deinit() * @param a_block_size * @return */ -dap_chain_block_cache_t * dap_chain_block_cache_new(dap_chain_block_t * a_block, size_t a_block_size) +dap_chain_block_cache_t * dap_chain_block_cache_new(dap_chain_cs_blocks_t *a_blocks, dap_chain_block_t * a_block, size_t a_block_size) { if (! a_block) return NULL; @@ -61,8 +61,12 @@ dap_chain_block_cache_t * dap_chain_block_cache_new(dap_chain_block_t * a_block, dap_chain_block_cache_t * l_block_cache = DAP_NEW_Z(dap_chain_block_cache_t); l_block_cache->block = a_block; l_block_cache->block_size= a_block_size; - dap_chain_block_cache_update(l_block_cache); - + l_block_cache->_inheritor = a_blocks; + if (dap_chain_block_cache_update(l_block_cache)) { + log_it(L_WARNING, "Block cache can't be created, possible cause corrupted block inside"); + DAP_DELETE(l_block_cache); + return NULL; + } log_it(L_DEBUG,"Block cache created"); return l_block_cache; } @@ -84,26 +88,35 @@ dap_chain_block_cache_t * dap_chain_block_cache_dup(dap_chain_block_cache_t * a_ * @brief dap_chain_block_cache_update * @param a_block_cache */ -void dap_chain_block_cache_update(dap_chain_block_cache_t * a_block_cache) +int dap_chain_block_cache_update(dap_chain_block_cache_t * a_block_cache) { assert(a_block_cache); assert(a_block_cache->block); dap_hash_fast(a_block_cache->block, a_block_cache->block_size, &a_block_cache->block_hash); + if (a_block_cache->meta) + DAP_DELETE(a_block_cache->meta); if (a_block_cache->datum) DAP_DELETE(a_block_cache->datum); - a_block_cache->datum = dap_chain_block_get_datums( a_block_cache->block, a_block_cache->block_size, &a_block_cache->datum_count ); - a_block_cache->meta = dap_chain_block_get_meta (a_block_cache->block, a_block_cache->block_size, &a_block_cache->meta_count); - + a_block_cache->meta = dap_chain_block_get_meta(a_block_cache->block, a_block_cache->block_size, &a_block_cache->meta_count); + if (a_block_cache->meta_count != a_block_cache->block->hdr.meta_count) { + DAP_DELETE(a_block_cache->meta); + return -1; + } dap_chain_block_meta_extract( a_block_cache->meta,a_block_cache->meta_count, &a_block_cache->prev_hash, &a_block_cache->anchor_hash, + &a_block_cache->merkle_root, &a_block_cache->links_hash, &a_block_cache->links_hash_count, &a_block_cache->is_genesis, &a_block_cache->nonce, &a_block_cache->nonce2 ); - + a_block_cache->datum = dap_chain_block_get_datums( a_block_cache->block, a_block_cache->block_size, &a_block_cache->datum_count ); + if (a_block_cache->datum_count != a_block_cache->block->hdr.datum_count) { + DAP_DELETE(a_block_cache->datum); + return -2; + } for (size_t i = 0; i< a_block_cache->datum_count; i++){ dap_chain_datum_t * l_datum = a_block_cache->datum[i]; if ( l_datum && l_datum->header.data_size && l_datum->header.type_id == DAP_CHAIN_DATUM_TX){ @@ -119,6 +132,7 @@ void dap_chain_block_cache_update(dap_chain_block_cache_t * a_block_cache) } } } + return 0; } /** @@ -143,4 +157,3 @@ void dap_chain_block_cache_delete(dap_chain_block_cache_t * a_block_cache) DAP_DELETE(a_block_cache); log_it(L_DEBUG,"Block cache deleted"); } - diff --git a/modules/type/blocks/dap_chain_block_chunk.c b/modules/type/blocks/dap_chain_block_chunk.c index 4661144d4cee82461ff92dd7e30e642f65beff43..76a2a15f4562531ec96ff25b408ad3ba46133506 100644 --- a/modules/type/blocks/dap_chain_block_chunk.c +++ b/modules/type/blocks/dap_chain_block_chunk.c @@ -44,7 +44,7 @@ dap_chain_block_chunks_t * dap_chain_block_chunks_create(dap_chain_cs_blocks_t * size_t l_objs_count =0; dap_global_db_obj_t * l_objs= dap_chain_global_db_gr_load(l_ret->gdb_group, &l_objs_count); for(size_t n=0; n< l_objs_count; n++){ - dap_chain_block_cache_t * l_block_cache = dap_chain_block_cache_new((dap_chain_block_t*) l_objs[n].value,l_objs[n].value_len); + dap_chain_block_cache_t *l_block_cache = dap_chain_block_cache_new(a_blocks, (dap_chain_block_t*)l_objs[n].value, l_objs[n].value_len); dap_chain_block_chunks_add(l_ret, l_block_cache ); } dap_chain_global_db_objs_delete(l_objs,l_objs_count); @@ -84,6 +84,8 @@ void dap_chain_block_chunks_delete(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) { + if (!a_block_cache) + return; dap_chain_block_cache_hash_t * l_chunk_cache_hash = NULL; // Parse block and produce cache object dap_chain_block_t *l_block = a_block_cache->block; diff --git a/modules/type/blocks/dap_chain_cs_blocks.c b/modules/type/blocks/dap_chain_cs_blocks.c index ed9170c9f0d9e21de15cff38b54556cc31d4e73e..276a349df52e7985a1e9c27f064016f2920e7648 100644 --- a/modules/type/blocks/dap_chain_cs_blocks.c +++ b/modules/type/blocks/dap_chain_cs_blocks.c @@ -26,12 +26,13 @@ #include "dap_common.h" #include "dap_enc_base58.h" #include "dap_chain.h" +#include "dap_chain_cell.h" #include "dap_chain_cs.h" #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_chain_node_cli.h" #include "dap_chain_node_cli_cmd.h" #define LOG_TAG "dap_chain_cs_blocks" @@ -59,7 +60,7 @@ typedef struct dap_chain_cs_blocks_pvt dap_chain_tx_block_index_t * tx_block_index; // To find block hash by tx hash - // General lins + // General links dap_chain_block_cache_t * block_cache_first; // Mapped area start dap_chain_block_cache_t * block_cache_last; // Last block in mapped area dap_chain_hash_fast_t genesis_block_hash; @@ -71,6 +72,10 @@ typedef struct dap_chain_cs_blocks_pvt size_t block_size_maximum; // Maximum block size bool is_celled; + dap_timerfd_t *fill_timer; + pthread_rwlock_t datums_lock; + uint64_t fill_timeout; + } dap_chain_cs_blocks_pvt_t; typedef struct dap_chain_cs_blocks_iter @@ -79,7 +84,7 @@ typedef struct dap_chain_cs_blocks_iter dap_chain_block_cache_t * cache; } dap_chain_cs_blocks_iter_t; -#define PVT(a) ((dap_chain_cs_blocks_pvt_t *) a->_pvt ) +#define PVT(a) ((dap_chain_cs_blocks_pvt_t *)(a)->_pvt ) #define ITER_PVT(a) ((dap_chain_cs_blocks_iter_t *) a->_inheritor ) @@ -122,7 +127,7 @@ static dap_chain_atom_ptr_t *s_callback_atom_iter_get_lasts( dap_chain_atom_iter // Delete iterator static void s_callback_atom_iter_delete(dap_chain_atom_iter_t * a_atom_iter ); // Get the fisrt block -static size_t s_callback_add_datums(dap_chain_t * a_chain, dap_chain_datum_t ** a_datums, size_t a_datums_size); +static size_t s_callback_add_datums(dap_chain_t * a_chain, dap_chain_datum_t ** a_datums, size_t a_datums_count); static bool s_seed_mode=false; @@ -181,6 +186,7 @@ int dap_chain_cs_blocks_new(dap_chain_t * a_chain, dap_config_t * a_chain_config { dap_chain_cs_blocks_t * l_cs_blocks = DAP_NEW_Z(dap_chain_cs_blocks_t); a_chain->_inheritor = l_cs_blocks; + l_cs_blocks->chain = a_chain; a_chain->callback_delete = s_callback_delete; @@ -209,8 +215,8 @@ int dap_chain_cs_blocks_new(dap_chain_t * a_chain, dap_config_t * a_chain_config dap_chain_cs_blocks_pvt_t *l_cs_blocks_pvt = DAP_NEW_Z(dap_chain_cs_blocks_pvt_t); l_cs_blocks->_pvt = l_cs_blocks_pvt; - a_chain->_pvt = l_cs_blocks_pvt; pthread_rwlock_init(&l_cs_blocks_pvt->rwlock,NULL); + pthread_rwlock_init(&l_cs_blocks_pvt->datums_lock, 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 ){ @@ -222,15 +228,10 @@ int dap_chain_cs_blocks_new(dap_chain_t * a_chain, dap_config_t * a_chain_config l_cs_blocks_pvt->is_celled = dap_config_get_item_bool_default(a_chain_config,"blocks","is_celled",false); l_cs_blocks_pvt->chunks = dap_chain_block_chunks_create(l_cs_blocks); -// dap_chain_node_role_t l_net_role= dap_chain_net_get_role( dap_chain_net_by_id(a_chain->net_id) ); - // Datum operations callbacks -/* - a_chain->callback_datum_iter_create = s_chain_callback_datum_iter_create; // Datum iterator create - a_chain->callback_datum_iter_delete = s_chain_callback_datum_iter_delete; // Datum iterator delete - a_chain->callback_datum_iter_get_first = s_chain_callback_datum_iter_get_first; // Get the fisrt datum from chain - a_chain->callback_datum_iter_get_next = s_chain_callback_datum_iter_get_next; // Get the next datum from chain from the current one -*/ + l_cs_blocks_pvt->block_size_maximum = 10 * 1024 * 1024; // 10 Mb + l_cs_blocks_pvt->fill_timeout = dap_config_get_item_uint64_default(a_chain_config, "blocks", "fill_timeout", 60) * 1000; // 1 min + return 0; } @@ -240,8 +241,7 @@ int dap_chain_cs_blocks_new(dap_chain_t * a_chain, dap_config_t * a_chain_config */ void dap_chain_cs_blocks_delete(dap_chain_t * a_chain) { - pthread_rwlock_destroy(&PVT( DAP_CHAIN_CS_BLOCKS(a_chain) )->rwlock ); - dap_chain_block_chunks_delete(PVT(DAP_CHAIN_CS_BLOCKS(a_chain))->chunks ); + s_callback_delete(a_chain); } /** @@ -381,8 +381,9 @@ static int s_cli_blocks(int a_argc, char ** a_argv, char **a_str_reply) pthread_rwlock_wrlock( &PVT(l_blocks)->rwlock ); if ( l_blocks->block_new ) DAP_DELETE( l_blocks->block_new ); - l_blocks->block_new = dap_chain_block_new( PVT(l_blocks)->block_cache_last? &PVT(l_blocks)->block_cache_last->block_hash: NULL ); - l_blocks->block_new_size = sizeof (l_blocks->block_new->hdr); + l_blocks->block_new = dap_chain_block_new(PVT(l_blocks)->block_cache_last ? + &PVT(l_blocks)->block_cache_last->block_hash : NULL, + &l_blocks->block_new_size); pthread_rwlock_unlock( &PVT(l_blocks)->rwlock ); } break; @@ -476,7 +477,7 @@ static int s_cli_blocks(int a_argc, char ** a_argv, char **a_str_reply) dap_chain_block_meta_t * l_meta = l_block_cache->meta[i]; switch (l_meta->hdr.type) { case DAP_CHAIN_BLOCK_META_GENESIS:{ - dap_string_append_printf(l_str_tmp,"\t\tGENESIS\n"); + dap_string_append_printf(l_str_tmp, "\t\tGENESIS\n"); }break; case DAP_CHAIN_BLOCK_META_PREV:{ s_cli_meta_hash_print(l_str_tmp, "PREV", l_meta); @@ -594,6 +595,8 @@ static void s_callback_delete(dap_chain_t * a_chain) DAP_DELETE(l_blocks->_pvt); pthread_rwlock_unlock(&PVT(l_blocks)->rwlock); pthread_rwlock_destroy(&PVT(l_blocks)->rwlock); + pthread_rwlock_destroy(&PVT(l_blocks)->datums_lock); + dap_chain_block_chunks_delete(PVT(l_blocks)->chunks ); log_it(L_INFO,"callback_delete() called"); } @@ -676,9 +679,7 @@ static int s_add_atom_to_blocks(dap_chain_cs_blocks_t * a_blocks, dap_ledger_t * pthread_rwlock_unlock( &PVT(a_blocks)->rwlock ); res = s_add_atom_to_ledger(a_blocks, a_ledger, a_block_cache); if (res) { - pthread_rwlock_rdlock( &PVT(a_blocks)->rwlock ); log_it(L_INFO,"Block %s checked, but ledger declined", a_block_cache->block_hash_str ); - pthread_rwlock_unlock( &PVT(a_blocks)->rwlock ); return res; } //All correct, no matter for result @@ -686,7 +687,8 @@ static int s_add_atom_to_blocks(dap_chain_cs_blocks_t * a_blocks, dap_ledger_t * HASH_ADD(hh, PVT(a_blocks)->blocks,block_hash,sizeof (a_block_cache->block_hash), a_block_cache); if (! (PVT(a_blocks)->block_cache_first ) ) PVT(a_blocks)->block_cache_first = a_block_cache; - PVT(a_blocks)->block_cache_last->next = a_block_cache; + if (PVT(a_blocks)->block_cache_last) + PVT(a_blocks)->block_cache_last->next = a_block_cache; a_block_cache->prev = PVT(a_blocks)->block_cache_last; PVT(a_blocks)->block_cache_last = a_block_cache; @@ -779,7 +781,11 @@ static dap_chain_atom_verify_res_t s_callback_atom_add(dap_chain_t * a_chain, da log_it(L_DEBUG, "... already present in blocks %s",l_block_cache->block_hash_str); return ATOM_PASS; } else { - l_block_cache = dap_chain_block_cache_new( l_block, l_block_size); + l_block_cache = dap_chain_block_cache_new(l_blocks, l_block, l_block_size); + if (!l_block_cache) { + log_it(L_DEBUG, "... corrupted block"); + return ATOM_REJECT; + } log_it(L_DEBUG, "... new block %s",l_block_cache->block_hash_str); ret = ATOM_ACCEPT; } @@ -787,7 +793,8 @@ static dap_chain_atom_verify_res_t s_callback_atom_add(dap_chain_t * a_chain, da // verify hashes and consensus if(ret == ATOM_ACCEPT){ ret = s_callback_atom_verify (a_chain, a_atom, a_atom_size); - log_it(L_DEBUG, "Verified atom %p: code %d", a_atom, ret); + log_it(L_DEBUG, "Verified atom %p: %s", a_atom, ret == ATOM_ACCEPT ? "accepted" : + (ret == ATOM_REJECT ? "rejected" : "thresholded")); } if( ret == ATOM_ACCEPT){ @@ -847,6 +854,7 @@ static dap_chain_atom_verify_res_t s_callback_atom_verify(dap_chain_t * a_chain, &l_block_anchor_hash, NULL, NULL, + NULL, &l_is_genesis, &l_nonce, &l_nonce2 ) ; @@ -863,7 +871,7 @@ static dap_chain_atom_verify_res_t s_callback_atom_verify(dap_chain_t * a_chain, log_it(L_NOTICE,"Accepting new genesis block"); return ATOM_ACCEPT; }else if(s_seed_mode){ - log_it(L_WARNING,"Cant accept genesis blockt: already present data in blockchain"); + log_it(L_WARNING,"Cant accept genesis block: already present data in blockchain"); return ATOM_REJECT; } }else{ @@ -915,7 +923,8 @@ static dap_chain_atom_iter_t* s_callback_atom_iter_create_from(dap_chain_t * a_c dap_hash_fast(a_atom, a_atom_size, &l_atom_hash); dap_chain_atom_iter_t * l_atom_iter = s_callback_atom_iter_create(a_chain); if (l_atom_iter){ - l_atom_iter->cur_item =ITER_PVT(l_atom_iter)->cache = dap_chain_block_cache_get_by_hash(l_atom_hash); + dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(a_chain); + l_atom_iter->cur_item = ITER_PVT(l_atom_iter)->cache = dap_chain_block_cs_cache_get_by_hash(l_blocks, &l_atom_hash); l_atom_iter->cur = a_atom; l_atom_iter->cur_size = a_atom_size; return l_atom_iter; @@ -961,7 +970,7 @@ static dap_chain_datum_tx_t* s_callback_atom_iter_find_by_tx_hash(dap_chain_t * dap_chain_tx_block_index_t * l_tx_block_index = NULL; HASH_FIND(hh, PVT(l_cs_blocks)->tx_block_index,a_tx_hash, sizeof (*a_tx_hash), l_tx_block_index); if (l_tx_block_index){ - dap_chain_block_cache_t * l_block_cache = dap_chain_block_cache_get_by_hash( l_tx_block_index->block_hash ); + dap_chain_block_cache_t *l_block_cache = dap_chain_block_cs_cache_get_by_hash(l_cs_blocks, &l_tx_block_index->block_hash); if ( l_block_cache){ return dap_chain_block_cache_get_tx_by_hash(l_block_cache, a_tx_hash); }else @@ -1050,7 +1059,8 @@ static dap_chain_atom_ptr_t *s_callback_atom_iter_get_links( dap_chain_atom_iter *a_links_size = l_block_cache->links_hash_count; dap_chain_atom_ptr_t * l_ret = DAP_NEW_Z_SIZE(dap_chain_atom_ptr_t, l_block_cache->links_hash_count *sizeof (dap_chain_atom_ptr_t) ); for (size_t i = 0; i< l_block_cache->links_hash_count; i ++){ - dap_chain_block_cache_t * l_link = dap_chain_block_cache_get_by_hash(l_block_cache->links_hash[i]); + dap_chain_cs_blocks_t *l_cs_blocks = (dap_chain_cs_blocks_t *)l_block_cache->_inheritor; + dap_chain_block_cache_t *l_link = dap_chain_block_cs_cache_get_by_hash(l_cs_blocks, &l_block_cache->links_hash[i]); assert(l_link); (*a_links_size_ptr)[i] = l_link->block_size; l_ret[i] = l_link->block; @@ -1098,6 +1108,35 @@ static void s_callback_atom_iter_delete(dap_chain_atom_iter_t * a_atom_iter ) DAP_DELETE(a_atom_iter); } +static int s_new_block_complete(dap_chain_cs_blocks_t *a_blocks) +{ + dap_hash_fast_t l_merkle_root = {}; // TODO compute the merkle root of block's datums + a_blocks->block_new_size = dap_chain_block_meta_add(&a_blocks->block_new, a_blocks->block_new_size, + DAP_CHAIN_BLOCK_META_MERKLE, &l_merkle_root, sizeof(l_merkle_root)); + size_t l_signed_size = a_blocks->callback_block_sign(a_blocks, &a_blocks->block_new, a_blocks->block_new_size); + if (l_signed_size) + a_blocks->block_new_size = l_signed_size; + else { + log_it(L_WARNING, "Block signing failed"); + return -1; + } + dap_chain_atom_verify_res_t l_res = s_callback_atom_add(a_blocks->chain, a_blocks->block_new, a_blocks->block_new_size); + DAP_DEL_Z(a_blocks->block_new); + if (l_res == ATOM_ACCEPT) + return 0; + return -2; +} + +static bool s_callback_datums_timer(void *a_arg) +{ + dap_chain_cs_blocks_pvt_t *l_blocks_pvt = PVT((dap_chain_cs_blocks_t *)a_arg); + pthread_rwlock_wrlock(&l_blocks_pvt->datums_lock); + s_new_block_complete((dap_chain_cs_blocks_t *)a_arg); + pthread_rwlock_unlock(&l_blocks_pvt->datums_lock); + l_blocks_pvt->fill_timer = NULL; + return false; +} + /** * @brief s_callback_datums_pool_proc * @param a_chain @@ -1105,13 +1144,31 @@ static void s_callback_atom_iter_delete(dap_chain_atom_iter_t * a_atom_iter ) * @param a_datums_size * @return */ -static size_t s_callback_add_datums(dap_chain_t * a_chain, dap_chain_datum_t ** a_datums, size_t a_datums_size) +static size_t s_callback_add_datums(dap_chain_t *a_chain, dap_chain_datum_t **a_datums, size_t a_datums_count) { - // IMPORTANT - all datums on input should be checket before for curruption because datum size is taken from datum's header - for (size_t i = 0; i < a_datums_size; i++) { - DAP_CHAIN_CS_BLOCKS(a_chain)->block_new_size = dap_chain_block_datum_add( &DAP_CHAIN_CS_BLOCKS(a_chain)->block_new, - DAP_CHAIN_CS_BLOCKS(a_chain)->block_new_size, - a_datums[i],dap_chain_datum_size(a_datums[i]) ); + dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(a_chain); + dap_chain_cs_blocks_pvt_t *l_blocks_pvt = PVT(l_blocks); + // IMPORTANT - all datums on input should be checked before for curruption because datum size is taken from datum's header + pthread_rwlock_wrlock(&l_blocks_pvt->datums_lock); + if (!l_blocks->block_new) { + l_blocks->block_new = dap_chain_block_new(&l_blocks_pvt->block_cache_last->block_hash, &l_blocks->block_new_size); + dap_chain_net_t *l_net = dap_chain_net_by_id(l_blocks->chain->net_id); + l_blocks->block_new->hdr.cell_id.uint64 = l_net->pub.cell_id.uint64; + l_blocks->block_new->hdr.chain_id.uint64 = l_blocks->chain->id.uint64; + } + for (size_t i = 0; i < a_datums_count; i++) { + size_t l_datum_size = dap_chain_datum_size(a_datums[i]); + if (l_blocks->block_new_size + l_datum_size > l_blocks_pvt->block_size_maximum) { + s_new_block_complete(l_blocks); + pthread_rwlock_unlock(&l_blocks_pvt->datums_lock); + s_callback_add_datums(a_chain, &a_datums[i], a_datums_count - i); + pthread_rwlock_wrlock(&l_blocks_pvt->datums_lock); + } + l_blocks->block_new_size = dap_chain_block_datum_add(&l_blocks->block_new, l_blocks->block_new_size, + a_datums[i], l_datum_size); } - return DAP_CHAIN_CS_BLOCKS(a_chain)->block_new_size; + if (!l_blocks_pvt->fill_timer) + l_blocks_pvt->fill_timer = dap_timerfd_start(l_blocks_pvt->fill_timeout, s_callback_datums_timer, l_blocks); + pthread_rwlock_unlock(&l_blocks_pvt->datums_lock); + return l_blocks->block_new_size; } diff --git a/modules/type/blocks/include/dap_chain_block.h b/modules/type/blocks/include/dap_chain_block.h index 6364350205650328e7e49866169e9280b064cc9d..bcb81167a6f6fcb9b1df12d2d1347583c544c14b 100644 --- a/modules/type/blocks/include/dap_chain_block.h +++ b/modules/type/blocks/include/dap_chain_block.h @@ -69,6 +69,7 @@ typedef struct dap_chain_block_meta{ #define DAP_CHAIN_BLOCK_META_LINK 0x12 #define DAP_CHAIN_BLOCK_META_NONCE 0x20 #define DAP_CHAIN_BLOCK_META_NONCE2 0x21 +#define DAP_CHAIN_BLOCK_META_MERKLE 0x30 /** @@ -86,7 +87,7 @@ int dap_chain_block_init(); void dap_chain_block_deinit(); // Create new block -dap_chain_block_t * dap_chain_block_new(dap_chain_hash_fast_t * a_prev_block ); +dap_chain_block_t *dap_chain_block_new(dap_chain_hash_fast_t *a_prev_block, size_t *a_block_size); // Add metadata in block size_t dap_chain_block_meta_add(dap_chain_block_t ** a_block_ptr, size_t a_block_size, uint8_t a_meta_type, const void * a_data, size_t a_data_size); @@ -96,8 +97,10 @@ size_t dap_chain_block_datum_add(dap_chain_block_t ** a_block_ptr, size_t a_bloc size_t dap_chain_block_datum_del_by_hash(dap_chain_block_t ** a_block_ptr, size_t a_block_size, dap_chain_hash_fast_t* a_datum_hash); // Add sign in block -size_t dap_chain_block_sign_add( dap_chain_block_t ** a_block_ptr, size_t a_block_size, dap_cert_t * a_cert ); +size_t dap_chain_block_sign_add(dap_chain_block_t ** a_block_ptr, size_t a_block_size, dap_enc_key_t *a_key); dap_sign_t *dap_chain_block_sign_get ( dap_chain_block_t * a_block_ptr, size_t a_block_size, uint16_t a_sign_num ); +size_t dap_chain_block_get_signs_count(dap_chain_block_t * a_block, size_t a_block_size); +size_t dap_chain_block_get_sign_offset(dap_chain_block_t *a_block, size_t a_block_size); // Create and return datums list dap_chain_datum_t** dap_chain_block_get_datums(dap_chain_block_t * a_block, size_t a_block_size,size_t * a_datums_count ); @@ -108,6 +111,7 @@ dap_chain_block_meta_t** dap_chain_block_get_meta(dap_chain_block_t * a_block, s void dap_chain_block_meta_extract(dap_chain_block_meta_t ** a_meta, size_t a_meta_count, dap_chain_hash_fast_t * a_block_prev_hash, dap_chain_hash_fast_t * a_block_anchor_hash, + dap_chain_hash_fast_t *a_merkle, dap_chain_hash_fast_t ** a_block_links, size_t *a_block_links_count, bool * a_is_genesis, diff --git a/modules/type/blocks/include/dap_chain_block_cache.h b/modules/type/blocks/include/dap_chain_block_cache.h index f89199984f8150814f3e84d932d5729a5ca1566c..01f0a8d3b616edc569d6b42c0cf186c8bdb95c0b 100644 --- a/modules/type/blocks/include/dap_chain_block_cache.h +++ b/modules/type/blocks/include/dap_chain_block_cache.h @@ -27,6 +27,8 @@ #include "dap_hash.h" #include "uthash.h" +typedef struct dap_chain_cs_blocks dap_chain_cs_blocks_t; + typedef struct dap_chain_block_cache_tx_index { dap_chain_hash_fast_t tx_hash; @@ -55,6 +57,7 @@ typedef struct dap_chain_block_cache{ // Extracted metadata dap_chain_hash_fast_t prev_hash; dap_chain_hash_fast_t anchor_hash; + dap_chain_hash_fast_t merkle_root; dap_chain_hash_fast_t* links_hash; size_t links_hash_count; @@ -83,10 +86,9 @@ typedef struct dap_chain_block_cache{ int dap_chain_block_cache_init(); void dap_chain_block_cache_deinit(); -dap_chain_block_cache_t * dap_chain_block_cache_get_by_hash(dap_chain_hash_fast_t a_block_hash); -dap_chain_block_cache_t * dap_chain_block_cache_new(dap_chain_block_t * a_block, size_t a_block_size); +dap_chain_block_cache_t * dap_chain_block_cache_new(dap_chain_cs_blocks_t *a_blocks, dap_chain_block_t * a_block, size_t a_block_size); dap_chain_block_cache_t * dap_chain_block_cache_dup(dap_chain_block_cache_t * a_block); -void dap_chain_block_cache_update(dap_chain_block_cache_t * a_block_cache); +int dap_chain_block_cache_update(dap_chain_block_cache_t * a_block_cache); void dap_chain_block_cache_delete(dap_chain_block_cache_t * a_block_cache); dap_chain_datum_tx_t* dap_chain_block_cache_get_tx_by_hash (dap_chain_block_cache_t * a_block_cache, dap_chain_hash_fast_t * a_tx_hash); diff --git a/modules/type/blocks/include/dap_chain_cs_blocks.h b/modules/type/blocks/include/dap_chain_cs_blocks.h index a60432337e1c28e84feaf742dad563eaccb9c7c7..87c662785ea28ca3abd1a8ca0a83e5b54c1df8bd 100644 --- a/modules/type/blocks/include/dap_chain_cs_blocks.h +++ b/modules/type/blocks/include/dap_chain_cs_blocks.h @@ -30,7 +30,8 @@ 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 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_t)(dap_chain_cs_blocks_t *, dap_chain_block_t *, size_t); +typedef size_t (*dap_chain_cs_blocks_callback_block_sign_t)(dap_chain_cs_blocks_t *, dap_chain_block_t **, size_t); @@ -50,6 +51,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_sign_t callback_block_sign; void * _pvt; void * _inheritor; } dap_chain_cs_blocks_t; diff --git a/modules/type/dag/dap_chain_cs_dag.c b/modules/type/dag/dap_chain_cs_dag.c index 4241cba8a77956d3dd257d73ac11b9a429aaf43d..6309d93a2d6ae461da38021570d6adcd20bfadf2 100644 --- a/modules/type/dag/dap_chain_cs_dag.c +++ b/modules/type/dag/dap_chain_cs_dag.c @@ -398,7 +398,8 @@ static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_cha case ATOM_ACCEPT: ret = s_chain_callback_atom_verify(a_chain, a_atom, a_atom_size); if(s_debug_more) - log_it(L_DEBUG, "Verified atom %p: code %d", a_atom, ret); + log_it(L_DEBUG, "Verified atom %p: %s", a_atom, ret == ATOM_ACCEPT ? "accepted" : + (ret == ATOM_REJECT ? "rejected" : "thresholded")); break; case ATOM_PASS: if(s_debug_more) {