From 94965421872e0c75691e6e5e2cec6d43246ee752 Mon Sep 17 00:00:00 2001 From: "Dmitriy A. Gerasimov" <dmitriy.gerasimov@demlabs.net> Date: Sun, 8 Nov 2020 21:09:04 +0700 Subject: [PATCH] [+] Blockchain PoA consensus --- modules/CMakeLists.txt | 5 + modules/consensus/block-poa/CMakeLists.txt | 8 +- .../block-poa/dap_chain_cs_block_poa.c | 287 +++++++++++++++++- .../include/dap_chain_cs_block_poa.h | 29 +- .../consensus/dag-poa/dap_chain_cs_dag_poa.c | 14 +- .../dag-poa/include/dap_chain_cs_dag_poa.h | 14 +- modules/type/blocks/dap_chain_block.c | 84 +++++ modules/type/blocks/dap_chain_cs_blocks.c | 21 +- modules/type/blocks/include/dap_chain_block.h | 7 +- .../type/blocks/include/dap_chain_cs_blocks.h | 3 + 10 files changed, 417 insertions(+), 55 deletions(-) diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt index 2b3c7d0eac..ab3cfcab2b 100644 --- a/modules/CMakeLists.txt +++ b/modules/CMakeLists.txt @@ -57,6 +57,11 @@ if (CELLFRAME_MODULES MATCHES "cs-dag-pos") add_subdirectory(consensus/dag-pos) endif() +# Blocks PoA +if (CELLFRAME_MODULES MATCHES "cs-blocks-poa") + add_subdirectory(consensus/block-poa) +endif() + # Service App if (CELLFRAME_MODULES MATCHES "srv-app") add_subdirectory(service/app) diff --git a/modules/consensus/block-poa/CMakeLists.txt b/modules/consensus/block-poa/CMakeLists.txt index 0b44e6775e..5fa1723d36 100644 --- a/modules/consensus/block-poa/CMakeLists.txt +++ b/modules/consensus/block-poa/CMakeLists.txt @@ -1,13 +1,11 @@ cmake_minimum_required(VERSION 2.8) project (dap_chain_cs_block_poa) - + file(GLOB DAP_CHAIN_BLOCK_CS_POA_SRCS *.c) file(GLOB DAP_CHAIN_BLOCK_CS_POA_HEADERS include/*.h) add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_BLOCK_CS_POA_SRCS} ${DAP_CHAIN_BLOCK_CS_POA_HEADERS}) -add_definitions ("-DDAP_CHAIN_BLOCK_CS_POA") - -target_link_libraries(dap_chain_cs_block_poa dap_core dap_crypto dap_chain dap_chain_cs_block ) +target_link_libraries(dap_chain_cs_block_poa dap_core dap_crypto dap_chain dap_chain_cs_blocks dap_chain_net_srv_stake) target_include_directories(dap_chain_cs_block_poa INTERFACE .) - +target_include_directories(${PROJECT_NAME} PUBLIC include) 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 be64d5d40b..5aa85e5aa8 100644 --- a/modules/consensus/block-poa/dap_chain_cs_block_poa.c +++ b/modules/consensus/block-poa/dap_chain_cs_block_poa.c @@ -1,45 +1,304 @@ /* * Authors: * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net> - * DeM Labs Inc. https://demlabs.net - * Kelvin Project https://github.com/kelvinblockchain - * Copyright (c) 2017-2018 + * DeM Labs Limited https://demlabs.net + * DAP SDK https://gitlab.demlabs.net/dap/dap-sdk + * Copyright (c) 2017 * All rights reserved. - This file is part of DAP (Deus Applications Prototypes) the open source project + This file is part of DAP SDK the open source project - DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify + 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 is distributed in the hope that it will be useful, + 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 based project. If not, see <http://www.gnu.org/licenses/>. + along with any DAP SDK based project. If not, see <http://www.gnu.org/licenses/>. */ #include "dap_common.h" -#include "dap_chain_cs_block_poa.h" +#include "dap_strfuncs.h" +#include "dap_enc_base58.h" +#include "dap_cert.h" #include "dap_chain.h" +#include "dap_chain_block.h" +#include "dap_chain_block_cache.h" +#include "dap_chain_cs_blocks.h" +#include "dap_chain_cs_block_poa.h" +#include "dap_chain_net.h" +#include "dap_chain_node_cli.h" +#include "dap_chain_node_cli_cmd.h" +#include "dap_chain_global_db.h" +#include "dap_chain_cs.h" #include "dap_chain_cs_blocks.h" +#include "dap_chain_net_srv_stake.h" #define LOG_TAG "dap_chain_cs_block_poa" -dap_chain_t *s_callback_chain_new(); -void s_callback_delete(dap_chain_t * ); -void s_callback_blocks(dap_chain_cs_blocks_t *, dap_chain_block_t * ); -int dap_chain_cs_block_poa_init() +typedef struct dap_chain_cs_dag_poa_pvt { -// dap_chain_block_cs_add + dap_cert_t * sign_cert; + dap_cert_t ** auth_certs; + char * auth_certs_prefix; + uint16_t auth_certs_count; + uint16_t auth_certs_count_verify; // Number of signatures, needed for event verification + + dap_chain_callback_new_cfg_t prev_callback_created; // global network config init +} dap_chain_cs_block_poa_pvt_t; + +#define PVT(a) ((dap_chain_cs_block_poa_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); + +// CLI commands +static int s_cli_block_poa(int argc, char ** argv, void *arg_func, char **str_reply); + +static bool s_seed_mode = false; +/** + * @brief dap_chain_cs_block_poa_init + * @return + */ +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" + "\tSign new block with certificate <cert name> or withs own PoA certificate\n\n"); + return 0; } -void dap_chain_cs_block_poa_deinit() +/** + * @brief dap_chain_cs_block_poa_deinit + */ +void dap_chain_cs_block_poa_deinit(void) +{ + +} + + + +/** + * @brief s_cli_block_poa + * @param argc + * @param argv + * @param arg_func + * @param str_reply + * @return + */ +static int s_cli_block_poa(int argc, char ** argv, void *arg_func, char **a_str_reply) { + (void) arg_func; + int ret = -666; + int arg_index = 1; + dap_chain_net_t * l_chain_net = NULL; + dap_chain_t * l_chain = NULL; + + const char * l_hash_out_type = NULL; + dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-H", &l_hash_out_type); + if(!l_hash_out_type) + l_hash_out_type = "hex"; + if(dap_strcmp(l_hash_out_type, "hex") && dap_strcmp(l_hash_out_type, "base58")) { + dap_chain_node_cli_set_reply_text(a_str_reply, "invalid parameter -H, valid values: -H <hex | base58>"); + return -1; + } + + 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); + + // Load cert to sign if its present + if (l_cert_str) + l_cert = dap_cert_find_by_name( l_cert_str); + + // block hash may be in hex or base58 format + char *l_block_hash_hex_str; + char *l_event_hash_base58_str; + if(!dap_strncmp(l_block_hash_str, "0x", 2) || !dap_strncmp(l_block_hash_str, "0X", 2)) { + l_block_hash_hex_str = dap_strdup(l_block_hash_str); + l_event_hash_base58_str = dap_enc_base58_from_hex_str_to_str(l_block_hash_str); + } + else { + l_block_hash_hex_str = dap_enc_base58_to_hex_str_from_str(l_block_hash_str); + l_event_hash_base58_str = dap_strdup(l_block_hash_str); + } + + // Parse block ccmd + 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 ); + //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); + } + } + return ret; } + +/** + * @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_create(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 ); + + 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); + l_poa_pvt->auth_certs_count_verify = dap_config_get_item_uint16_default(a_chain_cfg,"block-poa","auth_certs_number_verify",0); + l_poa_pvt->auth_certs_prefix = strdup ( dap_config_get_item_str(a_chain_cfg,"block-poa","auth_certs_prefix") ); + if (l_poa_pvt->auth_certs_count && l_poa_pvt->auth_certs_count_verify ) { + l_poa_pvt->auth_certs = DAP_NEW_Z_SIZE ( dap_cert_t *, l_poa_pvt->auth_certs_count * sizeof(dap_cert_t)); + char l_cert_name[512]; + for (size_t i = 0; i < l_poa_pvt->auth_certs_count ; i++ ){ + dap_snprintf(l_cert_name,sizeof(l_cert_name),"%s.%lu",l_poa_pvt->auth_certs_prefix, i); + if ( (l_poa_pvt->auth_certs[i] = dap_cert_find_by_name( l_cert_name)) != NULL ) { + log_it(L_NOTICE, "Initialized auth cert \"%s\"", l_cert_name); + } else{ + log_it(L_ERROR, "Can't find cert \"%s\"", l_cert_name); + return -1; + } + } + } + } + log_it(L_NOTICE,"Initialized Block-PoA consensus with %u/%u minimum consensus",l_poa_pvt->auth_certs_count,l_poa_pvt->auth_certs_count_verify); + // Save old callback if present and set the call of its own (chain callbacks) + l_poa_pvt->prev_callback_created = l_blocks->chain->callback_created; + l_blocks->chain->callback_created = s_callback_created; + return 0; +} + +/** + * @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_poa_t * l_poa = DAP_CHAIN_CS_BLOCK_POA( l_blocks ); + + // Call previous callback if present. So the first called is the first in + 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); + + } + return 0; +} + +/** + * @brief s_chain_cs_dag_callback_delete + * @param a_dag + */ +static void s_callback_delete(dap_chain_cs_blocks_t * a_blocks) +{ + dap_chain_cs_block_poa_t * l_poa = DAP_CHAIN_CS_BLOCK_POA ( a_blocks ); + + if ( l_poa->_pvt ) { + dap_chain_cs_block_poa_pvt_t * l_poa_pvt = PVT ( l_poa ); + + if ( l_poa_pvt->auth_certs ) + DAP_DELETE ( l_poa_pvt->auth_certs); + + if ( l_poa_pvt->auth_certs_prefix ) + DAP_DELETE( l_poa_pvt->auth_certs_prefix ); + + DAP_DELETE ( l_poa->_pvt); + } + + if ( l_poa->_inheritor ) { + DAP_DELETE ( l_poa->_inheritor ); + } +} + + +/** + * @brief s_callbac_block_verify + * @param a_blocks + * @param a_block + * @param a_block_size + * @return + */ +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_poa_pvt_t * l_poa_pvt = PVT ( DAP_CHAIN_CS_BLOCK_POA( a_blocks ) ); + uint16_t l_signs_verified_count = 0; + + // Check for first signature + dap_sign_t * l_sign = dap_chain_block_sign_get(a_block,a_block_size,0); + if (! l_sign){ + log_it(L_ERROR, "No any signatures at all for block"); + 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_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; + } + // 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; + } + 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){ + l_signs_verified_count++; + break; + } + } + } + return l_signs_verified_count >= l_poa_pvt->auth_certs_count_verify ? 0 : -1; +} + diff --git a/modules/consensus/block-poa/include/dap_chain_cs_block_poa.h b/modules/consensus/block-poa/include/dap_chain_cs_block_poa.h index 0ee16e38fd..e2bc7b718b 100644 --- a/modules/consensus/block-poa/include/dap_chain_cs_block_poa.h +++ b/modules/consensus/block-poa/include/dap_chain_cs_block_poa.h @@ -1,29 +1,40 @@ /* * Authors: * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net> - * DeM Labs Inc. https://demlabs.net - * Kelvin Project https://github.com/kelvinblockchain - * Copyright (c) 2017-2018 + * DeM Labs Limited https://demlabs.net + * DAP SDK https://gitlab.demlabs.net/dap/dap-sdk + * Copyright (c) 2017 * All rights reserved. - This file is part of DAP (Deus Applications Prototypes) the open source project + This file is part of DAP SDK the open source project - DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify + 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 is distributed in the hope that it will be useful, + 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 based project. If not, see <http://www.gnu.org/licenses/>. + along with any DAP SDK based project. If not, see <http://www.gnu.org/licenses/>. */ #pragma once +#pragma once +#include "dap_chain_cs_blocks.h" + +typedef struct dap_chain_cs_block_poa +{ + dap_chain_t * chain; + dap_chain_cs_blocks_t * blocks; + void * _pvt; + void * _inheritor; +} dap_chain_cs_block_poa_t; +#define DAP_CHAIN_CS_BLOCK_POA(a) ( (dap_chain_cs_block_poa_t *) (a)->_inheritor) -int dap_chain_cs_block_poa_init(); -void dap_chain_cs_block_poa_deinit(); +int dap_chain_cs_block_poa_init(void); +void dap_chain_cs_block_poa_deinit(void); diff --git a/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c b/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c index 0f2e907ceb..0cbf2f2154 100644 --- a/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c +++ b/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c @@ -1,25 +1,25 @@ /* * Authors: * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net> - * DeM Labs Inc. https://demlabs.net - * Kelvin Project https://github.com/kelvinblockchain - * Copyright (c) 2017-2019 + * DeM Labs Limited https://demlabs.net + * CellFrame SDK https://cellframe.net + * Copyright (c) 2019 * All rights reserved. - This file is part of DAP (Deus Applications Prototypes) the open source project + This file is part of CellFrame SDK the open source project - DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify + CellFrame 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 is distributed in the hope that it will be useful, + CellFrame 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 based project. If not, see <http://www.gnu.org/licenses/>. + along with any DAP SDK based project. If not, see <http://www.gnu.org/licenses/>. */ #include <string.h> diff --git a/modules/consensus/dag-poa/include/dap_chain_cs_dag_poa.h b/modules/consensus/dag-poa/include/dap_chain_cs_dag_poa.h index b6f05be820..cdd0af9ff1 100644 --- a/modules/consensus/dag-poa/include/dap_chain_cs_dag_poa.h +++ b/modules/consensus/dag-poa/include/dap_chain_cs_dag_poa.h @@ -1,25 +1,25 @@ /* * Authors: * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net> - * DeM Labs Inc. https://demlabs.net - * Kelvin Project https://github.com/kelvinblockchain - * Copyright (c) 2017-2019 + * DeM Labs Limited https://demlabs.net + * CellFrame SDK https://cellframe.net + * Copyright (c) 2019 * All rights reserved. - This file is part of DAP (Deus Applications Prototypes) the open source project + This file is part of CellFrame SDK the open source project - DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify + CellFrame 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 is distributed in the hope that it will be useful, + CellFrame 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 based project. If not, see <http://www.gnu.org/licenses/>. + along with any DAP SDK based project. If not, see <http://www.gnu.org/licenses/>. */ #pragma once #include "dap_chain_cs_dag.h" diff --git a/modules/type/blocks/dap_chain_block.c b/modules/type/blocks/dap_chain_block.c index bace59def8..c504d8a95c 100644 --- a/modules/type/blocks/dap_chain_block.c +++ b/modules/type/blocks/dap_chain_block.c @@ -268,6 +268,90 @@ size_t dap_chain_block_datum_del_by_hash(dap_chain_block_t ** a_block_ptr, size_ return l_offset; } +static size_t s_block_get_sign_offset(dap_chain_block_t * a_block, size_t a_block_size) +{ + assert(a_block); + assert(a_block_size); + + 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 ; 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"); + return a_block_size; + } + // Check if size of of block size + if (l_datum_size+l_offset >a_block_size){ + log_it(L_ERROR,"Datum size is too big %zf thats with offset %zd is bigger than block size %zd", l_datum_size, l_offset, a_block_size); + return a_block_size; + } + 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){ + log_it(L_ERROR,"Offset %zd is bigger than block size %zd", l_offset, a_block_size); + return a_block_size; + } + + return l_offset; +} + +/** + * @brief dap_chain_block_sign_add + * @param a_block_ptr + * @param a_block_size + * @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 ) +{ + 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); + size_t l_block_sign_size = dap_sign_get_size(l_block_sign); + *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 ); + DAP_DELETE(l_block_sign); + return a_block_size+l_block_sign_size; +} + +/** + * @brief dap_chain_block_sign_get + * @param a_block + * @param a_block_size + * @param a_sign_num + * @return + */ +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_sign_size = dap_sign_get_size(l_sign); + if (!l_sign){ + 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 ); + 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; +} + /** * @brief dap_chain_block_get_datums * @param a_block diff --git a/modules/type/blocks/dap_chain_cs_blocks.c b/modules/type/blocks/dap_chain_cs_blocks.c index a9e618b7b6..dc1b335d92 100644 --- a/modules/type/blocks/dap_chain_cs_blocks.c +++ b/modules/type/blocks/dap_chain_cs_blocks.c @@ -64,9 +64,6 @@ typedef struct dap_chain_cs_blocks_pvt bool is_celled; - // For new block creating - dap_chain_block_t * block_new; - size_t block_new_size; } dap_chain_cs_blocks_pvt_t; typedef struct dap_chain_cs_blocks_iter @@ -370,10 +367,10 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void *a_arg_func, char **a_s // Flush memory for the new block case SUBCMD_NEW_FLUSH:{ pthread_rwlock_wrlock( &PVT(l_blocks)->rwlock ); - if ( PVT(l_blocks)->block_new ) - DAP_DELETE( PVT(l_blocks)->block_new ); - PVT(l_blocks)->block_new = dap_chain_block_new( PVT(l_blocks)->block_cache_last? &PVT(l_blocks)->block_cache_last->block_hash: NULL ); - PVT(l_blocks)->block_new_size = sizeof (PVT(l_blocks)->block_new->hdr); + 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); pthread_rwlock_unlock( &PVT(l_blocks)->rwlock ); } break; @@ -384,10 +381,10 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void *a_arg_func, char **a_s }break; case SUBCMD_NEW_DATUM_DEL:{ pthread_rwlock_wrlock( &PVT(l_blocks)->rwlock ); - if ( PVT(l_blocks)->block_new ){ + if ( l_blocks->block_new ){ dap_chain_hash_fast_t l_datum_hash; s_cli_parse_cmd_hash(a_argv,arg_index,a_argc,a_str_reply,"-datum", &l_datum_hash ); - PVT(l_blocks)->block_new_size=dap_chain_block_datum_del_by_hash( PVT(l_blocks)->block_new, PVT(l_blocks)->block_new_size, &l_datum_hash ); + l_blocks->block_new_size=dap_chain_block_datum_del_by_hash( &l_blocks->block_new, l_blocks->block_new_size, &l_datum_hash ); }else { dap_chain_node_cli_set_reply_text(a_str_reply, "Error! Can't delete datum from hash because no forming new block! Check pls you role, it must be MASTER NODE or greater"); @@ -1028,9 +1025,9 @@ static size_t s_callback_add_datums(dap_chain_t * a_chain, dap_chain_datum_t ** { // 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++) { - PVT(DAP_CHAIN_CS_BLOCKS(a_chain))->block_new_size = dap_chain_block_datum_add(PVT(DAP_CHAIN_CS_BLOCKS(a_chain))->block_new, - PVT(DAP_CHAIN_CS_BLOCKS(a_chain))->block_new_size, + 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]) ); } - return PVT(DAP_CHAIN_CS_BLOCKS(a_chain))->block_new_size; + return DAP_CHAIN_CS_BLOCKS(a_chain)->block_new_size; } diff --git a/modules/type/blocks/include/dap_chain_block.h b/modules/type/blocks/include/dap_chain_block.h index 31fc4b0e39..6364350205 100644 --- a/modules/type/blocks/include/dap_chain_block.h +++ b/modules/type/blocks/include/dap_chain_block.h @@ -2,7 +2,7 @@ * Authors: * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net> * DeM Labs Ltd https://demlabs.net - * Copyright (c) 2017-2020 + * Copyright (c) 2017 * All rights reserved. This file is part of DAP SDK the open source project @@ -24,6 +24,7 @@ #include "dap_common.h" #include "dap_math_ops.h" #include "dap_hash.h" +#include "dap_cert.h" #include "dap_chain_common.h" #include "dap_chain_datum.h" #include "dap_chain_datum_hashtree_roots.h" @@ -94,6 +95,10 @@ size_t dap_chain_block_meta_add(dap_chain_block_t ** a_block_ptr, 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); 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 ); +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 ); + // 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 ); diff --git a/modules/type/blocks/include/dap_chain_cs_blocks.h b/modules/type/blocks/include/dap_chain_cs_blocks.h index f2be5e7fa6..a60432337e 100644 --- a/modules/type/blocks/include/dap_chain_cs_blocks.h +++ b/modules/type/blocks/include/dap_chain_cs_blocks.h @@ -43,6 +43,9 @@ typedef dap_chain_block_t * (*dap_chain_cs_blocks_callback_block_create_t)(dap_c typedef struct dap_chain_cs_blocks { dap_chain_t * chain; + // For new block creating + dap_chain_block_t * block_new; + size_t block_new_size; dap_chain_cs_blocks_callback_t callback_delete; dap_chain_cs_blocks_callback_block_create_t callback_block_create; -- GitLab