diff --git a/CMakeLists.txt b/CMakeLists.txt index 4ed57cfbe6ed61d42b951aa773bb95b6fa6896eb..4cad786450e8bc9b9d7016fd84913178d93287ad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ project(cellframe-sdk C) cmake_minimum_required(VERSION 2.8) set(CMAKE_C_STANDARD 11) -set(CELLFRAME_SDK_NATIVE_VERSION "2.5-20") +set(CELLFRAME_SDK_NATIVE_VERSION "2.6-6") add_definitions ("-DCELLFRAME_SDK_VERSION=\"${CELLFRAME_SDK_NATIVE_VERSION}\"") set(DAPSDK_MODULES "") @@ -55,7 +55,7 @@ endif() # Networking if (CELLFRAME_MODULES MATCHES "network") message("[+] Module 'network'") - set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_server_core dap_enc_server dap_http_server dap_session + set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_server_core dap_json_rpc dap_enc_server dap_http_server dap_session dap_stream dap_stream_ch dap_client dap_stream_ch_chain dap_stream_ch_chain_net dap_chain_net dap_chain_mempool magic) endif() diff --git a/dap-sdk/crypto/include/dap_enc_base58.h b/dap-sdk/crypto/include/dap_enc_base58.h index 8392fb617e0f0c29a391484feaddb65a4e9193fe..8652d7bfd01a8626748f4cca624ba3925b0f8a79 100755 --- a/dap-sdk/crypto/include/dap_enc_base58.h +++ b/dap-sdk/crypto/include/dap_enc_base58.h @@ -47,6 +47,7 @@ char* dap_enc_base58_encode_hash_to_str(dap_chain_hash_fast_t *a_in_hash); char* dap_enc_base58_from_hex_str_to_str(const char *a_in_str); // convert from "Bura1HFrKsqbdytEXQVrxpbovtvLhR1VbrJs65JBx3gc" to "0xA21F1E865B6740A28E8708798ECF25D2C0AA596DF5EB1FD724186B6AD7FF2199" char* dap_enc_base58_to_hex_str_from_str(const char *a_in_str); +int dap_enc_base58_hex_to_hash(const char * a_hex_str, dap_chain_hash_fast_t * a_datum_hash); #ifdef __cplusplus } diff --git a/dap-sdk/crypto/src/dap_enc_base58.c b/dap-sdk/crypto/src/dap_enc_base58.c index acbfe8fcc550e359a81542ea00ab35564fe77636..fba7d9a63399290516220f17d4bf207fed7242bc 100755 --- a/dap-sdk/crypto/src/dap_enc_base58.c +++ b/dap-sdk/crypto/src/dap_enc_base58.c @@ -219,6 +219,34 @@ char* dap_enc_base58_encode_hash_to_str(dap_chain_hash_fast_t *a_in_hash) return dap_enc_base58_encode_to_str(a_in_hash->raw, sizeof(dap_chain_hash_fast_t)); } +/** + * @brief dap_enc_base58_hex_to_hash + * @param a_hex_str + * @param a_datum_hash + * @return + */ +int dap_enc_base58_hex_to_hash(const char * a_hex_str, dap_chain_hash_fast_t * a_datum_hash) +{ + assert(a_datum_hash); + + if (a_hex_str){ + char* l_datum_base58 = dap_enc_base58_from_hex_str_to_str(a_hex_str); + void * l_decoded = DAP_NEW_Z_SIZE(void,strlen(l_datum_base58)); + size_t l_decoded_size; + if (( l_decoded_size = dap_enc_base58_decode(l_datum_base58, l_decoded))!= sizeof (*a_datum_hash) ){ + memcpy( a_datum_hash, l_decoded, l_decoded_size); + return 0; + }else{ + log_it(L_ERROR,"Wrong hash format: can't parse \"%s\", decoded size %zd when expected %zd", a_hex_str, l_decoded_size, + sizeof (*a_datum_hash)); + return -1; + } + + }else + return -1; +} + + // convert from "0xA21F1E865B6740A28E8708798ECF25D2C0AA596DF5EB1FD724186B6AD7FF2199" to "Bura1HFrKsqbdytEXQVrxpbovtvLhR1VbrJs65JBx3gc" char* dap_enc_base58_from_hex_str_to_str(const char *a_in_str) { diff --git a/dap-sdk/net/core/dap_events.c b/dap-sdk/net/core/dap_events.c index fd786c671c1b1831f49cb734c6239ffa6f35185e..f29f7f3d8fde6dc2c51966100a673972b5739ccb 100644 --- a/dap-sdk/net/core/dap_events.c +++ b/dap-sdk/net/core/dap_events.c @@ -39,7 +39,7 @@ #include <sys/stat.h> #endif -#include <netdb.h> +//#include <netdb.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> diff --git a/dap-sdk/net/core/include/dap_events_socket.h b/dap-sdk/net/core/include/dap_events_socket.h index 474c26ad4ced342b3971f73dfb8d6a111fe74c40..0b9f6dcd07e380d975fc7c2a3a7eb94913c4fa4b 100644 --- a/dap-sdk/net/core/include/dap_events_socket.h +++ b/dap-sdk/net/core/include/dap_events_socket.h @@ -54,12 +54,12 @@ #define DAP_EVENTS_CAPS_PIPE_POSIX #endif -#if defined(DAP_EVENTS_CAPS_EPOLL) -#include <sys/epoll.h> -#define EPOLL_HANDLE int -#elif defined (DAP_EVENTS_CAPS_WEPOLL) +#if defined(DAP_EVENTS_CAPS_WEPOLL) #include "wepoll.h" #define EPOLL_HANDLE HANDLE +#elif defined (DAP_EVENTS_CAPS_EPOLL) +#include <sys/epoll.h> +#define EPOLL_HANDLE int #endif #define BIT( x ) ( 1 << x ) diff --git a/dap-sdk/net/server/CMakeLists.txt b/dap-sdk/net/server/CMakeLists.txt index dfc4ed963be9cd4d6bfd7e7d7dbaa46d5bbf32e8..498ed08f7e69ff297e6a347ddc215c5cdfc56b08 100644 --- a/dap-sdk/net/server/CMakeLists.txt +++ b/dap-sdk/net/server/CMakeLists.txt @@ -7,6 +7,7 @@ endif() add_subdirectory(http_server) add_subdirectory(enc_server) +add_subdirectory(json_rpc) if (BUILD_LIB_DAP_SERVER_TESTS) enable_testing() diff --git a/dap-sdk/net/server/http_server/http_client/dap_http_client.c b/dap-sdk/net/server/http_server/http_client/dap_http_client.c index 59f30cf660aefe3d5977ac80c5397f792e3355b6..8ee096e68d2b2fc0ad95c50161e7394e300c7a64 100644 --- a/dap-sdk/net/server/http_server/http_client/dap_http_client.c +++ b/dap-sdk/net/server/http_server/http_client/dap_http_client.c @@ -369,7 +369,7 @@ void dap_http_client_read( dap_events_socket_t *a_esocket, void *arg ) char *l_query_string; if( (l_query_string = strchr(l_http_client->url_path, '?')) != NULL ) { - size_t len_after = strlen( l_query_string + 1 ); + size_t len_after = MIN(strlen( l_query_string + 1 ), sizeof (l_http_client->url_path)-1); if ( len_after ) { if( len_after > (sizeof(l_http_client->in_query_string) - 1) ){ diff --git a/dap-sdk/net/server/json_rpc/CMakeLists.txt b/dap-sdk/net/server/json_rpc/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..7c6ac9cea29ad497ba58da6433ec80bfb2b8e1d3 --- /dev/null +++ b/dap-sdk/net/server/json_rpc/CMakeLists.txt @@ -0,0 +1,17 @@ +project(dap_json_rpc C) +cmake_minimum_required(VERSION 3.0) + +add_definitions ("-D_GNU_SOURCE") +add_definitions("-Dfpic") + +file(GLOB JSON_RPC_HEADERS include/*.h) +file(GLOB JSON_RPC_SRCS src/*.c) + +include_directories(${PROJECT_NAME} include/) + +add_library(${PROJECT_NAME} STATIC ${JSON_RPC_HEADERS} ${JSON_RPC_SRCS}) +target_include_directories(${PROJECT_NAME} INTERFACE . include/) +target_include_directories(${PROJECT_NAME} PUBLIC include) + +target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_server_core dap_http_server dap_client json-c ) +#target_link_libraries(${PROJECT_NAME} dap_core)# dap_http_server json-c) diff --git a/modules/type/block/include/dap_chain_cs_blocks.h b/dap-sdk/net/server/json_rpc/include/dap_json_rpc.h similarity index 55% rename from modules/type/block/include/dap_chain_cs_blocks.h rename to dap-sdk/net/server/json_rpc/include/dap_json_rpc.h index ae1dc4c701f888759bc73026ff47dc9917bfa925..8032fa93860dc67564100bfe949135da45d5d591 100644 --- a/modules/type/block/include/dap_chain_cs_blocks.h +++ b/dap-sdk/net/server/json_rpc/include/dap_json_rpc.h @@ -1,9 +1,9 @@ /* * Authors: - * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net> + * Alexey V. Stratulat <alexey.stratulat@demlabs.net> * DeM Labs Inc. https://demlabs.net - * Kelvin Project https://github.com/kelvinblockchain - * Copyright (c) 2017-2018 + * DeM Labs Open source community https://gitlab.demlabs.net/cellframe/cellframe-sdk + * Copyright (c) 2017-2020 * All rights reserved. This file is part of DAP (Deus Applications Prototypes) the open source project @@ -21,23 +21,27 @@ 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.h" -#include "dap_chain_block.h" -#include "dap_chain_block_cache.h" - -typedef struct dap_chain_cs_blocks -{ - dap_chain_t * chain; - void * _pvt; - void * _iheritor; -} dap_chain_cs_blocks_t; -typedef int (*dap_chain_blocks_block_callback_ptr_t)(dap_chain_cs_blocks_t *, dap_chain_block_t *); -int dap_chain_cs_blocks_init(); -void dap_chain_cs_blocks_deinit(); - -dap_chain_block_cache_t* dap_chain_cs_blocks_allocate_next_block(dap_chain_cs_blocks_t * a_cs_blocks); -void dap_chain_cs_blocks_new(dap_chain_t * a_chain); +#pragma once +#include "dap_http_simple.h" +#include "include/http_status_code.h" +#include "dap_strfuncs.h" +#include "dap_json_rpc_request.h" +#include "dap_json_rpc_request_handler.h" + +#ifdef __cplusplus +extern "C"{ +#endif + +typedef enum dap_json_rpc_version{ + RPC_VERSION_1 +}dap_json_rpc_version_t; + +int dap_json_rpc_init(); +void dap_json_rpc_deinit(); +void dap_json_rpc_add_proc_http(struct dap_http *sh, const char *URL); + +#ifdef __cplusplus +} +#endif diff --git a/dap-sdk/net/server/json_rpc/include/dap_json_rpc_errors.h b/dap-sdk/net/server/json_rpc/include/dap_json_rpc_errors.h new file mode 100644 index 0000000000000000000000000000000000000000..c0811b0afbdbfb33a61de35f6a67879f143d2eb0 --- /dev/null +++ b/dap-sdk/net/server/json_rpc/include/dap_json_rpc_errors.h @@ -0,0 +1,70 @@ +/* + * Authors: + * Alexey V. Stratulat <alexey.stratulat@demlabs.net> + * DeM Labs Inc. https://demlabs.net + * DeM Labs Open source community https://gitlab.demlabs.net/cellframe/cellframe-sdk + * Copyright (c) 2017-2020 + * 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_common.h" +#include "dap_strfuncs.h" +#include "utlist.h" +#include "json-c/json.h" + +#ifdef __cplusplus +extern "C"{ +#endif + +typedef struct dap_json_rpc_error +{ + int code_error; + char *msg; + void *next; +}dap_json_rpc_error_t; + +typedef struct dap_json_rpc_error_JSON +{ + json_object *obj_code; + json_object *obj_msg; +}dap_json_rpc_error_JSON_t; + +int dap_json_rpc_error_init(void); +void dap_json_rpc_error_deinit(void); + +dap_json_rpc_error_JSON_t * dap_json_rpc_error_JSON_create(); +void dap_json_rpc_error_JSON_free(dap_json_rpc_error_JSON_t *a_error_json); +dap_json_rpc_error_JSON_t * dap_json_rpc_error_JSON_add_data(int code, const char *msg); + +int dap_json_rpc_error_add(int a_code_error, const char *a_msg); + +dap_json_rpc_error_t *dap_json_rpc_error_search_by_code(int a_code_error); + +char *dap_json_rpc_error_get_json(dap_json_rpc_error_t *a_error); + +dap_json_rpc_error_t *dap_json_rpc_create_from_json(const char *a_json); + +dap_json_rpc_error_t *dap_json_rpc_create_from_json_object(json_object *a_jobj); + +void dap_json_rpc_add_standart_erros(void); + +#ifdef __cplusplus +} +#endif diff --git a/modules/type/block/include/dap_chain_block_cache.h b/dap-sdk/net/server/json_rpc/include/dap_json_rpc_notification.h similarity index 50% rename from modules/type/block/include/dap_chain_block_cache.h rename to dap-sdk/net/server/json_rpc/include/dap_json_rpc_notification.h index b2949d276da6b6ee459bfe7838e61e28c796a0bb..239ac8ecfea0bef24862d386b0ac6216aeb02819 100644 --- a/modules/type/block/include/dap_chain_block_cache.h +++ b/dap-sdk/net/server/json_rpc/include/dap_json_rpc_notification.h @@ -1,9 +1,9 @@ /* * Authors: - * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net> + * Alexey V. Stratulat <alexey.stratulat@demlabs.net> * DeM Labs Inc. https://demlabs.net - * Kelvin Project https://github.com/kelvinblockchain - * Copyright (c) 2017-2018 + * DeM Labs Open source community https://gitlab.demlabs.net/cellframe/cellframe-sdk + * Copyright (c) 2017-2020 * All rights reserved. This file is part of DAP (Deus Applications Prototypes) the open source project @@ -22,19 +22,28 @@ along with any DAP based project. If not, see <http://www.gnu.org/licenses/>. */ #pragma once -#include "dap_chain_block.h" -#include "dap_hash.h" -typedef struct dap_chain_block_cache{ - dap_chain_hash_t block_hash; - uint32_t sections_size; +#include "dap_json_rpc_request.h" +#include "uthash.h" - double block_mine_time; - dap_chain_block_t * block; -} dap_chain_block_cache_t; +#ifdef __cplusplus +extern "C"{ +#endif -dap_chain_block_cache_t * dap_chain_block_cache_new(dap_chain_block_t * a_block); -void dap_chain_block_cache_delete(dap_chain_block_cache_t * a_block_cache); -dap_chain_block_t* dap_chain_block_cache_sections_size_grow(dap_chain_block_cache_t * a_block_cache,size_t a_sections_size_grow ); +typedef void (notification_handler_func_t)(dap_json_rpc_params_t *a_param); -void dap_chain_block_cache_dump(dap_chain_block_cache_t * a_block_cache); +typedef struct dap_json_rpc_notification_handler +{ + char *method; + notification_handler_func_t *func; + UT_hash_handle hh; +}dap_json_rpc_notification_handler_t; + +int dap_json_rpc_notification_registration(const char *a_method, notification_handler_func_t *a_notification_func); +void dap_json_rpc_notification_unregistration(const char *a_method); + +void dap_json_rpc_notification_handler(const char *a_name_method, dap_json_rpc_params_t *a_params); + +#ifdef __cplusplus +} +#endif diff --git a/dap-sdk/net/server/json_rpc/include/dap_json_rpc_params.h b/dap-sdk/net/server/json_rpc/include/dap_json_rpc_params.h new file mode 100644 index 0000000000000000000000000000000000000000..9068f4a0ff217aee3e8a8533599c558882140601 --- /dev/null +++ b/dap-sdk/net/server/json_rpc/include/dap_json_rpc_params.h @@ -0,0 +1,73 @@ +/* + * Authors: + * Alexey V. Stratulat <alexey.stratulat@demlabs.net> + * DeM Labs Inc. https://demlabs.net + * DeM Labs Open source community https://gitlab.demlabs.net/cellframe/cellframe-sdk + * Copyright (c) 2017-2020 + * 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_common.h" +#include "dap_strfuncs.h" +#include "json-c/json.h" + +#ifdef __cplusplus +extern "C"{ +#endif + +typedef enum dap_json_rpc_type_param{ + TYPE_PARAM_NULL, + TYPE_PARAM_STRING, + TYPE_PARAM_INTEGER, + TYPE_PARAM_DOUBLE, + TYPE_PARAM_BOOLEAN +}dap_json_rpc_type_param_t; + +typedef struct dap_json_rpc_param +{ + void *value_param; + enum dap_json_rpc_type_param type; +}dap_json_rpc_param_t; + +typedef struct dap_json_rpc_params +{ + uint32_t lenght; + dap_json_rpc_param_t **params; +}dap_json_rpc_params_t; + +dap_json_rpc_params_t* dap_json_rpc_params_create(void); + +void dap_json_rpc_params_add_data(dap_json_rpc_params_t *a_params, const void *a_value, + dap_json_rpc_type_param_t a_type); +void dap_json_rpc_params_add_param(dap_json_rpc_params_t *a_params, dap_json_rpc_param_t *a_param); + +void dap_json_rpc_params_remove_all(dap_json_rpc_params_t *a_params); + +uint32_t dap_json_rpc_params_lenght(dap_json_rpc_params_t *a_params); +void *dap_json_rpc_params_get(dap_json_rpc_params_t *a_params, uint32_t index); +dap_json_rpc_type_param_t dap_json_rpc_params_get_type_param(dap_json_rpc_params_t *a_params, uint32_t index); + +void dap_json_rpc_param_remove(dap_json_rpc_param_t *param); + +dap_json_rpc_params_t * dap_json_rpc_params_create_from_array_list(json_object *a_array_list); +char *dap_json_rpc_params_get_string_json(dap_json_rpc_params_t * a_params); + +#ifdef __cplusplus +} +#endif diff --git a/dap-sdk/net/server/json_rpc/include/dap_json_rpc_request.h b/dap-sdk/net/server/json_rpc/include/dap_json_rpc_request.h new file mode 100644 index 0000000000000000000000000000000000000000..9182f64c757982166eaf5e6c6557a1a281aa5e4c --- /dev/null +++ b/dap-sdk/net/server/json_rpc/include/dap_json_rpc_request.h @@ -0,0 +1,57 @@ +/* + * Authors: + * Alexey V. Stratulat <alexey.stratulat@demlabs.net> + * DeM Labs Inc. https://demlabs.net + * DeM Labs Open source community https://gitlab.demlabs.net/cellframe/cellframe-sdk + * Copyright (c) 2017-2020 + * 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_common.h" +#include "dap_json_rpc_params.h" +#include "json-c/json.h" +#include "dap_json_rpc_response_handler.h" +#include "dap_string.h" +#include "dap_client_http.h" + +#ifdef __cplusplus +extern "C"{ +#endif + +typedef struct dap_json_rpc_request +{ + char* method; + dap_json_rpc_params_t *params; + uint64_t id; +}dap_json_rpc_request_t; + +int dap_json_rpc_request_init(const char *a_url_service); + +dap_json_rpc_request_t *dap_json_rpc_request_creation(const char *a_method, dap_json_rpc_params_t *a_params, int64_t a_id); + +dap_json_rpc_request_t *dap_json_rpc_request_from_json(const char *a_data); +char *dap_json_rpc_request_to_json(const dap_json_rpc_request_t *a_request); + +void dap_json_rpc_request_send(dap_json_rpc_request_t *a_request, dap_json_rpc_response_handler_func_t *response_handler, + const char *a_uplink_addr, const uint16_t a_uplink_port, + dap_client_http_callback_error_t func_error); + +#ifdef __cplusplus +} +#endif diff --git a/dap-sdk/net/server/json_rpc/include/dap_json_rpc_request_handler.h b/dap-sdk/net/server/json_rpc/include/dap_json_rpc_request_handler.h new file mode 100644 index 0000000000000000000000000000000000000000..64f9adc60e9ef37180c78894436ddd8235df4c50 --- /dev/null +++ b/dap-sdk/net/server/json_rpc/include/dap_json_rpc_request_handler.h @@ -0,0 +1,56 @@ +/* + * Authors: + * Alexey V. Stratulat <alexey.stratulat@demlabs.net> + * DeM Labs Inc. https://demlabs.net + * DeM Labs Open source community https://gitlab.demlabs.net/cellframe/cellframe-sdk + * Copyright (c) 2017-2020 + * 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_common.h" +#include "dap_strfuncs.h" +#include "dap_json_rpc_request.h" +#include "dap_json_rpc_params.h" +#include "dap_http_simple.h" +#include "dap_json_rpc_errors.h" +#include "dap_json_rpc_response.h" +#include "dap_json_rpc_notification.h" +#include "uthash.h" + +#ifdef __cplusplus +extern "C"{ +#endif + +typedef void (handler_func_t)(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); + +typedef struct dap_json_rpc_request_handler +{ + char *name; + handler_func_t *func; + UT_hash_handle hh; +}dap_json_rpc_request_handler_t; + +int dap_json_rpc_registration_request_handler(const char *a_name, handler_func_t *a_func); +int dap_json_rpc_unregistration_request_handler(const char *a_name); + +void dap_json_rpc_request_handler(dap_json_rpc_request_t *a_request, dap_http_simple_t *a_client); +#ifdef __cplusplus +} +#endif diff --git a/dap-sdk/net/server/json_rpc/include/dap_json_rpc_response.h b/dap-sdk/net/server/json_rpc/include/dap_json_rpc_response.h new file mode 100644 index 0000000000000000000000000000000000000000..40ef6ac826e0b774eea4b2ea04a65ecfdbf693f0 --- /dev/null +++ b/dap-sdk/net/server/json_rpc/include/dap_json_rpc_response.h @@ -0,0 +1,74 @@ +/* + * Authors: + * Alexey V. Stratulat <alexey.stratulat@demlabs.net> + * DeM Labs Inc. https://demlabs.net + * DeM Labs Open source community https://gitlab.demlabs.net/cellframe/cellframe-sdk + * Copyright (c) 2017-2020 + * 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_http_simple.h" +#include "dap_json_rpc_errors.h" +#include "json-c/json.h" + +#ifdef __cplusplus +extern "C"{ +#endif + +typedef enum dap_json_rpc_response_type_result{ + TYPE_RESPONSE_NULL, + TYPE_RESPONSE_STRING, + TYPE_RESPONSE_INTEGER, + TYPE_RESPONSE_DOUBLE, + TYPE_RESPONSE_BOOLEAN +}dap_json_rpc_response_type_result_t; + +typedef struct dap_json_rpc_response_JSON +{ + json_object *obj_result; + json_object *obj_error; + dap_json_rpc_error_JSON_t *struct_error; + json_object *obj_id; +}dap_json_rpc_request_JSON_t; + +void dap_json_rpc_request_JSON_free(dap_json_rpc_request_JSON_t *l_request_JSON); + +typedef struct dap_json_rpc_response +{ + dap_json_rpc_response_type_result_t type_result; + char* result_string; + int64_t result_int; + double result_double; + bool result_boolean; + dap_json_rpc_error_t* error; + int64_t id; +}dap_json_rpc_response_t; + + +void dap_json_rpc_response_free(dap_json_rpc_response_t *a_response); + +void dap_json_rpc_response_send(dap_json_rpc_response_t *a_response, dap_http_simple_t *a_client); + +dap_json_rpc_response_t *dap_json_rpc_response_from_json(char *a_data_json); + + +#ifdef __cplusplus +} +#endif diff --git a/dap-sdk/net/server/json_rpc/include/dap_json_rpc_response_handler.h b/dap-sdk/net/server/json_rpc/include/dap_json_rpc_response_handler.h new file mode 100644 index 0000000000000000000000000000000000000000..1861ac2ce9a8bd08b738b498389529d356a9769f --- /dev/null +++ b/dap-sdk/net/server/json_rpc/include/dap_json_rpc_response_handler.h @@ -0,0 +1,55 @@ +/* + * Authors: + * Alexey V. Stratulat <alexey.stratulat@demlabs.net> + * DeM Labs Inc. https://demlabs.net + * DeM Labs Open source community https://gitlab.demlabs.net/cellframe/cellframe-sdk + * Copyright (c) 2017-2020 + * 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_json_rpc_response.h" +#include "uthash.h" + +#ifdef __cplusplus +extern "C"{ +#endif + +typedef void (dap_json_rpc_response_handler_func_t)(dap_json_rpc_response_t *a_response); + +typedef struct dap_json_rpc_response_handler +{ + dap_json_rpc_response_handler_func_t *func; + uint64_t id; + UT_hash_handle hh; +}dap_json_rpc_response_handler_t; + +int dap_json_rpc_response_registration_with_id(uint64_t a_id, dap_json_rpc_response_handler_func_t *func); +uint64_t dap_json_rpc_response_registration(dap_json_rpc_response_handler_func_t *func); +void dap_json_rpc_response_unregistration(uint64_t a_id); + +void dap_json_rpc_response_handler(dap_json_rpc_response_t *a_response); + +uint64_t dap_json_rpc_response_get_new_id(void); + +void dap_json_rpc_response_accepted(void *a_data, size_t a_size_data, void *a_obj); + +#ifdef __cplusplus +} +#endif diff --git a/dap-sdk/net/server/json_rpc/src/dap_json_rpc.c b/dap-sdk/net/server/json_rpc/src/dap_json_rpc.c new file mode 100644 index 0000000000000000000000000000000000000000..57832ccd9438745f63b2b641dacd9382e9ce5a98 --- /dev/null +++ b/dap-sdk/net/server/json_rpc/src/dap_json_rpc.c @@ -0,0 +1,35 @@ +#include "dap_json_rpc.h" + +#define LOG_TAG "dap_json_rpc_rpc" + +static bool init_module = false; + +int dap_json_rpc_init() +{ + init_module = true; + return 0; +} + +void dap_json_rpc_deinit() +{ + // +} + +void _json_rpc_http_proc(struct dap_http_simple *a_client, void *a_arg) +{ + log_it(L_DEBUG, "Proc json_rpc request"); + http_status_code_t *l_http_code = (http_status_code_t*)a_arg; + dap_json_rpc_request_t *l_request = dap_json_rpc_request_from_json(a_client->request); + if (l_request){ + dap_json_rpc_request_handler(l_request, a_client); + } else { + *l_http_code = Http_Status_NotFound; + } + *l_http_code = Http_Status_OK; +} + +void dap_json_rpc_add_proc_http(struct dap_http *sh, const char *URL) +{ + dap_http_simple_proc_add(sh, URL, 140000, _json_rpc_http_proc); + dap_json_rpc_request_init(URL); +} diff --git a/dap-sdk/net/server/json_rpc/src/dap_json_rpc_errors.c b/dap-sdk/net/server/json_rpc/src/dap_json_rpc_errors.c new file mode 100644 index 0000000000000000000000000000000000000000..6d465ddcc6553e861eede6ab1ccd7870f9b97696 --- /dev/null +++ b/dap-sdk/net/server/json_rpc/src/dap_json_rpc_errors.c @@ -0,0 +1,120 @@ +#include "dap_json_rpc_errors.h" + +#define LOG_TAG "dap_json_rpc_errors" + +static dap_json_rpc_error_t *s_errors; +int _dap_json_rpc_error_cmp_by_code(dap_json_rpc_error_t *a_error, int a_code_error); + +int dap_json_rpc_error_init(void) +{ + s_errors = NULL; + return 0; +} +void dap_json_rpc_error_deinit(void) +{ + dap_json_rpc_error_t *err, *tmp; + if (s_errors != NULL){ + LL_FOREACH_SAFE(s_errors, err, tmp){ + LL_DELETE(s_errors, err); + DAP_FREE(err->msg); + DAP_FREE(err); + } + } +} + +dap_json_rpc_error_JSON_t * dap_json_rpc_error_JSON_create() +{ + dap_json_rpc_error_JSON_t *l_json = DAP_NEW(dap_json_rpc_error_JSON_t); + l_json->obj_msg = NULL; + l_json->obj_code = NULL; + return l_json; +} +void dap_json_rpc_error_JSON_free(dap_json_rpc_error_JSON_t *a_error_json) +{ + json_object_put(a_error_json->obj_code); + json_object_put(a_error_json->obj_msg); + DAP_FREE(a_error_json); +} +dap_json_rpc_error_JSON_t * dap_json_rpc_error_JSON_add_data(int code, const char *msg) +{ + dap_json_rpc_error_JSON_t *l_json_err = dap_json_rpc_error_JSON_create(); + l_json_err->obj_code = json_object_new_int(code); + l_json_err->obj_msg = json_object_new_string(msg); + return l_json_err; +} + +int dap_json_rpc_error_add(int a_code_error, const char *a_msg) +{ + dap_json_rpc_error_t *l_el_search =dap_json_rpc_error_search_by_code(a_code_error); + if (l_el_search != NULL) + return 1; + dap_json_rpc_error_t *l_error = DAP_NEW(dap_json_rpc_error_t); + l_error->code_error = a_code_error; + l_error->msg = dap_strdup(a_msg); + LL_APPEND(s_errors, l_error); + log_it(L_NOTICE, "Registration type error. Code error: %d message: %s", a_code_error, a_msg); + return 0; +} + +int _dap_json_rpc_error_cmp_by_code(dap_json_rpc_error_t *a_error, int a_code_error) +{ + if (a_error->code_error == a_code_error) + return 0; + if (a_error->code_error < a_code_error) + return -1; + if (a_error->code_error > a_code_error) + return 1; +} + +dap_json_rpc_error_t *dap_json_rpc_error_search_by_code(int a_code_error) +{ + dap_json_rpc_error_t *l_element = NULL; + LL_SEARCH(s_errors, l_element, a_code_error, _dap_json_rpc_error_cmp_by_code); + return l_element; +} + +char *dap_json_rpc_error_get_json(dap_json_rpc_error_t *a_error) +{ + log_it(L_NOTICE, "Translation JSON string to struct dap_json_rpc_error"); + json_object *l_jobj_code = json_object_new_int64(a_error->code_error); + json_object *l_jobj_msg = json_object_new_string(a_error->msg); + json_object *l_jobj = json_object_new_object(); + json_object_object_add(l_jobj, "code", l_jobj_code); + json_object_object_add(l_jobj, "message", l_jobj_msg); + json_object *l_jobj_err = json_object_new_object(); + json_object_object_add(l_jobj_err, "error", l_jobj); + char *l_json_str = dap_strdup(json_object_to_json_string(l_jobj_err)); + json_object_put(l_jobj_err); + json_object_put(l_jobj_code); + json_object_put(l_jobj_msg); + json_object_put(l_jobj); + return l_json_str; +} + +dap_json_rpc_error_t *dap_json_rpc_create_from_json(const char *a_json) +{ + log_it(L_NOTICE, "Translation struct dap_json_rpc_error to JSON string"); + json_object *l_jobj = json_tokener_parse(a_json); + dap_json_rpc_error_t *l_error = dap_json_rpc_create_from_json_object(l_jobj); + json_object_put(l_jobj); + return l_error; +} + +void dap_json_rpc_add_standart_erros(void) +{ + log_it(L_DEBUG, "Registration standart type erros"); + dap_json_rpc_error_add(0, "Unknown error"); + dap_json_rpc_error_add(1, "Not found handler for this request"); +} + +dap_json_rpc_error_t *dap_json_rpc_create_from_json_object(json_object *a_jobj) +{ + dap_json_rpc_error_t *l_error = DAP_NEW(dap_json_rpc_error_t); + json_object *l_jobj_code_eror = json_object_object_get(a_jobj, "code"); + json_object *l_jobj_msg = json_object_object_get(a_jobj, "message"); + l_error->code_error = json_object_get_int64(l_jobj_code_eror); + l_error->msg = dap_strdup(json_object_get_string(l_jobj_msg)); + json_object_put(l_jobj_code_eror); + json_object_put(l_jobj_msg); + return l_error; +} diff --git a/dap-sdk/net/server/json_rpc/src/dap_json_rpc_notification.c b/dap-sdk/net/server/json_rpc/src/dap_json_rpc_notification.c new file mode 100644 index 0000000000000000000000000000000000000000..8c4e973bab1d1e57ab1c9b94c61f4b834b556b65 --- /dev/null +++ b/dap-sdk/net/server/json_rpc/src/dap_json_rpc_notification.c @@ -0,0 +1,44 @@ +#include "dap_json_rpc_notification.h" + +#define LOG_TAG "dap_json_rpc_notification" + +static dap_json_rpc_notification_handler_t *s_handler_notifications = NULL; + + +int dap_json_rpc_notification_registration(const char *a_method, notification_handler_func_t *a_notification_func) +{ + dap_json_rpc_notification_handler_t *l_handler; + HASH_FIND_STR(s_handler_notifications, a_method, l_handler); + if (l_handler == 0){ + l_handler = DAP_NEW(dap_json_rpc_notification_handler_t); + l_handler->method = dap_strdup(a_method); + l_handler->func = a_notification_func; + HASH_ADD_STR(s_handler_notifications, method, l_handler); + log_it(L_NOTICE, "Registration method %s for handler notification", a_method); + return 0; + } + return 1; +} +void dap_json_rpc_notification_unregistration(const char *a_method) +{ + dap_json_rpc_notification_handler_t *l_handler; + HASH_FIND_STR(s_handler_notifications, a_method, l_handler); + if (l_handler != NULL){ + HASH_DEL(s_handler_notifications, l_handler); + DAP_FREE(l_handler->method); + DAP_FREE(l_handler); + log_it(L_NOTICE, "Unregistration method %s. This method handler notification", a_method); + } +} + +void dap_json_rpc_notification_handler(const char *a_name_method, dap_json_rpc_params_t *a_params) +{ + dap_json_rpc_notification_handler_t *l_handler = NULL; + HASH_FIND_STR(s_handler_notifications, a_name_method, l_handler); + if (l_handler != NULL){ + l_handler->func(a_params); + log_it(L_DEBUG, "Call method handling notfication: %s", a_name_method); + } else { + log_it(L_NOTICE, "Not found method %s. This method handler notification"); + } +} diff --git a/dap-sdk/net/server/json_rpc/src/dap_json_rpc_params.c b/dap-sdk/net/server/json_rpc/src/dap_json_rpc_params.c new file mode 100644 index 0000000000000000000000000000000000000000..07d3835e8eb5269cebd9485dc6b7c1e1c4f831f8 --- /dev/null +++ b/dap-sdk/net/server/json_rpc/src/dap_json_rpc_params.c @@ -0,0 +1,160 @@ +#include "dap_json_rpc_params.h" + +#define LOG_TAG "dap_json_rpc_params" + +dap_json_rpc_params_t* dap_json_rpc_params_create(void) +{ + dap_json_rpc_params_t *l_params = DAP_NEW(dap_json_rpc_params_t); + l_params->lenght = 0; + return l_params; +} + + +void dap_json_rpc_params_add_data(dap_json_rpc_params_t *a_params, const void *a_value, + dap_json_rpc_type_param_t a_type) +{ + log_it(L_DEBUG, "Add data in params"); + dap_json_rpc_param_t *l_param = DAP_NEW(dap_json_rpc_param_t); + //l_param->name_param = dap_strdup(a_name); + l_param->type = a_type; + size_t l_len_value; + switch (a_type) { + case TYPE_PARAM_STRING: + l_param->value_param = dap_strdup((char*)a_value); + break; + case TYPE_PARAM_BOOLEAN: + l_len_value = sizeof(bool); + l_param->value_param = DAP_NEW(bool); + memcpy(l_param->value_param, a_value, l_len_value); + break; + case TYPE_PARAM_INTEGER: + l_len_value = sizeof(int64_t); + l_param->value_param = DAP_NEW(int64_t); + memcpy(l_param->value_param, a_value, l_len_value); + break; + case TYPE_PARAM_DOUBLE: + l_len_value = sizeof(double); + l_param->value_param = DAP_NEW(double); + memcpy(l_param->value_param, a_value, l_len_value); + break; + default: + l_param->value_param = NULL; + break; + } + dap_json_rpc_params_add_param(a_params, l_param); +} +void dap_json_rpc_params_add_param(dap_json_rpc_params_t *a_params, dap_json_rpc_param_t *a_param) +{ + uint32_t l_len_new_params = a_params->lenght + 1; + dap_json_rpc_param_t **l_new_params = DAP_NEW_SIZE(dap_json_rpc_param_t*, l_len_new_params); + memcpy(l_new_params, a_params->params, sizeof(dap_json_rpc_param_t*) * a_params->lenght); + memcpy(l_new_params+a_params->lenght, &a_param, sizeof(dap_json_rpc_param_t*)); + if (a_params->lenght != 0) + DAP_FREE(a_params->params); + a_params->params = l_new_params; + a_params->lenght++; +} + +void dap_json_rpc_params_remove_all(dap_json_rpc_params_t *a_params) +{ + log_it(L_DEBUG, "Clean params"); + for (uint32_t i=0x0 ; i < dap_json_rpc_params_lenght(a_params); i++){ + dap_json_rpc_param_remove(a_params->params[i]); + } + DAP_FREE(a_params); +} + +uint32_t dap_json_rpc_params_lenght(dap_json_rpc_params_t *a_params) +{ + return a_params->lenght; +} + +void *dap_json_rpc_params_get(dap_json_rpc_params_t *a_params, uint32_t index) +{ + if (a_params->lenght > index) + return a_params->params[index]->value_param; + return NULL; +} + +dap_json_rpc_type_param_t dap_json_rpc_params_get_type_param(dap_json_rpc_params_t *a_params, uint32_t index) +{ + if (a_params->lenght > index) + return a_params->params[index]->type; + return TYPE_PARAM_NULL; +} + +void dap_json_rpc_param_remove(dap_json_rpc_param_t *param) +{ + DAP_FREE(param->value_param); + DAP_FREE(param); +} + +dap_json_rpc_params_t * dap_json_rpc_params_create_from_array_list(json_object *a_array_list) +{ + log_it(L_NOTICE, "Translation json_object to dap_json_rpc_params"); + if (a_array_list == NULL) + return NULL; + dap_json_rpc_params_t *l_params = dap_json_rpc_params_create(); + int l_lenght = json_object_array_length(a_array_list); + for (int i = 0; i < l_lenght; i++){ + json_object *l_jobj = json_object_array_get_idx(a_array_list, i); + json_type l_jobj_type = json_object_get_type(l_jobj); + char *l_str_tmp = NULL; + bool l_bool_tmp; + int64_t l_int_tmp; + double l_double_tmp; + switch (l_jobj_type) { + case json_type_string: + l_str_tmp = dap_strdup(json_object_get_string(l_jobj)); + dap_json_rpc_params_add_data(l_params, l_str_tmp, TYPE_PARAM_STRING); + DAP_FREE(l_str_tmp); + break; + case json_type_boolean: + l_bool_tmp = json_object_get_boolean(l_jobj); + dap_json_rpc_params_add_data(l_params, &l_bool_tmp, TYPE_PARAM_BOOLEAN); + break; + case json_type_int: + l_int_tmp = json_object_get_int64(l_jobj); + dap_json_rpc_params_add_data(l_params, &l_int_tmp, TYPE_PARAM_INTEGER); + break; + case json_type_double: + l_double_tmp = json_object_get_double(l_jobj); + dap_json_rpc_params_add_data(l_params, &l_double_tmp, TYPE_PARAM_DOUBLE); + break; + default: + dap_json_rpc_params_add_data(l_params, NULL, TYPE_PARAM_NULL); + } + } + return l_params; +} + +char *dap_json_rpc_params_get_string_json(dap_json_rpc_params_t * a_params) +{ + log_it(L_NOTICE, "Translation struct params to JSON string"); + json_object *l_jobj_array = json_object_new_array(); + for (uint32_t i = 0; i <= a_params->lenght; i++){ + json_object *l_jobj_tmp = NULL; + switch (a_params->params[i]->type) { + case TYPE_PARAM_NULL: + l_jobj_tmp = json_object_new_object(); + break; + case TYPE_PARAM_STRING: + l_jobj_tmp = json_object_new_string((char*)a_params->params[i]->value_param); + break; + case TYPE_PARAM_INTEGER: + l_jobj_tmp = json_object_new_int64(*((int64_t*)a_params->params[i]->value_param)); + break; + case TYPE_PARAM_DOUBLE: + l_jobj_tmp = json_object_new_double(*((double*)a_params->params[i]->value_param)); + break; + case TYPE_PARAM_BOOLEAN: + l_jobj_tmp = json_object_new_boolean(*((bool*)a_params->params[i]->value_param)); + break; + } + json_object_array_add(l_jobj_array, l_jobj_tmp); + json_object_put(l_jobj_tmp); + }; + char *l_str = dap_strjoin(NULL, "\"params\":", json_object_to_json_string(l_jobj_array), NULL); + json_object_put(l_jobj_array); + return l_str; +} diff --git a/dap-sdk/net/server/json_rpc/src/dap_json_rpc_request.c b/dap-sdk/net/server/json_rpc/src/dap_json_rpc_request.c new file mode 100644 index 0000000000000000000000000000000000000000..1754423f852b97fe8d3f8ad8e5f19533dd43530c --- /dev/null +++ b/dap-sdk/net/server/json_rpc/src/dap_json_rpc_request.c @@ -0,0 +1,85 @@ +#include "dap_json_rpc_request.h" + +#define LOG_TAG "dap_json_rpc_request" + +static char *s_url_service = NULL; + +int dap_json_rpc_request_init(const char *a_url_service) +{ + if (s_url_service == NULL){ + s_url_service = dap_strdup(a_url_service); + return 0; + } + return 1; +} + +dap_json_rpc_request_t *dap_json_rpc_request_creation(const char *a_method, dap_json_rpc_params_t *a_params, int64_t a_id) +{ + dap_json_rpc_request_t *l_request = DAP_NEW(dap_json_rpc_request_t); + l_request->method = dap_strdup(a_method); + l_request->params = a_params; + l_request->id = a_id; + return l_request; +} + +dap_json_rpc_request_t *dap_json_rpc_request_from_json(const char *a_data) +{ + log_it(L_DEBUG, "Translation JSON string to struct dap_json_rpc_request"); + enum json_tokener_error l_jterr; + json_object *l_jobj = json_tokener_parse_verbose(a_data, &l_jterr); + json_object *l_jobj_id = NULL; + json_object *l_jobj_method = NULL; + json_object *l_jobj_params = NULL; + dap_json_rpc_request_t *l_request = DAP_NEW(dap_json_rpc_request_t); + l_request->params = NULL; + bool l_err_parse_request = false; + if (l_jterr == json_tokener_success){ + if (json_object_object_get_ex(l_jobj, "id", &l_jobj_id)){ + l_request->id = json_object_get_int64(l_jobj_id); + }else{ + log_it(L_ERROR, "Error parse JSON string, Can't searching id request"); + l_err_parse_request = true; + } + if (json_object_object_get_ex(l_jobj, "method", &l_jobj_method)){ + l_request->method = dap_strdup(json_object_get_string(l_jobj_method)); + }else{ + log_it(L_ERROR, "Error parse JSON string, Can't searching method for request with id: %lu", l_request->id); + l_err_parse_request = true; + } + if (json_object_object_get_ex(l_jobj, "params", &l_jobj_params) && !l_err_parse_request){ + l_request->params = dap_json_rpc_params_create_from_array_list(l_jobj_params); + }else{ + log_it(L_ERROR, "Error parse JSON string, Can't searching array params for request with id: %lu", l_request->id); + l_err_parse_request = true; + } + } else { + log_it(L_ERROR, "Error parse json tokener: %s", json_tokener_error_desc(l_jterr)); + l_err_parse_request = true; + } + if (l_err_parse_request){ + DAP_FREE(l_request->method); + DAP_FREE(l_request); + return NULL; + } + return l_request; + +} +char *dap_json_rpc_request_to_json(const dap_json_rpc_request_t *a_request) +{ + log_it(L_DEBUG, "Translation struct dap_json_rpc_request to JSON string"); + char *l_str = dap_strjoin(NULL, "{\"method=\":", "\"", a_request->method, "\"", "\"", "\"params\":", + dap_json_rpc_params_get_string_json(a_request->params), ", \"id\": ", a_request->id, "}", NULL); + return l_str; +} + +void dap_json_rpc_request_send(dap_json_rpc_request_t *a_request, dap_json_rpc_response_handler_func_t *response_handler, + const char *a_uplink_addr, const uint16_t a_uplink_port, + dap_client_http_callback_error_t func_error) +{ + uint64_t l_id_response = dap_json_rpc_response_registration(response_handler); + a_request->id = l_id_response; + char *l_str = dap_json_rpc_request_to_json(a_request); + log_it(L_NOTICE, "Sending request in address: %s", a_uplink_addr); + dap_client_http_request(a_uplink_addr, a_uplink_port, "POST", "application/json", s_url_service, l_str, strlen(l_str), + NULL, dap_json_rpc_response_accepted, func_error, NULL, NULL); +} diff --git a/dap-sdk/net/server/json_rpc/src/dap_json_rpc_request_handler.c b/dap-sdk/net/server/json_rpc/src/dap_json_rpc_request_handler.c new file mode 100644 index 0000000000000000000000000000000000000000..593c9c2104cf11600a7c501dcbdbfd2433d22c4e --- /dev/null +++ b/dap-sdk/net/server/json_rpc/src/dap_json_rpc_request_handler.c @@ -0,0 +1,58 @@ +#include "dap_json_rpc_request_handler.h" + +#define LOG_TAG "dap_json_rpc_request_handler" + +static dap_json_rpc_request_handler_t *s_handler_hash_table = NULL; + +int dap_json_rpc_registration_request_handler(const char *a_name, handler_func_t *a_func) +{ + dap_json_rpc_request_handler_t *l_handler; + HASH_FIND_STR(s_handler_hash_table, a_name, l_handler); + if (l_handler == NULL){ + l_handler = DAP_NEW(dap_json_rpc_request_handler_t); + l_handler->name = dap_strdup(a_name); + l_handler->func = a_func; + HASH_ADD_STR(s_handler_hash_table, name, l_handler); + log_it(L_NOTICE, "Registration handler for request name: %s", a_name); + return 0; + } + return 1; +} +int dap_json_rpc_unregistration_request_handler(const char *a_name) +{ + dap_json_rpc_request_handler_t *l_handler; + HASH_FIND_STR(s_handler_hash_table, a_name, l_handler); + if (l_handler == NULL){ + return 1; + } else { + log_it(L_NOTICE, "Unregistration for handler request name: %s", a_name); + HASH_DEL(s_handler_hash_table, l_handler); + DAP_FREE(l_handler->name); + DAP_FREE(l_handler); + return 0; + } +} + +void dap_json_rpc_request_handler(dap_json_rpc_request_t *a_request, dap_http_simple_t *a_client) +{ + log_it(L_DEBUG, "Processing request"); + if (a_request->id == 0){ + dap_json_rpc_notification_handler(a_request->method, a_request->params); + } else { + dap_json_rpc_response_t *l_response = DAP_NEW(dap_json_rpc_response_t); + l_response->id = a_request->id; + dap_json_rpc_request_handler_t *l_handler = NULL; + HASH_FIND_STR(s_handler_hash_table, a_request->method, l_handler); + if (l_handler == NULL){ + dap_json_rpc_error_t *l_err = dap_json_rpc_error_search_by_code(1); + l_response->type_result = TYPE_RESPONSE_NULL; + l_response->error = l_err; + log_it(L_NOTICE, "Can't processing the request. Handler %s not registration. ", a_request->method); + } else { + l_response->error = NULL; + l_handler->func(a_request->params, l_response); + log_it(L_NOTICE, "Calling handler request name: %s", a_request->method); + } + dap_json_rpc_response_send(l_response, a_client); + } +} diff --git a/dap-sdk/net/server/json_rpc/src/dap_json_rpc_response.c b/dap-sdk/net/server/json_rpc/src/dap_json_rpc_response.c new file mode 100644 index 0000000000000000000000000000000000000000..ee3e4b3e16766825ed06ea5188967fb722a6e34f --- /dev/null +++ b/dap-sdk/net/server/json_rpc/src/dap_json_rpc_response.c @@ -0,0 +1,106 @@ +#include "dap_json_rpc_response.h" + +#define LOG_TAG "dap_json_rpc_response" + +void dap_json_rpc_request_JSON_free(dap_json_rpc_request_JSON_t *l_request_JSON) +{ + json_object_put(l_request_JSON->obj_error); + if (l_request_JSON->struct_error) + dap_json_rpc_error_JSON_free(l_request_JSON->struct_error); + json_object_put(l_request_JSON->obj_id); + json_object_put(l_request_JSON->obj_result); + DAP_FREE(l_request_JSON); +} + +void dap_json_rpc_response_free(dap_json_rpc_response_t *a_response) +{ + DAP_FREE(a_response->error); + if (a_response->type_result == TYPE_RESPONSE_STRING){ + DAP_FREE(a_response->result_string); + } + DAP_FREE(a_response); +} + +void dap_json_rpc_response_send(dap_json_rpc_response_t *a_response, dap_http_simple_t *a_client) +{ + dap_json_rpc_request_JSON_t *l_JSON = DAP_NEW(dap_json_rpc_request_JSON_t); + json_object *l_jobj = json_object_new_object(); + l_JSON->obj_id = json_object_new_int64(a_response->id); + l_JSON->obj_error = NULL; + l_JSON->obj_result = NULL; + l_JSON->struct_error = NULL; + char *str_response = NULL; + if (a_response->error == NULL){ + switch (a_response->type_result) { + case TYPE_RESPONSE_STRING: + l_JSON->obj_result = json_object_new_string(a_response->result_string); + break; + case TYPE_RESPONSE_DOUBLE: + l_JSON->obj_result = json_object_new_double(a_response->result_double); + break; + case TYPE_RESPONSE_BOOLEAN: + l_JSON->obj_result = json_object_new_boolean(a_response->result_boolean); + break; + case TYPE_RESPONSE_INTEGER: + l_JSON->obj_result = json_object_new_int64(a_response->result_int); + break; + } + }else{ + l_JSON->struct_error = dap_json_rpc_error_JSON_add_data(a_response->error->code_error, a_response->error->msg); + l_JSON->obj_error = json_object_new_object(); + json_object_object_add(l_JSON->obj_error, "code", l_JSON->struct_error->obj_code); + json_object_object_add(l_JSON->obj_error, "message", l_JSON->struct_error->obj_msg); + } + json_object_object_add(l_jobj, "result", l_JSON->obj_result); + json_object_object_add(l_jobj, "id", l_JSON->obj_id); + json_object_object_add(l_jobj, "error", l_JSON->obj_error); + str_response = dap_strdup(json_object_to_json_string(l_jobj)); + dap_http_simple_reply(a_client, str_response, strlen(str_response)); + DAP_FREE(str_response); + json_object_put(l_jobj); + dap_json_rpc_request_JSON_free(l_JSON); +} + +dap_json_rpc_response_t *dap_json_rpc_response_from_json(char *a_data_json) +{ + json_object *l_jobj = json_tokener_parse(a_data_json); + json_object *l_jobj_result = json_object_object_get(l_jobj, "result"); + json_object *l_jobj_error = json_object_object_get(l_jobj, "error"); + json_object *l_jobj_id = json_object_object_get(l_jobj, "id"); + dap_json_rpc_response_t *l_response = DAP_NEW(dap_json_rpc_response_t); + l_response->id = json_object_get_int64(l_jobj_id); + if (json_object_is_type(l_jobj_error, json_type_null)){ + l_response->error = NULL; + switch(json_object_get_type(l_jobj_result)){ + case json_type_int: + l_response->type_result = TYPE_RESPONSE_INTEGER; + l_response->result_int = json_object_get_int64(l_jobj_result); + break; + case json_type_double: + l_response->type_result = TYPE_RESPONSE_DOUBLE; + l_response->result_double = json_object_get_double(l_jobj_result); + break; + case json_type_boolean: + l_response->type_result = TYPE_RESPONSE_BOOLEAN; + l_response->result_boolean = json_object_get_boolean(l_jobj_result); + break; + case json_type_string: + l_response->type_result = TYPE_RESPONSE_STRING; + l_response->result_string = dap_strdup(json_object_get_string(l_jobj_result)); + break; + default: + l_response->type_result = TYPE_RESPONSE_NULL; + break; + } + } else { + l_response->error = dap_json_rpc_create_from_json_object(l_jobj_error); + l_response->type_result = TYPE_RESPONSE_NULL; + } + json_object_put(l_jobj_id); + json_object_put(l_jobj_error); + json_object_put(l_jobj_result); + json_object_put(l_jobj); + return l_response; +} + + diff --git a/dap-sdk/net/server/json_rpc/src/dap_json_rpc_response_handler.c b/dap-sdk/net/server/json_rpc/src/dap_json_rpc_response_handler.c new file mode 100644 index 0000000000000000000000000000000000000000..4419221d31e689ce06d101e563f764d3bf8f1138 --- /dev/null +++ b/dap-sdk/net/server/json_rpc/src/dap_json_rpc_response_handler.c @@ -0,0 +1,69 @@ +#include "dap_json_rpc_response_handler.h" + +#define LOG_TAG "dap_json_rpc_response_handler" + +static dap_json_rpc_response_handler_t *s_response_handlers = NULL; +static uint64_t s_delta = 0; + +int dap_json_rpc_response_registration_with_id(uint64_t a_id, dap_json_rpc_response_handler_func_t *func) +{ + dap_json_rpc_response_handler_t *l_handler = NULL; + HASH_FIND_INT(s_response_handlers, &a_id, l_handler); + if (l_handler == NULL){ + l_handler = DAP_NEW(dap_json_rpc_response_handler_t); + l_handler->id = a_id; + l_handler->func = func; + HASH_ADD_INT(s_response_handlers, id, l_handler); + log_it(L_NOTICE, "Registrayion handler response with id: %d", a_id); + return 0; + } + return 1; +} +uint64_t dap_json_rpc_response_registration(dap_json_rpc_response_handler_func_t *func) +{ + uint64_t l_id_registration_response = dap_json_rpc_response_get_new_id(); + int res = dap_json_rpc_response_registration_with_id(l_id_registration_response, func); + return res; +} +void dap_json_rpc_response_unregistration(uint64_t a_id) +{ + dap_json_rpc_response_handler_t *l_handler = NULL; + HASH_FIND_INT(s_response_handlers, &a_id, l_handler); + if (l_handler != NULL){ + HASH_DEL(s_response_handlers, l_handler); + DAP_FREE(l_handler); + log_it(L_NOTICE, "Unregistrayion handler response with id: %d", a_id); + } +} + +void dap_json_rpc_response_handler(dap_json_rpc_response_t *a_response) +{ + dap_json_rpc_response_handler_t *l_handler = NULL; + HASH_FIND_INT(s_response_handlers, (void*)a_response->id, l_handler); + if (l_handler != NULL){ + log_it(L_NOTICE, "Calling handler response id: %d", a_response->id); + l_handler->func(a_response); + dap_json_rpc_response_unregistration(a_response->id); + } else { + log_it(L_NOTICE, "Can't calling handler response id: %d. This handler not found", a_response->id); + } +} + +uint64_t dap_json_rpc_response_get_new_id(void) +{ + uint64_t l_ret = s_delta; + s_delta++; + return l_ret; +} + +void dap_json_rpc_response_accepted(void *a_data, size_t a_size_data, void *a_obj) +{ + (void) a_obj; + log_it(L_NOTICE, "Pre handling response"); + char *l_str = DAP_NEW_SIZE(char, a_size_data); + memcpy(l_str, a_data, a_size_data); + dap_json_rpc_response_t *l_response = dap_json_rpc_response_from_json(l_str); + DAP_FREE(l_str); + dap_json_rpc_response_handler(l_response); + dap_json_rpc_response_free(l_response); +} diff --git a/dap-sdk/net/stream/session/dap_stream_session.c b/dap-sdk/net/stream/session/dap_stream_session.c index 1dcfa0c62168210cf60170b677c5b31e0dbfe74b..5c1cb1a29a18aa997e723c3b7eb43a638bcfa1b2 100644 --- a/dap-sdk/net/stream/session/dap_stream_session.c +++ b/dap-sdk/net/stream/session/dap_stream_session.c @@ -64,6 +64,32 @@ void dap_stream_session_deinit() pthread_mutex_unlock(&sessions_mutex); } +/** + * + * note: dap_stream_session_get_list_sessions_unlock() must be run after this function + */ +dap_list_t* dap_stream_session_get_list_sessions(void) +{ + dap_list_t *l_list = NULL; + dap_stream_session_t *current, *tmp; + pthread_mutex_lock(&sessions_mutex); + HASH_ITER(hh, sessions, current, tmp) + { + l_list = dap_list_append(l_list, current); + //dap_chain_net_srv_stream_session_t * l_srv_session = current->_inheritor; + //if(l_srv_session) { + //dap_net_stats_t *l_stats = DAP_NEW(dap_net_stats_t); + //memcpy(l_stats, l_srv_session->stats); + //l_list = dap_list_append(l_list, l_stats); + //} + } + return l_list; +} + +void dap_stream_session_get_list_sessions_unlock(void) +{ + pthread_mutex_unlock(&sessions_mutex); +} static void * session_check(void * data) { diff --git a/dap-sdk/net/stream/session/include/dap_stream_session.h b/dap-sdk/net/stream/session/include/dap_stream_session.h index 921c9ff700227301a39eef1d946e699925796eb7..9106aca423520d4cafad1ab2de868acf32e2ffe2 100644 --- a/dap-sdk/net/stream/session/include/dap_stream_session.h +++ b/dap-sdk/net/stream/session/include/dap_stream_session.h @@ -31,6 +31,7 @@ #include "uthash.h" #include "dap_enc_key.h" #include "dap_hash.h" +#include "dap_list.h" typedef enum stream_session_type {STREAM_SESSION_TYPE_MEDIA=0,STREAM_SESSION_TYPE_VPN} stream_session_type_t; typedef enum stream_session_connection_type {STEAM_SESSION_HTTP = 0, STREAM_SESSION_UDP, STREAM_SESSION_END_TYPE} stream_session_connection_type_t; @@ -69,6 +70,8 @@ typedef struct dap_stream_session dap_stream_session_t; void dap_stream_session_init(); void dap_stream_session_deinit(); +dap_list_t* dap_stream_session_get_list_sessions(void); +void dap_stream_session_get_list_sessions_unlock(void); dap_stream_session_t * dap_stream_session_pure_new(); dap_stream_session_t * dap_stream_session_new(unsigned int media_id, bool open_preview); diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt index 6d1abf4cf3a5c10ff884a89ed9cc27c5d21277ac..78ae7458e46f0e6299760dea12620a7d16d03a5b 100644 --- a/modules/CMakeLists.txt +++ b/modules/CMakeLists.txt @@ -7,6 +7,7 @@ endif() # Chains if (CELLFRAME_MODULES MATCHES "chains") add_subdirectory(chain) + add_subdirectory(chain/btc_rpc) add_subdirectory(wallet) add_subdirectory(global-db) endif() @@ -37,8 +38,8 @@ if (CELLFRAME_MODULES MATCHES "cs-dag") endif() # Consensus type dag -if (CELLFRAME_MODULES MATCHES "cs-block") - add_subdirectory(type/block) +if (CELLFRAME_MODULES MATCHES "cs-blocks") + add_subdirectory(type/blocks) endif() # No consensus diff --git a/modules/chain/btc_rpc/CMakeLists.txt b/modules/chain/btc_rpc/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..9e9ded64a179d2bda42ee9430c581d9fc0fc3ce0 --- /dev/null +++ b/modules/chain/btc_rpc/CMakeLists.txt @@ -0,0 +1,18 @@ +project(dap_chain_btc_rpc C) +cmake_minimum_required(VERSION 3.0) + +add_definitions ("-D_GNU_SOURCE") +add_definitions("-Dfpic") + +file(GLOB BTC_RPC_HEADERS include/*.h) +file(GLOB BTC_RPC_SRCS *.c) + +include_directories(${PROJECT_NAME} include/) + +add_library(${PROJECT_NAME} STATIC ${BTC_RPC_HEADERS} ${BTC_RPC_SRCS}) +target_include_directories(${PROJECT_NAME} INTERFACE . include/) +target_include_directories(${PROJECT_NAME} PUBLIC include) + +target_link_libraries(${PROJECT_NAME} dap_core dap_json_rpc) +#target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_server_core dap_http_server dap_client json-c ) +#target_link_libraries(${PROJECT_NAME} dap_core)# dap_http_server json-c) diff --git a/modules/chain/btc_rpc/dap_chain_btc_rpc.c b/modules/chain/btc_rpc/dap_chain_btc_rpc.c new file mode 100644 index 0000000000000000000000000000000000000000..448528116b41719aa8000aa430b130b82a4e334c --- /dev/null +++ b/modules/chain/btc_rpc/dap_chain_btc_rpc.c @@ -0,0 +1,9 @@ +#include "dap_chain_btc_rpc.h" + +int dap_chain_btc_rpc_init(){ + dap_chain_btc_rpc_registration_handlers(); + return 0; +} +void dap_chain_btc_rpc_deinit(){ + dap_chain_btc_rpc_unregistration_handlers(); +} diff --git a/modules/chain/btc_rpc/dap_chain_btc_rpc_handlers.c b/modules/chain/btc_rpc/dap_chain_btc_rpc_handlers.c new file mode 100644 index 0000000000000000000000000000000000000000..e39ce1a2e702aa9f0b3fe55bf0952526c5241c17 --- /dev/null +++ b/modules/chain/btc_rpc/dap_chain_btc_rpc_handlers.c @@ -0,0 +1,143 @@ +#include "dap_chain_btc_rpc_handlers.h" + +void dap_chain_btc_rpc_registration_handlers(){ + dap_json_rpc_registration_request_handler("addmultisigaddress", dap_chain_btc_rpc_handler_addmultisigaddress); + dap_json_rpc_registration_request_handler("addnode", dap_chain_btc_rpc_handler_addnode); + dap_json_rpc_registration_request_handler("backupwallet", dap_chain_btc_rpc_handler_backupwallet); + dap_json_rpc_registration_request_handler("createmultisig", dap_chain_btc_rpc_handler_createmultisig); + dap_json_rpc_registration_request_handler("createrawtransaction", dap_chain_btc_rpc_handler_createrawtransaction); + dap_json_rpc_registration_request_handler("decoderawtransaction", dap_chain_btc_rpc_handler_decoderawtransaction); + dap_json_rpc_registration_request_handler("dumpprivkey", dap_chain_btc_rpc_handler_dumpprivkey); + dap_json_rpc_registration_request_handler("dumpwallet", dap_chain_btc_rpc_handler_dumpwallet); + dap_json_rpc_registration_request_handler("encryptwallet", dap_chain_btc_rpc_handler_encryptwallet); + dap_json_rpc_registration_request_handler("getaccount", dap_chain_btc_rpc_handler_getaccount); + dap_json_rpc_registration_request_handler("getaccountaddress", dap_chain_btc_rpc_handler_getaccountaddress); + dap_json_rpc_registration_request_handler("getaddednodeinfo", dap_chain_btc_rpc_handler_getaddednodeinfo); + dap_json_rpc_registration_request_handler("getaddressesbyaccount", dap_chain_btc_rpc_handler_getaddressesbyaccount); + dap_json_rpc_registration_request_handler("getbalance", dap_chain_btc_rpc_handler_getbalance); + dap_json_rpc_registration_request_handler("getbestblockhash", dap_chain_btc_rpc_handler_getbestblockhash); + dap_json_rpc_registration_request_handler("getblock", dap_chain_btc_rpc_handler_getblock); + dap_json_rpc_registration_request_handler("getblockcount", dap_chain_btc_rpc_handler_getblockcount); + dap_json_rpc_registration_request_handler("getblockhash", dap_chain_btc_rpc_handler_getblockhash); + dap_json_rpc_registration_request_handler("getblocknumber", dap_chain_btc_rpc_handler_getblocknumber); + dap_json_rpc_registration_request_handler("getblocktemplate", dap_chain_btc_rpc_handler_getblocktemplate); + dap_json_rpc_registration_request_handler("getconnectioncount", dap_chain_btc_rpc_handler_getconnectioncount); + dap_json_rpc_registration_request_handler("getdifficulty", dap_chain_btc_rpc_handler_getdifficulty); + dap_json_rpc_registration_request_handler("getgenerate", dap_chain_btc_rpc_handler_getgenerate); + dap_json_rpc_registration_request_handler("gethashespersec", dap_chain_btc_rpc_handler_gethashespersec); + dap_json_rpc_registration_request_handler("getinfo", dap_chain_btc_rpc_handler_getinfo); + dap_json_rpc_registration_request_handler("getmemorypool", dap_chain_btc_rpc_handler_getmemorypool); + dap_json_rpc_registration_request_handler("getmininginfo", dap_chain_btc_rpc_handler_getmininginfo); + dap_json_rpc_registration_request_handler("getnewaddress", dap_chain_btc_rpc_handler_getnewaddress); + dap_json_rpc_registration_request_handler("getpeerinfo", dap_chain_btc_rpc_handler_getpeerinfo); + dap_json_rpc_registration_request_handler("getrawchangeaddress", dap_chain_btc_rpc_handler_getrawchangeaddress); + dap_json_rpc_registration_request_handler("getrawmempool", dap_chain_btc_rpc_handler_getrawmempool); + dap_json_rpc_registration_request_handler("getrawtransaction", dap_chain_btc_rpc_handler_getrawtransaction); + dap_json_rpc_registration_request_handler("getreceivedbyaccount", dap_chain_btc_rpc_handler_getreceivedbyaccount); + dap_json_rpc_registration_request_handler("getreceivedbyaddress", dap_chain_btc_rpc_handler_getreceivedbyaddress); + dap_json_rpc_registration_request_handler("gettransaction", dap_chain_btc_rpc_handler_gettransaction); + dap_json_rpc_registration_request_handler("gettxout", dap_chain_btc_rpc_handler_gettxout); + dap_json_rpc_registration_request_handler("gettxoutsetinfo", dap_chain_btc_rpc_handler_gettxoutsetinfo); + dap_json_rpc_registration_request_handler("getwork", dap_chain_btc_rpc_handler_getwork); + dap_json_rpc_registration_request_handler("help", dap_chain_btc_rpc_handler_help); + dap_json_rpc_registration_request_handler("importprivkey", dap_chain_btc_rpc_handler_importprivkey); + dap_json_rpc_registration_request_handler("invalidateblock", dap_chain_btc_rpc_handler_invalidateblock); + dap_json_rpc_registration_request_handler("keypoolrefill", dap_chain_btc_rpc_handler_keypoolrefill); + dap_json_rpc_registration_request_handler("listaccounts", dap_chain_btc_rpc_handler_listaccounts); + dap_json_rpc_registration_request_handler("listaddressgroupings", dap_chain_btc_rpc_handler_listaddressgroupings); + dap_json_rpc_registration_request_handler("listreceivedbyaccount", dap_chain_btc_rpc_handler_listreceivedbyaccount); + dap_json_rpc_registration_request_handler("listreceivedbyaddress", dap_chain_btc_rpc_handler_listreceivedbyaddress); + dap_json_rpc_registration_request_handler("listsinceblock", dap_chain_btc_rpc_handler_listsinceblock); + dap_json_rpc_registration_request_handler("listtransactions", dap_chain_btc_rpc_handler_listtransactions); + dap_json_rpc_registration_request_handler("listunspent", dap_chain_btc_rpc_handler_listunspent); + dap_json_rpc_registration_request_handler("listlockunspent", dap_chain_btc_rpc_handler_listlockunspent); + dap_json_rpc_registration_request_handler("lockunspent", dap_chain_btc_rpc_handler_lockunspent); + dap_json_rpc_registration_request_handler("move", dap_chain_btc_rpc_handler_move); + dap_json_rpc_registration_request_handler("sendfrom", dap_chain_btc_rpc_handler_sendfrom); + dap_json_rpc_registration_request_handler("sendmany", dap_chain_btc_rpc_handler_sendmany); + dap_json_rpc_registration_request_handler("sendrawtransaction", dap_chain_btc_rpc_handler_sendrawtransaction); + dap_json_rpc_registration_request_handler("sendtoaddress", dap_chain_btc_rpc_handler_sendtoaddress); + dap_json_rpc_registration_request_handler("setaccount", dap_chain_btc_rpc_handler_setaccount); + dap_json_rpc_registration_request_handler("setgenerate", dap_chain_btc_rpc_handler_setgenerate); + dap_json_rpc_registration_request_handler("settxfee", dap_chain_btc_rpc_handler_settxfee); + dap_json_rpc_registration_request_handler("signmessage", dap_chain_btc_rpc_handler_signmessage); + dap_json_rpc_registration_request_handler("signrawtransaction", dap_chain_btc_rpc_handler_signrawtransaction); + dap_json_rpc_registration_request_handler("stop", dap_chain_btc_rpc_handler_stop); + dap_json_rpc_registration_request_handler("submitblock", dap_chain_btc_rpc_handler_submitblock); + dap_json_rpc_registration_request_handler("validateaddress", dap_chain_btc_rpc_handler_validateaddress); + dap_json_rpc_registration_request_handler("verifymessage", dap_chain_btc_rpc_handler_verifymessage); + dap_json_rpc_registration_request_handler("walletlock", dap_chain_btc_rpc_handler_walletlock); + dap_json_rpc_registration_request_handler("walletpassphrase", dap_chain_btc_rpc_handler_walletpassphrase); + dap_json_rpc_registration_request_handler("walletpassphrasechange", dap_chain_btc_rpc_handler_walletpassphrasechange); +} + +void dap_chain_btc_rpc_unregistration_handlers(){ + dap_json_rpc_unregistration_request_handler("addmultisigaddress"); + dap_json_rpc_unregistration_request_handler("addnode"); + dap_json_rpc_unregistration_request_handler("backupwallet"); + dap_json_rpc_unregistration_request_handler("createmultisig"); + dap_json_rpc_unregistration_request_handler("createrawtransaction"); + dap_json_rpc_unregistration_request_handler("decoderawtransaction"); + dap_json_rpc_unregistration_request_handler("dumpprivkey"); + dap_json_rpc_unregistration_request_handler("dumpwallet"); + dap_json_rpc_unregistration_request_handler("encryptwallet"); + dap_json_rpc_unregistration_request_handler("getaccount"); + dap_json_rpc_unregistration_request_handler("getaccountaddress"); + dap_json_rpc_unregistration_request_handler("getaddednodeinfo"); + dap_json_rpc_unregistration_request_handler("getaddressesbyaccount"); + dap_json_rpc_unregistration_request_handler("getbalance"); + dap_json_rpc_unregistration_request_handler("getbestblockhash"); + dap_json_rpc_unregistration_request_handler("getblock"); + dap_json_rpc_unregistration_request_handler("getblockcount"); + dap_json_rpc_unregistration_request_handler("getblockhash"); + dap_json_rpc_unregistration_request_handler("getblocknumber"); + dap_json_rpc_unregistration_request_handler("getblocktemplate"); + dap_json_rpc_unregistration_request_handler("getconnectioncount"); + dap_json_rpc_unregistration_request_handler("getdifficulty"); + dap_json_rpc_unregistration_request_handler("getgenerate"); + dap_json_rpc_unregistration_request_handler("gethashespersec"); + dap_json_rpc_unregistration_request_handler("getinfo"); + dap_json_rpc_unregistration_request_handler("getmemorypool"); + dap_json_rpc_unregistration_request_handler("getmininginfo"); + dap_json_rpc_unregistration_request_handler("getnewaddress"); + dap_json_rpc_unregistration_request_handler("getpeerinfo"); + dap_json_rpc_unregistration_request_handler("getrawchangeaddress"); + dap_json_rpc_unregistration_request_handler("getrawmempool"); + dap_json_rpc_unregistration_request_handler("getrawtransaction"); + dap_json_rpc_unregistration_request_handler("getreceivedbyaccount"); + dap_json_rpc_unregistration_request_handler("getreceivedbyaddress"); + dap_json_rpc_unregistration_request_handler("gettransaction"); + dap_json_rpc_unregistration_request_handler("gettxout"); + dap_json_rpc_unregistration_request_handler("gettxoutsetinfo"); + dap_json_rpc_unregistration_request_handler("getwork"); + dap_json_rpc_unregistration_request_handler("help"); + dap_json_rpc_unregistration_request_handler("importprivkey"); + dap_json_rpc_unregistration_request_handler("invalidateblock"); + dap_json_rpc_unregistration_request_handler("keypoolrefill"); + dap_json_rpc_unregistration_request_handler("listaccounts"); + dap_json_rpc_unregistration_request_handler("listaddressgroupings"); + dap_json_rpc_unregistration_request_handler("listreceivedbyaccount"); + dap_json_rpc_unregistration_request_handler("listreceivedbyaddress"); + dap_json_rpc_unregistration_request_handler("listsinceblock"); + dap_json_rpc_unregistration_request_handler("listtransactions"); + dap_json_rpc_unregistration_request_handler("listunspent"); + dap_json_rpc_unregistration_request_handler("listlockunspent"); + dap_json_rpc_unregistration_request_handler("lockunspent"); + dap_json_rpc_unregistration_request_handler("move"); + dap_json_rpc_unregistration_request_handler("sendfrom"); + dap_json_rpc_unregistration_request_handler("sendmany"); + dap_json_rpc_unregistration_request_handler("sendrawtransaction"); + dap_json_rpc_unregistration_request_handler("sendtoaddress"); + dap_json_rpc_unregistration_request_handler("setaccount"); + dap_json_rpc_unregistration_request_handler("setgenerate"); + dap_json_rpc_unregistration_request_handler("settxfee"); + dap_json_rpc_unregistration_request_handler("signmessage"); + dap_json_rpc_unregistration_request_handler("signrawtransaction"); + dap_json_rpc_unregistration_request_handler("stop"); + dap_json_rpc_unregistration_request_handler("submitblock"); + dap_json_rpc_unregistration_request_handler("validateaddress"); + dap_json_rpc_unregistration_request_handler("verifymessage"); + dap_json_rpc_unregistration_request_handler("walletlock"); + dap_json_rpc_unregistration_request_handler("walletpassphrase"); + dap_json_rpc_unregistration_request_handler("walletpassphrasechange"); +} diff --git a/modules/chain/btc_rpc/include/dap_chain_btc_rpc.h b/modules/chain/btc_rpc/include/dap_chain_btc_rpc.h new file mode 100644 index 0000000000000000000000000000000000000000..1196448f3ed1a4f94a81d491c3e3c9ace35cd16d --- /dev/null +++ b/modules/chain/btc_rpc/include/dap_chain_btc_rpc.h @@ -0,0 +1,5 @@ +#pragma once +#include "dap_chain_btc_rpc_handlers.h" + +int dap_chain_btc_rpc_init(); +void dap_chain_btc_rpc_deinit(); diff --git a/modules/chain/btc_rpc/include/dap_chain_btc_rpc_handlers.h b/modules/chain/btc_rpc/include/dap_chain_btc_rpc_handlers.h new file mode 100644 index 0000000000000000000000000000000000000000..601c9dd1ff4aed16aec43cd25e18f7e1bc051752 --- /dev/null +++ b/modules/chain/btc_rpc/include/dap_chain_btc_rpc_handlers.h @@ -0,0 +1,84 @@ +#pragma once + +#include "dap_json_rpc_request_handler.h" + +void dap_chain_btc_rpc_registration_handlers(); +void dap_chain_btc_rpc_unregistration_handlers(); + +void dap_chain_btc_rpc_handler_addmultisigaddress(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_addnode(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_backupwallet(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_createmultisig(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_createrawtransaction(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_decoderawtransaction(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_dumpprivkey(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_dumpwallet(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_encryptwallet(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_getaccount(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_getaccountaddress(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_getaddednodeinfo(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_getaddressesbyaccount(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_getbalance(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_getbestblockhash(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_getblock(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_getblockcount(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_getblockhash(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_getblocknumber(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_getblocktemplate(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_getconnectioncount(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_getdifficulty(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_getgenerate(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_gethashespersec(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_getinfo(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_getmemorypool(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_getmininginfo(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); + +void dap_chain_btc_rpc_handler_getnewaddress(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_getpeerinfo(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_getrawchangeaddress(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_getrawmempool(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_getrawtransaction(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_getreceivedbyaccount(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_getreceivedbyaddress(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_gettransaction(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_gettxout(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_gettxoutsetinfo(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_getwork(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); + +void dap_chain_btc_rpc_handler_help(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); + +void dap_chain_btc_rpc_handler_importprivkey(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_invalidateblock(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_keypoolrefill(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_listaccounts(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_listaddressgroupings(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_listreceivedbyaccount(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); + +void dap_chain_btc_rpc_handler_listreceivedbyaccount(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_listreceivedbyaddress(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_listsinceblock(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_listtransactions(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_listunspent(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_listlockunspent(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_lockunspent(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_move(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); + +void dap_chain_btc_rpc_handler_sendfrom(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_sendmany(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_sendrawtransaction(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_sendtoaddress(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_setaccount(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_setgenerate(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_settxfee(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_signmessage(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_signrawtransaction(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_stop(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_submitblock(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); + +void dap_chain_btc_rpc_handler_validateaddress(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_verifymessage(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_walletlock(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_walletpassphrase(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); +void dap_chain_btc_rpc_handler_walletpassphrasechange(dap_json_rpc_params_t *a_params, dap_json_rpc_response_t *a_response); + + diff --git a/modules/chain/dap_chain.c b/modules/chain/dap_chain.c index b7d05539b15f8fd2de45a09918ff039f52b82cfa..db90df595e0f8f19ad47e9a1343ae0a7f30b59bd 100644 --- a/modules/chain/dap_chain.c +++ b/modules/chain/dap_chain.c @@ -165,6 +165,21 @@ void dap_chain_delete(dap_chain_t * a_chain) pthread_rwlock_unlock(&s_chain_items_rwlock); } +/** + * @brief dap_chain_get_atom_by_hash + * @param a_chain + * @param a_atom_hash + * @param a_atom_size + * @return + */ +dap_chain_atom_ptr_t dap_chain_get_atom_by_hash(dap_chain_t * a_chain, dap_chain_hash_fast_t * a_atom_hash, size_t * a_atom_size) +{ + dap_chain_atom_iter_t * l_iter = a_chain->callback_atom_iter_create(a_chain); + dap_chain_atom_ptr_t *l_ret = a_chain->callback_atom_find_by_hash(l_iter, a_atom_hash, a_atom_size); + a_chain->callback_atom_iter_delete(l_iter); + return l_ret; +} + /** * @brief dap_chain_find_by_id * @param a_chain_net_id diff --git a/modules/chain/dap_chain_cell.c b/modules/chain/dap_chain_cell.c index 5e229297e4c2650b97b13eb99e3225e34bca8a00..238e97a4a69df20aafab2d60b05c1d165f0dfa1c 100644 --- a/modules/chain/dap_chain_cell.c +++ b/modules/chain/dap_chain_cell.c @@ -131,7 +131,7 @@ int dap_chain_cell_load(dap_chain_t * a_chain, const char * a_cell_file_path) size_t l_element_size = 0; if ( fread(&l_element_size,1,sizeof(l_element_size),l_cell->file_storage) == sizeof(l_element_size) ){ - if ( l_element_size > 0 ){ + if ( l_element_size > 0){ dap_chain_atom_ptr_t * l_element = DAP_NEW_Z_SIZE (dap_chain_atom_ptr_t, l_element_size ); if ( l_element){ size_t l_read_bytes = fread( l_element,1,l_element_size,l_cell->file_storage ); diff --git a/modules/chain/dap_chain_cs.c b/modules/chain/dap_chain_cs.c index cc88a25baf6e5909289d9c3fde67996ad1acdaf7..491a35002a51330d1a2c4cb69dc8d37bf5d81046 100644 --- a/modules/chain/dap_chain_cs.c +++ b/modules/chain/dap_chain_cs.c @@ -66,7 +66,7 @@ void dap_chain_cs_deinit(void) * @param a_cs_str * @param a_callback_init */ -void dap_chain_class_add (const char * a_cs_str, dap_chain_callback_new_cfg_t a_callback_init) +void dap_chain_cs_type_add (const char * a_cs_str, dap_chain_callback_new_cfg_t a_callback_init) { dap_chain_callback_new_cfg_item_t *l_item = DAP_NEW_Z ( dap_chain_callback_new_cfg_item_t ); strncpy(l_item->name, a_cs_str, sizeof (l_item->name) ); @@ -80,7 +80,7 @@ void dap_chain_class_add (const char * a_cs_str, dap_chain_callback_new_cfg_t a * @param a_chain_cfg * @return */ -int dap_chain_class_create(dap_chain_t * a_chain, dap_config_t * a_chain_cfg) +int dap_chain_cs_type_create(dap_chain_t * a_chain, dap_config_t * a_chain_cfg) { dap_chain_callback_new_cfg_item_t *l_item = NULL; @@ -123,7 +123,7 @@ int dap_chain_cs_create(dap_chain_t * a_chain, dap_config_t * a_chain_cfg) if ( l_item ) { log_it(L_NOTICE,"Consensus \"%s\" found, prepare to parse config file",l_item->name ); l_item->callback_init( a_chain, a_chain_cfg); - // TODO + DAP_CHAIN_PVT(a_chain)->cs_name = l_item->name; return 0; } else { log_it(L_ERROR,"Can't find consensus \"%s\"",dap_config_get_item_str( a_chain_cfg, "chain", "consensus")); diff --git a/modules/chain/dap_chain_ledger.c b/modules/chain/dap_chain_ledger.c index e0cf28cbf82400ac48ceb062dd45b6956c66352f..0f66f0343ac4482091d452ee3de40a29048f30c1 100644 --- a/modules/chain/dap_chain_ledger.c +++ b/modules/chain/dap_chain_ledger.c @@ -52,7 +52,6 @@ #include "dap_chain_datum_token.h" #include "dap_chain_mempool.h" #include "dap_chain_global_db.h" -#include "dap_chain_net.h" #include "dap_chain_ledger.h" #define LOG_TAG "dap_chain_ledger" @@ -69,18 +68,12 @@ static pthread_rwlock_t s_verificators_rwlock; #define MAX_OUT_ITEMS 10 typedef struct dap_chain_ledger_token_emission_item { dap_chain_hash_fast_t datum_token_emission_hash; - // while these are not needed - //dap_chain_hash_fast_t datum_tx_token_hash; - //dap_chain_tx_token_t * tx_token; - dap_chain_datum_token_emission_t *datum_token_emission; UT_hash_handle hh; } dap_chain_ledger_token_emission_item_t; typedef struct dap_chain_ledger_token_item { char ticker[DAP_CHAIN_TICKER_SIZE_MAX]; - dap_chain_hash_fast_t datum_token_hash; - uint8_t padding[6]; dap_chain_datum_token_t * datum_token; uint64_t total_supply; pthread_rwlock_t token_emissions_rwlock; @@ -88,17 +81,18 @@ typedef struct dap_chain_ledger_token_item { UT_hash_handle hh; } dap_chain_ledger_token_item_t; -// ledger cache item - one of unspendet outputs +// ledger cache item - one of unspent outputs typedef struct dap_chain_ledger_tx_item { dap_chain_hash_fast_t tx_hash_fast; dap_chain_datum_tx_t *tx; - time_t ts_created; - int n_outs; - int n_outs_used; - char token_tiker[10]; - // TODO dynamically allocates the memory in order not to limit the number of outputs in transaction - dap_chain_hash_fast_t tx_hash_spent_fast[MAX_OUT_ITEMS]; // spent outs list - uint8_t padding[6]; + struct { + time_t ts_created; + int n_outs; + int n_outs_used; + char token_tiker[10]; + // TODO dynamically allocates the memory in order not to limit the number of outputs in transaction + dap_chain_hash_fast_t tx_hash_spent_fast[MAX_OUT_ITEMS]; // spent outs list + } cache_data; UT_hash_handle hh; } dap_chain_ledger_tx_item_t; @@ -123,21 +117,24 @@ typedef struct dap_chain_ledger_tx_bound { dap_chain_ledger_tx_item_t *item_out; } dap_chain_ledger_tx_bound_t; -// Gotta use a regular null-terminated string instead, for uthash usability -/*typedef struct dap_ledger_wallet_balance_key{ - dap_chain_addr_t addr; - char ticker[DAP_CHAIN_TICKER_SIZE_MAX]; -} DAP_ALIGN_PACKED dap_ledger_wallet_balance_key_t; */ - // in-memory wallet balance typedef struct dap_ledger_wallet_balance { - //dap_ledger_wallet_balance_key_t key; char *key; char token_ticker[DAP_CHAIN_TICKER_SIZE_MAX]; uint128_t balance; UT_hash_handle hh; } dap_ledger_wallet_balance_t; +typedef struct dap_ledger_cache_item { + dap_chain_hash_fast_t *hash; + bool found; +} dap_ledger_cache_item_t; + +typedef struct dap_ledger_cache_str_item { + char *key; + bool found; +} dap_ledger_cache_str_item_t; + // dap_ledget_t private section typedef struct dap_ledger_private { // List of ledger - unspent transactions cache @@ -163,6 +160,11 @@ typedef struct dap_ledger_private { bool check_cells_ds; bool check_token_emission; dap_chain_cell_id_t local_cell_id; + /* Cache section */ + dap_ledger_cache_item_t last_tx; + dap_ledger_cache_item_t last_thres_tx; + dap_ledger_cache_item_t last_emit; + dap_ledger_cache_str_item_t last_ticker; } dap_ledger_private_t; #define PVT(a) ( (dap_ledger_private_t* ) a->_internal ) @@ -282,13 +284,19 @@ int dap_chain_ledger_token_add(dap_ledger_t * a_ledger, dap_chain_datum_token_t l_token_item = DAP_NEW_Z(dap_chain_ledger_token_item_t); dap_snprintf(l_token_item->ticker,sizeof (l_token_item->ticker),"%s",a_token->ticker); pthread_rwlock_init(&l_token_item->token_emissions_rwlock,NULL); - l_token_item->datum_token = DAP_NEW_Z_SIZE(dap_chain_datum_token_t, a_token_size); - memcpy(l_token_item->datum_token, a_token,a_token_size); - dap_hash_fast(a_token,a_token_size, &l_token_item->datum_token_hash); + HASH_ADD_STR(PVT(a_ledger)->tokens, ticker, l_token_item); + // Add it to cache + dap_chain_datum_token_t *l_token_cache = DAP_NEW_Z_SIZE(dap_chain_datum_token_t, a_token_size); + memcpy(l_token_cache, a_token, a_token_size); + char *l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, "tokens"); + if (!dap_chain_global_db_gr_set(dap_strdup(a_token->ticker), l_token_cache, a_token_size, l_gdb_group)) { + log_it(L_WARNING, "Ledger cache mismatch"); + DAP_DELETE(l_token_cache); + } + DAP_DELETE(l_gdb_group); - HASH_ADD_STR(PVT(a_ledger)->tokens, ticker, l_token_item) ; switch(a_token->type){ case DAP_CHAIN_DATUM_TOKEN_TYPE_SIMPLE: l_token_item->total_supply = a_token->header_private.total_supply; @@ -311,6 +319,15 @@ int dap_chain_ledger_token_add(dap_ledger_t * a_ledger, dap_chain_datum_token_t return 0; } +int dap_chain_ledger_token_load(dap_ledger_t *a_ledger, dap_chain_datum_token_t *a_token, size_t a_token_size) +{ + if (PVT(a_ledger)->last_ticker.found) { + return dap_chain_ledger_token_add(a_ledger, a_token, a_token_size); + } else if (!strncmp(PVT(a_ledger)->last_ticker.key, a_token->ticker, DAP_CHAIN_TICKER_SIZE_MAX)) { + PVT(a_ledger)->last_ticker.found = true; + } + return 0; +} /** * @brief s_treshold_emissions_proc * @param a_ledger @@ -332,21 +349,120 @@ static void s_treshold_txs_proc( dap_ledger_t * a_ledger) } +void dap_chain_ledger_load_cache(dap_ledger_t *a_ledger) +{ + dap_ledger_private_t *l_ledger_pvt = PVT(a_ledger); + + char *l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, "tokens"); + size_t l_objs_count = 0; + dap_global_db_obj_t *l_objs = dap_chain_global_db_gr_load(l_gdb_group, &l_objs_count); + for (size_t i = 0; i < l_objs_count; i++) { + dap_chain_ledger_token_item_t *l_token_item = DAP_NEW_Z(dap_chain_ledger_token_item_t); + strncpy(l_token_item->ticker, l_objs[i].key, sizeof(l_token_item->ticker)); + l_token_item->datum_token = DAP_NEW_Z_SIZE(dap_chain_datum_token_t, l_objs[i].value_len); + memcpy(l_token_item->datum_token, l_objs[i].value, l_objs[i].value_len); + pthread_rwlock_init(&l_token_item->token_emissions_rwlock, NULL); + if (l_token_item->datum_token->type == DAP_CHAIN_DATUM_TOKEN_TYPE_SIMPLE) { + l_token_item->total_supply = l_token_item->datum_token->header_private.total_supply; + } + HASH_ADD_STR(PVT(a_ledger)->tokens, ticker, l_token_item); + if (i == l_objs_count - 1) { + l_ledger_pvt->last_ticker.key = l_token_item->ticker; + } + } + dap_chain_global_db_objs_delete(l_objs, l_objs_count); + DAP_DELETE(l_gdb_group); + if (l_objs_count == 0) { + l_ledger_pvt->last_ticker.found = true; + } + + l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, "emissions"); + l_objs_count = 0; + l_objs = dap_chain_global_db_gr_load(l_gdb_group, &l_objs_count); + for (size_t i = 0; i < l_objs_count; i++) { + dap_chain_ledger_token_emission_item_t *l_emission_item = DAP_NEW_Z(dap_chain_ledger_token_emission_item_t); + dap_chain_str_to_hash_fast(l_objs[i].key, &l_emission_item->datum_token_emission_hash); + l_emission_item->datum_token_emission = DAP_NEW_Z_SIZE(dap_chain_datum_token_emission_t, l_objs[i].value_len); + memcpy(l_emission_item->datum_token_emission, l_objs[i].value, l_objs[i].value_len); + const char * c_token_ticker = l_emission_item->datum_token_emission->hdr.ticker; + dap_chain_ledger_token_item_t *l_token_item = NULL; + HASH_FIND_STR(l_ledger_pvt->tokens, c_token_ticker, l_token_item); + if (l_token_item) { + HASH_ADD(hh, l_token_item->token_emissions, datum_token_emission_hash, + sizeof(dap_chain_hash_fast_t), l_emission_item); + } else { + HASH_ADD(hh, l_ledger_pvt->treshold_emissions, datum_token_emission_hash, + sizeof(dap_chain_hash_fast_t), l_emission_item); + } + if (i == l_objs_count - 1) { + l_ledger_pvt->last_emit.hash = &l_emission_item->datum_token_emission_hash; + } + } + dap_chain_global_db_objs_delete(l_objs, l_objs_count); + DAP_DELETE(l_gdb_group); + if (l_objs_count == 0) { + l_ledger_pvt->last_emit.found = true; + } + + l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, "txs"); + l_objs_count = 0; + l_objs = dap_chain_global_db_gr_load(l_gdb_group, &l_objs_count); + for (size_t i = 0; i < l_objs_count; i++) { + dap_chain_ledger_tx_item_t *l_tx_item = DAP_NEW_Z(dap_chain_ledger_tx_item_t); + dap_chain_str_to_hash_fast(l_objs[i].key, &l_tx_item->tx_hash_fast); + l_tx_item->tx = DAP_NEW_Z_SIZE(dap_chain_datum_tx_t, l_objs[i].value_len - sizeof(l_tx_item->cache_data)); + memcpy(l_tx_item->tx, l_objs[i].value + sizeof(l_tx_item->cache_data), l_objs[i].value_len - sizeof(l_tx_item->cache_data)); + memcpy(&l_tx_item->cache_data, l_objs[i].value, sizeof(l_tx_item->cache_data)); + HASH_ADD(hh, l_ledger_pvt->ledger_items, tx_hash_fast, sizeof(dap_chain_hash_fast_t), l_tx_item); + if (i == l_objs_count - 1) { + PVT(a_ledger)->last_tx.hash = &l_tx_item->tx_hash_fast; + } + } + dap_chain_global_db_objs_delete(l_objs, l_objs_count); + DAP_DELETE(l_gdb_group); + if (l_objs_count == 0) { + l_ledger_pvt->last_tx.found = true; + } + + //TODO add tx threshold cache if need + l_ledger_pvt->last_thres_tx.found = true; + + l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, "balances"); + l_objs_count = 0; + l_objs = dap_chain_global_db_gr_load(l_gdb_group, &l_objs_count); + for (size_t i = 0; i < l_objs_count; i++) { + dap_ledger_wallet_balance_t *l_balance_item = DAP_NEW_Z(dap_ledger_wallet_balance_t); + l_balance_item->key = DAP_NEW_Z_SIZE(char, strlen(l_objs[i].key) + 1); + strcpy(l_balance_item->key, l_objs[i].key); + char *l_ptr = strchr(l_balance_item->key, ' '); + if (l_ptr++) { + strcpy(l_balance_item->token_ticker, l_ptr); + } + l_balance_item->balance = *(uint128_t *)l_objs[i].value; + HASH_ADD_KEYPTR(hh, l_ledger_pvt->balance_accounts, l_balance_item->key, + strlen(l_balance_item->key), l_balance_item); + } + dap_chain_global_db_objs_delete(l_objs, l_objs_count); + DAP_DELETE(l_gdb_group); +} + /** * @brief dap_chain_ledger_create * @param a_check_flags * @return dap_ledger_t */ -dap_ledger_t* dap_chain_ledger_create(uint16_t a_check_flags) +dap_ledger_t* dap_chain_ledger_create(uint16_t a_check_flags, char *a_net_name) { dap_ledger_t *l_ledger = dap_chain_ledger_handle_new(); + l_ledger->net_name = a_net_name; dap_ledger_private_t *l_ledger_priv = PVT(l_ledger); l_ledger_priv->check_flags = a_check_flags; l_ledger_priv->check_ds = a_check_flags & DAP_CHAIN_LEDGER_CHECK_LOCAL_DS; l_ledger_priv->check_cells_ds = a_check_flags & DAP_CHAIN_LEDGER_CHECK_CELLS_DS; l_ledger_priv->check_token_emission = a_check_flags & DAP_CHAIN_LEDGER_CHECK_TOKEN_EMISSION; - // load ledger from mempool - return l_ledger; //dap_chain_ledger_load(l_ledger, "kelvin-testnet", "plasma"); + // load ledger cache from GDB + dap_chain_ledger_load_cache(l_ledger); + return l_ledger; } int dap_chain_ledger_token_emission_add_check(dap_ledger_t *a_ledger, const dap_chain_datum_token_emission_t *a_token_emission @@ -430,16 +546,23 @@ int dap_chain_ledger_token_emission_add(dap_ledger_t *a_ledger, memcpy(l_token_emission_item->datum_token_emission, a_token_emission, a_token_emission_size); memcpy(&l_token_emission_item->datum_token_emission_hash, l_token_emission_hash_ptr, sizeof(l_token_emission_hash)); - dap_chain_ledger_token_emission_item_t * l_token_emissions = l_token_item ? - l_token_item->token_emissions : l_ledger_priv->treshold_emissions; - HASH_ADD(hh, l_token_emissions , - datum_token_emission_hash, sizeof(l_token_emission_hash), - l_token_emission_item); - // save pointer to structure - if(l_token_item) - l_token_item->token_emissions = l_token_emissions; - else - l_ledger_priv->treshold_emissions = l_token_emissions; + if (l_token_item) { + HASH_ADD(hh, l_token_item->token_emissions, datum_token_emission_hash, + sizeof(l_token_emission_hash), l_token_emission_item); + } else { + HASH_ADD(hh, l_ledger_priv->treshold_emissions, datum_token_emission_hash, + sizeof(l_token_emission_hash), l_token_emission_item); + } + // Add it to cache + dap_chain_datum_token_emission_t *l_emission_cache = DAP_NEW_Z_SIZE(dap_chain_datum_token_emission_t, a_token_emission_size); + memcpy(l_emission_cache, a_token_emission, a_token_emission_size); + char *l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, "emissions"); + if (!dap_chain_global_db_gr_set(dap_strdup(l_hash_str), l_emission_cache, a_token_emission_size, l_gdb_group)) { + log_it(L_WARNING, "Ledger cache mismatch"); + DAP_DELETE(l_emission_cache); + } + DAP_DELETE(l_gdb_group); + char * l_token_emission_address_str = dap_chain_addr_to_str( &(a_token_emission->hdr.address) ); log_it(L_NOTICE, "Added token emission datum to %s: type=%s value=%.1llf token=%s to_addr=%s ", @@ -466,6 +589,20 @@ int dap_chain_ledger_token_emission_add(dap_ledger_t *a_ledger, return ret; } +int dap_chain_ledger_token_emission_load(dap_ledger_t *a_ledger, const dap_chain_datum_token_emission_t *a_token_emission, size_t a_token_emission_size) +{ + if (PVT(a_ledger)->last_emit.found) { + return dap_chain_ledger_token_emission_add(a_ledger, a_token_emission, a_token_emission_size); + } else { + dap_chain_hash_fast_t l_token_emission_hash = {}; + dap_hash_fast(a_token_emission, a_token_emission_size, &l_token_emission_hash); + if (!memcmp(PVT(a_ledger)->last_emit.hash, &l_token_emission_hash, sizeof(dap_chain_hash_fast_t))) { + PVT(a_ledger)->last_emit.found = true; + } + } + return 0; +} + /** * @brief dap_chain_ledger_token_emission_find * @param a_token_ticker @@ -522,7 +659,7 @@ const char* dap_chain_ledger_tx_get_token_ticker_by_hash(dap_ledger_t *a_ledger, pthread_rwlock_rdlock(&l_ledger_priv->ledger_rwlock); HASH_FIND(hh, l_ledger_priv->ledger_items, a_tx_hash, sizeof ( *a_tx_hash), l_item ); pthread_rwlock_unlock(&l_ledger_priv->ledger_rwlock); - return l_item? l_item->token_tiker: NULL; + return l_item ? l_item->cache_data.token_tiker : NULL; } /** @@ -548,7 +685,7 @@ void dap_chain_ledger_addr_get_token_ticker_all(dap_ledger_t *a_ledger, dap_chai for(size_t i = 0; i < l_tickers_size; i++) { if (l_tickers[i]==NULL) break; - if(l_tickers[i] && strcmp(l_tickers[i], l_tx_item->token_tiker) == 0) { + if(l_tickers[i] && strcmp(l_tickers[i], l_tx_item->cache_data.token_tiker) == 0) { l_is_not_in_list = false; break; } @@ -558,7 +695,7 @@ void dap_chain_ledger_addr_get_token_ticker_all(dap_ledger_t *a_ledger, dap_chai l_tickers_size += (l_tickers_size / 2); l_tickers = DAP_REALLOC(l_tickers, l_tickers_size); } - l_tickers[l_tickers_pos] = dap_strdup(l_tx_item->token_tiker); + l_tickers[l_tickers_pos] = dap_strdup(l_tx_item->cache_data.token_tiker); l_tickers_pos++; } dap_chain_hash_fast_t* l_tx_hash = dap_chain_node_datum_tx_calc_hash(l_tx_item->tx); @@ -647,8 +784,8 @@ static bool dap_chain_ledger_item_is_used_out(dap_chain_ledger_tx_item_t *a_item } assert(a_idx_out < MAX_OUT_ITEMS); // if there are used 'out' items - if(a_item->n_outs_used > 0) { - if(!dap_hash_fast_is_blank(&(a_item->tx_hash_spent_fast[a_idx_out]))) + if(a_item->cache_data.n_outs_used > 0) { + if(!dap_hash_fast_is_blank(&(a_item->cache_data.tx_hash_spent_fast[a_idx_out]))) l_used_out = true; } return l_used_out; @@ -888,7 +1025,7 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t l_token = NULL; } if (!l_token || !*l_token) { - l_token = l_item_out->token_tiker; + l_token = l_item_out->cache_data.token_tiker; } if (!*l_token) { log_it(L_WARNING, "No token ticker found in previous transaction"); @@ -1057,6 +1194,19 @@ int dap_chain_ledger_tx_add_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t * return 0; } +int dap_chain_ledger_balance_cache_update(dap_ledger_t *a_ledger, dap_ledger_wallet_balance_t *a_balance) +{ + char *l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, "balances"); + uint128_t *l_balance_value = DAP_NEW_Z(uint128_t); + *l_balance_value = a_balance->balance; + if (!dap_chain_global_db_gr_set(dap_strdup(a_balance->key), l_balance_value, sizeof(uint128_t), l_gdb_group)) { + log_it(L_WARNING, "Ledger cache mismatch"); + DAP_DELETE(l_balance_value); + return -1; + } + return 0; +} + /** * Add new transaction to the cache list * @@ -1113,8 +1263,8 @@ int dap_chain_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx) void *l_item_in = *(void **)&bound_item->in; dap_chain_tx_item_type_t l_type = *(uint8_t *)l_item_in; dap_chain_ledger_tx_item_t *l_prev_item_out = bound_item->item_out; - if (*l_prev_item_out->token_tiker) { - l_token_ticker = l_prev_item_out->token_tiker; + if (*l_prev_item_out->cache_data.token_tiker) { + l_token_ticker = l_prev_item_out->cache_data.token_tiker; } else { // Previous multichannel transaction l_token_ticker = bound_item->out.tx_prev_out_ext->token; } @@ -1140,26 +1290,28 @@ int dap_chain_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx) bound_item->out.tx_prev_out_ext->header.value; //log_it(L_DEBUG,"SPEND %lu from addr: %s", l_value, l_wallet_balance_key); wallet_balance->balance -= l_value; + // Update the cache + dap_chain_ledger_balance_cache_update(a_ledger, wallet_balance); } else { log_it(L_ERROR,"!!! Attempt to SPEND from some non-existent balance !!!: %s %s", l_addr_str, l_token_ticker); } DAP_DELETE(l_addr_str); DAP_DELETE(l_wallet_balance_key); /// Mark 'out' item in cache because it used - l_tx_prev_hash = &(l_prev_item_out->tx_hash_spent_fast[l_tx_in->header.tx_out_prev_idx]); + l_tx_prev_hash = &(l_prev_item_out->cache_data.tx_hash_spent_fast[l_tx_in->header.tx_out_prev_idx]); } else { // TX_ITEM_TYPE_IN_COND // all balance deducts performed with previous conditional transaction dap_chain_tx_in_cond_t *l_tx_in_cond = bound_item->in.tx_cur_in_cond; /// Mark 'out' item in cache because it used - l_tx_prev_hash = &(l_prev_item_out->tx_hash_spent_fast[l_tx_in_cond->header.tx_out_prev_idx]); + l_tx_prev_hash = &(l_prev_item_out->cache_data.tx_hash_spent_fast[l_tx_in_cond->header.tx_out_prev_idx]); } memcpy(l_tx_prev_hash, l_tx_hash, sizeof(dap_chain_hash_fast_t)); // add a used output - l_prev_item_out->n_outs_used++; + l_prev_item_out->cache_data.n_outs_used++; char * l_tx_prev_hash_str = dap_chain_hash_fast_to_str_new(l_tx_prev_hash); // delete previous transactions from cache because all out is used - if(l_prev_item_out->n_outs_used == l_prev_item_out->n_outs) { + if(l_prev_item_out->cache_data.n_outs_used == l_prev_item_out->cache_data.n_outs) { dap_chain_hash_fast_t l_tx_prev_hash_to_del = bound_item->tx_prev_hash_fast; // remove from memory ledger int res = dap_chain_ledger_tx_remove(a_ledger, &l_tx_prev_hash_to_del); @@ -1237,6 +1389,8 @@ int dap_chain_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx) //log_it(L_DEBUG, "Balance item is present in cache"); wallet_balance->balance += l_value; DAP_DELETE (l_wallet_balance_key); + // Update the cache + dap_chain_ledger_balance_cache_update(a_ledger, wallet_balance); } else { wallet_balance = DAP_NEW_Z(dap_ledger_wallet_balance_t); wallet_balance->key = l_wallet_balance_key; @@ -1245,6 +1399,8 @@ int dap_chain_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx) //log_it(L_DEBUG,"!!! Create new balance item: %s %s", l_addr_str, l_token_ticker); HASH_ADD_KEYPTR(hh, PVT(a_ledger)->balance_accounts, wallet_balance->key, strlen(l_wallet_balance_key), wallet_balance); + // Add it to cache + dap_chain_ledger_balance_cache_update(a_ledger, wallet_balance); } #ifdef __ANDROID__ log_it(L_INFO, "Updated balance +%.3Lf %s on addr %s", @@ -1272,15 +1428,15 @@ int dap_chain_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx) l_item_tmp = DAP_NEW_Z(dap_chain_ledger_tx_item_t); memcpy(&l_item_tmp->tx_hash_fast, l_tx_hash, sizeof(dap_chain_hash_fast_t)); l_item_tmp->tx = DAP_NEW_SIZE(dap_chain_datum_tx_t, dap_chain_datum_tx_get_size(a_tx)); - l_item_tmp->ts_created = (time_t) a_tx->header.ts_created; + l_item_tmp->cache_data.ts_created = (time_t) a_tx->header.ts_created; //calculate l_item_tmp->n_outs; // If debug mode dump the UTXO if ( dap_log_level_get() == L_DEBUG){ - l_item_tmp->n_outs = 0; - if( l_item_tmp->n_outs){ - dap_list_t *l_tist_tmp = dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_OUT, &l_item_tmp->n_outs); - for (size_t i =0; i < (size_t) l_item_tmp->n_outs; i++){ + l_item_tmp->cache_data.n_outs = 0; + if( l_item_tmp->cache_data.n_outs){ + dap_list_t *l_tist_tmp = dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_OUT, &l_item_tmp->cache_data.n_outs); + for (size_t i =0; i < (size_t) l_item_tmp->cache_data.n_outs; i++){ // TODO list conditional outputs dap_chain_tx_out_t * l_tx_out = l_tist_tmp->data; char * l_tx_out_addr_str = dap_chain_addr_to_str( &l_tx_out->addr ); @@ -1303,10 +1459,20 @@ int dap_chain_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx) } } if (l_token_ticker && !l_multichannel) - strncpy(l_item_tmp->token_tiker, l_token_ticker, sizeof(l_item_tmp->token_tiker) - 1); - - memcpy(l_item_tmp->tx, a_tx, dap_chain_datum_tx_get_size(a_tx)); - HASH_ADD(hh, l_ledger_priv->ledger_items, tx_hash_fast, sizeof(dap_chain_hash_fast_t), l_item_tmp); // tx_hash_fast: name of key field + strncpy(l_item_tmp->cache_data.token_tiker, l_token_ticker, sizeof(l_item_tmp->cache_data.token_tiker) - 1); + size_t l_tx_size = dap_chain_datum_tx_get_size(a_tx); + memcpy(l_item_tmp->tx, a_tx, l_tx_size); + HASH_ADD(hh, l_ledger_priv->ledger_items, tx_hash_fast, sizeof(dap_chain_hash_fast_t), l_item_tmp); // tx_hash_fast: name of key field + // Add it to cache + uint8_t *l_tx_cache = DAP_NEW_Z_SIZE(uint8_t, l_tx_size + sizeof(l_item_tmp->cache_data)); + memcpy(l_tx_cache, &l_item_tmp->cache_data, sizeof(l_item_tmp->cache_data)); + memcpy(l_tx_cache + sizeof(l_item_tmp->cache_data), a_tx, l_tx_size); + char *l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, "txs"); + if (!dap_chain_global_db_gr_set(dap_strdup(l_tx_hash_str), l_tx_cache, l_tx_size + sizeof(l_item_tmp->cache_data), l_gdb_group)) { + log_it(L_WARNING, "Ledger cache mismatch"); + DAP_DELETE(l_tx_cache); + } + DAP_DELETE(l_gdb_group); ret = 1; } FIN: @@ -1316,6 +1482,25 @@ FIN: return ret; } +int dap_chain_ledger_tx_load(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx) +{ + if (PVT(a_ledger)->last_tx.found && PVT(a_ledger)->last_thres_tx.found) { + return dap_chain_ledger_tx_add(a_ledger, a_tx); + } else { + dap_chain_hash_fast_t l_tx_hash = {}; + dap_hash_fast(a_tx, dap_chain_datum_tx_get_size(a_tx), &l_tx_hash); + if (!PVT(a_ledger)->last_tx.found && + !memcmp(PVT(a_ledger)->last_tx.hash, &l_tx_hash, sizeof(dap_chain_hash_fast_t))) { + PVT(a_ledger)->last_tx.found = true; + } + if (!PVT(a_ledger)->last_thres_tx.found && + !memcmp(PVT(a_ledger)->last_thres_tx.hash, &l_tx_hash, sizeof(dap_chain_hash_fast_t))) { + PVT(a_ledger)->last_thres_tx.found = true; + } + } + return 1; +} + /** * Delete transaction from the cache * @@ -1332,18 +1517,20 @@ int dap_chain_ledger_tx_remove(dap_ledger_t *a_ledger, dap_chain_hash_fast_t *a_ HASH_FIND(hh, l_ledger_priv->ledger_items, a_tx_hash, sizeof(dap_chain_hash_fast_t), l_item_tmp); if(l_item_tmp != NULL) { HASH_DEL(l_ledger_priv->ledger_items, l_item_tmp); + // delete transaction + DAP_DELETE(l_item_tmp->tx); + // del struct for hash + DAP_DELETE(l_item_tmp); + // Remove it from cache + char *l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, "txs"); + dap_chain_global_db_gr_del(dap_chain_hash_fast_to_str_new(a_tx_hash), l_gdb_group); + DAP_DELETE(l_gdb_group); l_ret = 1; } else // hash not found in the cache l_ret = -2; pthread_rwlock_unlock(&l_ledger_priv->ledger_rwlock); - if(!l_ret) { - // delete transaction - DAP_DELETE(l_item_tmp->tx); - // del struct for hash - DAP_DELETE(l_item_tmp); - } return l_ret; } @@ -1353,16 +1540,82 @@ int dap_chain_ledger_tx_remove(dap_ledger_t *a_ledger, dap_chain_hash_fast_t *a_ void dap_chain_ledger_purge(dap_ledger_t *a_ledger) { dap_ledger_private_t *l_ledger_priv = PVT(a_ledger); - dap_chain_ledger_tx_item_t *l_iter_current, *l_item_tmp; + const int l_hash_str_size = DAP_CHAIN_HASH_FAST_SIZE * 2 + 2; + char l_hash_str[l_hash_str_size]; pthread_rwlock_wrlock(&l_ledger_priv->ledger_rwlock); - HASH_ITER(hh, l_ledger_priv->ledger_items , l_iter_current, l_item_tmp) - { - // delete transaction - DAP_DELETE(l_iter_current->tx); - // del struct for hash - HASH_DEL(l_ledger_priv->ledger_items, l_iter_current); + pthread_rwlock_wrlock(&l_ledger_priv->tokens_rwlock); + pthread_rwlock_wrlock(&l_ledger_priv->treshold_emissions_rwlock); + pthread_rwlock_wrlock(&l_ledger_priv->treshold_txs_rwlock); + + // delete transactions + dap_chain_ledger_tx_item_t *l_item_current, *l_item_tmp; + char *l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, "txs"); + HASH_ITER(hh, l_ledger_priv->ledger_items , l_item_current, l_item_tmp) { + DAP_DELETE(l_item_current->tx); + HASH_DEL(l_ledger_priv->ledger_items, l_item_current); + dap_chain_hash_fast_to_str(&l_item_current->tx_hash_fast, l_hash_str, l_hash_str_size); + dap_chain_global_db_gr_del(l_hash_str, l_gdb_group); + DAP_DELETE(l_item_current); + } + DAP_DELETE(l_gdb_group); + + // delete threshold txs + l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, "thres_txs"); + HASH_ITER(hh, l_ledger_priv->treshold_txs, l_item_current, l_item_tmp) { + HASH_DEL(l_ledger_priv->treshold_txs, l_item_current); + dap_chain_hash_fast_to_str(&l_item_current->tx_hash_fast, l_hash_str, l_hash_str_size); + dap_chain_global_db_gr_del(l_hash_str, l_gdb_group); + DAP_DELETE(l_item_current->tx); + DAP_DELETE(l_item_current); + } + DAP_DELETE(l_gdb_group); + + // delete balances + dap_ledger_wallet_balance_t *l_balance_current, *l_balance_tmp; + l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, "balances"); + HASH_ITER(hh, l_ledger_priv->balance_accounts, l_balance_current, l_balance_tmp) { + HASH_DEL(l_ledger_priv->balance_accounts, l_balance_current); + dap_chain_global_db_gr_del(l_balance_current->key, l_gdb_group); + DAP_DELETE(l_balance_current->key); + DAP_DELETE(l_balance_current); } + DAP_DELETE(l_gdb_group); + + // delete threshold emissions + dap_chain_ledger_token_emission_item_t *l_emission_current, *l_emission_tmp; + char *l_emissions_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, "emissions"); + HASH_ITER(hh, l_ledger_priv->treshold_emissions, l_emission_current, l_emission_tmp) { + HASH_DEL(l_ledger_priv->treshold_emissions, l_emission_current); + dap_chain_hash_fast_to_str(&l_emission_current->datum_token_emission_hash, l_hash_str, l_hash_str_size); + dap_chain_global_db_gr_del(l_hash_str, l_emissions_gdb_group); + DAP_DELETE(l_emission_current->datum_token_emission); + DAP_DELETE(l_emission_current); + } + + // delete tokens & its emissions + dap_chain_ledger_token_item_t *l_token_current, *l_token_tmp; + l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, "tokens"); + HASH_ITER(hh, l_ledger_priv->tokens, l_token_current, l_token_tmp) { + HASH_DEL(l_ledger_priv->tokens, l_token_current); + HASH_ITER(hh, l_token_current->token_emissions, l_emission_current, l_emission_tmp) { + HASH_DEL(l_token_current->token_emissions, l_emission_current); + dap_chain_hash_fast_to_str(&l_emission_current->datum_token_emission_hash, l_hash_str, l_hash_str_size); + dap_chain_global_db_gr_del(l_hash_str, l_emissions_gdb_group); + DAP_DELETE(l_emission_current->datum_token_emission); + DAP_DELETE(l_emission_current); + } + dap_chain_global_db_gr_del(l_token_current->ticker, l_gdb_group); + DAP_DELETE(l_token_current->datum_token); + pthread_rwlock_destroy(&l_token_current->token_emissions_rwlock); + DAP_DELETE(l_token_current); + } + DAP_DELETE(l_gdb_group); + DAP_DELETE(l_emissions_gdb_group); + pthread_rwlock_unlock(&l_ledger_priv->ledger_rwlock); + pthread_rwlock_unlock(&l_ledger_priv->tokens_rwlock); + pthread_rwlock_unlock(&l_ledger_priv->treshold_emissions_rwlock); + pthread_rwlock_unlock(&l_ledger_priv->treshold_txs_rwlock); } /** @@ -1370,16 +1623,7 @@ void dap_chain_ledger_purge(dap_ledger_t *a_ledger) */ _dap_int128_t dap_chain_ledger_count(dap_ledger_t *a_ledger) { - _dap_int128_t l_ret = 0; - dap_ledger_private_t *l_ledger_priv = PVT(a_ledger); - dap_chain_ledger_tx_item_t *l_iter_current, *l_item_tmp; - pthread_rwlock_wrlock(&l_ledger_priv->ledger_rwlock); - HASH_ITER(hh, l_ledger_priv->ledger_items , l_iter_current, l_item_tmp) - { - l_ret++; - } - pthread_rwlock_unlock(&l_ledger_priv->ledger_rwlock); - return l_ret; + return HASH_COUNT(PVT(a_ledger)->ledger_items); } /** @@ -1397,17 +1641,17 @@ uint64_t dap_chain_ledger_count_from_to(dap_ledger_t * a_ledger, time_t a_ts_fro pthread_rwlock_wrlock(&l_ledger_priv->ledger_rwlock); if ( a_ts_from && a_ts_to) { HASH_ITER(hh, l_ledger_priv->ledger_items , l_iter_current, l_item_tmp){ - if ( l_iter_current->ts_created >= a_ts_from && l_iter_current->ts_created <= a_ts_to ) + if ( l_iter_current->cache_data.ts_created >= a_ts_from && l_iter_current->cache_data.ts_created <= a_ts_to ) l_ret++; } } else if ( a_ts_to ){ HASH_ITER(hh, l_ledger_priv->ledger_items , l_iter_current, l_item_tmp){ - if ( l_iter_current->ts_created <= a_ts_to ) + if ( l_iter_current->cache_data.ts_created <= a_ts_to ) l_ret++; } } else if ( a_ts_from ){ HASH_ITER(hh, l_ledger_priv->ledger_items , l_iter_current, l_item_tmp){ - if ( l_iter_current->ts_created >= a_ts_from ) + if ( l_iter_current->cache_data.ts_created >= a_ts_from ) l_ret++; } }else { @@ -1512,7 +1756,7 @@ uint64_t dap_chain_ledger_calc_balance_full(dap_ledger_t *a_ledger, const dap_ch if (l_type == TX_ITEM_TYPE_OUT) { const dap_chain_tx_out_t *l_tx_out = (const dap_chain_tx_out_t*) l_list_tmp->data; // Check for token name - if (!strcmp(a_token_ticker, l_iter_current->token_tiker)) + if (!strcmp(a_token_ticker, l_iter_current->cache_data.token_tiker)) { // if transaction has the out item with requested addr if (!memcmp(a_addr, &l_tx_out->addr, sizeof(dap_chain_addr_t))) { // if 'out' item not used & transaction is valid @@ -1563,7 +1807,8 @@ static dap_chain_ledger_tx_item_t* tx_item_find_by_addr(dap_ledger_t *a_ledger, HASH_ITER(hh, l_ledger_priv->ledger_items , l_iter_current, l_item_tmp) { // If a_token is setup we check if its not our token - miss it - if (a_token && *l_iter_current->token_tiker && dap_strcmp(l_iter_current->token_tiker, a_token)) + if (a_token && *l_iter_current->cache_data.token_tiker && + dap_strcmp(l_iter_current->cache_data.token_tiker, a_token)) continue; // Now work with it dap_chain_datum_tx_t *l_tx = l_iter_current->tx; @@ -1715,7 +1960,7 @@ dap_chain_datum_tx_t* dap_chain_ledger_tx_cache_find_out_cond(dap_ledger_t *a_le l_cur_tx = l_tx_tmp; memcpy(a_tx_first_hash, l_tx_hash_tmp, sizeof(dap_chain_hash_fast_t)); if (a_token_ticker) { - strcpy(a_token_ticker, l_iter_current->token_tiker); + strcpy(a_token_ticker, l_iter_current->cache_data.token_tiker); } break; } diff --git a/modules/chain/include/dap_chain.h b/modules/chain/include/dap_chain.h index fc03b2f72db531bc7704eff954fbacecd549d25c..baad228c8660bfde5ac7a7cb9a425e7b0d6107c0 100644 --- a/modules/chain/include/dap_chain.h +++ b/modules/chain/include/dap_chain.h @@ -80,8 +80,8 @@ typedef dap_chain_atom_ptr_t * (*dap_chain_callback_atom_iter_get_atoms_t)(dap_c typedef dap_chain_atom_ptr_t (*dap_chain_callback_atom_iter_get_next_t)(dap_chain_atom_iter_t * ,size_t*); typedef void (*dap_chain_callback_atom_iter_delete_t)(dap_chain_atom_iter_t * ); -typedef size_t (*dap_chain_datum_callback_datum_pool_proc_add_t)(dap_chain_t * , dap_chain_datum_t **, size_t ); -typedef size_t (*dap_chain_datum_callback_datum_pool_proc_add_with_group_t)(dap_chain_t * , dap_chain_datum_t **, size_t, const char *); +typedef size_t (*dap_chain_callback_add_datums_t)(dap_chain_t * , dap_chain_datum_t **, size_t ); +typedef size_t (*dap_chain_callback_add_datums_with_group_t)(dap_chain_t * , dap_chain_datum_t **, size_t, const char *); typedef void (*dap_chain_callback_notify_t)(void * a_arg, dap_chain_t *a_chain, dap_chain_cell_id_t a_id, void* a_atom, size_t a_atom_size); //change in chain happened @@ -118,13 +118,14 @@ typedef struct dap_chain{ dap_chain_callback_new_cfg_t callback_created; dap_chain_callback_t callback_delete; + dap_chain_callback_t callback_purge; dap_chain_callback_atom_t callback_atom_add; dap_chain_callback_atom_form_treshold_t callback_atom_add_from_treshold; dap_chain_callback_atom_verify_t callback_atom_verify; - dap_chain_datum_callback_datum_pool_proc_add_t callback_datums_pool_proc; - dap_chain_datum_callback_datum_pool_proc_add_with_group_t callback_datums_pool_proc_with_group; + dap_chain_callback_add_datums_t callback_add_datums; + dap_chain_callback_add_datums_with_group_t callback_add_datums_with_group; dap_chain_callback_atom_get_hdr_size_t callback_atom_get_hdr_static_size; // Get atom header's size @@ -173,3 +174,4 @@ dap_chain_t * dap_chain_load_from_cfg(dap_ledger_t* a_ledger,const char * a_chai void dap_chain_delete(dap_chain_t * a_chain); void dap_chain_add_callback_notify(dap_chain_t * a_chain, dap_chain_callback_notify_t a_callback, void * a_arg); +dap_chain_atom_ptr_t dap_chain_get_atom_by_hash(dap_chain_t * a_chain, dap_chain_hash_fast_t * a_atom_hash, size_t * a_atom_size); diff --git a/modules/chain/include/dap_chain_cs.h b/modules/chain/include/dap_chain_cs.h index 9a5d4620a37fbb8bdbeaefb1e8a3dac94988471a..f76d443f57eabbf60e2fcc55287683f64fa68438 100644 --- a/modules/chain/include/dap_chain_cs.h +++ b/modules/chain/include/dap_chain_cs.h @@ -39,5 +39,5 @@ void dap_chain_cs_deinit(void); void dap_chain_cs_add (const char * a_cs_str, dap_chain_callback_new_cfg_t a_callback_init); int dap_chain_cs_create(dap_chain_t * a_chain, dap_config_t * a_chain_cfg); -void dap_chain_class_add (const char * a_cs_str, dap_chain_callback_new_cfg_t a_callback_init); -int dap_chain_class_create(dap_chain_t * a_chain, dap_config_t * a_chain_cfg); +void dap_chain_cs_type_add (const char * a_cs_str, dap_chain_callback_new_cfg_t a_callback_init); +int dap_chain_cs_type_create(dap_chain_t * a_chain, dap_config_t * a_chain_cfg); diff --git a/modules/chain/include/dap_chain_ledger.h b/modules/chain/include/dap_chain_ledger.h index 29b7b7e9f0ecf06987174d0b66e1ca87b3370b82..3eb630475f066d7069f58607450e42edfd9e5265 100644 --- a/modules/chain/include/dap_chain_ledger.h +++ b/modules/chain/include/dap_chain_ledger.h @@ -38,6 +38,7 @@ #include "dap_chain_datum_tx_items.h" typedef struct dap_ledger { + char *net_name; void *_internal; } dap_ledger_t; @@ -52,7 +53,7 @@ typedef bool (* dap_chain_ledger_verificator_callback_t)(dap_chain_tx_out_cond_t // Check the double spending in all cells #define DAP_CHAIN_LEDGER_CHECK_CELLS_DS 0x0100 -dap_ledger_t* dap_chain_ledger_create(uint16_t a_check_flags); +dap_ledger_t* dap_chain_ledger_create(uint16_t a_check_flags, char *a_net_name); // Remove dap_ledger_t structure void dap_chain_ledger_handle_free(dap_ledger_t *a_ledger); @@ -67,19 +68,28 @@ void dap_chain_ledger_set_local_cell_id(dap_ledger_t *a_ledger, dap_chain_cell_i * @param a_tx * @return */ -static inline dap_chain_hash_fast_t* dap_chain_node_datum_tx_calc_hash(dap_chain_datum_tx_t *a_tx) +DAP_STATIC_INLINE dap_chain_hash_fast_t* dap_chain_node_datum_tx_calc_hash(dap_chain_datum_tx_t *a_tx) { dap_chain_hash_fast_t *tx_hash = DAP_NEW_Z(dap_chain_hash_fast_t); dap_hash_fast(a_tx, dap_chain_datum_tx_get_size(a_tx), tx_hash); return tx_hash; } +DAP_STATIC_INLINE char *dap_chain_ledger_get_gdb_group(dap_ledger_t *a_ledger, const char *a_suffix) +{ + if (a_ledger) { + return dap_strdup_printf("local.ledger-cache.%s.%s", a_ledger->net_name, a_suffix); + } + return NULL; +} + /** * Add new transaction to the cache * * return 1 OK, -1 error */ int dap_chain_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx); +int dap_chain_ledger_tx_load(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx); int dap_chain_ledger_tx_add_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx); @@ -97,6 +107,7 @@ int dap_chain_ledger_token_ticker_check(dap_ledger_t * a_ledger, const char *a_t */ int dap_chain_ledger_token_add(dap_ledger_t * a_ledger,dap_chain_datum_token_t *a_token, size_t a_token_size); +int dap_chain_ledger_token_load(dap_ledger_t * a_ledger,dap_chain_datum_token_t *a_token, size_t a_token_size); int dap_chain_ledger_token_decl_add_check(dap_ledger_t * a_ledger,dap_chain_datum_token_t *a_token); /** @@ -104,6 +115,8 @@ int dap_chain_ledger_token_decl_add_check(dap_ledger_t * a_ledger,dap_chain_datu */ int dap_chain_ledger_token_emission_add(dap_ledger_t *a_ledger, const dap_chain_datum_token_emission_t *a_token_emission, size_t a_token_emission_size); +int dap_chain_ledger_token_emission_load(dap_ledger_t *a_ledger, + const dap_chain_datum_token_emission_t *a_token_emission, size_t a_token_emission_size); // Check if it addable int dap_chain_ledger_token_emission_add_check(dap_ledger_t *a_ledger, diff --git a/modules/chain/include/dap_chain_pvt.h b/modules/chain/include/dap_chain_pvt.h index d18e434a8f0300db0f245c688dc17e75f3f358c9..4af990d5fcdf6b2650e6ba1a44785a67400d26dd 100644 --- a/modules/chain/include/dap_chain_pvt.h +++ b/modules/chain/include/dap_chain_pvt.h @@ -41,6 +41,8 @@ typedef struct dap_chain_pvt { dap_chain_t * chain; char * file_storage_dir; + char * cs_name; + int celled; } dap_chain_pvt_t; #define DAP_CHAIN_PVT(a) ((dap_chain_pvt_t *) a->_pvt ) diff --git a/modules/channel/chain/dap_stream_ch_chain.c b/modules/channel/chain/dap_stream_ch_chain.c index 27e9d17d4c1de614755cf6cbc72720b54a983b7b..e7a5ce4f4d815fa870297537332323fa67776c8b 100644 --- a/modules/channel/chain/dap_stream_ch_chain.c +++ b/modules/channel/chain/dap_stream_ch_chain.c @@ -152,6 +152,9 @@ bool s_sync_chains_callback(dap_proc_thread_t *a_thread, void *a_arg) l_ch_chain->request_cell_id, &l_request, sizeof(l_request)); DAP_DEL_Z(l_ch_chain->request_atom_iter); l_ch_chain->state = CHAIN_STATE_IDLE; + if (l_ch_chain->callback_notify_packet_out) + l_ch_chain->callback_notify_packet_out(l_ch_chain, DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_CHAINS, + NULL, 0, l_ch_chain->callback_notify_arg); } dap_stream_ch_set_ready_to_write_unsafe(l_ch, true); dap_events_socket_assign_on_worker_mt(l_ch->stream->esocket, l_ch->stream_worker->worker); @@ -349,9 +352,9 @@ bool s_gdb_pkt_callback(dap_proc_thread_t *a_thread, void *a_arg) // apply received transaction dap_chain_t *l_chain = dap_chain_find_by_id(l_ch_chain->request_net_id, l_ch_chain->request_chain_id); if(l_chain) { - if(l_chain->callback_datums_pool_proc_with_group){ + if(l_chain->callback_add_datums_with_group){ void * restrict l_store_obj_value = l_store_obj->value; - l_chain->callback_datums_pool_proc_with_group(l_chain, + l_chain->callback_add_datums_with_group(l_chain, (dap_chain_datum_t** restrict) l_store_obj_value, 1, l_store_obj[i].group); } diff --git a/modules/common/include/dap_chain_datum.h b/modules/common/include/dap_chain_datum.h index cd6f7b45b39591619545bd7ffe43c80f3dec065a..3293a2c3720093431032dccdb5101f03458e6839 100644 --- a/modules/common/include/dap_chain_datum.h +++ b/modules/common/include/dap_chain_datum.h @@ -88,7 +88,7 @@ typedef struct dap_chain_datum{ /// Create timestamp (GM time) uint64_t ts_create; } DAP_ALIGN_PACKED header; - uint8_t data[]; /// Stored datum body + byte_t data[]; /// Stored datum body } DAP_ALIGN_PACKED dap_chain_datum_t; diff --git a/modules/common/include/dap_chain_datum_token.h b/modules/common/include/dap_chain_datum_token.h index d130cec690b5597b0cd196cf8b8974d980de3709..5d3b8644eae22e7b795c8f86cc03f6eef9294674 100644 --- a/modules/common/include/dap_chain_datum_token.h +++ b/modules/common/include/dap_chain_datum_token.h @@ -135,7 +135,7 @@ static inline uint16_t dap_chain_datum_token_flag_from_str(const char* a_str) // TSD section - Type-Size-Data typedef struct dap_chain_datum_token_tsd{ uint16_t type; /// Section type - size_t size; /// Data size trailing the section + uint32_t size; /// Data size trailing the section byte_t data[]; /// Section's data } DAP_ALIGN_PACKED dap_chain_datum_token_tsd_t; diff --git a/modules/consensus/none/dap_chain_cs_none.c b/modules/consensus/none/dap_chain_cs_none.c index 82f54c1fcba42a767a57817e115ebb97428e5812..1e9b966aeaa474b3baba928adca1341b8f939ed1 100644 --- a/modules/consensus/none/dap_chain_cs_none.c +++ b/modules/consensus/none/dap_chain_cs_none.c @@ -65,8 +65,6 @@ typedef struct dap_chain_gdb_private #define PVT(a) ( (a) ? (dap_chain_gdb_private_t* ) (a)->_internal : NULL) -static int dap_chain_gdb_ledger_load(dap_chain_gdb_t *a_gdb, dap_chain_net_t *a_net); - // Atomic element organization callbacks static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_chain, dap_chain_atom_ptr_t, size_t); // Accept new event in gdb static dap_chain_atom_verify_res_t s_chain_callback_atom_verify(dap_chain_t * a_chain, dap_chain_atom_ptr_t, size_t); // Verify new event in gdb @@ -114,7 +112,7 @@ static int s_cs_callback_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg) int dap_chain_gdb_init(void) { dap_chain_cs_add(CONSENSUS_NAME, s_cs_callback_new); - dap_chain_class_add(CONSENSUS_NAME, dap_chain_gdb_new); + dap_chain_cs_type_add(CONSENSUS_NAME, dap_chain_gdb_new); log_it(L_NOTICE, "Initialized GDB chain items organization class"); return 0; @@ -138,10 +136,16 @@ static void s_history_callback_notify(void * a_arg, const char a_op_code, const dap_chain_net_t *l_net = dap_chain_net_by_id( l_gdb->chain->net_id); log_it(L_DEBUG,"%s.%s: op_code='%c' group=\"%s\" key=\"%s\" value_size=%u",l_net->pub.name, l_gdb->chain->name, a_op_code, a_group, a_key, a_value_size); + dap_chain_node_mempool_autoproc_notify((void *)l_net, a_op_code, a_prefix, a_group, a_key, a_value, a_value_size); dap_chain_net_sync_gdb_broadcast((void *)l_net, a_op_code, a_prefix, a_group, a_key, a_value, a_value_size); } } +static void s_dap_chain_gdb_callback_purge(dap_chain_t *a_chain) +{ + PVT(DAP_CHAIN_GDB(a_chain))->is_load_mode = true; +} + /** * @brief dap_chain_gdb_new * @param a_chain @@ -176,10 +180,10 @@ int dap_chain_gdb_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg) // load ledger l_gdb_priv->is_load_mode = true; - dap_chain_gdb_ledger_load(l_gdb, l_net); - l_gdb_priv->is_load_mode = false; + dap_chain_gdb_ledger_load(l_gdb_priv->group_datums, a_chain); a_chain->callback_delete = dap_chain_gdb_delete; + a_chain->callback_purge = s_dap_chain_gdb_callback_purge; // Atom element callbacks a_chain->callback_atom_add = s_chain_callback_atom_add; // Accept new element in chain @@ -191,8 +195,8 @@ int dap_chain_gdb_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg) a_chain->callback_atom_iter_delete = s_chain_callback_atom_iter_delete; a_chain->callback_atom_find_by_hash = s_chain_callback_atom_iter_find_by_hash; - a_chain->callback_datums_pool_proc = s_chain_callback_datums_pool_proc; - a_chain->callback_datums_pool_proc_with_group = s_chain_callback_datums_pool_proc_with_group; + a_chain->callback_add_datums = s_chain_callback_datums_pool_proc; + a_chain->callback_add_datums_with_group = s_chain_callback_datums_pool_proc_with_group; // Linear pass through a_chain->callback_atom_iter_get_first = s_chain_callback_atom_iter_get_first; // Get the fisrt element from chain @@ -258,23 +262,17 @@ const char* dap_chain_gdb_get_group(dap_chain_t * a_chain) * * return 0 if OK otherwise negative error code */ -static int dap_chain_gdb_ledger_load(dap_chain_gdb_t *a_gdb, dap_chain_net_t *a_net) +int dap_chain_gdb_ledger_load(char *a_gdb_group, dap_chain_t *a_chain) { - dap_chain_gdb_private_t *l_gdb_priv = PVT(a_gdb); - // protect from reloading - if(dap_chain_ledger_count( a_net->pub.ledger ) > 0) - return 0; - size_t l_data_size = 0; - - // Read the entire database into an array of size bytes - dap_global_db_obj_t *data = dap_chain_global_db_gr_load(l_gdb_priv->group_datums , &l_data_size); + dap_global_db_obj_t *data = dap_chain_global_db_gr_load(a_gdb_group, &l_data_size); // make list of datums for(size_t i = 0; i < l_data_size; i++) { - s_chain_callback_atom_add(a_gdb->chain,data[i].value, data[i].value_len); + s_chain_callback_atom_add(a_chain, data[i].value, data[i].value_len); } dap_chain_global_db_objs_delete(data, l_data_size); + PVT(DAP_CHAIN_GDB(a_chain))->is_load_mode = false; return 0; } @@ -321,11 +319,11 @@ static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_cha switch (l_datum->header.type_id) { case DAP_CHAIN_DATUM_TOKEN_DECL:{ dap_chain_datum_token_t *l_token = (dap_chain_datum_token_t*) l_datum->data; - dap_chain_ledger_token_add(a_chain->ledger,l_token, l_datum->header.data_size); + dap_chain_ledger_token_load(a_chain->ledger,l_token, l_datum->header.data_size); }break; case DAP_CHAIN_DATUM_TOKEN_EMISSION: { dap_chain_datum_token_emission_t *l_token_emission = (dap_chain_datum_token_emission_t*) l_datum->data; - dap_chain_ledger_token_emission_add(a_chain->ledger, l_token_emission, l_datum->header.data_size); + dap_chain_ledger_token_emission_load(a_chain->ledger, l_token_emission, l_datum->header.data_size); }break; case DAP_CHAIN_DATUM_TX:{ dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t*) l_datum->data; @@ -334,7 +332,7 @@ static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_cha //if(dap_chain_datum_tx_get_size(l_tx) == l_datum->header.data_size){ // don't save bad transactions to base - if(dap_chain_ledger_tx_add(a_chain->ledger, l_tx) != 1) + if(dap_chain_ledger_tx_load(a_chain->ledger, l_tx) != 1) return ATOM_REJECT; //}else // return -2; diff --git a/modules/consensus/none/include/dap_chain_cs_none.h b/modules/consensus/none/include/dap_chain_cs_none.h index e40ae2184e63b48f74f699755053ed77c5420eb5..adf5cd6f0082c2239fd221d6c976fc6e74d60f31 100644 --- a/modules/consensus/none/include/dap_chain_cs_none.h +++ b/modules/consensus/none/include/dap_chain_cs_none.h @@ -39,4 +39,4 @@ int dap_chain_gdb_init(void); int dap_chain_gdb_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg); void dap_chain_gdb_delete(dap_chain_t * a_chain); const char* dap_chain_gdb_get_group(dap_chain_t * a_chain); - +int dap_chain_gdb_ledger_load(char *a_gdb_group, dap_chain_t *a_chain); diff --git a/modules/mempool/dap_chain_mempool.c b/modules/mempool/dap_chain_mempool.c index c5150e1cfd84094cb2abaee51480592e0c446545..b74867c4a7a55d236152bd947ca05eecd3ae44a7 100644 --- a/modules/mempool/dap_chain_mempool.c +++ b/modules/mempool/dap_chain_mempool.c @@ -568,7 +568,7 @@ dap_chain_hash_fast_t* dap_chain_proc_tx_create_cond(dap_chain_net_t * a_net, if(!l_datum) return NULL; - size_t l_datums_number = l_chain->callback_datums_pool_proc(l_chain, &l_datum, 1); + size_t l_datums_number = l_chain->callback_add_datums(l_chain, &l_datum, 1); if(!l_datums_number) return NULL; diff --git a/modules/net/CMakeLists.txt b/modules/net/CMakeLists.txt index e5d055725660d5a26b7aa656d5037c7616204d48..104d304db2ca5a35ca2cb8e215b77affb1e62b30 100644 --- a/modules/net/CMakeLists.txt +++ b/modules/net/CMakeLists.txt @@ -40,12 +40,12 @@ add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_NET_SRCS} ${DAP_CHAIN_NET_HEADERS if(WIN32) target_link_libraries(dap_chain_net dap_core dap_crypto dap_client dap_stream_ch_chain dap_stream_ch_chain_net dap_stream_ch_chain_net_srv dap_chain dap_chain_crypto dap_chain_wallet dap_chain_net_srv - dap_chain_mempool dap_chain_global_db dap_chain_net_srv_stake) + dap_chain_mempool dap_chain_global_db dap_chain_net_srv_stake dap_chain_cs_none) endif() if(UNIX) target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_client dap_stream_ch_chain dap_stream_ch_chain_net dap_stream_ch_chain_net_srv dap_chain - dap_chain_wallet dap_chain_net_srv dap_chain_mempool dap_chain_global_db dap_chain_net_srv_stake + dap_chain_wallet dap_chain_net_srv dap_chain_mempool dap_chain_global_db dap_chain_net_srv_stake dap_chain_cs_none resolv ) endif() diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c index 10061b1e3eedd8f138ae46c1ea0919f6b0d59187..567229f2ef4811d02c137fdb6f4f66e198e37e97 100644 --- a/modules/net/dap_chain_net.c +++ b/modules/net/dap_chain_net.c @@ -67,10 +67,12 @@ #include "dap_enc_http.h" #include "dap_chain_common.h" #include "dap_chain_net.h" +#include "dap_chain_pvt.h" #include "dap_chain_node_client.h" #include "dap_chain_node_cli.h" #include "dap_chain_node_cli_cmd.h" #include "dap_chain_ledger.h" +#include "dap_chain_cs_none.h" #include "dap_chain_global_db.h" #include "dap_chain_global_db_remote.h" @@ -889,7 +891,8 @@ int dap_chain_net_init() "\tPrint list of authority cetificates from GDB group\n" "net -net <chain net name> ca del -hash <cert hash> [-H hex|base58(default)]\n" "\tDelete certificate from list of authority cetificates in GDB group by it's hash\n" - ); + "net -net <chain net name> ledger reload\n" + "\tPurge the cache of chain net ledger and recalculate it from chain file\n" ); s_seed_mode = dap_config_get_item_bool_default(g_config,"general","seed_mode",false); dap_chain_global_db_add_history_group_prefix("global", GROUP_LOCAL_HISTORY); @@ -1028,12 +1031,14 @@ static int s_cli_net( int argc, char **argv, void *arg_func, char **a_str_reply) const char *l_get_str = NULL; const char *l_stats_str = NULL; const char *l_ca_str = NULL; + const char *l_ledger_str = NULL; dap_chain_node_cli_find_option_val(argv, arg_index, argc, "sync", &l_sync_str); dap_chain_node_cli_find_option_val(argv, arg_index, argc, "link", &l_links_str); dap_chain_node_cli_find_option_val(argv, arg_index, argc, "go", &l_go_str); dap_chain_node_cli_find_option_val(argv, arg_index, argc, "get", &l_get_str); dap_chain_node_cli_find_option_val(argv, arg_index, argc, "stats", &l_stats_str); dap_chain_node_cli_find_option_val(argv, arg_index, argc, "ca", &l_ca_str); + dap_chain_node_cli_find_option_val(argv, arg_index, argc, "ledger", &l_ledger_str); if ( l_stats_str ){ if ( strcmp(l_stats_str,"tx") == 0 ) { @@ -1269,6 +1274,19 @@ static int s_cli_net( int argc, char **argv, void *arg_func, char **a_str_reply) "Subcommand \"ca\" requires one of parameter: add, list, del\n"); ret = -5; } + } else if (l_ledger_str && !strcmp(l_ledger_str, "reload")) { + dap_chain_ledger_purge(l_net->pub.ledger); + dap_chain_t *l_chain; + DL_FOREACH(l_net->pub.chains, l_chain) { + if (l_chain->callback_purge) { + l_chain->callback_purge(l_chain); + } + if (!strcmp(DAP_CHAIN_PVT(l_chain)->cs_name, "none")) { + dap_chain_gdb_ledger_load((char *)dap_chain_gdb_get_group(l_chain), l_chain); + } else { + dap_chain_load_all(l_chain); + } + } } else { dap_chain_node_cli_set_reply_text(a_str_reply,"Command requires one of subcomand: sync, links\n"); ret = -1; @@ -1405,7 +1423,7 @@ int s_net_load(const char * a_net_name, uint16_t a_acl_idx) l_ledger_flags |= DAP_CHAIN_LEDGER_CHECK_LOCAL_DS; } // init LEDGER model - l_net->pub.ledger = dap_chain_ledger_create(l_ledger_flags); + l_net->pub.ledger = dap_chain_ledger_create(l_ledger_flags, l_net->pub.name); // Check if seed nodes are present in local db alias char **l_seed_aliases = dap_config_get_array_str( l_cfg , "general" ,"seed_nodes_aliases" ,&PVT(l_net)->seed_aliases_count); @@ -2099,7 +2117,7 @@ void dap_chain_net_proc_mempool (dap_chain_net_t * a_net) } } } - size_t l_objs_processed = l_chain->callback_datums_pool_proc(l_chain, l_datums, l_datums_size); + size_t l_objs_processed = l_chain->callback_add_datums(l_chain, l_datums, l_datums_size); // Delete processed objects size_t l_objs_processed_tmp = (l_objs_processed > 15) ? min(l_objs_processed, 10) : l_objs_processed; for(size_t i = 0; i < l_objs_processed; i++) { diff --git a/modules/net/dap_chain_node.c b/modules/net/dap_chain_node.c index 22484d478b6ae9870866abafc8c1b1719b48faba..a27bb9a8bde60d52cbd5d593efc48594ed1ea698 100644 --- a/modules/net/dap_chain_node.c +++ b/modules/net/dap_chain_node.c @@ -260,7 +260,7 @@ bool dap_chain_node_mempool_process(dap_chain_t *a_chain, dap_chain_node_role_t } } } - if (a_chain->callback_datums_pool_proc(a_chain, &a_datum, 1) != 1) { + if (a_chain->callback_add_datums(a_chain, &a_datum, 1) != 1) { return false; } return true; diff --git a/modules/net/dap_chain_node_cli.c b/modules/net/dap_chain_node_cli.c index 405fdedcdf7b9a4c59276ed65765734de7859c1e..4628c7a4d1aa98078fdfd1d9f79ed1f812af44ef 100644 --- a/modules/net/dap_chain_node_cli.c +++ b/modules/net/dap_chain_node_cli.c @@ -679,6 +679,32 @@ void dap_chain_node_cli_set_reply_text(char **str_reply, const char *str, ...) } } +/** + * @brief dap_chain_node_cli_check_option + * @param argv + * @param arg_start + * @param arg_end + * @param opt_name + * @return + */ +int dap_chain_node_cli_check_option( char** argv, int arg_start, int arg_end, const char *opt_name) +{ + int arg_index = arg_start; + const char *arg_string; + + while(arg_index < arg_end) + { + char * l_argv_cur = argv[arg_index]; + arg_string = l_argv_cur; + // find opt_name + if(arg_string && opt_name && arg_string[0] && opt_name[0] && !strcmp(arg_string, opt_name)) { + return arg_index; + } + arg_index++; + } + return -1; +} + /** * find option value * diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c index 6c3f58918094a1439dc9d335ea7d3d682f56caec..c74f2a5ef470007ee523c993ba52fd39675b02f7 100644 --- a/modules/net/dap_chain_node_cli_cmd.c +++ b/modules/net/dap_chain_node_cli_cmd.c @@ -2245,8 +2245,8 @@ int com_mempool_proc(int argc, char ** argv, void *arg_func, char ** a_str_reply l_verify_datum); ret = -9; }else{ - if (l_chain->callback_datums_pool_proc){ - if (l_chain->callback_datums_pool_proc(l_chain, &l_datum, 1) ==0 ){ + if (l_chain->callback_add_datums){ + if (l_chain->callback_add_datums(l_chain, &l_datum, 1) ==0 ){ dap_string_append_printf(l_str_tmp, "Error! Datum doesn't pass verifications, examine node log files"); ret = -6; }else{ diff --git a/modules/net/include/dap_chain_node_cli.h b/modules/net/include/dap_chain_node_cli.h index e9f9e81285841034f5426920590532760acabcd3..f67aca3a3f0b0f945829720de690ea31e12d15a3 100644 --- a/modules/net/include/dap_chain_node_cli.h +++ b/modules/net/include/dap_chain_node_cli.h @@ -73,6 +73,7 @@ void dap_chain_node_cli_cmd_item_apply_overrides(const char * a_name, const dap_ void dap_chain_node_cli_set_reply_text(char **str_reply, const char *str, ...); int dap_chain_node_cli_find_option_val( char** argv, int arg_start, int arg_end, const char *opt_name, const char **opt_value); +int dap_chain_node_cli_check_option( char** argv, int arg_start, int arg_end, const char *opt_name); /** diff --git a/modules/net/srv/dap_chain_net_srv_order.c b/modules/net/srv/dap_chain_net_srv_order.c index 8aba700a30215b038b580b8d0ee49744bd6684e3..869461dc4f5340562c2a40ee97251d6fa451f224 100644 --- a/modules/net/srv/dap_chain_net_srv_order.c +++ b/modules/net/srv/dap_chain_net_srv_order.c @@ -524,17 +524,17 @@ static void s_srv_order_callback_notify(void *a_arg, const char a_op_code, const if (!strcmp(a_group, l_gdb_group_str)) { dap_chain_net_srv_order_t *l_order = (dap_chain_net_srv_order_t *)a_value; if (l_order->version == 1) { - dap_chain_global_db_gr_del((char *)a_key, a_group); + dap_chain_global_db_gr_del(dap_strdup(a_key), a_group); } else { dap_sign_t *l_sign = (dap_sign_t *)&l_order->ext[l_order->ext_size]; if (!dap_sign_verify(l_sign, l_order, sizeof(dap_chain_net_srv_order_t) + l_order->ext_size)) { - dap_chain_global_db_gr_del((char *)a_key, a_group); + dap_chain_global_db_gr_del(dap_strdup(a_key), a_group); DAP_DELETE(l_gdb_group_str); return; } dap_chain_hash_fast_t l_pkey_hash; if (!dap_sign_get_pkey_hash(l_sign, &l_pkey_hash)) { - dap_chain_global_db_gr_del((char *)a_key, a_group); + dap_chain_global_db_gr_del(dap_strdup(a_key), a_group); DAP_DELETE(l_gdb_group_str); return; } @@ -542,7 +542,7 @@ static void s_srv_order_callback_notify(void *a_arg, const char a_op_code, const dap_chain_addr_fill(&l_addr, l_sign->header.type, &l_pkey_hash, l_net->pub.id); uint64_t l_solvency = dap_chain_ledger_calc_balance(l_net->pub.ledger, &l_addr, l_order->price_ticker); if (l_solvency < l_order->price && !dap_chain_net_srv_stake_key_delegated(&l_addr)) { - dap_chain_global_db_gr_del((char *)a_key, a_group); + dap_chain_global_db_gr_del(dap_strdup(a_key), a_group); } } DAP_DELETE(l_gdb_group_str); diff --git a/modules/service/vpn/dap_chain_net_srv_vpn.c b/modules/service/vpn/dap_chain_net_srv_vpn.c index aaf563d863221a664b0a72364784bf60975043ec..4041396e1503f092f573f3cdd1c8bd821902e32a 100644 --- a/modules/service/vpn/dap_chain_net_srv_vpn.c +++ b/modules/service/vpn/dap_chain_net_srv_vpn.c @@ -69,6 +69,8 @@ #include "dap_chain_net_srv_stream_session.h" #include "dap_chain_net_vpn_client.h" #include "dap_chain_net_vpn_client_tun.h" +#include "dap_chain_net_srv_vpn_cmd.h" +#include "dap_chain_node_cli.h" #include "dap_chain_ledger.h" #include "dap_events.h" @@ -769,6 +771,10 @@ int dap_chain_net_srv_vpn_init(dap_config_t * g_config) { dap_stream_ch_proc_add(DAP_STREAM_CH_ID_NET_SRV_VPN, s_ch_vpn_new, s_ch_vpn_delete, s_ch_packet_in, s_ch_packet_out); + // add console command to display vpn statistics + dap_chain_node_cli_cmd_item_create ("vpn_stat", com_vpn_statistics, NULL, "VPN statistics", + "vpn_stat -net <net name> [-full]\n" + ); return 0; } @@ -934,9 +940,9 @@ void s_ch_vpn_new(dap_stream_ch_t* a_ch, void* a_arg) * @param ch * @param arg */ -void s_ch_vpn_delete(dap_stream_ch_t* ch, void* arg) +void s_ch_vpn_delete(dap_stream_ch_t* a_ch, void* arg) { - dap_chain_net_srv_ch_vpn_t * l_ch_vpn = CH_VPN(ch); + dap_chain_net_srv_ch_vpn_t * l_ch_vpn = CH_VPN(a_ch); dap_chain_net_srv_vpn_t * l_srv_vpn =(dap_chain_net_srv_vpn_t *) l_ch_vpn->net_srv->_inhertor; diff --git a/modules/service/vpn/dap_chain_net_srv_vpn_cmd.c b/modules/service/vpn/dap_chain_net_srv_vpn_cmd.c index d676903d06a3d87c6d0dbd4f3930ba43bb5feee3..59d99cc44cdfb95f965756b980cfc2872276b2f5 100644 --- a/modules/service/vpn/dap_chain_net_srv_vpn_cmd.c +++ b/modules/service/vpn/dap_chain_net_srv_vpn_cmd.c @@ -1,8 +1,95 @@ -#include <dap_chain_node_cli.h> +#include "dap_common.h" +#include "dap_chain_node_cli.h" #include "dap_chain_node_cli_cmd.h" #include "dap_chain_net_srv_vpn_cmd.h" #include "dap_chain_net_vpn_client.h" + +static char* get_value_text(uintmax_t a_value) +{ + if(a_value < 2048) + return dap_strdup_printf("%d bytes", a_value); + else if(a_value < 2048 * 1024) + return dap_strdup_printf("%.2lf Kb", (double) a_value / 1024); + else if(a_value < 2048ll * 1024 * 1024) + return dap_strdup_printf("%.2lf Mb", (double) a_value / (1024 * 1024)); + else if(a_value < 2048ll * 1024 * 1024 * 1024) + return dap_strdup_printf("%.2lf Gb", (double) a_value / (1024 * 1024 * 1024)); + return dap_strdup_printf("%.2lf Tb", (double) a_value / (1024ll * 1024 * 1024 * 1024)); +} + +static void add_value_text(dap_string_t *l_str, char *l_addstr, uintmax_t a_value) +{ + char *l_str_val = get_value_text(a_value); + dap_string_append_printf(l_str, "%s.%s\n", l_addstr, l_str_val); + DAP_DELETE(l_str_val); +} +#include <arpa/inet.h> +/** + * vpn_client command + * + * VPN statistics + */ +int com_vpn_statistics(int a_argc, char ** a_argv, void *arg_func, char **a_str_reply) +{ + dap_stream_ch_t* a_ch; + dap_stream_t * stream; + dap_stream_session_t * session; + // get statistics for all actual sessions + dap_list_t *l_list = dap_stream_session_get_list_sessions(); + dap_string_t *l_str = dap_string_new(NULL); + int l_conn = 0; + // display statistic for all sessions + while(l_list) { + dap_stream_session_t * l_session = (dap_stream_session_t*) l_list->data; + dap_chain_net_srv_stream_session_t * l_srv_str_session = l_session->_inheritor; + if(l_srv_str_session) { + dap_net_stats_t l_stats = l_srv_str_session->stats; //(dap_net_stats_t*) l_list; + dap_string_append_printf(l_str, "VPN connection %d\n", l_conn); + l_conn++; + // time start/length + time_t l_time_len_sec = time(NULL) - l_session->time_created; + char l_buf[1024]; + if(dap_time_to_str_rfc822(l_buf, sizeof(l_buf), l_session->time_created) > 0) + dap_string_append_printf(l_str, " start at %s (length %02d:%02d:%02d)\n", l_buf, + l_time_len_sec / 3600, (l_time_len_sec % 3600) / 60, l_time_len_sec % 60); + // client ip + const int l_tun_client_addr_str_len = 128; + char *l_tun_client_addr_str = DAP_NEW_S_SIZE(char, l_tun_client_addr_str_len); + if(inet_ntop(AF_INET, &(l_session->tun_client_addr), l_tun_client_addr_str, l_tun_client_addr_str_len)) + dap_string_append_printf(l_str, " client addr........%s\n", l_tun_client_addr_str); + else + dap_string_append(l_str, " client addr........???\n"); + add_value_text(l_str, " recv..............", l_stats.bytes_recv); + add_value_text(l_str, " recv lost.........", l_stats.bytes_recv_lost); + add_value_text(l_str, " send..............", l_stats.bytes_sent); + add_value_text(l_str, " send lost.........", l_stats.bytes_sent_lost); + dap_string_append_printf(l_str, " packets recv.......%d\n", l_stats.packets_recv); + dap_string_append_printf(l_str, " packets recv lost..%d\n", l_stats.packets_recv_lost); + dap_string_append_printf(l_str, " packets send.......%d\n", l_stats.packets_sent); + dap_string_append_printf(l_str, " packets send lost..%d\n", l_stats.packets_sent_lost); + // average bitrate + double l_bitrate = (l_stats.bytes_recv - l_stats.bytes_recv_lost + + l_stats.bytes_sent - l_stats.bytes_sent_lost) * 1. / l_time_len_sec; + dap_string_append_printf(l_str, " average bitrate....%.2lf kbps\n", l_bitrate / 1024.); + // not add line break after last session + if(l_list->next) + dap_string_append_printf(l_str, "\n"); + } + // next session + l_list = dap_list_next(l_list); + } + // unlock sessions list + dap_stream_session_get_list_sessions_unlock(); + if(l_conn>0) + dap_chain_node_cli_set_reply_text(a_str_reply, l_str->str); + else + dap_chain_node_cli_set_reply_text(a_str_reply, "No VPN connections"); + // free tmp memory + dap_string_free(l_str, true); + return 0; +} + /** * vpn_client command * diff --git a/modules/service/vpn/dap_chain_net_srv_vpn_cmd.h b/modules/service/vpn/dap_chain_net_srv_vpn_cmd.h index 4ce2243e8703bc14aa9ead66b5120f38562e8b00..0a70e7791c640db79c8f12b506425c10efa1bdbe 100644 --- a/modules/service/vpn/dap_chain_net_srv_vpn_cmd.h +++ b/modules/service/vpn/dap_chain_net_srv_vpn_cmd.h @@ -1,4 +1,6 @@ #pragma once +// VPN statistics +int com_vpn_statistics(int a_argc, char ** a_argv, void *arg_func, char **a_str_reply); // vpn_client command int com_vpn_client(int a_argc, char ** a_argv, void *arg_func, char **a_str_reply); diff --git a/modules/service/xchange/dap_chain_net_srv_xchange.c b/modules/service/xchange/dap_chain_net_srv_xchange.c index b7bd5071492e047932395300fca186099c49d41c..6336a366903b8bb6b989257ab085598fd4846351 100644 --- a/modules/service/xchange/dap_chain_net_srv_xchange.c +++ b/modules/service/xchange/dap_chain_net_srv_xchange.c @@ -653,7 +653,6 @@ static int s_cli_srv_xchange_price(int a_argc, char **a_argv, int a_arg_index, c } DAP_DELETE(l_order_hash_str); DAP_DELETE(l_price->wallet_str); - DAP_DELETE(l_price->key_ptr); DAP_DELETE(l_price); if (!l_str_reply->len) { dap_string_append(l_str_reply, "Price successfully removed"); @@ -715,7 +714,7 @@ static int s_cli_srv_xchange_price(int a_argc, char **a_argv, int a_arg_index, c return -14; } HASH_DEL(s_srv_xchange->pricelist, l_price); - dap_chain_global_db_gr_del(l_price->key_ptr, GROUP_LOCAL_XCHANGE); + dap_chain_global_db_gr_del(dap_strdup(l_price->key_ptr), GROUP_LOCAL_XCHANGE); bool l_ret = s_xchage_tx_invalidate(l_price, l_wallet); // may be changed to old price later dap_chain_wallet_close(l_wallet); if (!l_ret) { diff --git a/modules/type/block/dap_chain_block.c b/modules/type/block/dap_chain_block.c deleted file mode 100644 index 9fce5b10c9aefc2e9eef2d51cc13ab0c77e48f91..0000000000000000000000000000000000000000 --- a/modules/type/block/dap_chain_block.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * 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/>. -*/ - -#include "string.h" -#include "dap_common.h" - -#include "dap_chain_block.h" - -#define LOG_TAG "dap_chain_block" - -/** - * @brief dap_chain_block_init - * @return - */ -int dap_chain_block_init() -{ - return 0; -} - -/** - * @brief dap_chain_block_deinit - */ -void dap_chain_block_deinit() -{ - -} - - -/** - * @brief dap_chain_block_new - * @param a_prev_block - * @return - */ -dap_chain_block_t * dap_chain_block_new(dap_chain_hash_t * a_prev_block ) -{ - dap_chain_block_t * l_block = DAP_NEW_Z_SIZE (dap_chain_block_t,sizeof(l_block->header)); - if( l_block == NULL){ - log_it(L_CRITICAL, "Can't allocate memory for the new block"); - return NULL; - }else{ - l_block->header.signature = DAP_CHAIN_BLOCK_SIGNATURE; - l_block->header.version = 1; - l_block->header.timestamp = time(NULL); - if( a_prev_block ){ - memcpy(&l_block->header.prev_block,a_prev_block,sizeof(l_block->header.prev_block)); - }else{ - log_it(L_INFO, "Genesis block produced"); - memset(&l_block->header.prev_block,0xff,sizeof(l_block->header.prev_block)); - } - - l_block->header.size = sizeof(l_block->header); - return l_block; - } -} - -/** - * @brief dap_chain_block_create_section - * @param a_block - * @param a_section_type - * @param a_section_data_size - * @return - */ -dap_chain_datum_t * dap_chain_block_create_section(dap_chain_block_t * a_block, uint32_t a_section_offset, - uint16_t a_section_type, uint32_t a_section_data_size ) -{ - if ( a_block) { - uint32_t l_sections_size = ( a_block->header.size - sizeof(a_block->header) ); - if( l_sections_size > a_section_offset ){ - if( l_sections_size > (a_section_offset + a_section_data_size ) ) { - dap_chain_datum_t * l_section = (dap_chain_datum_t *) ( a_block->datums +a_section_offset) ; - l_section->header.type_id = a_section_type; - return l_section; - }else{ - log_it(L_ERROR, "Section data size %lu is bigger then left for sections in block (%lu)" - ,a_section_data_size,l_sections_size - a_section_offset ); - return NULL; - } - }else{ - log_it(L_ERROR, "Section offset %lu is bigger then section size %lu",a_section_offset,l_sections_size); - return NULL; - } - }else{ - log_it(L_ERROR, "Block is NULL"); - return NULL; - } -} - diff --git a/modules/type/block/dap_chain_block_cache.c b/modules/type/block/dap_chain_block_cache.c deleted file mode 100644 index e8e7004b2eaa208d212a1cdfa169c5038eddee48..0000000000000000000000000000000000000000 --- a/modules/type/block/dap_chain_block_cache.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - * 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/>. -*/ -#include <stdlib.h> -#include <time.h> -#include "dap_common.h" -#include "dap_chain_block_cache.h" -#include "dap_chain_datum_coin.h" -#include "dap_chain_datum_tx.h" -#include "dap_chain_datum_tx_in.h" -#include "dap_chain_datum_tx_out.h" - -#define LOG_TAG "dap_chain_block_cache" - -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; - log_it(L_DEBUG,"Block cache created"); - return l_block_cache; -} - -/** - * @brief dap_chain_block_cache_delete - * @param a_block - */ -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"); -} - -/** - * @brief dap_chain_block_cache_dump - * @param a_block_cache - */ -void dap_chain_block_cache_dump(dap_chain_block_cache_t * a_block_cache) -{ - if ( a_block_cache ) { - dap_chain_block_t * l_block = a_block_cache->block; - if( l_block ){ - char * l_hash_str = dap_chain_hash_to_str_new(&a_block_cache->block_hash); - char * l_prev_hash_str = dap_chain_hash_to_str_new(&l_block->header.prev_block); - char * l_root_sections_str = dap_chain_hash_to_str_new(&l_block->header.root_sections); - log_it(L_INFO, " ** block_hash %s",l_hash_str); - log_it(L_INFO, " ** version %d",l_block->header.version); - log_it(L_INFO, " ** timestamp %s", ctime( (time_t*) &l_block->header.timestamp) ); - log_it(L_INFO, " ** difficulty %llu",l_block->header.difficulty); - log_it(L_INFO, " ** nonce %llu",l_block->header.nonce); - log_it(L_INFO, " ** prev_block %s",l_prev_hash_str); - log_it(L_INFO, " ** root_sections %s",l_root_sections_str ); - log_it(L_INFO, " ** size %u",l_block->header.size); - log_it(L_INFO, " ** sections[]"); - DAP_DELETE(l_hash_str); - DAP_DELETE(l_prev_hash_str); - - size_t i, l_sections_size = l_block->header.size - sizeof(l_block->header); - for( i = 0; i< l_sections_size; i++ ){ - dap_chain_datum_t * l_datum = (dap_chain_datum_t *) (l_block->datums + i); - switch ( l_datum->header.type_id ) { - case DAP_CHAIN_DATUM_TX:{ - dap_chain_datum_tx_t * l_tx = (dap_chain_datum_tx_t *) l_datum->data; - log_it(L_INFO, " ** tx"); - log_it(L_INFO, " ** lock_time %s", l_tx->header.lock_time? - ctime( (time_t *) &l_tx->header.lock_time ) : "0x0000000000000000" ); - log_it(L_INFO, " ** tx_items_size %u ",l_tx->header.tx_items_size); - /*uint32_t l_data_offset; - for ( l_data_offset = 0; l_data_offset < l_tx->header.tx_items_size; ++l_data_offset ){ - - }*/ - i += sizeof (l_tx->header); - i += l_tx->header.tx_items_size ; - }break; - default: - i = l_sections_size; - } - } - }else{ - log_it(L_ERROR,"block in block cache for dump is NULL"); - } - }else{ - log_it(L_ERROR,"block cache for dump is NULL"); - } - -} - -/** - * @brief dap_chain_block_cache_sections_size_grow - * @param a_block_cache - * @param a_sections_size_grow - */ -dap_chain_block_t* dap_chain_block_cache_sections_size_grow(dap_chain_block_cache_t * a_block_cache,size_t a_sections_size_grow ) -{ - log_it(L_DEBUG,"Block section size reallocation: grow up +%lu",a_sections_size_grow); - a_block_cache->block->header.size += a_sections_size_grow; - a_block_cache->block=(dap_chain_block_t *) realloc(a_block_cache->block,a_block_cache->block->header.size ); - if( a_block_cache->block ){ - a_block_cache->sections_size += a_sections_size_grow; - return a_block_cache->block; - }else{ - log_it(L_ERROR, "Can't reallocate block!"); - return NULL; - } -} - diff --git a/modules/type/block/dap_chain_cs_blocks.c b/modules/type/block/dap_chain_cs_blocks.c deleted file mode 100644 index d997e54ae2604dd7a60794f5c9cfa5454908da60..0000000000000000000000000000000000000000 --- a/modules/type/block/dap_chain_cs_blocks.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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/>. -*/ -#include "dap_common.h" -#include "dap_chain_cs_blocks.h" -#include "dap_chain_block.h" -#include "dap_chain_block_cache.h" - -#define LOG_TAG "dap_chain_cs_blocks" - -typedef struct dap_chain_cs_blocks_pvt -{ - dap_chain_cs_blocks_t * blocks; - - dap_chain_block_cache_t * block_cache_first; // Mapped area start - dap_chain_block_cache_t * block_cache_last; // Last block in mapped area - uint64_t blocks_count; - uint64_t difficulty; - -} dap_chain_cs_blocks_pvt_t; - - -#define PVT(a) ((dap_chain_cs_blocks_pvt_t *) a->_pvt ) - - -/** - * @brief dap_chain_cs_blocks_init - * @return - */ -int dap_chain_cs_blocks_init() -{ - return 0; -} - -/** - * @brief dap_chain_cs_blocks_deinit - */ -void dap_chain_cs_blocks_deinit() -{ - -} - -dap_chain_block_cache_t* dap_chain_cs_blocks_allocate_next_block(dap_chain_cs_blocks_t * a_cs_blocks) -{ - dap_chain_block_t* l_block = NULL; - dap_chain_block_cache_t* l_block_cache = NULL; - if ( PVT(a_cs_blocks)->block_cache_last ) - l_block = dap_chain_block_new( &PVT(a_cs_blocks)->block_cache_last->block_hash ); - else - l_block = dap_chain_block_new( NULL ); - - if( l_block ){ - l_block->header.difficulty = PVT(a_cs_blocks)->difficulty; - l_block_cache = dap_chain_block_cache_new(l_block); - return l_block_cache; - }else{ - log_it(L_ERROR, "Can't allocate next block!"); - return NULL; - } -} - - - diff --git a/modules/type/block/include/dap_chain_block.h b/modules/type/block/include/dap_chain_block.h deleted file mode 100644 index 18a81cc2cb2016ab2d7b4252fbdc6d7201540163..0000000000000000000000000000000000000000 --- a/modules/type/block/include/dap_chain_block.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 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 <stdalign.h> -#include <stdint.h> -#include <stddef.h> -#include "dap_common.h" -#include "dap_math_ops.h" -#include "dap_hash.h" -#include "dap_chain_common.h" -#include "dap_chain_datum.h" -#include "dap_chain_datum_hashtree_roots.h" - -#define DAP_CHAIN_BLOCK_SIGNATURE 0xDA05BF8E - -#define DAP_CHAIN_BLOCK_ID_SIZE 4 - -typedef union dap_chain_block_typeid{ - uint8_t data[DAP_CHAIN_BLOCK_ID_SIZE]; -} DAP_ALIGN_PACKED dap_chain_block_typeid_t; - -/** - * @brief The dap_chain_block struct - */ -typedef struct dap_chain_block{ - struct block_header{ - uint32_t signature; /// @param signature @brief Magic number, always equels to DAP_CHAIN_BLOCK_SIGNATURE - int32_t version; /// @param version @brief block version (be carefull, signed value, as Bitcoin has) - uint32_t size; /// @param size of the whole block - uint64_t timestamp; /// @param timestamp @brief Block create time timestamp - uint64_t difficulty; /// difficulty level - uint64_t nonce; /// Nonce value to allow header variation for mining - union{ - struct{ // Zero-level block without sharding - dap_chain_hash_t prev_block; /// @param prev_block Hash of the previous block - dap_chain_hash_t padding0; // - uint32_t padding1; // - uint64_t padding2; // Always zero (should be well compresed) - }; - struct{ - dap_chain_hash_t prev_block_0lvl; /// @param prev_block Hash of the previous block - dap_chain_hash_t prev_block_shard; /// @param prev_block Hash of the previous block - uint32_t shard_id; // Shard id - uint64_t nonce2; // Second NonCE for block mining inside the shard - }; - }; - dap_chain_hash_t root_sections;/// @param root_main Main tree's root for all sections's hashes - } DAP_ALIGN_PACKED header; - uint8_t datums[]; // Sections -} DAP_ALIGN_PACKED dap_chain_block_t; - -int dap_chain_block_init(); -void dap_chain_block_deinit(); - -dap_chain_block_t * dap_chain_block_new(dap_chain_hash_t * a_prev_block ); - -dap_chain_datum_t * dap_chain_block_create_section(dap_chain_block_t * a_block, uint32_t a_section_offset - , uint16_t a_section_type, uint32_t a_section_data_size ); - - -/** - * @brief dap_chain_block_calc_hash - * @param a_block - * @return - */ -static inline void dap_chain_block_hash_calc(dap_chain_block_t * a_block, dap_chain_hash_t * a_hash){ - dap_hash(a_block,a_block->header.size,a_hash->raw, - sizeof(a_hash->raw),DAP_HASH_TYPE_SLOW_0); -} - diff --git a/modules/type/block/CMakeLists.txt b/modules/type/blocks/CMakeLists.txt similarity index 62% rename from modules/type/block/CMakeLists.txt rename to modules/type/blocks/CMakeLists.txt index d5b23c531ad189a996f19a98e6ecd220c96be294..38bae326446f2e224c1259f28dbcfffcadae35ba 100644 --- a/modules/type/block/CMakeLists.txt +++ b/modules/type/blocks/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 2.8) -project (dap_chain_cs_block) +project (dap_chain_cs_blocks) file(GLOB DAP_CHAIN_BLOCK_SRCS *.c) file(GLOB DAP_CHAIN_BLOCK_HEADERS include/*.h) @@ -7,6 +7,6 @@ file(GLOB DAP_CHAIN_BLOCK_HEADERS include/*.h) add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_BLOCK_SRCS} ${DAP_CHAIN_BLOCK_HEADERS}) -target_link_libraries(dap_chain_cs_block dap_core dap_crypto dap_chain ) -target_include_directories(dap_chain_cs_block INTERFACE .) +target_link_libraries(dap_chain_cs_blocks dap_core dap_crypto dap_chain ) +target_include_directories(dap_chain_cs_blocks INTERFACE .) target_include_directories(${PROJECT_NAME} PUBLIC include) diff --git a/modules/type/blocks/dap_chain_block.c b/modules/type/blocks/dap_chain_block.c new file mode 100644 index 0000000000000000000000000000000000000000..daee181c47d5df5cd523fd53a34bc77176c9ea57 --- /dev/null +++ b/modules/type/blocks/dap_chain_block.c @@ -0,0 +1,99 @@ +/* + * Authors: + * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net> + * DeM Labs Ltd https://demlabs.net + * Copyright (c) 2017-2020 + * All rights reserved. + + This file is part of DAP SDK the open source project + + DAP SDK is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + DAP SDK is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with any DAP SDK based project. If not, see <http://www.gnu.org/licenses/>. +*/ +#include <stddef.h> +#include "string.h" +#include "dap_common.h" +#include "dap_hash.h" + +#include "dap_chain_block.h" +#include "dap_chain_block_cache.h" + +#define LOG_TAG "dap_chain_block" + +/** + * @brief dap_chain_block_init + * @return + */ +int dap_chain_block_init() +{ + return 0; +} + +/** + * @brief dap_chain_block_deinit + */ +void dap_chain_block_deinit() +{ + +} + + +/** + * @brief dap_chain_block_new + * @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 * l_block = DAP_NEW_Z_SIZE (dap_chain_block_t,sizeof(l_block->hdr)); + if( l_block == NULL){ + log_it(L_CRITICAL, "Can't allocate memory for the new block"); + return NULL; + }else{ + 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); + 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) ); + }else{ + log_it(L_INFO, "Genesis block produced"); + } + return l_block; + } + + +} + +// Add metadata in block +size_t dap_chain_block_meta_add(dap_chain_block_t * a_block, size_t a_block_size, uint8_t a_meta_type, const void * a_data, size_t a_data_size) +{ + return a_block_size; +} + + +size_t dap_chain_block_datum_add(dap_chain_block_t * a_block, size_t a_block_size, dap_chain_datum_t * a_datum, size_t a_datum_size) +{ + if ( a_block) { + // + }else{ + log_it(L_ERROR, "Block is NULL"); + return a_block_size; + } +} + +size_t dap_chain_block_datum_del_by_hash(dap_chain_block_t * a_block, size_t a_block_size, dap_chain_hash_fast_t* a_datum_hash) +{ + return a_block_size; +} + diff --git a/modules/type/blocks/dap_chain_block_cache.c b/modules/type/blocks/dap_chain_block_cache.c new file mode 100644 index 0000000000000000000000000000000000000000..cf55de237f9d06df99bf004acd6d4d90800b9a0c --- /dev/null +++ b/modules/type/blocks/dap_chain_block_cache.c @@ -0,0 +1,99 @@ +/* + * Authors: + * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net> + * DeM Labs Ltd https://demlabs.net + * Copyright (c) 2017-2020 + * All rights reserved. + + This file is part of DAP SDK the open source project + + DAP SDK is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + DAP SDK is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with any DAP SDK based project. If not, see <http://www.gnu.org/licenses/>. +*/ +#include <stdlib.h> +#include <time.h> +#include "dap_common.h" +#include "dap_chain_block_cache.h" +#include "dap_chain_datum_tx.h" +#include "dap_chain_datum_tx_in.h" +#include "dap_chain_datum_tx_out.h" + +#define LOG_TAG "dap_chain_block_cache" + +/** + * @brief dap_chain_block_cache_init + * @return + */ +int dap_chain_block_cache_init() +{ + return 0; +} + +/** + * @brief dap_chain_block_cache_deinit + */ +void dap_chain_block_cache_deinit() +{ + +} + +/** + * @brief dap_chain_block_cache_new + * @param a_block + * @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) +{ + if (! a_block) + return NULL; + + 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); + + log_it(L_DEBUG,"Block cache created"); + return l_block_cache; +} + +/** + * @brief dap_chain_block_cache_get_by_hash + * @param a_block_hash + * @return + */ +dap_chain_block_cache_t * dap_chain_block_cache_get_by_hash(dap_chain_hash_fast_t a_block_hash) +{ + return NULL; +} + +/** + * @brief dap_chain_block_cache_update + * @param a_block_cache + */ +void 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); +} + +/** + * @brief dap_chain_block_cache_delete + * @param a_block + */ +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_cs_blocks.c b/modules/type/blocks/dap_chain_cs_blocks.c new file mode 100644 index 0000000000000000000000000000000000000000..62869d706cd5e3053c59c592977dd143dd11ef8c --- /dev/null +++ b/modules/type/blocks/dap_chain_cs_blocks.c @@ -0,0 +1,686 @@ +/* + * Authors: + * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net> + * DeM Labs Ltd https://demlabs.net + * Copyright (c) 2017-2020 + * All rights reserved. + + This file is part of DAP SDK the open source project + + DAP SDK is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + DAP SDK is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with any DAP SDK based project. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <pthread.h> +#include "dap_common.h" +#include "dap_enc_base58.h" +#include "dap_chain.h" +#include "dap_chain_net.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_node_cli.h" +#include "dap_chain_node_cli_cmd.h" +#define LOG_TAG "dap_chain_cs_blocks" + +typedef struct dap_chain_cs_blocks_pvt +{ + pthread_rwlock_t rwlock; + dap_chain_cs_blocks_t * blocks; + + dap_chain_block_cache_t * block_cache_first; // Mapped area start + dap_chain_block_cache_t * block_cache_last; // Last block in mapped area + + + uint64_t blocks_count; + uint64_t difficulty; + + dap_chain_block_t * block_new; + size_t block_new_size; +} dap_chain_cs_blocks_pvt_t; + +#define PVT(a) ((dap_chain_cs_blocks_pvt_t *) a->_pvt ) + +static int s_cli_parse_cmd_hash(char ** a_argv, int a_arg_index, int a_argc, char **a_str_reply,const char * a_param, dap_chain_hash_fast_t * a_datum_hash); +static void s_cli_meta_hash_print( dap_string_t * a_str_tmp, const char * a_meta_title, dap_chain_block_meta_t * a_meta); +static int s_cli_blocks(int a_argc, char ** a_argv, void *a_arg_func, char **a_str_reply); + +// Callbacks +static void s_callback_delete(dap_chain_t * a_chain); +// Accept new block +static dap_chain_atom_verify_res_t s_callback_atom_add(dap_chain_t * a_chain, dap_chain_atom_ptr_t , size_t); +// Verify new block +static dap_chain_atom_verify_res_t s_callback_atom_verify(dap_chain_t * a_chain, dap_chain_atom_ptr_t , size_t); + +// Get block header size +static size_t s_callback_atom_get_static_hdr_size(void); + +static dap_chain_atom_iter_t* s_callback_atom_iter_create(dap_chain_t * a_chain ); +static dap_chain_atom_iter_t* s_callback_atom_iter_create_from(dap_chain_t * , + dap_chain_atom_ptr_t , size_t); + + +static dap_chain_atom_ptr_t s_callback_atom_iter_find_by_hash(dap_chain_atom_iter_t * a_atom_iter , + dap_chain_hash_fast_t * a_atom_hash, size_t * a_atom_size); +static dap_chain_datum_tx_t* s_callback_atom_iter_find_by_tx_hash(dap_chain_t * a_chain , + dap_chain_hash_fast_t * a_atom_hash); + +static dap_chain_datum_t* s_callback_atom_get_datum(dap_chain_atom_ptr_t a_event, size_t a_atom_size); +// Get blocks +static dap_chain_atom_ptr_t s_callback_atom_iter_get_first( dap_chain_atom_iter_t * a_atom_iter, size_t *a_atom_size ); // Get the fisrt block +static dap_chain_atom_ptr_t s_callback_atom_iter_get_next( dap_chain_atom_iter_t * a_atom_iter,size_t *a_atom_size ); // Get the next block +static dap_chain_atom_ptr_t *s_callback_atom_iter_get_links( dap_chain_atom_iter_t * a_atom_iter , size_t *a_links_size, + size_t ** a_links_size_ptr ); // Get list of linked blocks +static dap_chain_atom_ptr_t *s_callback_atom_iter_get_lasts( dap_chain_atom_iter_t * a_atom_iter ,size_t *a_links_size, + size_t ** a_lasts_size_ptr ); // Get list of linked blocks + +// 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); + +bool s_seed_mode=false; + + +/** + * @brief dap_chain_cs_blocks_init + * @return + */ +int dap_chain_cs_blocks_init() +{ + dap_chain_cs_type_add("blocks", dap_chain_cs_blocks_new ); + s_seed_mode = dap_config_get_item_bool_default(g_config,"general","seed_mode",false); + dap_chain_node_cli_cmd_item_create ("block", s_cli_blocks, NULL, "Create and explore blockchains", + "New block create, fill and complete commands:" + "\tblock -net <chain net name> -chain <chain name> new\n" + "\t\tCreate new block and flush memory if was smth formed before\n\n" + + "\tblock -net <chain net name> -chain <chain name> new_datum_add <datum hash>\n" + "\t\tAdd block section from datum <datum hash> taken from the mempool\n\n" + + "\tblock -net <chain net name> -chain <chain name> new_datum_del <datum hash>\n" + "\t\tDel block section with datum <datum hash>\n\n" + + "\tblock -net <chain net name> -chain <chain name> new_datum_list\n" + "\t\tList block sections and show their datums hashes\n\n" + + "\tblock -net <chain net name> -chain <chain name> new_datum\n\n" + "\t\tComplete the current new round, verify it and if everything is ok - publish new events in chain\n\n" + + "Blockchain explorer:" + "\tblock -net <chain net name> -chain <chain name> dump <block hash>\n" + "\t\tDump block info\n\n" + + "\tblock -net <chain net name> -chain <chain name> list [-from_hash <block hash>] [-to_hash <block hash>]" + "\t [-from_dt <datetime>] [-to_dt <datetime>]" + "\t\t List blocks" + + ); + if (dap_chain_block_cache_init() != 0){ + log_it(L_WARNING, "Can't init blocks cache"); + } + log_it(L_NOTICE,"Initialized blocks chain type"); + + return 0; +} + +/** + * @brief dap_chain_cs_blocks_deinit + */ +void dap_chain_cs_blocks_deinit() +{ + dap_chain_block_cache_deinit(); +} + +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; + + a_chain->callback_delete = s_callback_delete; + + // Atom element callbacks + a_chain->callback_atom_add = s_callback_atom_add ; // Accept new element in chain + a_chain->callback_atom_verify = s_callback_atom_verify ; // Verify new element in chain + a_chain->callback_atom_get_hdr_static_size = s_callback_atom_get_static_hdr_size; // Get block hdr size + + a_chain->callback_atom_iter_create = s_callback_atom_iter_create; + a_chain->callback_atom_iter_create_from = s_callback_atom_iter_create_from; + a_chain->callback_atom_iter_delete = s_callback_atom_iter_delete; + + // Linear pass through + a_chain->callback_atom_iter_get_first = s_callback_atom_iter_get_first; // Get the fisrt element from chain + a_chain->callback_atom_iter_get_next = s_callback_atom_iter_get_next; // Get the next element from chain from the current one + a_chain->callback_atom_get_datum = s_callback_atom_get_datum; + + a_chain->callback_atom_iter_get_links = s_callback_atom_iter_get_links; // Get the next element from chain from the current one + a_chain->callback_atom_iter_get_lasts = s_callback_atom_iter_get_lasts; + + a_chain->callback_atom_find_by_hash = s_callback_atom_iter_find_by_hash; + a_chain->callback_tx_find_by_hash = s_callback_atom_iter_find_by_tx_hash; + + + a_chain->callback_add_datums = s_callback_add_datums; + + 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); + +// 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 +*/ + return 0; +} + +/** + * @brief dap_chain_cs_blocks_delete + * @param a_chain + */ +void dap_chain_cs_blocks_delete(dap_chain_t * a_chain) +{ + pthread_rwlock_destroy(&PVT(a_chain)->rwlock ); +} + + +/** + * @brief s_cli_parse_cmd_hash + * @param a_argv + * @param a_arg_index + * @param a_argc + * @param a_str_reply + * @param a_param + * @param a_datum_hash + * @return + */ +static int s_cli_parse_cmd_hash(char ** a_argv, int a_arg_index, int a_argc, char **a_str_reply,const char * a_param, + dap_chain_hash_fast_t * a_datum_hash) +{ + assert(a_datum_hash); + + const char *l_datum_hash_str = NULL; + dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, a_param, &l_datum_hash_str); + + return dap_enc_base58_hex_to_hash(l_datum_hash_str, a_datum_hash); +} + +/** + * @brief s_cli_meta_hash_print + * @param a_str_tmp + * @param a_meta_title + * @param a_meta + */ +static void s_cli_meta_hash_print( dap_string_t * a_str_tmp, const char * a_meta_title, dap_chain_block_meta_t * a_meta) +{ + if(a_meta->hdr.size == sizeof (dap_chain_hash_fast_t) ){ + char * l_hash_str = dap_chain_hash_fast_to_str_new( (dap_chain_hash_fast_t *) a_meta->data); + dap_string_append_printf(a_str_tmp,"\t\tPREV: \"%s\"\n", a_meta_title,l_hash_str); + DAP_DELETE(l_hash_str); + }else{ + char * l_data_hex = DAP_NEW_Z_SIZE(char,a_meta->hdr.size*2+3); + dap_bin2hex(l_data_hex, a_meta->data, a_meta->hdr.size); + dap_string_append_printf(a_str_tmp,"\t\t\%s: 0x%s\n", a_meta_title, l_data_hex ); + } +} + +/** + * @brief s_cli_meta_hex_print + * @param a_str_tmp + * @param a_meta_title + * @param a_meta + */ +static void s_cli_meta_hex_print( dap_string_t * a_str_tmp, const char * a_meta_title, dap_chain_block_meta_t * a_meta) +{ + char * l_data_hex = DAP_NEW_Z_SIZE(char,a_meta->hdr.size*2+3); + dap_bin2hex(l_data_hex, a_meta->data, a_meta->hdr.size); + dap_string_append_printf(a_str_tmp,"\t\t\%s: 0x%s\n", a_meta_title, l_data_hex ); +} + +/** + * @brief s_cli_blocks + * @param argc + * @param argv + * @param arg_func + * @param a_str_reply + * @return + */ +static int s_cli_blocks(int a_argc, char ** a_argv, void *a_arg_func, char **a_str_reply) +{ + (void) a_arg_func; + enum { + SUBCMD_UNDEFINED =0, + SUBCMD_NEW_FLUSH, + SUBCMD_NEW_DATUM_ADD, + SUBCMD_NEW_DATUM_DEL, + SUBCMD_NEW_DATUM_LIST, + SUBCMD_NEW_COMPLETE, + SUBCMD_DUMP, + SUBCMD_LIST, + SUBCMD_DROP + } l_subcmd={0}; + + const char* l_subcmd_strs[]={ + [SUBCMD_NEW_FLUSH]="new", + [SUBCMD_NEW_DATUM_ADD]="new_datum_add", + [SUBCMD_NEW_DATUM_DEL]="new_datum_del", + [SUBCMD_NEW_DATUM_LIST]="new_datum_del", + [SUBCMD_NEW_COMPLETE]="new_complete", + [SUBCMD_DUMP]="dump", + [SUBCMD_LIST]="list", + [SUBCMD_DROP]="drop", + [SUBCMD_UNDEFINED]=NULL + }; + const size_t l_subcmd_str_count=sizeof(l_subcmd_strs)/sizeof(*l_subcmd_strs)-1; + const char* l_subcmd_str_args[l_subcmd_str_count]; + const char* l_subcmd_str_arg; + const char* l_subcmd_str; + + + int arg_index = 1; + + const char * l_net_name = NULL; + const char * l_chain_name = NULL; + + dap_chain_t * l_chain = NULL; + dap_chain_cs_blocks_t * l_blocks = NULL; + dap_chain_net_t * l_net = NULL; + + // Parse default values + if(dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index, a_argc, a_argv, a_str_reply, &l_chain, &l_net) < 0) + return -11; + + l_blocks = DAP_CHAIN_CS_BLOCKS(l_chain); + + // Parse commands + for (size_t i=0; i<l_subcmd_str_count; i++){ + int l_opt_idx = dap_chain_node_cli_check_option(a_argv, arg_index,a_argc, l_subcmd_strs[i]); + if( l_opt_idx >= 0 ){ + dap_chain_node_cli_find_option_val(a_argv, l_opt_idx, a_argc, l_subcmd_strs[i], &l_subcmd_str_args[i] ); + l_subcmd = i; + l_subcmd_str = l_subcmd_strs[i]; + l_subcmd_str_arg = l_subcmd_str_args[i]; + } + } + int ret=-1000; + // Do subcommand action + switch ( l_subcmd ){ + // Flush memory for the new block + case SUBCMD_NEW_FLUSH:{ + 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); + } break; + + // Add datum to the forming new block + case SUBCMD_NEW_DATUM_LIST:{ + + }break; + case SUBCMD_NEW_DATUM_DEL:{ + if ( PVT(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 ); + }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"); + ret = -12; + } + }break; + case SUBCMD_NEW_DATUM_ADD:{ + size_t l_datums_count=1; + char * l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool(l_chain); + dap_chain_datum_t ** l_datums = DAP_NEW_Z_SIZE(dap_chain_datum_t*, + sizeof(dap_chain_datum_t*)*l_datums_count); + size_t l_datum_size = 0; + + dap_chain_datum_t * l_datum = (dap_chain_datum_t*) dap_chain_global_db_gr_get( l_subcmd_str_arg , + &l_datum_size, + l_gdb_group_mempool); + l_datums[0] = l_datum; + if ( s_callback_add_datums(l_chain,l_datums,l_datums_count ) == l_datums_count ){ + for ( size_t i = 0; i <l_datums_count; i++){ + dap_chain_hash_fast_t l_datum_hash; + dap_hash_fast(l_datums[i],dap_chain_datum_size(l_datums[i]),&l_datum_hash); + char * l_datums_datum_hash_str = dap_chain_hash_fast_to_str_new(&l_datum_hash); + + if ( dap_chain_global_db_gr_del( dap_strdup(l_datums_datum_hash_str),l_gdb_group_mempool ) ){ + dap_chain_node_cli_set_reply_text(a_str_reply, + "Converted datum %s from mempool to event in the new forming round ", + l_datums_datum_hash_str); + DAP_DELETE(l_datums_datum_hash_str); + ret = 0; + }else { + dap_chain_node_cli_set_reply_text(a_str_reply, + "Warning! Can't delete datum %s from mempool after conversion to event in the new forming round ", + l_datums_datum_hash_str); + ret = 1; + } + } + }else { + dap_chain_node_cli_set_reply_text(a_str_reply, + "Warning! Can't convert datum %s from mempool to the new forming block's section ", l_subcmd_str_arg); + ret = -13; + } + + DAP_DELETE(l_gdb_group_mempool); + }break; + + case SUBCMD_NEW_COMPLETE:{ + dap_chain_net_sync_all(l_net); + } break; + + case SUBCMD_DROP:{ + dap_chain_net_sync_all(l_net); + }break; + case SUBCMD_DUMP:{ + dap_chain_block_t * l_block; + size_t l_block_size = 0; + dap_chain_hash_fast_t l_block_hash={0}; + dap_enc_base58_hex_to_hash( l_subcmd_str_arg, &l_block_hash); // Convert argument to hash + l_block = (dap_chain_block_t*) dap_chain_get_atom_by_hash( l_chain, &l_block_hash, &l_block_size); + if ( l_block){ + dap_chain_block_cache_t *l_block_cache = dap_chain_block_cache_get(l_block, l_block_size); + if ( l_block_cache ){ + dap_string_t * l_str_tmp = dap_string_new(NULL); + char buf[50]; + time_t l_ts_reated = (time_t) l_block->hdr.ts_created; + // Header + dap_string_append_printf(l_str_tmp,"Block %s:\n", l_subcmd_str_arg); + dap_string_append_printf(l_str_tmp,"\t\t\tversion: 0x%04sX\n",l_block->hdr.version); + dap_string_append_printf(l_str_tmp,"\t\t\tcell_id: 0x%016llX\n",l_block->hdr.cell_id.uint64); + dap_string_append_printf(l_str_tmp,"\t\t\tchain_id: 0x%016llX\n",l_block->hdr.chain_id.uint64); + dap_string_append_printf(l_str_tmp,"\t\t\tts_created: %s\n",ctime_r(&l_ts_reated, buf) ); + + // Dump Metadata + dap_string_append_printf(l_str_tmp,"\tMetadata. Count: %us\n",l_block->hdr.meta_count ); + for (uint32_t i=0; i < l_block_cache->meta_count; i++){ + 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"); + }break; + case DAP_CHAIN_BLOCK_META_PREV:{ + s_cli_meta_hash_print(l_str_tmp, "PREV", l_meta); + }break; + case DAP_CHAIN_BLOCK_META_ANCHOR:{ + s_cli_meta_hash_print(l_str_tmp, "ANCHOR", l_meta); + }break; + case DAP_CHAIN_BLOCK_META_LINK:{ + s_cli_meta_hash_print(l_str_tmp, "LINK", l_meta); + }break; + case DAP_CHAIN_BLOCK_META_NONCE:{ + s_cli_meta_hex_print(l_str_tmp,"NONCE", l_meta); + }break; + case DAP_CHAIN_BLOCK_META_NONCE2:{ + s_cli_meta_hex_print(l_str_tmp,"NONCE2", l_meta); + }break; + default:{ + char * l_data_hex = DAP_NEW_Z_SIZE(char,l_meta->hdr.size*2+3); + dap_bin2hex(l_data_hex, l_meta->data, l_meta->hdr.size); + dap_string_append_printf(l_str_tmp,"\t\t\0x%0X: 0x%s\n", l_data_hex ); + } + } + } + dap_string_append_printf(l_str_tmp,"\t\tdatums:\tcount: %uz\n",l_block_cache->datum_count); + for (uint32_t i=0; i < l_block_cache->datum_count ; i++){ + dap_chain_datum_t * l_datum = l_block_cache->datum[i]; + size_t l_datum_size = dap_chain_datum_size(l_datum); + dap_string_append_printf(l_str_tmp,"\t\t\tdatum:\tdatum_size: %u\n",l_datum_size); + if (l_datum_size < sizeof (l_datum->header) ){ + dap_string_append_printf(l_str_tmp,"\t\t\tERROR: datum size %zd is smaller than header size %zd \n",l_datum_size, + sizeof (l_datum->header)); + break; + } + time_t l_datum_ts_create = (time_t) l_datum->header.ts_create; + // Nested datums + dap_string_append_printf(l_str_tmp,"\t\t\t\tversion:=0x%02X\n", l_datum->header.version_id); + dap_string_append_printf(l_str_tmp,"\t\t\t\ttype_id:=%s\n", c_datum_type_str[l_datum->header.type_id]); + dap_string_append_printf(l_str_tmp,"\t\t\t\tts_create=%s\n",ctime_r( &l_datum_ts_create,buf )); + dap_string_append_printf(l_str_tmp,"\t\t\t\tdata_size=%u\n", l_datum->header.data_size); + dap_chain_net_dump_datum(l_str_tmp, l_datum, "hex" ); + } + // Signatures + dap_string_append_printf(l_str_tmp,"\t\tsignatures:\tcount: %u\n",l_block_cache->sign_count ); + for (uint32_t i=0; i < l_block_cache->sign_count ; i++){ + dap_sign_t * l_sign =l_block_cache->sign[i]; + size_t l_sign_size = dap_sign_get_size(l_sign); + dap_chain_addr_t l_addr = {0}; + dap_chain_hash_fast_t l_pkey_hash; + dap_sign_get_pkey_hash(l_sign, &l_pkey_hash); + dap_chain_addr_fill(&l_addr, l_sign->header.type, &l_pkey_hash, l_net->pub.id); + char * l_pkey_hash_str = dap_chain_hash_fast_to_str_new(&l_pkey_hash); + dap_string_append_printf(l_str_tmp,"\t\t\t: type:%s size: %zd pkey_hash: %s data_hash: " + "n", dap_sign_type_to_str( l_sign->header.type ), l_sign_size, l_pkey_hash_str ); + DAP_DELETE( l_pkey_hash_str ); + } + dap_chain_node_cli_set_reply_text(a_str_reply, l_str_tmp->str); + dap_string_free(l_str_tmp,false); + ret=0; + } + }else { + dap_chain_node_cli_set_reply_text(a_str_reply, "Can't find block %s ", l_subcmd_str_arg); + ret=-10; + } + }break; + case SUBCMD_LIST:{ + + dap_string_t * l_str_tmp = dap_string_new(NULL); + dap_string_append_printf(l_str_tmp,"%s.%s: Have %u blocks :\n", + l_net->pub.name,l_chain->name,PVT(l_blocks)->blocks_count); + dap_chain_block_cache_t * l_block_cache = NULL,*l_block_cache_tmp = NULL; + + pthread_rwlock_rdlock(&PVT(l_blocks)->rwlock); + HASH_ITER(hh,PVT(l_blocks)->block_cache_first,l_block_cache, l_block_cache_tmp ) { + char l_buf[50]; + dap_string_append_printf(l_str_tmp,"\t%s: ts_create=%s", + l_block_cache->block_hash_str, ctime_r( &l_block_cache->ts_created,l_buf ) ); + } + pthread_rwlock_unlock(&PVT(l_blocks)->rwlock); + + dap_chain_node_cli_set_reply_text(a_str_reply, l_str_tmp->str); + dap_string_free(l_str_tmp,false); + + }break; + + case SUBCMD_UNDEFINED: { + dap_chain_node_cli_set_reply_text(a_str_reply, + "Undefined block subcommand \"%s\" ", + l_subcmd_str); + ret=-11; + } + } + return ret; +} + + +/** + * @brief s_callback_delete + * @details Destructor for blocks consensus chain + * @param a_chain + */ +static void s_callback_delete(dap_chain_t * a_chain) +{ + dap_chain_cs_blocks_t * l_blocks = DAP_CHAIN_CS_BLOCKS ( a_chain ); + if(l_blocks->callback_delete ) + l_blocks->callback_delete(l_blocks); + if(l_blocks->_inheritor) + DAP_DELETE(l_blocks->_inheritor); + if(l_blocks->_pvt) + DAP_DELETE(l_blocks->_pvt); +} + +/** + * @brief s_callback_atom_add + * @details Accept new atom in blockchain + * @param a_chain + * @param a_atom + * @param a_atom_size + * @return + */ +static dap_chain_atom_verify_res_t s_callback_atom_add(dap_chain_t * a_chain, dap_chain_atom_ptr_t a_atom , size_t a_atom_size) +{ + +} + +/** + * @brief s_callback_atom_verify + * @param a_chain + * @param a_atom + * @param a_atom_size + * @return + */ +static dap_chain_atom_verify_res_t s_callback_atom_verify(dap_chain_t * a_chain, dap_chain_atom_ptr_t a_atom , size_t a_atom_size) +{ + +} + +/** + * @brief s_callback_atom_get_static_hdr_size + * @return + */ +static size_t s_callback_atom_get_static_hdr_size(void) +{ + +} + +/** + * @brief s_callback_atom_iter_create + * @param a_chain + * @return + */ +static dap_chain_atom_iter_t* s_callback_atom_iter_create(dap_chain_t * a_chain ) +{ + +} + +/** + * @brief s_callback_atom_iter_create_from + * @param a_chain + * @param a_atom + * @param a_atom_size + * @return + */ +static dap_chain_atom_iter_t* s_callback_atom_iter_create_from(dap_chain_t * a_chain, dap_chain_atom_ptr_t a_atom, size_t a_atom_size) +{ + +} + +/** + * @brief s_callback_atom_iter_find_by_hash + * @param a_atom_iter + * @param a_atom_hash + * @param a_atom_size + * @return + */ +static dap_chain_atom_ptr_t s_callback_atom_iter_find_by_hash(dap_chain_atom_iter_t * a_atom_iter, dap_chain_hash_fast_t * a_atom_hash, + size_t * a_atom_size) +{ + +} + +/** + * @brief s_callback_atom_iter_find_by_tx_hash + * @param a_chain + * @param a_atom_hash + * @return + */ +static dap_chain_datum_tx_t* s_callback_atom_iter_find_by_tx_hash(dap_chain_t * a_chain, dap_chain_hash_fast_t * a_atom_hash) +{ + +} + +/** + * @brief s_callback_atom_get_datum + * @param a_event + * @param a_atom_size + * @return + */ +static dap_chain_datum_t* s_callback_atom_get_datum(dap_chain_atom_ptr_t a_event, size_t a_atom_size) +{ + +} + +/** + * @brief s_callback_atom_iter_get_first + * @param a_atom_iter + * @param a_atom_size + * @return + */ +static dap_chain_atom_ptr_t s_callback_atom_iter_get_first( dap_chain_atom_iter_t * a_atom_iter, size_t *a_atom_size ) +{ + +} + +/** + * @brief s_callback_atom_iter_get_next + * @param a_atom_iter + * @param a_atom_size + * @return + */ +static dap_chain_atom_ptr_t s_callback_atom_iter_get_next( dap_chain_atom_iter_t * a_atom_iter,size_t *a_atom_size ) +{ + +} + +/** + * @brief s_callback_atom_iter_get_links + * @param a_atom_iter + * @param a_links_size + * @param a_links_size_ptr + * @return + */ +static dap_chain_atom_ptr_t *s_callback_atom_iter_get_links( dap_chain_atom_iter_t * a_atom_iter , size_t *a_links_size, size_t ** a_links_size_ptr ) +{ + +} + +/** + * @brief s_callback_atom_iter_get_lasts + * @param a_atom_iter + * @param a_links_size + * @param a_lasts_size_ptr + * @return + */ +static dap_chain_atom_ptr_t *s_callback_atom_iter_get_lasts( dap_chain_atom_iter_t * a_atom_iter ,size_t *a_links_size, size_t ** a_lasts_size_ptr ) +{ + +} + +/** + * @brief s_callback_atom_iter_delete + * @param a_atom_iter + */ +static void s_callback_atom_iter_delete(dap_chain_atom_iter_t * a_atom_iter ) +{ + +} + +/** + * @brief s_callback_datums_pool_proc + * @param a_chain + * @param a_datums + * @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) +{ + +} diff --git a/modules/type/blocks/include/dap_chain_block.h b/modules/type/blocks/include/dap_chain_block.h new file mode 100644 index 0000000000000000000000000000000000000000..cad3a151794549465eacedaa0f9d8239a1efd284 --- /dev/null +++ b/modules/type/blocks/include/dap_chain_block.h @@ -0,0 +1,95 @@ +/* + * Authors: + * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net> + * DeM Labs Ltd https://demlabs.net + * Copyright (c) 2017-2020 + * All rights reserved. + + This file is part of DAP SDK the open source project + + DAP SDK is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + DAP SDK is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with any DAP SDK based project. If not, see <http://www.gnu.org/licenses/>. +*/ +#pragma once +#include "dap_common.h" +#include "dap_math_ops.h" +#include "dap_hash.h" +#include "dap_chain_common.h" +#include "dap_chain_datum.h" +#include "dap_chain_datum_hashtree_roots.h" + +#define DAP_CHAIN_BLOCK_SIGNATURE 0xDA05BF8E +#define DAP_CHAIN_BLOCK_ID_SIZE 4 + + +typedef union dap_chain_block_typeid{ + uint8_t data[DAP_CHAIN_BLOCK_ID_SIZE]; +} DAP_ALIGN_PACKED dap_chain_block_typeid_t; + +/** + * @struct dap_chain_block_hdr + * @brief Block header + */ +typedef struct dap_chain_block_hdr{ + uint32_t signature; /// @param signature @brief Magic number, always equels to DAP_CHAIN_BLOCK_SIGNATURE + int32_t version; /// @param version @brief block version (be carefull, signed value, as Bitcoin has) + dap_chain_cell_id_t cell_id; /// Cell id + dap_chain_cell_id_t chain_id; /// Chain id + uint32_t meta_n_datums_size; /// @param size of the whole block except signatures meta + dap_chain_time_t ts_created; /// @param timestamp @brief Block create time timestamp + uint16_t meta_count; // Meta values number + uint16_t datum_count; // Datums's count +} DAP_ALIGN_PACKED dap_chain_block_hdr_t; + +// Metadata item +typedef struct dap_chain_block_meta{ + struct { + uint8_t type; /// Meta type + uint16_t size; /// Data size trailing the section + } DAP_ALIGN_PACKED hdr; + byte_t data[]; /// Section's data +} DAP_ALIGN_PACKED dap_chain_block_meta_t; + +// Block metadata types + +#define DAP_CHAIN_BLOCK_META_GENESIS 0x01 +#define DAP_CHAIN_BLOCK_META_PREV 0x10 +#define DAP_CHAIN_BLOCK_META_ANCHOR 0x11 +#define DAP_CHAIN_BLOCK_META_LINK 0x12 +#define DAP_CHAIN_BLOCK_META_NONCE 0x20 +#define DAP_CHAIN_BLOCK_META_NONCE2 0x21 + + +/** + * @struct dap_chain_block + * @brief The dap_chain_block struct + */ +typedef struct dap_chain_block{ + dap_chain_block_hdr_t hdr; + uint8_t meta_n_datum_n_sign[]; // Here are: metadata, datum sections and verificator signatures +} DAP_ALIGN_PACKED dap_chain_block_t; + +// Init module +int dap_chain_block_init(); +// Deinit module +void dap_chain_block_deinit(); + +// Create new block +dap_chain_block_t * dap_chain_block_new(dap_chain_hash_fast_t * a_prev_block ); + +// Add metadata in block +size_t dap_chain_block_meta_add(dap_chain_block_t * a_block, size_t a_block_size, uint8_t a_meta_type, const void * a_data, size_t a_data_size); + +// Add datum in block +size_t dap_chain_block_datum_add(dap_chain_block_t * a_block, 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, size_t a_block_size, dap_chain_hash_fast_t* a_datum_hash); diff --git a/modules/type/blocks/include/dap_chain_block_cache.h b/modules/type/blocks/include/dap_chain_block_cache.h new file mode 100644 index 0000000000000000000000000000000000000000..35f115cdd34656b7c041077e80b42177a12fb8ea --- /dev/null +++ b/modules/type/blocks/include/dap_chain_block_cache.h @@ -0,0 +1,66 @@ +/* + * Authors: + * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net> + * DeM Labs Ltd https://demlabs.net + * Copyright (c) 2017-2020 + * All rights reserved. + + This file is part of DAP SDK the open source project + + DAP SDK is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + DAP SDK is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with any DAP SDK based project. If not, see <http://www.gnu.org/licenses/>. +*/ +#pragma once +#include "dap_chain_block.h" +#include "dap_sign.h" +#include "dap_hash.h" +#include "uthash.h" + +typedef struct dap_chain_block_cache{ + // Block's general non-nested attributes + dap_chain_hash_fast_t block_hash; + char* block_hash_str; + size_t block_size; + + // Local platform values representation + time_t ts_created; + + // Block's datums + uint32_t datum_count; + dap_chain_datum_t ** datum; + + // Block's metadatas + uint32_t meta_count; + dap_chain_block_meta_t** meta; + + // Block's signatures + size_t sign_count; // Number of signatures in block's tail + dap_sign_t ** sign; // Pointer to signatures in block + + // Pointer to block itself + dap_chain_block_t * block; + + // Inhertied nested data + void * _inheritor; + + // uthash handle + UT_hash_handle hh; +} dap_chain_block_cache_t; + +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); +void 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); diff --git a/modules/type/blocks/include/dap_chain_cs_blocks.h b/modules/type/blocks/include/dap_chain_cs_blocks.h new file mode 100644 index 0000000000000000000000000000000000000000..f2be5e7fa63f0b63d87dd0a8f2e3ab24e3414ae7 --- /dev/null +++ b/modules/type/blocks/include/dap_chain_cs_blocks.h @@ -0,0 +1,61 @@ +/* + * Authors: + * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net> + * DeM Labs Inc. https://demlabs.net + * Copyright (c) 2017-2020 + * 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.h" +#include "dap_chain_block.h" +#include "dap_chain_block_cache.h" + + +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 dap_chain_block_t * (*dap_chain_cs_blocks_callback_block_create_t)(dap_chain_cs_blocks_t *, + dap_chain_datum_t *, + dap_chain_hash_fast_t *, + size_t, size_t*); + + +typedef struct dap_chain_cs_blocks +{ + dap_chain_t * chain; + + 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; + void * _pvt; + void * _inheritor; +} dap_chain_cs_blocks_t; + +#define DAP_CHAIN_CS_BLOCKS(a) ((dap_chain_cs_blocks_t*) a->_inheritor) +typedef int (*dap_chain_blocks_block_callback_ptr_t)(dap_chain_cs_blocks_t *, dap_chain_block_t *); + +int dap_chain_cs_blocks_init(); +void dap_chain_cs_blocks_deinit(); + +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); diff --git a/modules/type/dag/dap_chain_cs_dag.c b/modules/type/dag/dap_chain_cs_dag.c index 15da786b6919f505b3c36663535ed4c593d8da56..69e50b3968bee1cc102c902ec75dc5b5039fa99b 100644 --- a/modules/type/dag/dap_chain_cs_dag.c +++ b/modules/type/dag/dap_chain_cs_dag.c @@ -78,6 +78,7 @@ typedef struct dap_chain_cs_dag_pvt { #define PVT(a) ((dap_chain_cs_dag_pvt_t *) a->_pvt ) +static void s_dap_chain_cs_dag_purge(dap_chain_t *a_chain); dap_chain_cs_dag_event_item_t* dap_chain_cs_dag_proc_treshold(dap_chain_cs_dag_t * a_dag, dap_ledger_t * a_ledger); // Atomic element organization callbacks @@ -128,7 +129,7 @@ static bool s_seed_mode = false; int dap_chain_cs_dag_init(void) { srand((unsigned int) time(NULL)); - dap_chain_class_add( "dag", dap_chain_cs_dag_new ); + dap_chain_cs_type_add( "dag", dap_chain_cs_dag_new ); s_seed_mode = dap_config_get_item_bool_default(g_config,"general","seed_mode",false); dap_chain_node_cli_cmd_item_create ("dag", s_cli_dag, NULL, "DAG commands", "dag -net <chain net name> -chain <chain name> event create -datum <datum hash> [-H hex|base58(default)]\n" @@ -171,6 +172,7 @@ int dap_chain_cs_dag_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg) pthread_rwlock_init(& PVT(l_dag)->events_rwlock,NULL); a_chain->callback_delete = dap_chain_cs_dag_delete; + a_chain->callback_purge = s_dap_chain_cs_dag_purge; // Atom element callbacks a_chain->callback_atom_add = s_chain_callback_atom_add ; // Accept new element in chain @@ -194,7 +196,7 @@ int dap_chain_cs_dag_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg) a_chain->callback_tx_find_by_hash = s_chain_callback_atom_iter_find_by_tx_hash; - a_chain->callback_datums_pool_proc = s_chain_callback_datums_pool_proc; + a_chain->callback_add_datums = s_chain_callback_datums_pool_proc; // Datum operations callbacks /* @@ -231,6 +233,34 @@ int dap_chain_cs_dag_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg) return 0; } +static void s_dap_chain_cs_dag_purge(dap_chain_t *a_chain) +{ + dap_chain_cs_dag_pvt_t *l_dag_pvt = PVT(DAP_CHAIN_CS_DAG(a_chain)); + pthread_rwlock_wrlock(&l_dag_pvt->events_rwlock); + dap_chain_cs_dag_event_item_t *l_event_current, *l_event_tmp; + HASH_ITER(hh, l_dag_pvt->events, l_event_current, l_event_tmp) { + HASH_DEL(l_dag_pvt->events, l_event_current); + DAP_DELETE(l_event_current); + } + HASH_ITER(hh, l_dag_pvt->events_lasts_unlinked, l_event_current, l_event_tmp) { + HASH_DEL(l_dag_pvt->events_lasts_unlinked, l_event_current); + DAP_DELETE(l_event_current); + } + HASH_ITER(hh, l_dag_pvt->events_treshold, l_event_current, l_event_tmp) { + HASH_DEL(l_dag_pvt->events_treshold, l_event_current); + DAP_DELETE(l_event_current); + } + HASH_ITER(hh, l_dag_pvt->events_treshold_conflicted, l_event_current, l_event_tmp) { + HASH_DEL(l_dag_pvt->events_treshold_conflicted, l_event_current); + DAP_DELETE(l_event_current); + } + HASH_ITER(hh, l_dag_pvt->tx_events, l_event_current, l_event_tmp) { + HASH_DEL(l_dag_pvt->tx_events, l_event_current); + DAP_DELETE(l_event_current); + } + pthread_rwlock_unlock(&l_dag_pvt->events_rwlock); +} + /** * @brief dap_chain_cs_dag_delete * @param a_dag @@ -238,6 +268,7 @@ int dap_chain_cs_dag_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg) */ void dap_chain_cs_dag_delete(dap_chain_t * a_chain) { + s_dap_chain_cs_dag_purge(a_chain); dap_chain_cs_dag_t * l_dag = DAP_CHAIN_CS_DAG ( a_chain ); pthread_rwlock_destroy(& PVT(l_dag)->events_rwlock); @@ -255,12 +286,12 @@ static int s_dap_chain_add_atom_to_ledger(dap_chain_cs_dag_t * a_dag, dap_ledger switch (l_datum->header.type_id) { case DAP_CHAIN_DATUM_TOKEN_DECL: { dap_chain_datum_token_t *l_token = (dap_chain_datum_token_t*) l_datum->data; - return dap_chain_ledger_token_add(a_ledger, l_token, l_datum->header.data_size); + return dap_chain_ledger_token_load(a_ledger, l_token, l_datum->header.data_size); } break; case DAP_CHAIN_DATUM_TOKEN_EMISSION: { dap_chain_datum_token_emission_t *l_token_emission = (dap_chain_datum_token_emission_t*) l_datum->data; - return dap_chain_ledger_token_emission_add(a_ledger, l_token_emission, l_datum->header.data_size); + return dap_chain_ledger_token_emission_load(a_ledger, l_token_emission, l_datum->header.data_size); } break; case DAP_CHAIN_DATUM_TX: { @@ -274,7 +305,7 @@ static int s_dap_chain_add_atom_to_ledger(dap_chain_cs_dag_t * a_dag, dap_ledger HASH_ADD(hh,PVT(a_dag)->tx_events,hash,sizeof (l_tx_event->hash),l_tx_event); // don't save bad transactions to base - if(dap_chain_ledger_tx_add(a_ledger, l_tx) != 1) { + if(dap_chain_ledger_tx_load(a_ledger, l_tx) != 1) { return -1; } }