diff --git a/3rdparty/cuttdb/CMakeLists.txt b/3rdparty/cuttdb/CMakeLists.txt index 948b986642c799003bfa48b0893c3b022f6805b0..2fb2bf49fcd21fd80fb7fa7f79a133ffcb2775fc 100755 --- a/3rdparty/cuttdb/CMakeLists.txt +++ b/3rdparty/cuttdb/CMakeLists.txt @@ -23,9 +23,5 @@ endif() add_library(${PROJECT_NAME} STATIC ${cuttdb_src}) set_target_properties(${PROJECT_NAME} PROPERTIES LINKER_LANGUAGE C) set_target_properties(${PROJECT_NAME} PROPERTIES COMPILER_LANGUAGE C) - -set_target_properties(${PROJECT_NAME} PROPERTIES LINKER_LANGUAGE C) - -target_link_libraries(${PROJECT_NAME}) - target_include_directories(${PROJECT_NAME} INTERFACE src) +target_compile_options(${PROJECT_NAME} PRIVATE -Wno-sign-compare) diff --git a/3rdparty/cuttdb/src/cdb_core.c b/3rdparty/cuttdb/src/cdb_core.c index 62c35371b3d26b07d6a275e6f1bb87706b2b6153..75aabebe36dd7a12e0101d14a2229e0824d4ee64 100644 --- a/3rdparty/cuttdb/src/cdb_core.c +++ b/3rdparty/cuttdb/src/cdb_core.c @@ -41,6 +41,9 @@ static void _cdb_pagewarmup(CDB *db, bool loadbf); /* it isn't necessary to rehash bid in hash table cache */ static uint32_t _pagehash(const void *key, int len) { + uint32_t tst = 0; + if (len < tst) + return 0; (void) len; return *(uint32_t*)key; } diff --git a/3rdparty/libmaxminddb/CMakeLists.txt b/3rdparty/libmaxminddb/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..e9ae197bd4727e21acbbafec2c0f3310aaad83bb --- /dev/null +++ b/3rdparty/libmaxminddb/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.10) + +project(maxminddb C) + +add_definitions ("-D_GNU_SOURCE") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") + +file(GLOB maxminddb_src ${CMAKE_CURRENT_SOURCE_DIR} *.c) +file(GLOB maxminddb_h ${CMAKE_CURRENT_SOURCE_DIR} *.h) + +add_library(${PROJECT_NAME} STATIC ${maxminddb_src} ${maxminddb_h}) +set_target_properties(${PROJECT_NAME} PROPERTIES LINKER_LANGUAGE C) +set_target_properties(${PROJECT_NAME} PROPERTIES COMPILER_LANGUAGE C) +target_include_directories(${PROJECT_NAME} INTERFACE .) +target_compile_options(${PROJECT_NAME} PRIVATE -Wno-sign-compare) diff --git a/modules/net/srv/libmaxminddb/data-pool.c b/3rdparty/libmaxminddb/data-pool.c similarity index 100% rename from modules/net/srv/libmaxminddb/data-pool.c rename to 3rdparty/libmaxminddb/data-pool.c diff --git a/modules/net/srv/libmaxminddb/data-pool.h b/3rdparty/libmaxminddb/data-pool.h similarity index 100% rename from modules/net/srv/libmaxminddb/data-pool.h rename to 3rdparty/libmaxminddb/data-pool.h diff --git a/modules/net/srv/libmaxminddb/maxminddb-compat-util.h b/3rdparty/libmaxminddb/maxminddb-compat-util.h similarity index 100% rename from modules/net/srv/libmaxminddb/maxminddb-compat-util.h rename to 3rdparty/libmaxminddb/maxminddb-compat-util.h diff --git a/modules/net/srv/libmaxminddb/maxminddb.c b/3rdparty/libmaxminddb/maxminddb.c similarity index 100% rename from modules/net/srv/libmaxminddb/maxminddb.c rename to 3rdparty/libmaxminddb/maxminddb.c diff --git a/modules/net/srv/libmaxminddb/maxminddb.h b/3rdparty/libmaxminddb/maxminddb.h similarity index 100% rename from modules/net/srv/libmaxminddb/maxminddb.h rename to 3rdparty/libmaxminddb/maxminddb.h diff --git a/modules/net/srv/libmaxminddb/maxminddb_config.h b/3rdparty/libmaxminddb/maxminddb_config.h similarity index 100% rename from modules/net/srv/libmaxminddb/maxminddb_config.h rename to 3rdparty/libmaxminddb/maxminddb_config.h diff --git a/modules/net/srv/libmaxminddb/mmdblookup.c b/3rdparty/libmaxminddb/mmdblookup.c similarity index 100% rename from modules/net/srv/libmaxminddb/mmdblookup.c rename to 3rdparty/libmaxminddb/mmdblookup.c diff --git a/3rdparty/libmdbx/config.h b/3rdparty/libmdbx/config.h new file mode 100644 index 0000000000000000000000000000000000000000..b8983250d7e7eccd96e832d50ebb0aca5ad225d2 --- /dev/null +++ b/3rdparty/libmdbx/config.h @@ -0,0 +1,63 @@ +/* This is CMake-template for libmdbx's config.h + ******************************************************************************/ + +/* *INDENT-OFF* */ +/* clang-format off */ + +/* #undef LTO_ENABLED */ +/* #undef MDBX_USE_VALGRIND */ +/* #undef ENABLE_GPROF */ +/* #undef ENABLE_GCOV */ +/* #undef ENABLE_ASAN */ +/* #undef ENABLE_UBSAN */ +#define MDBX_FORCE_ASSERTIONS 0 + +/* Common */ +#define MDBX_TXN_CHECKOWNER 1 +#define MDBX_ENV_CHECKPID_AUTO +#ifndef MDBX_ENV_CHECKPID_AUTO +#define MDBX_ENV_CHECKPID 0 +#endif +#define MDBX_LOCKING_AUTO +#ifndef MDBX_LOCKING_AUTO +/* #undef MDBX_LOCKING */ +#endif +#define MDBX_TRUST_RTC_AUTO +#ifndef MDBX_TRUST_RTC_AUTO +#define MDBX_TRUST_RTC 0 +#endif +#define MDBX_DISABLE_PAGECHECKS 0 + +/* Windows */ +#define MDBX_WITHOUT_MSVC_CRT 0 + +/* MacOS & iOS */ +#define MDBX_OSX_SPEED_INSTEADOF_DURABILITY 0 + +/* POSIX */ +#define MDBX_DISABLE_GNU_SOURCE 0 +#define MDBX_USE_OFDLOCKS_AUTO +#ifndef MDBX_USE_OFDLOCKS_AUTO +#define MDBX_USE_OFDLOCKS 0 +#endif + +/* Build Info */ +#ifndef MDBX_BUILD_TIMESTAMP +#define MDBX_BUILD_TIMESTAMP "2022-11-07T16:21:48Z" +#endif +#ifndef MDBX_BUILD_TARGET +#define MDBX_BUILD_TARGET "x86_64-ELF-Linux" +#endif +#ifndef MDBX_BUILD_TYPE +#define MDBX_BUILD_TYPE "Debug" +#endif +#ifndef MDBX_BUILD_COMPILER +#define MDBX_BUILD_COMPILER "gcc (Debian 10.2.1-6) 10.2.1 20210110" +#endif +#ifndef MDBX_BUILD_FLAGS +#define MDBX_BUILD_FLAGS "-g MDBX_BUILD_SHARED_LIBRARY=0 -ffast-math -fvisibility=hidden" +#endif +/* #undef MDBX_BUILD_SOURCERY */ + +/* *INDENT-ON* */ +/* clang-format on */ diff --git a/CMakeLists.txt b/CMakeLists.txt index 7ee58dc40662dd89668b818460671143adf6a004..f07a3c7600feae3ffa59c913f06daf89a0a8fc9c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -105,10 +105,6 @@ endif() add_subdirectory(dap-sdk) add_subdirectory(3rdparty/monero_crypto) -add_subdirectory(3rdparty/cuttdb) -if (BUILD_WITH_GDB_DRIVER_MDBX) -add_subdirectory(3rdparty/libmdbx) -endif() if(DAPSDK_MODULES MATCHES "ssl-support") add_subdirectory(3rdparty/wolfssl) endif() @@ -250,7 +246,7 @@ endif() if (WIN32) set(CELLFRAME_LIBS ${CELLFRAME_LIBS} kernel32 user32 shell32 winmm gdi32 advapi32 ole32 version imm32 oleaut32 ws2_32 ntdll psapi - shlwapi bcrypt crypt32 secur32 userenv mqrt) + shlwapi bcrypt crypt32 secur32 userenv) #mqrt) endif() if (DARWIN) diff --git a/dap-sdk/core/include/dap_common.h b/dap-sdk/core/include/dap_common.h index c7dfb5a5d13eadb58d1a657ae2346f63e8dae941..5e8a7888323f654a21843a33407ab1809af0aa66 100755 --- a/dap-sdk/core/include/dap_common.h +++ b/dap-sdk/core/include/dap_common.h @@ -28,6 +28,16 @@ #ifndef __STDC_WANT_LIB_EXT1__ #define __STDC_WANT_LIB_EXT1__ 1 #endif + +#ifdef DAP_OS_WINDOWS +#ifndef _INC_WINDOWS +#include <winsock2.h> +#endif +#include <fcntl.h> +#define pipe(pfds) _pipe(pfds, 4096, _O_BINARY) +#define strerror_r(arg1, arg2, arg3) strerror_s(arg2, arg3, arg1) +#endif + #include <string.h> #include <stdarg.h> #include <stddef.h> @@ -45,12 +55,6 @@ #define atomic_uint _Atomic(uint) #endif -#include <time.h> -#ifdef DAP_OS_WINDOWS -#include <fcntl.h> -#define pipe(pfds) _pipe(pfds, 4096, _O_BINARY) -#define strerror_r(arg1, arg2, arg3) strerror_s(arg2, arg3, arg1) -#endif #ifdef __MACH__ #include <dispatch/dispatch.h> #endif diff --git a/dap-sdk/core/src/dap_list.c b/dap-sdk/core/src/dap_list.c index 86a93a231892432b3f53f13fcc3d7c7c7252e419..3cbdaa944f8ae8c5da5f9bd5d9a70ca152fde4e7 100755 --- a/dap-sdk/core/src/dap_list.c +++ b/dap-sdk/core/src/dap_list.c @@ -494,32 +494,20 @@ dap_list_t *dap_list_copy(dap_list_t *list) */ dap_list_t *dap_list_copy_deep(dap_list_t *list, dap_callback_copy_t func, void* user_data) { - dap_list_t *new_list = NULL; + dap_list_t *last, *new_list = NULL; - if(list) - { - dap_list_t *last; - - new_list = dap_list_alloc(); - if(func) - new_list->data = func(list->data, user_data); - else - new_list->data = list->data; - new_list->prev = NULL; - last = new_list; - list = list->next; - while(list) - { + while (list) { + if (new_list) { last->next = dap_list_alloc(); last->next->prev = last; last = last->next; - if(func) - last->data = func(list->data, user_data); - else - last->data = list->data; - list = list->next; - } - last->next = NULL; + } else + new_list = last = dap_list_alloc(); + if (func) + last->data = func(list->data, user_data); + else + last->data = list->data; + list = list->next; } return new_list; diff --git a/dap-sdk/core/src/win32/dap_cpu_monitor.c b/dap-sdk/core/src/win32/dap_cpu_monitor.c index 68e80f290c8a1620344a5733dea4d431dfdf3b59..0b843282305111b0278260139d40848cca6f8837 100644 --- a/dap-sdk/core/src/win32/dap_cpu_monitor.c +++ b/dap-sdk/core/src/win32/dap_cpu_monitor.c @@ -18,14 +18,13 @@ along with any DAP based project. If not, see <http://www.gnu.org/licenses/>. */ -#include <windows.h> -//#include <winnt.h> -#include <winternl.h> - #include <stdio.h> #include <stdint.h> #include <string.h> #include <stdlib.h> +#include <windows.h> +//#include <winnt.h> +#include <winternl.h> #include "dap_cpu_monitor.h" #include "dap_common.h" diff --git a/dap-sdk/core/src/win32/dap_cpu_monitor.h b/dap-sdk/core/src/win32/dap_cpu_monitor.h index efec16511a597a4bb970d20f463d55f64c76a2aa..a8f39ae5517478cf915f2431532b8fe0d9be8b65 100644 --- a/dap-sdk/core/src/win32/dap_cpu_monitor.h +++ b/dap-sdk/core/src/win32/dap_cpu_monitor.h @@ -1,5 +1,7 @@ #pragma once +#include <stdint.h> + #define MAX_CPU_COUNT 64 typedef struct dap_cpu { diff --git a/dap-sdk/core/src/win32/dap_process_memory.h b/dap-sdk/core/src/win32/dap_process_memory.h index d2f13c86a851a6e9654d6317ff16454d283bef26..78659cc2d7c52e4ee2cc4701ab7fbd132d8886cd 100644 --- a/dap-sdk/core/src/win32/dap_process_memory.h +++ b/dap-sdk/core/src/win32/dap_process_memory.h @@ -1,6 +1,6 @@ -//#include <stdint.h> -//#include <sys/types.h> +#include <stdint.h> +#include <sys/types.h> typedef struct dap_process_memory { diff --git a/dap-sdk/io/dap_context.c b/dap-sdk/io/dap_context.c index f7cd5f11ae9da2b273cd46b11f7e856dacbf0c66..d843236ff9b06706b5009be22d4a0bb6fbabaf46 100644 --- a/dap-sdk/io/dap_context.c +++ b/dap-sdk/io/dap_context.c @@ -887,6 +887,8 @@ static int s_thread_loop(dap_context_t * a_context) #elif defined (DAP_EVENTS_CAPS_QUEUE_POSIX) l_bytes_sent = mq_send(a_es->mqd, (const char *)&a_arg,sizeof (a_arg),0); #elif defined DAP_EVENTS_CAPS_MSMQ + /* TODO: Windows-way message waiting and handling + * DWORD l_mp_id = 0; MQMSGPROPS l_mps; MQPROPVARIANT l_mpvar[1]; @@ -916,6 +918,11 @@ static int s_thread_loop(dap_context_t * a_context) } l_bytes_sent = sizeof(void*); } + */ + l_bytes_sent = dap_sendto(l_cur->socket, l_cur->port, l_cur->buf_out, l_cur->buf_out_size); + if (l_bytes_sent == SOCKET_ERROR) { + log_it(L_ERROR, "Write to socket error: %d", WSAGetLastError()); + } #elif defined (DAP_EVENTS_CAPS_QUEUE_MQUEUE) l_bytes_sent = mq_send(l_cur->mqd , (const char *)l_cur->buf_out,sizeof (void*),0); if(l_bytes_sent == 0) @@ -1610,13 +1617,7 @@ dap_events_socket_t *dap_context_find(dap_context_t * a_context, dap_events_sock unsigned long l_mode = 1; ioctlsocket(l_es->socket, FIONBIO, &l_mode); - int l_addr_len; - struct sockaddr_in l_addr; - l_addr.sin_family = AF_INET; - IN_ADDR _in_addr = { { .S_addr = htonl(INADDR_LOOPBACK) } }; - l_addr.sin_addr = _in_addr; - l_addr.sin_port = 0; //l_es->socket + 32768; - l_addr_len = sizeof(struct sockaddr_in); + struct sockaddr_in l_addr = { .sin_family = AF_INET, .sin_port = 0, .sin_addr = {{ .S_addr = htonl(INADDR_LOOPBACK) }} }; if (bind(l_es->socket, (struct sockaddr*)&l_addr, sizeof(l_addr)) < 0) { log_it(L_ERROR, "Bind error: %d", WSAGetLastError()); @@ -1624,9 +1625,8 @@ dap_events_socket_t *dap_context_find(dap_context_t * a_context, dap_events_sock int dummy = 100; getsockname(l_es->socket, (struct sockaddr*)&l_addr, &dummy); l_es->port = l_addr.sin_port; - //log_it(L_DEBUG, "Bound to port %d", l_addr.sin_port); } - + /* MQQUEUEPROPS l_qps; MQPROPVARIANT l_qp_var[1]; QUEUEPROPID l_qp_id[1]; @@ -1691,6 +1691,7 @@ dap_events_socket_t *dap_context_find(dap_context_t * a_context, dap_events_sock if (hr != MQ_OK) { log_it(L_DEBUG, "Message queue %u NOT purged, possible data corruption, err %ld", l_es->mq_num, hr); } + */ #elif defined (DAP_EVENTS_CAPS_KQUEUE) // We don't create descriptor for kqueue at all #else @@ -1779,13 +1780,7 @@ dap_events_socket_t * dap_context_create_event(dap_context_t * a_context, dap_ev if (setsockopt(l_es->socket, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse)) < 0) log_it(L_WARNING, "Can't set up REUSEADDR flag to the socket, err: %d", WSAGetLastError()); - int l_addr_len; - struct sockaddr_in l_addr; - l_addr.sin_family = AF_INET; - IN_ADDR _in_addr = { { .S_addr = htonl(INADDR_LOOPBACK) } }; - l_addr.sin_addr = _in_addr; - l_addr.sin_port = 0; //l_es->socket + 32768; - l_addr_len = sizeof(struct sockaddr_in); + struct sockaddr_in l_addr = { .sin_family = AF_INET, .sin_port = 0, .sin_addr = {{ .S_addr = htonl(INADDR_LOOPBACK) }} }; if (bind(l_es->socket, (struct sockaddr*)&l_addr, sizeof(l_addr)) < 0) { log_it(L_ERROR, "Bind error: %d", WSAGetLastError()); @@ -1793,7 +1788,6 @@ dap_events_socket_t * dap_context_create_event(dap_context_t * a_context, dap_ev int dummy = 100; getsockname(l_es->socket, (struct sockaddr*)&l_addr, &dummy); l_es->port = l_addr.sin_port; - //log_it(L_DEBUG, "Bound to port %d", l_addr.sin_port); } #elif defined(DAP_EVENTS_CAPS_KQUEUE) // nothing to do diff --git a/dap-sdk/io/dap_events.c b/dap-sdk/io/dap_events.c index 062d32dba5da53b25d75ea09a1816195cfdcfbfa..638be0c9a44dee0cd04ad13fd8c31384248a2742 100644 --- a/dap-sdk/io/dap_events.c +++ b/dap-sdk/io/dap_events.c @@ -221,7 +221,6 @@ void dap_cpu_assign_thread_on(uint32_t a_cpu_id) */ int dap_events_init( uint32_t a_threads_count, size_t a_conn_timeout ) { - g_debug_reactor = g_config ? dap_config_get_item_bool_default(g_config, "general", "debug_reactor", false) : false; uint32_t l_cpu_count = dap_get_cpu_count(); @@ -237,7 +236,6 @@ int dap_events_init( uint32_t a_threads_count, size_t a_conn_timeout ) if(dap_context_init() != 0){ log_it( L_CRITICAL, "Can't init client submodule dap_context( )" ); goto err; - } dap_worker_init(a_conn_timeout); diff --git a/dap-sdk/io/dap_events_socket.c b/dap-sdk/io/dap_events_socket.c index 7bf7a0bb04cb19b4aff6cca5b8334058f2a9a91c..30f0ded9065cd24bd230d326203b61098b08d3ab 100644 --- a/dap-sdk/io/dap_events_socket.c +++ b/dap-sdk/io/dap_events_socket.c @@ -468,7 +468,7 @@ dap_events_socket_t * dap_events_socket_queue_ptr_create_input(dap_events_socket l_es->socket = a_es->socket; l_es->port = a_es->port; l_es->mq_num = a_es->mq_num; - + /* WCHAR l_direct_name[MQ_MAX_Q_NAME_LEN] = { 0 }; int pos = 0; #ifdef DAP_BRAND @@ -497,6 +497,7 @@ dap_events_socket_t * dap_events_socket_queue_ptr_create_input(dap_events_socket log_it(L_ERROR, "Can't open message queue for queue type, error: %ld", hr); return NULL; } + */ #elif defined (DAP_EVENTS_CAPS_KQUEUE) // We don't create descriptor for kqueue at all #else @@ -532,9 +533,10 @@ dap_events_socket_t * dap_events_socket_create_type_queue_ptr_mt(dap_worker_t * int dap_events_socket_queue_proc_input_unsafe(dap_events_socket_t * a_esocket) { #ifdef DAP_OS_WINDOWS - int l_read = dap_recvfrom(a_esocket->socket, a_esocket->buf_in, a_esocket->buf_in_size_max); + ssize_t l_read = dap_recvfrom(a_esocket->socket, a_esocket->buf_in, a_esocket->buf_in_size_max); + int l_errno = WSAGetLastError(); if (l_read == SOCKET_ERROR) { - log_it(L_ERROR, "Queue socket %zu received invalid data, error %d", a_esocket->socket, WSAGetLastError()); + log_it(L_ERROR, "Queue socket %zu received invalid data, error %d", a_esocket->socket, l_errno); return -1; } #endif @@ -638,6 +640,7 @@ int dap_events_socket_queue_proc_input_unsafe(dap_events_socket_t * a_esocket) #endif a_esocket->callbacks.queue_ptr_callback (a_esocket, l_queue_ptr); #elif defined DAP_EVENTS_CAPS_MSMQ + /* DWORD l_mp_id = 0; MQMSGPROPS l_mps; MQPROPVARIANT l_mpvar[2]; @@ -675,6 +678,16 @@ int dap_events_socket_queue_proc_input_unsafe(dap_events_socket_t * a_esocket) } } } + */ + if(l_read > 0) { + debug_if(g_debug_reactor, L_NOTICE, "Got %ld bytes from socket", l_read); + for (long shift = 0; shift < l_read; shift += sizeof(void*)) { + l_queue_ptr = *(void **)(a_esocket->buf_in + shift); + a_esocket->callbacks.queue_ptr_callback(a_esocket, l_queue_ptr); + } + } + else if ((l_errno != EAGAIN) && (l_errno != EWOULDBLOCK)) // we use blocked socket for now but who knows... + log_it(L_ERROR, "Can't read message from socket"); #elif defined DAP_EVENTS_CAPS_KQUEUE l_queue_ptr = (void*) a_esocket->kqueue_event_catched_data.data; if(g_debug_reactor) @@ -757,14 +770,13 @@ void dap_events_socket_event_proc_input_unsafe(dap_events_socket_t *a_esocket) #elif defined DAP_OS_WINDOWS u_short l_value; int l_ret; - switch (l_ret = dap_recvfrom(a_esocket->socket, a_esocket->buf_in, a_esocket->buf_in_size)) { + switch (l_ret = dap_recvfrom(a_esocket->socket, &l_value, sizeof(char))) { case SOCKET_ERROR: log_it(L_CRITICAL, "Can't read from event socket, error: %d", WSAGetLastError()); break; case 0: return; default: - l_value = a_esocket->buf_out[0]; a_esocket->callbacks.event_callback(a_esocket, l_value); return; } @@ -1041,8 +1053,8 @@ int dap_events_socket_queue_ptr_send( dap_events_socket_t *a_es, void *a_arg) return l_errno; #elif defined DAP_EVENTS_CAPS_MSMQ - char *pbuf = (char *)&a_arg; - + /* TODO: Windows-way message waiting and handling + * DWORD l_mp_id = 0; MQMSGPROPS l_mps; MQPROPVARIANT l_mpvar[1]; @@ -1051,7 +1063,7 @@ int dap_events_socket_queue_ptr_send( dap_events_socket_t *a_es, void *a_arg) l_p_id[l_mp_id] = PROPID_M_BODY; l_mpvar[l_mp_id].vt = VT_VECTOR | VT_UI1; - l_mpvar[l_mp_id].caub.pElems = (unsigned char*)(pbuf); + l_mpvar[l_mp_id].caub.pElems = (unsigned char*)(&a_arg); l_mpvar[l_mp_id].caub.cElems = sizeof(void*); l_mp_id++; @@ -1065,12 +1077,8 @@ int dap_events_socket_queue_ptr_send( dap_events_socket_t *a_es, void *a_arg) log_it(L_ERROR, "An error occured on sending message to queue, errno: %ld", hr); return hr; } - - if(dap_sendto(a_es->socket, a_es->port, NULL, 0) == SOCKET_ERROR) { - return WSAGetLastError(); - } else { - return 0; - } + */ + return dap_sendto(a_es->socket, a_es->port, &a_arg, sizeof(void*)) == SOCKET_ERROR ? WSAGetLastError() : NO_ERROR; #elif defined (DAP_EVENTS_CAPS_KQUEUE) struct kevent l_event={0}; dap_events_socket_w_data_t * l_es_w_data = DAP_NEW_Z(dap_events_socket_w_data_t); @@ -1159,12 +1167,7 @@ int dap_events_socket_event_signal( dap_events_socket_t * a_es, uint64_t a_value else return 1; #elif defined (DAP_OS_WINDOWS) - a_es->buf_out[0] = (u_short)a_value; - if(dap_sendto(a_es->socket, a_es->port, a_es->buf_out, sizeof(uint64_t)) == SOCKET_ERROR) { - return WSAGetLastError(); - } else { - return 0; - } + return dap_sendto(a_es->socket, a_es->port, NULL, 0) == SOCKET_ERROR ? WSAGetLastError() : NO_ERROR; #elif defined (DAP_EVENTS_CAPS_KQUEUE) struct kevent l_event={0}; dap_events_socket_w_data_t * l_es_w_data = DAP_NEW_Z(dap_events_socket_w_data_t); diff --git a/dap-sdk/io/dap_proc_thread.c b/dap-sdk/io/dap_proc_thread.c index a5b13b97924ba090748c57feda5f9c1f7243c0c5..49d9243e569995daeb72fe391cd5a4dc054ba84d 100644 --- a/dap-sdk/io/dap_proc_thread.c +++ b/dap-sdk/io/dap_proc_thread.c @@ -23,10 +23,10 @@ #include <errno.h> #include <stdatomic.h> +#include "dap_events_socket.h" #include "dap_config.h" #include "dap_list.h" #include "dap_events.h" -#include "dap_events_socket.h" #include "dap_proc_thread.h" #include "dap_server.h" diff --git a/dap-sdk/io/dap_timerfd.c b/dap-sdk/io/dap_timerfd.c index d72233f2a700d3c7eca1d17c6857ffa2543f11cb..97300aca322f28790612cc76d874aa7757365bf4 100644 --- a/dap-sdk/io/dap_timerfd.c +++ b/dap-sdk/io/dap_timerfd.c @@ -76,15 +76,6 @@ dap_timerfd_t* dap_timerfd_start(uint64_t a_timeout_ms, dap_timerfd_callback_t a } #ifdef DAP_OS_WINDOWS -void __stdcall TimerAPCb(void* arg, DWORD low, DWORD high) { // Timer high value. - UNREFERENCED_PARAMETER(low) - UNREFERENCED_PARAMETER(high) - dap_timerfd_t *l_timerfd = (dap_timerfd_t *)arg; - if (dap_sendto(l_timerfd->tfd, l_timerfd->port, NULL, 0) == SOCKET_ERROR) { - log_it(L_CRITICAL, "Error occured on writing into socket from APC, errno: %d", WSAGetLastError()); - } -} - void __stdcall TimerRoutine(void* arg, BOOLEAN flag) { UNREFERENCED_PARAMETER(flag) dap_timerfd_t *l_timerfd = (dap_timerfd_t *)arg; @@ -199,27 +190,26 @@ dap_timerfd_t* dap_timerfd_create(uint64_t a_timeout_ms, dap_timerfd_callback_t #elif defined (DAP_OS_WINDOWS) l_timerfd->th = NULL; SOCKET l_tfd = socket(AF_INET, SOCK_DGRAM, 0); - int buffsize = 1024; + if (l_tfd == INVALID_SOCKET) { + log_it(L_ERROR, "Error creating socket for type 'timer': %d", WSAGetLastError()); + DAP_DELETE(l_timerfd); + DAP_DELETE(l_events_socket); + return NULL; + } + int buffsize = 4096; setsockopt(l_tfd, SOL_SOCKET, SO_RCVBUF, (char *)&buffsize, sizeof(int)); unsigned long l_mode = 1; ioctlsocket(l_tfd, FIONBIO, &l_mode); - int l_addr_len; - struct sockaddr_in l_addr; - l_addr.sin_family = AF_INET; - IN_ADDR _in_addr = { { .S_addr = htonl(INADDR_LOOPBACK) } }; - l_addr.sin_addr = _in_addr; - l_addr.sin_port = l_tfd + 32768; - l_addr_len = sizeof(struct sockaddr_in); + struct sockaddr_in l_addr = { .sin_family = AF_INET, .sin_port = l_tfd + 32768, .sin_addr = {{ .S_addr = htonl(INADDR_LOOPBACK) }} };; if (bind(l_tfd, (struct sockaddr*)&l_addr, sizeof(l_addr)) < 0) { log_it(L_ERROR, "Bind error: %d", WSAGetLastError()); } else { int dummy = 100; getsockname(l_tfd, (struct sockaddr*)&l_addr, &dummy); l_timerfd->port = l_addr.sin_port; - //log_it(L_DEBUG, "Bound to port %d", l_addr.sin_port); } if (!CreateTimerQueueTimer(&l_timerfd->th, hTimerQueue, diff --git a/dap-sdk/io/dap_worker.c b/dap-sdk/io/dap_worker.c index f3a116e183570aaba53cd0a355049ff3287e3824..d67711a2c2d86642b275f46d01b8c91250cf3aea 100644 --- a/dap-sdk/io/dap_worker.c +++ b/dap-sdk/io/dap_worker.c @@ -24,8 +24,6 @@ #include <errno.h> #include <unistd.h> -#include "dap_common.h" -#include "dap_config.h" #include "dap_context.h" #include "dap_math_ops.h" #include "dap_worker.h" @@ -33,6 +31,8 @@ #include "dap_events.h" #include "dap_enc_base64.h" #include "dap_proc_queue.h" +#include "dap_common.h" +#include "dap_config.h" #ifndef DAP_NET_CLIENT_NO_SSL #include <wolfssl/options.h> diff --git a/dap-sdk/io/include/dap_context.h b/dap-sdk/io/include/dap_context.h index 8acb573d20fd39137baf6519c034846e058f0eae..92cadc83f7a380105aaddff72960130b687761e5 100644 --- a/dap-sdk/io/include/dap_context.h +++ b/dap-sdk/io/include/dap_context.h @@ -24,9 +24,9 @@ #include <pthread.h> #include <uthash.h> -#include "dap_common.h" #include "dap_events_socket.h" #include "dap_proc_queue.h" +#include "dap_common.h" typedef struct dap_worker dap_worker_t; typedef struct dap_proc_thread dap_proc_thread_t; diff --git a/dap-sdk/io/include/dap_events_socket.h b/dap-sdk/io/include/dap_events_socket.h index bac00179684371d24d4d4b5599d527085a1e51b0..1d444e7a59123693fd0fb08bbdf3d60c42d00691 100644 --- a/dap-sdk/io/include/dap_events_socket.h +++ b/dap-sdk/io/include/dap_events_socket.h @@ -387,33 +387,19 @@ size_t dap_events_socket_insert_buf_out(dap_events_socket_t * a_es, void *a_dat DAP_STATIC_INLINE int dap_recvfrom(SOCKET s, void* buf_in, size_t buf_size) { struct sockaddr_in l_dummy; socklen_t l_size = sizeof(l_dummy); - int ret; - if (buf_in) { - memset(buf_in, 0, buf_size); - ret = recvfrom(s, (char*)buf_in, (long)buf_size, 0, (struct sockaddr *)&l_dummy, &l_size); - } else { - char l_tempbuf[sizeof(void*)]; - ret = recvfrom(s, l_tempbuf, sizeof(l_tempbuf), 0, (struct sockaddr *)&l_dummy, &l_size); - } - return ret; + char l_signal; + return recvfrom(s, buf_in && buf_size ? (char*)buf_in : &l_signal, + buf_in && buf_size ? buf_size : sizeof(char), + 0, (struct sockaddr*)&l_dummy, &l_size); + } DAP_STATIC_INLINE int dap_sendto(SOCKET s, u_short port, void* buf_out, size_t buf_out_size) { - int l_addr_len; - struct sockaddr_in l_addr; - l_addr.sin_family = AF_INET; - IN_ADDR _in_addr = { { .S_addr = htonl(INADDR_LOOPBACK) } }; - l_addr.sin_addr = _in_addr; - l_addr.sin_port = port; - l_addr_len = sizeof(struct sockaddr_in); - int ret; - if (buf_out) { - ret = sendto(s, (char*)buf_out, (long)buf_out_size, MSG_DONTWAIT | MSG_NOSIGNAL, (struct sockaddr *)&l_addr, l_addr_len); - } else { - char l_bytes[sizeof(void*)] = { 0 }; - ret = sendto(s, l_bytes, sizeof(l_bytes), MSG_DONTWAIT | MSG_NOSIGNAL, (struct sockaddr *)&l_addr, l_addr_len); - } - return ret; + struct sockaddr_in l_addr = { .sin_family = AF_INET, .sin_port = port, .sin_addr = {{ .S_addr = htonl(INADDR_LOOPBACK) }} }; + return sendto(s, buf_out && buf_out_size ? (char*)buf_out : "\0", + buf_out && buf_out_size ? buf_out_size : sizeof(char), + MSG_DONTWAIT | MSG_NOSIGNAL, (struct sockaddr *)&l_addr, sizeof(struct sockaddr_in)); + } #endif diff --git a/dap-sdk/net/app-cli/dap_app_cli_net.c b/dap-sdk/net/app-cli/dap_app_cli_net.c index a1f37d22c4bbc3849b97a9234825688b15dbf659..d1718e18707e1515b61aefa2ad737ddcb50651de 100644 --- a/dap-sdk/net/app-cli/dap_app_cli_net.c +++ b/dap-sdk/net/app-cli/dap_app_cli_net.c @@ -157,11 +157,9 @@ dap_app_cli_connect_param_t* dap_app_cli_connect(const char *a_socket_path) // connect int l_addr_len; #ifdef WIN32 - struct sockaddr_in l_remote_addr; - l_remote_addr.sin_family = AF_INET; - IN_ADDR _in_addr = { { .S_addr = htonl(INADDR_LOOPBACK) } }; - l_remote_addr.sin_addr = _in_addr; - l_remote_addr.sin_port = l_cli_port; + struct sockaddr_in l_remote_addr = { + .sin_family = AF_INET, .sin_port = l_cli_port, .sin_addr = {{ .S_addr = htonl(INADDR_LOOPBACK) }} + }; l_addr_len = sizeof(struct sockaddr_in); #else struct sockaddr_un l_remote_addr; diff --git a/dap-sdk/net/server/cli_server/dap_cli_server.c b/dap-sdk/net/server/cli_server/dap_cli_server.c index daa4002500a8f4a6e7fd4c06887b60380e12fbb5..b1f5b3c5f8d50502cbd817be55b5b7ff8929a5d8 100644 --- a/dap-sdk/net/server/cli_server/dap_cli_server.c +++ b/dap-sdk/net/server/cli_server/dap_cli_server.c @@ -479,8 +479,7 @@ int dap_cli_server_init(bool a_debug_more,const char * a_socket_path_or_address, server_addr.sin_family = AF_INET; #ifdef _WIN32 - struct in_addr _in_addr = { { .S_addr = htonl(INADDR_LOOPBACK) } }; - server_addr.sin_addr = _in_addr; + server_addr.sin_addr = (struct in_addr){{ .S_addr = htonl(INADDR_LOOPBACK) }}; server_addr.sin_port = l_listen_port; #else inet_pton( AF_INET, l_listen_addr_str, &server_addr.sin_addr ); 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 60cc038a3385f6e382b80bbe85b6cd687843ac8b..6fecc7f089bfc2bad9e807eabb33b1dd6bdde2dd 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 @@ -95,6 +95,7 @@ void dap_http_client_new( dap_events_socket_t *a_esocket, void *a_arg ) l_http_client->http = DAP_HTTP( a_esocket->server ); l_http_client->state_read = DAP_HTTP_CLIENT_STATE_START; l_http_client->state_write = DAP_HTTP_CLIENT_STATE_NONE; + l_http_client->socket_num = a_esocket->socket; return; } @@ -623,7 +624,7 @@ void dap_http_client_out_header_generate(dap_http_client_t *a_http_client) if ( a_http_client->reply_status_code == 200 ) { if (s_debug_http) - log_it(L_DEBUG, "Out headers generate for sock %"DAP_FORMAT_SOCKET, a_http_client->esocket->socket); + log_it(L_DEBUG, "Out headers generate for sock %"DAP_FORMAT_SOCKET, a_http_client->socket_num); if ( a_http_client->out_last_modified ) { dap_time_to_str_rfc822( buf, sizeof(buf), a_http_client->out_last_modified ); dap_http_header_add( &a_http_client->out_headers, "Last-Modified", buf ); @@ -639,7 +640,7 @@ void dap_http_client_out_header_generate(dap_http_client_t *a_http_client) } }else if (s_debug_http) - log_it(L_WARNING, "Out headers: nothing generate for sock %"DAP_FORMAT_SOCKET", http code %d", a_http_client->esocket->socket, + log_it(L_WARNING, "Out headers: nothing generate for sock %"DAP_FORMAT_SOCKET", http code %d", a_http_client->socket_num, a_http_client->reply_status_code); if ( a_http_client->out_connection_close || !a_http_client->keep_alive ) diff --git a/dap-sdk/net/server/http_server/http_client/include/dap_http_client.h b/dap-sdk/net/server/http_server/http_client/include/dap_http_client.h index e948a852b2f09595d439e73ad11313c08f27dac5..5f35aaa688b07ce6d0ac3b8137839b351fe578ce 100644 --- a/dap-sdk/net/server/http_server/http_client/include/dap_http_client.h +++ b/dap-sdk/net/server/http_server/http_client/include/dap_http_client.h @@ -69,6 +69,7 @@ typedef struct dap_http_client size_t out_cache_position; dap_events_socket_t *esocket; + SOCKET socket_num; struct dap_http * http; uint16_t reply_status_code; diff --git a/dap-sdk/net/stream/ch/dap_stream_ch.c b/dap-sdk/net/stream/ch/dap_stream_ch.c index b4f3b4a970889f6465f62370f793ae6d263d61a1..db3ec2d18648910860056c116a6ceab9e7322c69 100644 --- a/dap-sdk/net/stream/ch/dap_stream_ch.c +++ b/dap-sdk/net/stream/ch/dap_stream_ch.c @@ -142,51 +142,26 @@ void dap_stream_ch_delete(dap_stream_ch_t *a_ch) DAP_DELETE(a_ch); } -/** - * @brief dap_stream_ch_find_by_uuid_unsafe - * @param a_worker - * @param a_ch_uuid - * @return - */ -dap_stream_ch_t * dap_stream_ch_find_by_uuid_unsafe(dap_stream_worker_t * a_worker, dap_stream_ch_uuid_t a_ch_uuid) -{ - dap_stream_ch_t *l_ch = NULL; - - if( a_worker == NULL ){ - log_it(L_WARNING,"Attempt to search for uuid 0x%016"DAP_UINT64_FORMAT_U" in NULL worker", a_ch_uuid); - return NULL; - } - - - pthread_rwlock_rdlock(&a_worker->channels_rwlock); - if ( a_worker->channels) - HASH_FIND(hh_worker,a_worker->channels ,&a_ch_uuid, sizeof(a_ch_uuid), l_ch ); - pthread_rwlock_unlock(&a_worker->channels_rwlock); - return l_ch; - -} - /** * @brief Check ch uuid for presense in stream worker * @param a_worker * @param a_ch_uuid * @return */ -bool dap_stream_ch_check_uuid(dap_stream_worker_t * a_worker, dap_stream_ch_uuid_t a_ch_uuid) +dap_stream_ch_t *dap_stream_ch_find_by_uuid_unsafe(dap_stream_worker_t * a_worker, dap_stream_ch_uuid_t a_uuid) { dap_stream_ch_t *l_ch = NULL; if( a_worker == NULL ){ - log_it(L_WARNING,"Attempt to search for uuid 0x%016"DAP_UINT64_FORMAT_U" in NULL worker", a_ch_uuid); - return false; + log_it(L_WARNING,"Attempt to search for uuid 0x%016"DAP_UINT64_FORMAT_U" in NULL worker", a_uuid); + return NULL; } pthread_rwlock_rdlock(&a_worker->channels_rwlock); if ( a_worker->channels) - HASH_FIND(hh_worker,a_worker->channels ,&a_ch_uuid, sizeof(a_ch_uuid), l_ch ); + HASH_FIND(hh_worker,a_worker->channels, &a_uuid, sizeof(a_uuid), l_ch); pthread_rwlock_unlock(&a_worker->channels_rwlock); return l_ch; - } diff --git a/dap-sdk/net/stream/ch/include/dap_stream_ch.h b/dap-sdk/net/stream/ch/include/dap_stream_ch.h index 5ca3630ce7c96046722fbf49144c011293b1f232..837076ab0298378f2bc2c5abde919a83ad0f7800 100644 --- a/dap-sdk/net/stream/ch/include/dap_stream_ch.h +++ b/dap-sdk/net/stream/ch/include/dap_stream_ch.h @@ -64,9 +64,12 @@ void dap_stream_ch_set_ready_to_read_unsafe(dap_stream_ch_t * a_ch,bool a_is_rea void dap_stream_ch_set_ready_to_write_unsafe(dap_stream_ch_t * a_ch,bool a_is_ready); void dap_stream_ch_delete(dap_stream_ch_t *a_ch); -dap_stream_ch_t * dap_stream_ch_find_by_uuid_unsafe(dap_stream_worker_t * a_worker, dap_stream_ch_uuid_t a_uuid); +dap_stream_ch_t *dap_stream_ch_find_by_uuid_unsafe(dap_stream_worker_t *a_worker, dap_stream_ch_uuid_t a_uuid); // MT-safe functions -bool dap_stream_ch_check_uuid(dap_stream_worker_t * a_worker, dap_stream_ch_uuid_t a_ch_uuid); +DAP_STATIC_INLINE bool dap_stream_ch_check_uuid(dap_stream_worker_t *a_worker, dap_stream_ch_uuid_t a_ch_uuid) +{ + return dap_stream_ch_find_by_uuid_unsafe(a_worker, a_ch_uuid); +} #endif diff --git a/modules/chain/CMakeLists.txt b/modules/chain/CMakeLists.txt index 0ab8bba61d611fd64bef75dd5442d264b77d6408..e3fc6f7f2c7e18c8d543ade7fc944d5f07839067 100644 --- a/modules/chain/CMakeLists.txt +++ b/modules/chain/CMakeLists.txt @@ -14,7 +14,7 @@ endif() #find_package(PkgConfig REQUIRED) #pkg_search_module(GLIB REQUIRED glib-2.0) -target_link_libraries(${PROJECT_NAME} dap_chain_net_srv dap_chain_net_srv_xchange dap_chain_net_srv_stake_pos_delegate dap_chain_net_srv_stake_lock ${GLIB_LDFLAGS}) +target_link_libraries(${PROJECT_NAME} dap_chain_common dap_chain_global_db ${GLIB_LDFLAGS}) target_include_directories(${PROJECT_NAME} INTERFACE . include/ ${GLIB_INCLUDE_DIRS}) target_include_directories(${PROJECT_NAME} PUBLIC include) target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../3rdparty/uthash/src) diff --git a/modules/chain/dap_chain.c b/modules/chain/dap_chain.c index 7a15202bdf797092024af67069b0096cb3283bb4..f971680a3c1cc90c8fa290423c185bb3333cd703 100644 --- a/modules/chain/dap_chain.c +++ b/modules/chain/dap_chain.c @@ -27,7 +27,6 @@ #include <stdc-predef.h> #endif #include <unistd.h> -#include "dap_chain_net_srv.h" #include "dap_chain_common.h" #include "dap_chain_datum.h" #include "dap_chain_datum_decree.h" @@ -42,7 +41,6 @@ #include "dap_chain_ledger.h" #include "dap_chain_cs.h" #include "dap_cert_file.h" -#include "dap_chain_vf.h" #include <uthash.h> #include <pthread.h> @@ -75,7 +73,6 @@ int dap_chain_init(void) dap_chain_cell_init(); dap_chain_ledger_init(); dap_chain_cs_init(); - dap_chain_vf_init(); //dap_chain_show_hash_blocks_file(g_gold_hash_blocks_file); //dap_chain_show_hash_blocks_file(g_silver_hash_blocks_file); return 0; diff --git a/modules/chain/dap_chain_cell.c b/modules/chain/dap_chain_cell.c index 74a65ce7a6e01731ee471a6947135d4d55f2dd90..ff45cc9fb8a67728b5cae4ce22ad9ebf5634e10f 100644 --- a/modules/chain/dap_chain_cell.c +++ b/modules/chain/dap_chain_cell.c @@ -30,6 +30,7 @@ #include "dap_common.h" #include "dap_config.h" #include "dap_strfuncs.h" +#include "dap_file_utils.h" #define LOG_TAG "dap_chain_cell" @@ -188,6 +189,11 @@ int dap_chain_cell_load(dap_chain_t * a_chain, const char * a_cell_file_path) fclose(l_f); return -3; } + if (l_hdr.version < DAP_CHAIN_CELL_FILE_VERSION ){ + log_it(L_ERROR, "Too low chain version, backup files"); + fclose(l_f); + return -3; + } size_t l_el_size = 0; unsigned long q = 0; volatile int l_dummy; diff --git a/modules/chain/dap_chain_ledger.c b/modules/chain/dap_chain_ledger.c index eb138da2b6feb5c4d1aad8bb7f486084e9ffc8b5..737ce807c5b089a8abbd49faf4bcb7a8262f767e 100644 --- a/modules/chain/dap_chain_ledger.c +++ b/modules/chain/dap_chain_ledger.c @@ -63,11 +63,8 @@ #include "json-c/json.h" #include "json-c/json_object.h" #include "dap_notify_srv.h" +#include "dap_chain_net_tx.h" #include "dap_chain_net_srv.h" -#include "dap_chain_net_srv_xchange.h" -#include "dap_chain_net_srv_stake_lock.h" -#include "dap_chain_net_srv_stake_pos_delegate.h" - #define LOG_TAG "dap_chain_ledger" @@ -83,15 +80,12 @@ static pthread_rwlock_t s_verificators_rwlock; #define MAX_OUT_ITEMS 10 -typedef struct dap_chain_ledger_token_emission_for_stake_lock_item { - dap_chain_hash_fast_t datum_token_emission_for_stake_lock_hash; +typedef struct dap_chain_ledger_stake_lock_item { + dap_chain_hash_fast_t tx_for_stake_lock_hash; dap_chain_hash_fast_t tx_used_out; // const char datum_token_emission_hash[DAP_CHAIN_HASH_FAST_STR_SIZE]; UT_hash_handle hh; -} dap_chain_ledger_token_emission_for_stake_lock_item_t; - -static dap_chain_ledger_token_emission_for_stake_lock_item_t *s_emission_for_stake_lock; -static pthread_rwlock_t s_emission_for_stake_lock_rwlock; +} dap_chain_ledger_stake_lock_item_t; typedef struct dap_chain_ledger_token_emission_item { dap_chain_hash_fast_t datum_token_emission_hash; @@ -101,6 +95,14 @@ typedef struct dap_chain_ledger_token_emission_item { UT_hash_handle hh; } dap_chain_ledger_token_emission_item_t; +typedef struct dap_chain_ledger_token_update_item { + dap_hash_fast_t update_token_hash; + dap_chain_datum_token_t *datum_token_update; + size_t datum_token_update_size; + time_t updated_time; + UT_hash_handle hh; +} dap_chain_ledger_token_update_item_t; + typedef struct dap_chain_ledger_token_item { char ticker[DAP_CHAIN_TICKER_SIZE_MAX]; uint16_t type; @@ -113,6 +115,10 @@ typedef struct dap_chain_ledger_token_item { pthread_rwlock_t token_emissions_rwlock; dap_chain_ledger_token_emission_item_t * token_emissions; + pthread_rwlock_t token_ts_updated_rwlock; + dap_chain_ledger_token_update_item_t * token_ts_updated; + time_t last_update_token_time; + // for auth operations dap_sign_t ** auth_signs; dap_chain_hash_fast_t * auth_signs_pkey_hash; @@ -136,19 +142,26 @@ typedef struct dap_chain_ledger_tx_item { dap_chain_datum_tx_t *tx; struct { dap_time_t ts_created; - int n_outs; - int n_outs_used; + uint32_t n_outs; + uint32_t n_outs_used; char token_ticker[DAP_CHAIN_TICKER_SIZE_MAX]; + char padding[6]; + byte_t multichannel; + char pad[15]; // 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; + } DAP_ALIGN_PACKED cache_data; UT_hash_handle hh; } dap_chain_ledger_tx_item_t; typedef struct dap_chain_ledger_tx_spent_item { dap_chain_hash_fast_t tx_hash_fast; - dap_time_t spent_time; - char token_ticker[DAP_CHAIN_TICKER_SIZE_MAX]; + struct { + dap_time_t spent_time; + char token_ticker[DAP_CHAIN_TICKER_SIZE_MAX]; + char padding[22]; + dap_chain_hash_fast_t tx_hash_spent_fast; // spent outs list + } DAP_ALIGN_PACKED cache_data; UT_hash_handle hh; } dap_chain_ledger_tx_spent_item_t; @@ -159,7 +172,7 @@ typedef struct dap_chain_ledger_tokenizer { } dap_chain_ledger_tokenizer_t; typedef struct dap_chain_ledger_tx_bound { - dap_chain_hash_fast_t tx_prev_hash_fast; + dap_chain_hash_fast_t tx_prev_hash; dap_chain_datum_tx_t *tx_prev; union { dap_chain_tx_in_t *tx_cur_in; @@ -175,6 +188,7 @@ typedef struct dap_chain_ledger_tx_bound { union { dap_chain_ledger_tx_item_t *item_out; dap_chain_ledger_token_emission_item_t *item_emission; + dap_chain_ledger_stake_lock_item_t *stake_lock_item; }; } dap_chain_ledger_tx_bound_t; @@ -205,16 +219,15 @@ typedef struct dap_ledger_private { dap_chain_ledger_tx_item_t *ledger_items; dap_chain_ledger_tx_spent_item_t *spent_items; - dap_chain_ledger_token_item_t *tokens; - + dap_chain_ledger_stake_lock_item_t *emissions_for_stake_lock; dap_ledger_wallet_balance_t *balance_accounts; // for separate access to ledger pthread_rwlock_t ledger_rwlock; // for separate access to tokens pthread_rwlock_t tokens_rwlock; - + pthread_rwlock_t stake_lock_rwlock; pthread_rwlock_t threshold_txs_rwlock; pthread_rwlock_t threshold_emissions_rwlock; pthread_rwlock_t balance_accounts_rwlock; @@ -230,6 +243,7 @@ typedef struct dap_ledger_private { dap_chain_cell_id_t local_cell_id; bool load_mode; + bool cached; // TPS section dap_timerfd_t *tps_timer; struct timespec tps_start_time; @@ -247,6 +261,7 @@ static void s_threshold_txs_proc( dap_ledger_t * a_ledger); static int s_token_tsd_parse(dap_ledger_t * a_ledger, dap_chain_ledger_token_item_t *a_token_item , dap_chain_datum_token_t * a_token, size_t a_token_size); static int s_ledger_permissions_check(dap_chain_ledger_token_item_t * a_token_item, uint16_t a_permission_id, const void * a_data,size_t a_data_size ); static bool s_ledger_tps_callback(void *a_arg); +static int s_sort_ledger_tx_item(dap_chain_ledger_tx_item_t* a, dap_chain_ledger_tx_item_t* b); static inline int s_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash, bool a_from_threshold, bool a_safe_call); static int s_tx_add_unsafe(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash, bool a_from_threshold); @@ -256,14 +271,11 @@ static int s_token_emission_add_unsafe(dap_ledger_t *a_ledger, byte_t *a_token_e static inline int s_token_emission_add(dap_ledger_t *a_ledger, byte_t *a_token_emission, size_t a_token_emission_size, dap_hash_fast_t *a_emission_hash, bool a_from_threshold, bool a_safe_call); - - static size_t s_threshold_emissions_max = 1000; static size_t s_threshold_txs_max = 10000; static bool s_debug_more = false; struct json_object *wallet_info_json_collect(dap_ledger_t *a_ledger, dap_ledger_wallet_balance_t* a_bal); -static void wallet_info_notify(); /** * @brief dap_chain_ledger_init @@ -273,20 +285,8 @@ static void wallet_info_notify(); int dap_chain_ledger_init() { s_debug_more = dap_config_get_item_bool_default(g_config,"ledger","debug_more",false); - return 0; -} - -bool dap_chain_global_rwlocks_and_verificators_init(void) -{ pthread_rwlock_init(&s_verificators_rwlock, NULL); - pthread_rwlock_init(&s_emission_for_stake_lock_rwlock, NULL); - dap_chain_ledger_verificator_add(DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY, dap_chain_net_srv_pay_verificator, NULL); - dap_chain_ledger_verificator_add(DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE, dap_chain_ledger_fee_verificator, NULL); - dap_chain_ledger_verificator_add(DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE, dap_chain_net_srv_xchange_verificator, NULL); - dap_chain_ledger_verificator_add(DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE, dap_chain_net_srv_stake_pos_delegate_verificator, NULL); - dap_chain_ledger_verificator_add(DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE_UPDATE, dap_chain_net_srv_stake_updater, NULL); - dap_chain_ledger_verificator_add(DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK, s_callback_verificator, s_callback_verificator_added); - return true; + return 0; } /** @@ -301,6 +301,7 @@ void dap_chain_ledger_deinit() dap_chain_ledger_purge(l_net_list[i]->pub.ledger, true); } DAP_DELETE(l_net_list); + pthread_rwlock_destroy(&s_verificators_rwlock); } /** @@ -320,6 +321,7 @@ static dap_ledger_t * dap_chain_ledger_handle_new(void) pthread_rwlock_init(&l_ledger_pvt->threshold_txs_rwlock , NULL); pthread_rwlock_init(&l_ledger_pvt->threshold_emissions_rwlock , NULL); pthread_rwlock_init(&l_ledger_pvt->balance_accounts_rwlock , NULL); + pthread_rwlock_init(&l_ledger_pvt->stake_lock_rwlock, NULL); return l_ledger; } @@ -336,9 +338,10 @@ void dap_chain_ledger_handle_free(dap_ledger_t *a_ledger) // Destroy Read/Write Lock pthread_rwlock_destroy(&PVT(a_ledger)->ledger_rwlock); pthread_rwlock_destroy(&PVT(a_ledger)->tokens_rwlock); - pthread_rwlock_destroy(&PVT(a_ledger)->threshold_txs_rwlock ); - pthread_rwlock_destroy(&PVT(a_ledger)->threshold_emissions_rwlock ); - pthread_rwlock_destroy(&PVT(a_ledger)->balance_accounts_rwlock ); + pthread_rwlock_destroy(&PVT(a_ledger)->threshold_txs_rwlock); + pthread_rwlock_destroy(&PVT(a_ledger)->threshold_emissions_rwlock); + pthread_rwlock_destroy(&PVT(a_ledger)->balance_accounts_rwlock); + pthread_rwlock_destroy(&PVT(a_ledger)->stake_lock_rwlock); DAP_DELETE(PVT(a_ledger)); DAP_DELETE(a_ledger); @@ -377,6 +380,81 @@ struct json_object *wallet_info_json_collect(dap_ledger_t *a_ledger, dap_ledger_ return l_json; } +/** + * @brief s_chain_ledger_token_update_check + * @param a_cur_token_item + * @param a_token_update + * @param a_token_update_size + * @return true or false + */ +static bool s_ledger_token_update_check(dap_chain_ledger_token_item_t *a_cur_token_item, dap_chain_datum_token_t *a_token_update, size_t a_token_update_size) +{ + dap_sign_t **l_signs_upd_token; + size_t auth_signs_total = 0; + size_t auth_signs_valid = 0; + dap_chain_ledger_token_update_item_t *l_token_update_item; + dap_hash_fast_t l_hash_token_update; + + dap_hash_fast(a_token_update, a_token_update_size, &l_hash_token_update); + pthread_rwlock_rdlock(&a_cur_token_item->token_ts_updated_rwlock); + HASH_FIND(hh, a_cur_token_item->token_ts_updated, &l_hash_token_update, sizeof(dap_hash_fast_t), + l_token_update_item); + pthread_rwlock_unlock(&a_cur_token_item->token_ts_updated_rwlock); + if (l_token_update_item + && a_cur_token_item->last_update_token_time == l_token_update_item->updated_time) { + if (s_debug_more) + log_it(L_WARNING,"This upadate already applied for token with ticker '%s' ", a_token_update->ticker); + return false; + } + + /*if (a_cur_token_item->auth_signs_total != a_token_update->signs_total + || a_cur_token_item->auth_signs_valid != a_token_update->signs_valid) { + if(s_debug_more) + log_it(L_WARNING,"Can't update token with ticker '%s' because: " + "l_token_item auth signs total/valid == %lu/%lu | " + "token_update auth signs total/valid == %hu/%hu", + a_token_update->ticker, + a_cur_token_item->auth_signs_total, a_cur_token_item->auth_signs_valid, + a_token_update->signs_total, a_token_update->signs_valid); + return false; + }*/ + + l_signs_upd_token = dap_chain_datum_token_signs_parse(a_token_update, a_token_update_size, + &auth_signs_total, &auth_signs_valid); + if (a_cur_token_item->auth_signs_total != auth_signs_total + || a_cur_token_item->auth_signs_valid != auth_signs_valid) { + DAP_DEL_Z(l_signs_upd_token); + if(s_debug_more) + log_it(L_WARNING,"Can't update token with ticker '%s' because: " + "l_token_item auth signs total/valid == %lu/%lu | " + "token_update auth signs total/valid == %lu/%lu", + a_token_update->ticker, + a_cur_token_item->auth_signs_total, a_cur_token_item->auth_signs_valid, + auth_signs_total, auth_signs_valid); + return false; + } + if(auth_signs_total) { + for(uint16_t i = 0; i < auth_signs_total; i++){ + if (!dap_sign_match_pkey_signs(a_cur_token_item->auth_signs[i], l_signs_upd_token[i])) { + DAP_DEL_Z(l_signs_upd_token); + if(s_debug_more) + log_it(L_WARNING, "Can't update token with ticker '%s' because: Signs not compare", a_token_update->ticker); + return false; + } + } + } + DAP_DEL_Z(l_signs_upd_token); + if (!IS_ZERO_256(a_token_update->total_supply)){ + if (compare256(a_token_update->total_supply, a_cur_token_item->total_supply) < 0) {//compare old 'total_supply' to updated + if(s_debug_more) + log_it(L_WARNING, "Can't update token with ticker '%s' because: the new 'total_supply' cannot be smaller than the old one", a_token_update->ticker); + return false; + } + } + return true; +} + + /** * @brief dap_chain_ledger_token_check * @param a_ledger @@ -392,36 +470,51 @@ int dap_chain_ledger_token_decl_add_check(dap_ledger_t *a_ledger, dap_chain_datu return -1; } + bool update_token = false; dap_chain_ledger_token_item_t *l_token_item; pthread_rwlock_rdlock(&PVT(a_ledger)->tokens_rwlock); HASH_FIND_STR(PVT(a_ledger)->tokens, a_token->ticker, l_token_item); pthread_rwlock_unlock(&PVT(a_ledger)->tokens_rwlock); - if ( l_token_item != NULL ){ - log_it(L_WARNING,"Duplicate token declaration for ticker '%s' ", a_token->ticker); - return -3; + if (a_token->type == DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_UPDATE + || a_token->type == DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_UPDATE) + update_token = true; + + if (l_token_item != NULL) { + if (update_token == false) { + log_it(L_WARNING,"Duplicate token declaration for ticker '%s' ", a_token->ticker); + return -3; + } else if (s_ledger_token_update_check(l_token_item, a_token, a_token_size) == false) { + return -2; + } + } + else if (l_token_item == NULL && update_token == true) { + log_it(L_WARNING,"Can't update token that doesn't exist for ticker '%s' ", a_token->ticker); + return -6; } // Check signs -// dap_chain_datum_token_signs_parse(a_token, a_token_size, ) size_t l_signs_unique = 0; size_t l_size_tsd_section = 0; switch (a_token->type) { case DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL: - case DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL: l_size_tsd_section = a_token->header_native_decl.tsd_total_size; break; + case DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL: + l_size_tsd_section = a_token->header_private_decl.tsd_total_size; + break; + case DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_UPDATE: + l_size_tsd_section = a_token->header_native_update.tsd_total_size; + break; + case DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_UPDATE: + l_size_tsd_section = a_token->header_private_update.tsd_total_size; + break; } size_t l_signs_size = a_token_size - sizeof(dap_chain_datum_token_t) - l_size_tsd_section; dap_sign_t **l_signs = dap_sign_get_unique_signs(a_token->data_n_tsd + l_size_tsd_section, l_signs_size, &l_signs_unique); if (l_signs_unique == a_token->signs_total){ size_t l_signs_approve = 0; - for (size_t i=0; i < l_signs_unique; i++){ - dap_sign_t *l_sign = l_signs[i]; - if (dap_sign_verify_size(l_sign, l_signs_size)) { - if (dap_sign_verify(l_sign, a_token, sizeof(dap_chain_datum_token_t) - sizeof(uint16_t)) == 1) { - l_signs_approve++; - } - } - } + for (size_t i=0; i < l_signs_unique; i++) + if (!dap_sign_verify_all(l_signs[i], l_signs_size, a_token, sizeof(dap_chain_datum_token_t) - sizeof(uint16_t))) + l_signs_approve++; if (l_signs_approve == a_token->signs_total){ return 0; } else { @@ -464,7 +557,7 @@ dap_chain_datum_token_t *dap_chain_ledger_token_ticker_check(dap_ledger_t * a_le * @param a_ledger ledger object * @param l_token_item token item object */ -void s_update_token_cache(dap_ledger_t *a_ledger, dap_chain_ledger_token_item_t *l_token_item) +void s_ledger_token_cache_update(dap_ledger_t *a_ledger, dap_chain_ledger_token_item_t *l_token_item) { char *l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, DAP_CHAIN_LEDGER_TOKENS_STR); size_t l_cache_size = l_token_item->datum_token_size + sizeof(uint256_t); @@ -479,6 +572,63 @@ void s_update_token_cache(dap_ledger_t *a_ledger, dap_chain_ledger_token_item_t DAP_DELETE(l_gdb_group); } +/** + * @brief s_ledger_update_token_add_in_hash_table + * @param a_cur_token_item + * @param a_token_update + * @param a_token_update_size + * @return true or false + */ +static bool s_ledger_update_token_add_in_hash_table(dap_chain_ledger_token_item_t *a_cur_token_item, dap_chain_datum_token_t *a_token_update, size_t a_token_update_size) +{ + dap_chain_ledger_token_update_item_t *l_token_update_item; + dap_hash_fast_t l_hash_token_update; + bool new_item = false; + + dap_hash_fast(a_token_update, a_token_update_size, &l_hash_token_update); + pthread_rwlock_rdlock(&a_cur_token_item->token_ts_updated_rwlock); + HASH_FIND(hh, a_cur_token_item->token_ts_updated, &l_hash_token_update, sizeof(dap_hash_fast_t), + l_token_update_item); + pthread_rwlock_unlock(&a_cur_token_item->token_ts_updated_rwlock); + if (l_token_update_item + && a_cur_token_item->last_update_token_time == l_token_update_item->updated_time) { + if (s_debug_more) + log_it(L_WARNING, "Error: item 'dap_chain_ledger_token_update_item_t' already exist in hash-table"); + return false; + } else if (!l_token_update_item){ + new_item = true; + l_token_update_item = DAP_NEW(dap_chain_ledger_token_update_item_t); + if (!l_token_update_item) { + if (s_debug_more) + log_it(L_ERROR, "Error: memory allocation when try adding item 'dap_chain_ledger_token_update_item_t' to hash-table"); + return false; + } + *l_token_update_item = (dap_chain_ledger_token_update_item_t) { + .update_token_hash = l_hash_token_update, + .datum_token_update = a_token_update, + .datum_token_update_size = a_token_update_size + }; + } + + l_token_update_item->updated_time = dap_time_now(); + + if (new_item) { + pthread_rwlock_wrlock(&a_cur_token_item->token_ts_updated_rwlock); + HASH_ADD(hh, a_cur_token_item->token_ts_updated, update_token_hash, sizeof(dap_chain_hash_fast_t), l_token_update_item); + pthread_rwlock_unlock(&a_cur_token_item->token_ts_updated_rwlock); + } + + if (!l_token_update_item) { + if (s_debug_more) + log_it(L_ERROR, "Error: adding to hash-table. Be careful, there may be leaks"); + return false; + } + + a_cur_token_item->last_update_token_time = l_token_update_item->updated_time; + + return true; +} + /** * @brief dap_chain_ledger_token_add * @param a_token @@ -487,51 +637,81 @@ void s_update_token_cache(dap_ledger_t *a_ledger, dap_chain_ledger_token_item_t */ int dap_chain_ledger_token_add(dap_ledger_t *a_ledger, dap_chain_datum_token_t *a_token, size_t a_token_size) { - if ( !a_ledger){ - if(s_debug_more) - log_it(L_ERROR, "NULL ledger, can't add datum with token declaration!"); + if (!a_ledger) { + debug_if(s_debug_more, L_ERROR, "NULL ledger, can't add datum with token declaration!"); return -1; } + + bool update_token = false; + if (a_token->type == DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_UPDATE + || a_token->type == DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_UPDATE) + update_token = true; + + dap_chain_ledger_token_item_t * l_token_item; pthread_rwlock_rdlock(&PVT(a_ledger)->tokens_rwlock); HASH_FIND_STR(PVT(a_ledger)->tokens, a_token->ticker,l_token_item); pthread_rwlock_unlock(&PVT(a_ledger)->tokens_rwlock); - if (l_token_item) { - if(s_debug_more) + if (l_token_item != NULL) { + if (update_token == false) { log_it(L_WARNING,"Duplicate token declaration for ticker '%s' ", a_token->ticker); - return -3; + return -3; + } else if (s_ledger_token_update_check(l_token_item, a_token, a_token_size) == true) { + if (s_ledger_update_token_add_in_hash_table(l_token_item, a_token, a_token_size) == false) { + if (s_debug_more) + log_it(L_ERROR, "Failed to add ticker '%s' to hash-table", a_token->ticker); + return -5; + } + if (!IS_ZERO_256(a_token->total_supply)){ + SUBTRACT_256_256(l_token_item->total_supply, l_token_item->current_supply, &l_token_item->current_supply); + SUBTRACT_256_256(a_token->total_supply, l_token_item->current_supply, &l_token_item->current_supply); + } else { + l_token_item->current_supply = a_token->total_supply; + } + l_token_item->total_supply = a_token->total_supply; + DAP_DEL_Z(l_token_item->datum_token); + } else { + return -2; + } + } + else if (l_token_item == NULL && update_token == true) { + log_it(L_WARNING,"Can't update token that doesn't exist for ticker '%s' ", a_token->ticker); + return -6; } - - 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); dap_chain_datum_token_t *l_token = a_token->type == DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_SIMPLE ? - dap_chain_datum_token_read((byte_t *)a_token, &a_token_size) : a_token; - - l_token_item->datum_token_size = a_token_size; - l_token_item->type = a_token->type; - l_token_item->datum_token = DAP_DUP_SIZE(a_token, a_token_size); - l_token_item->total_supply = l_token->total_supply; - l_token_item->auth_signs_total = l_token->signs_total; - l_token_item->auth_signs_valid = l_token->signs_valid; - - l_token_item->auth_signs = dap_chain_datum_token_signs_parse(a_token, a_token_size, - &l_token_item->auth_signs_total, - &l_token_item->auth_signs_valid); - if(l_token_item->auth_signs_total) { - l_token_item->auth_signs_pkey_hash = DAP_NEW_Z_SIZE(dap_chain_hash_fast_t, sizeof(dap_chain_hash_fast_t) * l_token_item->auth_signs_total); - for(uint16_t k=0; k<l_token_item->auth_signs_total;k++){ - dap_sign_get_pkey_hash(l_token_item->auth_signs[k], &l_token_item->auth_signs_pkey_hash[k]); + dap_chain_datum_token_read((byte_t *)a_token, &a_token_size) : a_token; + + if (update_token == false) {//create new token + l_token_item = DAP_NEW_Z(dap_chain_ledger_token_item_t); + dap_snprintf(l_token_item->ticker,sizeof (l_token_item->ticker), "%s", l_token->ticker); + pthread_rwlock_init(&l_token_item->token_emissions_rwlock,NULL); + pthread_rwlock_init(&l_token_item->token_ts_updated_rwlock,NULL); + l_token_item->type = l_token->type; + l_token_item->total_supply = l_token->total_supply; + l_token_item->current_supply = l_token_item->total_supply; + l_token_item->auth_signs_total = l_token->signs_total; + l_token_item->auth_signs_valid = l_token->signs_valid; + l_token_item->auth_signs = dap_chain_datum_token_signs_parse(l_token, a_token_size, + &l_token_item->auth_signs_total,&l_token_item->auth_signs_valid); + if (l_token_item->auth_signs_total) { + l_token_item->auth_signs_pkey_hash = DAP_NEW_Z_SIZE(dap_chain_hash_fast_t, sizeof(dap_chain_hash_fast_t) * l_token_item->auth_signs_total); + for(uint16_t k=0; k<l_token_item->auth_signs_total;k++){ + dap_sign_get_pkey_hash(l_token_item->auth_signs[k], &l_token_item->auth_signs_pkey_hash[k]); + } } } - l_token_item->current_supply = l_token_item->total_supply; + l_token_item->datum_token_size = a_token_size; + l_token_item->datum_token = DAP_DUP_SIZE(l_token, a_token_size); + l_token_item->datum_token->type = l_token_item->type; - pthread_rwlock_wrlock(&PVT(a_ledger)->tokens_rwlock); - HASH_ADD_STR(PVT(a_ledger)->tokens, ticker, l_token_item); - pthread_rwlock_unlock(&PVT(a_ledger)->tokens_rwlock); + if (update_token == false) { + pthread_rwlock_wrlock(&PVT(a_ledger)->tokens_rwlock); + HASH_ADD_STR(PVT(a_ledger)->tokens, ticker, l_token_item); + pthread_rwlock_unlock(&PVT(a_ledger)->tokens_rwlock); + } int l_res_token_tsd_parse = 0; switch(a_token->type) { @@ -539,19 +719,19 @@ int dap_chain_ledger_token_add(dap_ledger_t *a_ledger, dap_chain_datum_token_t * case DAP_CHAIN_DATUM_TOKEN_TYPE_SIMPLE: if(s_debug_more) { char *l_balance = dap_chain_balance_to_coins(l_token->total_supply); - log_it(L_NOTICE, "Simple token %s added (total_supply = %s total_signs_valid=%hu signs_total=%hu type=DAP_CHAIN_DATUM_TOKEN_TYPE_SIMPLE )", + log_it(L_NOTICE, "Simple token %s added (total_supply = %s total_signs_valid=%hu signs_total=%hu)", l_token->ticker, l_balance, l_token->signs_valid, l_token->signs_total); - DAP_DELETE(l_balance); + DAP_DEL_Z(l_balance); } break; case DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL: if(s_debug_more) { char *l_balance = dap_chain_balance_to_coins(a_token->total_supply); - log_it(L_NOTICE, "Private token %s added (total_supply = %s total_signs_valid=%hu signs_total=%hu type=DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL)", + log_it(L_NOTICE, "Private token %s added (total_supply = %s total_signs_valid=%hu signs_total=%hu)", a_token->ticker, l_balance, a_token->signs_valid, a_token->signs_total); - DAP_DELETE(l_balance); + DAP_DEL_Z(l_balance); } l_res_token_tsd_parse = s_token_tsd_parse(a_ledger,l_token_item, a_token, a_token_size); break; @@ -566,11 +746,26 @@ int dap_chain_ledger_token_add(dap_ledger_t *a_ledger, dap_chain_datum_token_t * l_res_token_tsd_parse = s_token_tsd_parse(a_ledger,l_token_item, a_token, a_token_size); break; case DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_UPDATE: - if(s_debug_more) - log_it( L_WARNING, "Private token %s type=DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_UPDATE. Not processed, wait for software update", a_token->ticker); - // TODO: Check authorithy - //l_res_token_tsd_parse = s_token_tsd_parse(a_ledger,l_token_item, a_token, a_token_size); + if(s_debug_more) { + char *l_balance = dap_chain_balance_to_coins(a_token->total_supply); + log_it(L_NOTICE, "Private token %s updated (total_supply = %s total_signs_valid=%hu signs_total=%hu)", + a_token->ticker, l_balance, + a_token->signs_valid, a_token->signs_total); + DAP_DEL_Z(l_balance); + } + l_res_token_tsd_parse = s_token_tsd_parse(a_ledger,l_token_item, a_token, a_token_size); break; + case DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_UPDATE: + if(s_debug_more) { + char *l_balance = dap_chain_balance_to_coins(a_token->total_supply); + log_it(L_NOTICE, "CF20 token %s updated (total_supply = %s total_signs_valid=%hu signs_total=%hu)", + a_token->ticker, l_balance, + a_token->signs_valid, a_token->signs_total); + DAP_DEL_Z(l_balance); + } + l_res_token_tsd_parse = s_token_tsd_parse(a_ledger,l_token_item, a_token, a_token_size); + break; + default: if(s_debug_more) log_it(L_WARNING,"Unknown token declaration type 0x%04X", a_token->type ); @@ -582,7 +777,8 @@ int dap_chain_ledger_token_add(dap_ledger_t *a_ledger, dap_chain_datum_token_t * return -1; } s_threshold_emissions_proc(a_ledger); //TODO process thresholds only for no-consensus chains - s_update_token_cache(a_ledger, l_token_item); + if (PVT(a_ledger)->cached) + s_ledger_token_cache_update(a_ledger, l_token_item); if (a_token->type == DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_SIMPLE) DAP_DELETE(l_token); return 0; @@ -606,7 +802,7 @@ static int s_token_tsd_parse(dap_ledger_t * a_ledger, dap_chain_ledger_token_ite a_token_item->flags = a_token->header_native_decl.flags; for( size_t l_offset=0; l_offset < l_tsd_total_size; l_offset += l_tsd_size ){ - l_tsd = (dap_tsd_t *)(((byte_t*)l_tsd ) + l_tsd_size); + l_tsd = (dap_tsd_t *)(((byte_t *)l_tsd ) + l_tsd_size); l_tsd_size = l_tsd? dap_tsd_size(l_tsd): 0; if( l_tsd_size==0 ){ if(s_debug_more) @@ -1059,11 +1255,13 @@ dap_chain_net_t* dap_chain_ledger_get_net(dap_ledger_t* a_ledger) 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)->load_mode) { + bool l_update_token = (a_token->type != DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_UPDATE && + a_token->type != DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_UPDATE) ? false : true; dap_chain_ledger_token_item_t *l_token_item; pthread_rwlock_rdlock(&PVT(a_ledger)->tokens_rwlock); HASH_FIND_STR(PVT(a_ledger)->tokens, a_token->ticker, l_token_item); pthread_rwlock_unlock(&PVT(a_ledger)->tokens_rwlock); - if (l_token_item) + if (l_token_item && l_update_token == false) return 0; } return dap_chain_ledger_token_add(a_ledger, a_token, a_token_size); @@ -1159,13 +1357,11 @@ dap_string_t *dap_chain_ledger_threshold_hash_info(dap_ledger_t *a_ledger, dap_c dap_string_t *dap_chain_ledger_balance_info(dap_ledger_t *a_ledger) { dap_ledger_private_t *l_ledger_pvt = PVT(a_ledger); - dap_chain_ledger_tx_item_t *l_tx_item, *l_tx_tmp; dap_string_t *l_str_ret = dap_string_new(""); pthread_rwlock_rdlock(&l_ledger_pvt->balance_accounts_rwlock); uint32_t l_counter = 0; dap_ledger_wallet_balance_t *l_balance_item, *l_balance_tmp; - HASH_ITER(hh, l_ledger_pvt->balance_accounts, l_balance_item, l_balance_tmp){ - char l_time[1024] = {0}; + HASH_ITER(hh, l_ledger_pvt->balance_accounts, l_balance_item, l_balance_tmp) { //log_it(L_DEBUG,"Ledger balance key %s, token_ticker: %s, balance: %s", l_balance_key, l_balance_item->token_ticker, // dap_chain_balance_print(l_balance_item->balance)); dap_string_append(l_str_ret, "Ledger balance key: "); @@ -1193,11 +1389,12 @@ dap_string_t *dap_chain_ledger_balance_info(dap_ledger_t *a_ledger) dap_list_t *dap_chain_ledger_token_info(dap_ledger_t *a_ledger) { dap_list_t *l_ret_list = NULL; + dap_string_t *l_str_tmp = dap_string_new(""); dap_chain_ledger_token_item_t *l_token_item, *l_tmp_item; pthread_rwlock_rdlock(&PVT(a_ledger)->tokens_rwlock); HASH_ITER(hh, PVT(a_ledger)->tokens, l_token_item, l_tmp_item) { const char *l_type_str; - const char *l_flags_str = s_flag_str_from_code(l_token_item->datum_token->header_private_decl.flags);; + //const char *l_flags_str = s_flag_str_from_code(l_token_item->datum_token->header_private_decl.flags);; switch (l_token_item->type) { case DAP_CHAIN_DATUM_TOKEN_TYPE_SIMPLE: // 256 case DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_SIMPLE: @@ -1219,36 +1416,51 @@ dap_list_t *dap_chain_ledger_token_info(dap_ledger_t *a_ledger) char *l_item_str = NULL; if ((l_token_item->type == DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL) - || (l_token_item->type == DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_UPDATE)){ + || (l_token_item->type == DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_UPDATE) + || (l_token_item->type == DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL) + || (l_token_item->type == DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_UPDATE)) { char *l_balance_cur = dap_chain_balance_print(l_token_item->current_supply); char *l_balance_total = dap_chain_balance_print(l_token_item->total_supply); - l_item_str = dap_strdup_printf("Token name '%s', type %s, flags: %s\n" + s_datum_token_dump_tsd(l_str_tmp, l_token_item->datum_token, l_token_item->datum_token_size, "hex"); + size_t l_certs_field_size = l_token_item->datum_token_size - sizeof(*l_token_item->datum_token) - l_token_item->datum_token->header_native_decl.tsd_total_size; + dap_chain_datum_token_certs_dump(l_str_tmp, l_token_item->datum_token->data_n_tsd + l_token_item->datum_token->header_native_decl.tsd_total_size, + l_certs_field_size, "hex"); + l_item_str = dap_strdup_printf("-->Token name '%s', type %s, flags: %s\n" "\tSupply (current/total) %s/%s\n" "\tDecimals: 18\n" "\tAuth signs (valid/total) %zu/%zu\n" - "\tTotal emissions %u\n", - &l_token_item->ticker, l_type_str, s_flag_str_from_code(l_token_item->datum_token->header_private_decl.flags), - l_balance_cur, l_balance_total, l_token_item->auth_signs_valid, l_token_item->auth_signs_total, + "TSD and Signs:\n" + "%s" + "\tTotal emissions %u\n___\n", + &l_token_item->ticker, l_type_str, s_flag_str_from_code(l_token_item->datum_token->header_native_decl.flags), + l_balance_cur, l_balance_total, + l_token_item->auth_signs_valid, l_token_item->auth_signs_total, + l_str_tmp->str, HASH_COUNT(l_token_item->token_emissions)); DAP_DEL_Z(l_balance_cur); DAP_DEL_Z(l_balance_total); } else { char *l_balance_cur = dap_chain_balance_print(l_token_item->current_supply); char *l_balance_total = dap_chain_balance_print(l_token_item->total_supply); - l_item_str = dap_strdup_printf("Token name '%s', type %s, flags: %s\n" + size_t l_certs_field_size = l_token_item->datum_token_size - sizeof(*l_token_item->datum_token); + dap_chain_datum_token_certs_dump(l_str_tmp, l_token_item->datum_token->data_n_tsd, + l_certs_field_size, "hex"); + l_item_str = dap_strdup_printf("-->Token name '%s', type %s, flags: %s\n" "\tSupply (current/total) %s/%s\n" "\tDecimals: 18\n" "\tAuth signs (valid/total) %zu/%zu\n" - "\tTotal emissions %u\n", - &l_token_item->ticker, l_type_str, s_flag_str_from_code(l_token_item->datum_token->header_private_decl.flags), + "%s" + "\tTotal emissions %u\n___\n", + &l_token_item->ticker, l_type_str, "SIMPLE token has no flags", l_balance_cur, l_balance_total, l_token_item->auth_signs_valid, l_token_item->auth_signs_total, + l_str_tmp->str, HASH_COUNT(l_token_item->token_emissions)); DAP_DEL_Z(l_balance_cur); DAP_DEL_Z(l_balance_total); } - l_ret_list = dap_list_append(l_ret_list, l_item_str); + dap_string_free(l_str_tmp, true); } pthread_rwlock_unlock(&PVT(a_ledger)->tokens_rwlock); return l_ret_list; @@ -1375,14 +1587,7 @@ static bool s_load_cache_gdb_loaded_spent_txs_callback(dap_global_db_context_t * for (size_t i = 0; i < a_values_count; i++) { dap_chain_ledger_tx_spent_item_t *l_tx_spent_item = DAP_NEW_Z(dap_chain_ledger_tx_spent_item_t); dap_chain_hash_fast_from_str(a_values[i].key, &l_tx_spent_item->tx_hash_fast); - strncpy(l_tx_spent_item->token_ticker, (char *)a_values[i].value, - min(a_values[i].value_len, DAP_CHAIN_TICKER_SIZE_MAX - 1)); - size_t l_spent_time_len = 0; - byte_t* l_spent_time_data = dap_global_db_get_sync(DAP_CHAIN_LEDGER_SPENT_TXS_TIME_STR, a_values[i].key, &l_spent_time_len, NULL, NULL); - if (l_spent_time_data && l_spent_time_len == sizeof(dap_time_t)) { - l_tx_spent_item->spent_time = *(dap_time_t*)l_spent_time_data; - DAP_DELETE(l_spent_time_data); - } + l_tx_spent_item->cache_data = *(typeof(((dap_chain_ledger_tx_spent_item_t*)0)->cache_data)*)a_values[i].value; HASH_ADD(hh, l_ledger_pvt->spent_items, tx_hash_fast, sizeof(dap_chain_hash_fast_t), l_tx_spent_item); } @@ -1418,7 +1623,7 @@ static bool s_load_cache_gdb_loaded_txs_callback(dap_global_db_context_t * a_glo l_tx_item->tx = DAP_NEW_Z_SIZE(dap_chain_datum_tx_t, a_values[i].value_len - sizeof(l_tx_item->cache_data)); memcpy(&l_tx_item->cache_data, a_values[i].value, sizeof(l_tx_item->cache_data)); memcpy(l_tx_item->tx, a_values[i].value + sizeof(l_tx_item->cache_data), a_values[i].value_len - 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); + HASH_ADD_INORDER(hh, l_ledger_pvt->ledger_items, tx_hash_fast, sizeof(dap_chain_hash_fast_t), l_tx_item, s_sort_ledger_tx_item); } char *l_gdb_group = dap_chain_ledger_get_gdb_group(l_ledger, DAP_CHAIN_LEDGER_SPENT_TXS_STR); @@ -1427,6 +1632,34 @@ static bool s_load_cache_gdb_loaded_txs_callback(dap_global_db_context_t * a_glo return true; } +static bool s_load_cache_gdb_loaded_stake_lock_callback(dap_global_db_context_t * a_global_db_context,int a_rc, + const char * a_group, const char * a_key, + const size_t a_values_total, const size_t a_values_shift, + const size_t a_values_count, dap_global_db_obj_t * a_values, + void * a_arg) +{ + dap_ledger_t *l_ledger = (dap_ledger_t *) a_arg; + dap_ledger_private_t *l_ledger_pvt = PVT(l_ledger); + + for (size_t i = 0; i < a_values_count; i++) { + if (a_values[i].value_len != sizeof(dap_hash_fast_t)) + continue; + dap_chain_ledger_stake_lock_item_t *l_new_stake_lock_emission = DAP_NEW(dap_chain_ledger_stake_lock_item_t); + if (!l_new_stake_lock_emission) { + debug_if(s_debug_more, L_ERROR, "Error: memory allocation when try adding item 'dap_chain_ledger_stake_lock_item_t' to hash-table"); + continue; + } + dap_chain_hash_fast_from_str(a_values[i].key, &l_new_stake_lock_emission->tx_for_stake_lock_hash); + l_new_stake_lock_emission->tx_used_out = *(dap_hash_fast_t *)(a_values[i].value); + HASH_ADD(hh, l_ledger_pvt->emissions_for_stake_lock, tx_for_stake_lock_hash, sizeof(dap_chain_hash_fast_t), l_new_stake_lock_emission); + } + + char* l_gdb_group = dap_chain_ledger_get_gdb_group(l_ledger, DAP_CHAIN_LEDGER_TXS_STR); + dap_global_db_get_all(l_gdb_group,0, s_load_cache_gdb_loaded_txs_callback, l_ledger); + DAP_DELETE(l_gdb_group); + return true; +} + /** * @brief GDB callback for loaded emissions from cache @@ -1471,10 +1704,11 @@ static bool s_load_cache_gdb_loaded_emissions_callback(dap_global_db_context_t * sizeof(dap_chain_hash_fast_t), l_emission_item); } - char* l_gdb_group = dap_chain_ledger_get_gdb_group(l_ledger, DAP_CHAIN_LEDGER_TXS_STR); + char* l_gdb_group = dap_chain_ledger_get_gdb_group(l_ledger, DAP_CHAIN_LEDGER_STAKE_LOCK_STR); dap_global_db_get_all(l_gdb_group,0, s_load_cache_gdb_loaded_txs_callback, l_ledger); DAP_DELETE(l_gdb_group); return true; + } @@ -1579,13 +1813,17 @@ dap_ledger_t* dap_chain_ledger_create(uint16_t a_check_flags, char *a_net_name) l_ledger_priv->load_mode = true; l_ledger_priv->tps_timer = NULL; l_ledger_priv->tps_count = 0; -#ifdef DAP_CHAIN_LEDGER_TEST - if (dap_config_get_item_bool_default(g_config, "ledger", "cache_enabled", false)) { -#else + if (dap_config_get_item_bool_default(g_config, "ledger", "cache_enabled", true)) { + dap_chain_node_role_t l_role = dap_chain_net_get_role(l_ledger_priv->net); + if (l_role.enums != NODE_ROLE_MASTER && l_role.enums != NODE_ROLE_ROOT) { +#ifndef DAP_CHAIN_LEDGER_TEST + l_ledger_priv->cached = true; + // load ledger cache from GDB + dap_chain_ledger_load_cache(l_ledger); #endif - // load ledger cache from GDB - dap_chain_ledger_load_cache(l_ledger); + } + } return l_ledger; @@ -1661,9 +1899,9 @@ int dap_chain_ledger_token_emission_add_check(dap_ledger_t *a_ledger, byte_t *a_ } //additional check for private tokens - if ((l_token_item->type == DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL) - || (l_token_item->type == DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_UPDATE) - || (l_token_item->type == DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL) + if ((l_token_item->type == DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL) + || (l_token_item->type == DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_UPDATE) + || (l_token_item->type == DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL) || (l_token_item->type == DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_UPDATE)) { //s_ledger_permissions_check(l_token_item) // return -5; @@ -1766,6 +2004,19 @@ bool s_chain_ledger_token_tsd_check(dap_chain_ledger_token_item_t * a_token_item return true; } +static void s_ledger_emission_cache_update(dap_ledger_t *a_ledger, dap_chain_ledger_token_emission_item_t *a_emission_item) +{ + char *l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, DAP_CHAIN_LEDGER_EMISSIONS_STR); + size_t l_cache_size = a_emission_item->datum_token_emission_size + sizeof(dap_hash_fast_t); + uint8_t *l_cache = DAP_NEW_STACK_SIZE(uint8_t, l_cache_size); + memcpy(l_cache, &a_emission_item->tx_used_out, sizeof(dap_hash_fast_t)); + memcpy(l_cache + sizeof(dap_hash_fast_t), a_emission_item->datum_token_emission, a_emission_item->datum_token_emission_size); + char *l_hash_str = dap_hash_fast_to_str_new(&a_emission_item->datum_token_emission_hash); + if (!dap_global_db_set(l_gdb_group, l_hash_str, l_cache, l_cache_size, false, NULL, NULL)) { + log_it(L_WARNING, "Ledger cache mismatch"); + } + DAP_DELETE(l_gdb_group); +} /** * @brief dap_chain_ledger_token_emission_add @@ -1862,24 +2113,17 @@ static inline int s_token_emission_add(dap_ledger_t *a_ledger, byte_t *a_token_e DAP_DELETE(l_value); return -4; } - //update current_supply in ledger cache and ledger memory object - s_update_token_cache(a_ledger, l_token_item); + if (PVT(a_ledger)->cached) + s_ledger_token_cache_update(a_ledger, l_token_item); } pthread_rwlock_wrlock(&l_token_item->token_emissions_rwlock); HASH_ADD(hh, l_token_item->token_emissions, datum_token_emission_hash, sizeof(*a_emission_hash), l_token_emission_item); pthread_rwlock_unlock(&l_token_item->token_emissions_rwlock); - // Add it to cache - char *l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, DAP_CHAIN_LEDGER_EMISSIONS_STR); - size_t l_cache_size = a_token_emission_size + sizeof(dap_hash_fast_t); - uint8_t *l_cache = DAP_NEW_Z_SIZE(uint8_t, l_cache_size); - memcpy(l_cache + sizeof(dap_hash_fast_t), a_token_emission, a_token_emission_size); - if ( dap_global_db_set(l_gdb_group, l_hash_str, l_cache, l_cache_size, false, NULL, NULL ) ) { - log_it(L_WARNING, "Ledger cache mismatch"); - } - DAP_DELETE(l_cache); - DAP_DELETE(l_gdb_group); + if (PVT(a_ledger)->cached) + // Add it to cache + s_ledger_emission_cache_update(a_ledger, l_token_emission_item); if(s_debug_more) { char * l_token_emission_address_str = dap_chain_addr_to_str(&(l_token_emission_item->datum_token_emission->hdr.address)); char *l_balance = dap_chain_balance_to_coins(l_token_emission_item->datum_token_emission->hdr.value_256); @@ -1931,42 +2175,60 @@ static inline int s_token_emission_add(dap_ledger_t *a_ledger, byte_t *a_token_e return l_ret; } -dap_chain_ledger_token_emission_for_stake_lock_item_t *s_emission_for_stake_lock_item_add(dap_ledger_t *a_ledger, const dap_chain_hash_fast_t *a_token_emission_hash) +void s_ledger_stake_lock_cache_update(dap_ledger_t *a_ledger, dap_chain_ledger_stake_lock_item_t *a_stake_lock_item) +{ + char *l_hash_str = dap_chain_hash_fast_to_str_new(&a_stake_lock_item->tx_for_stake_lock_hash); + char *l_group = dap_chain_ledger_get_gdb_group(a_ledger, DAP_CHAIN_LEDGER_STAKE_LOCK_STR); + if (!dap_global_db_set(l_group, l_hash_str, &a_stake_lock_item->tx_used_out, sizeof(dap_hash_fast_t), false, NULL, NULL)) + log_it(L_WARNING, "Ledger cache mismatch"); + DAP_DEL_Z(l_hash_str); + DAP_DEL_Z(l_group); +} + +int dap_chain_ledger_emission_for_stake_lock_item_add(dap_ledger_t *a_ledger, const dap_chain_hash_fast_t *a_tx_hash) { dap_ledger_private_t *l_ledger_priv = PVT(a_ledger); - dap_chain_ledger_token_emission_for_stake_lock_item_t *l_new_stake_lock_emission; - pthread_rwlock_rdlock(&s_emission_for_stake_lock_rwlock); - HASH_FIND(hh, s_emission_for_stake_lock, a_token_emission_hash, sizeof(dap_hash_fast_t), + dap_chain_ledger_stake_lock_item_t *l_new_stake_lock_emission; + pthread_rwlock_rdlock(&l_ledger_priv->stake_lock_rwlock); + HASH_FIND(hh, l_ledger_priv->emissions_for_stake_lock, a_tx_hash, sizeof(dap_hash_fast_t), l_new_stake_lock_emission); - pthread_rwlock_unlock(&s_emission_for_stake_lock_rwlock); + pthread_rwlock_unlock(&l_ledger_priv->stake_lock_rwlock); if (l_new_stake_lock_emission) { - return l_new_stake_lock_emission; + return -1; } - l_new_stake_lock_emission = DAP_NEW(dap_chain_ledger_token_emission_for_stake_lock_item_t); - l_new_stake_lock_emission->datum_token_emission_for_stake_lock_hash = *a_token_emission_hash; - l_new_stake_lock_emission->tx_used_out = (dap_chain_hash_fast_t){ 0 }; - pthread_rwlock_wrlock(&s_emission_for_stake_lock_rwlock); - HASH_ADD(hh, s_emission_for_stake_lock, datum_token_emission_for_stake_lock_hash, sizeof(dap_chain_hash_fast_t), l_new_stake_lock_emission); - pthread_rwlock_unlock(&s_emission_for_stake_lock_rwlock); - - if (!l_new_stake_lock_emission - && s_debug_more) { - log_it(L_ERROR, "Error: memory allocation when adding item 'dap_chain_ledger_token_emission_for_stake_lock_item_t' to hash-table"); + l_new_stake_lock_emission = DAP_NEW_Z(dap_chain_ledger_stake_lock_item_t); + if (!l_new_stake_lock_emission) { + if (s_debug_more) { + log_it(L_ERROR, "Error: memory allocation when try adding item 'dap_chain_ledger_stake_lock_item_t' to hash-table"); + } + return -13; } - return l_new_stake_lock_emission; + l_new_stake_lock_emission->tx_for_stake_lock_hash = *a_tx_hash; + pthread_rwlock_wrlock(&l_ledger_priv->stake_lock_rwlock); + HASH_ADD(hh, l_ledger_priv->emissions_for_stake_lock, tx_for_stake_lock_hash, sizeof(dap_chain_hash_fast_t), l_new_stake_lock_emission); + pthread_rwlock_unlock(&l_ledger_priv->stake_lock_rwlock); + + if (!l_new_stake_lock_emission) + debug_if(s_debug_more, L_ERROR, "Error: adding to hash-table. Be careful, there may be leaks"); + else if (PVT(a_ledger)->cached) + s_ledger_stake_lock_cache_update(a_ledger, l_new_stake_lock_emission); + + return 0; + } -dap_chain_ledger_token_emission_for_stake_lock_item_t *s_emission_for_stake_lock_item_find(dap_ledger_t *a_ledger, const dap_chain_hash_fast_t *a_token_emission_hash) +dap_chain_ledger_stake_lock_item_t *s_emissions_for_stake_lock_item_find(dap_ledger_t *a_ledger, const dap_chain_hash_fast_t *a_token_emission_hash) { dap_ledger_private_t *l_ledger_priv = PVT(a_ledger); - dap_chain_ledger_token_emission_for_stake_lock_item_t *l_new_stake_lock_emission; - pthread_rwlock_rdlock(&s_emission_for_stake_lock_rwlock); - HASH_FIND(hh, s_emission_for_stake_lock, a_token_emission_hash, sizeof(dap_chain_hash_fast_t), + dap_chain_ledger_stake_lock_item_t *l_new_stake_lock_emission; + pthread_rwlock_rdlock(&l_ledger_priv->stake_lock_rwlock); + HASH_FIND(hh, l_ledger_priv->emissions_for_stake_lock, a_token_emission_hash, sizeof(dap_chain_hash_fast_t), l_new_stake_lock_emission); - pthread_rwlock_unlock(&s_emission_for_stake_lock_rwlock); + pthread_rwlock_unlock(&l_ledger_priv->stake_lock_rwlock); return l_new_stake_lock_emission; } + int dap_chain_ledger_token_emission_load(dap_ledger_t *a_ledger, byte_t *a_token_emission, size_t a_token_emission_size) { dap_chain_hash_fast_t l_token_emission_hash = {}; @@ -2065,7 +2327,7 @@ const char* dap_chain_ledger_tx_get_token_ticker_by_hash(dap_ledger_t *a_ledger, dap_chain_ledger_tx_spent_item_t *l_spent_item; HASH_FIND_BYHASHVALUE(hh, l_ledger_priv->spent_items, a_tx_hash, sizeof(*a_tx_hash), l_hash_value, l_spent_item); pthread_rwlock_unlock(&l_ledger_priv->ledger_rwlock); - return l_spent_item ? l_spent_item->token_ticker : NULL; + return l_spent_item ? l_spent_item->cache_data.token_ticker : NULL; } @@ -2216,6 +2478,50 @@ bool dap_chain_ledger_tx_spent_find_by_hash(dap_ledger_t *a_ledger, dap_chain_ha return l_tx_item; } +dap_hash_fast_t *dap_chain_ledger_get_final_chain_tx_hash(dap_ledger_t *a_ledger, dap_chain_tx_item_type_t a_cond_type, dap_chain_hash_fast_t *a_tx_hash) +{ + if(!a_ledger || !a_tx_hash || dap_hash_fast_is_blank(a_tx_hash)) + return NULL; + dap_ledger_private_t *l_ledger_priv = PVT(a_ledger); + dap_chain_ledger_tx_item_t *l_item; + unsigned l_hash_value; + dap_chain_hash_fast_t *l_tx_hash = a_tx_hash; + pthread_rwlock_rdlock(&l_ledger_priv->ledger_rwlock); + while (l_tx_hash) { + HASH_VALUE(l_tx_hash, sizeof(*l_tx_hash), l_hash_value); + HASH_FIND_BYHASHVALUE(hh, l_ledger_priv->ledger_items, l_tx_hash, sizeof(*l_tx_hash), l_hash_value, l_item); + if (l_item) { + int l_out_num = -1; + dap_chain_datum_tx_out_cond_get(l_item->tx, a_cond_type, &l_out_num); + if (l_out_num != -1 && l_out_num < MAX_OUT_ITEMS) { + if (dap_hash_fast_is_blank(&l_item->cache_data.tx_hash_spent_fast[l_out_num])) + break; // We have unused conditional output + else { + l_tx_hash = &l_item->cache_data.tx_hash_spent_fast[l_out_num]; + continue; // Conditional output is used out + } + } else { // No conditional output found + l_tx_hash = NULL; + break; + } + } + dap_chain_ledger_tx_spent_item_t *l_spent_item; + HASH_FIND_BYHASHVALUE(hh, l_ledger_priv->spent_items, l_tx_hash, sizeof(*l_tx_hash), l_hash_value, l_spent_item); + if (l_spent_item) { + l_tx_hash = &l_spent_item->cache_data.tx_hash_spent_fast; + if (dap_hash_fast_is_blank(l_tx_hash)) + break; // We have no condional outpul with spent item + } else { + l_tx_hash = NULL; // We can't find pointed hash in the ledger + break; + } + } + pthread_rwlock_unlock(&l_ledger_priv->ledger_rwlock); + if (l_tx_hash && !dap_hash_fast_is_blank(l_tx_hash)) + return l_tx_hash; + return NULL; +} + /** * Check whether used 'out' items (local function) */ @@ -2228,7 +2534,7 @@ static bool dap_chain_ledger_item_is_used_out(dap_chain_ledger_tx_item_t *a_item } if(a_idx_out >= MAX_OUT_ITEMS) { if(s_debug_more) - log_it(L_ERROR, "Too big index(%d) of 'out'items (max=%d)", a_idx_out, MAX_OUT_ITEMS); + log_it(L_ERROR, "Too big index(%d) of 'out' items (max=%d)", a_idx_out, MAX_OUT_ITEMS); } assert(a_idx_out < MAX_OUT_ITEMS); // if there are used 'out' items @@ -2290,7 +2596,6 @@ static int s_ledger_permissions_check(dap_chain_ledger_token_item_t * a_token_i */ bool s_tx_match_sign(dap_chain_datum_token_emission_t *a_datum_emission, dap_chain_datum_tx_t *a_tx) { - bool l_ret_value = false; if(!a_datum_emission || !a_tx) { return false; } @@ -2342,77 +2647,45 @@ bool s_tx_match_sign(dap_chain_datum_token_emission_t *a_datum_emission, dap_cha return false; } -static int s_check_out_cond_verificator_added(dap_ledger_t* a_ledger, dap_chain_datum_tx_t* a_tx, dap_list_t* a_list_tx_out_cond) -{ - for (dap_list_t* list_tmp = a_list_tx_out_cond; list_tmp; list_tmp = dap_list_next(list_tmp)) { - - dap_chain_tx_out_cond_t* l_tx_out = (dap_chain_tx_out_cond_t*)a_list_tx_out_cond->data; - - // Check for add out callback - dap_chain_ledger_verificator_t* l_verificator; - int l_tmp = l_tx_out->header.subtype; - - pthread_rwlock_rdlock(&s_verificators_rwlock); - HASH_FIND_INT(s_verificators, &l_tmp, l_verificator); - pthread_rwlock_unlock(&s_verificators_rwlock); - - if (!l_verificator) { - if (s_debug_more) - log_it(L_ERROR, "No verificator set for conditional output subtype %d", l_tmp); - return -13; - } - else if (l_verificator->callback_added && l_verificator->callback_added(a_ledger, a_tx, l_tx_out) == false) - return -14; - - /* - TODO: use this code when issuing for special emission-transactions is approved. needed for smart contracts in the future - - dap_ledger_private_t *l_ledger_priv = PVT(a_ledger); - dap_chain_ledger_token_item_t * l_token_item = NULL; - pthread_rwlock_rdlock(&l_ledger_priv->tokens_rwlock); - HASH_FIND_STR(l_ledger_priv->tokens, a_token_ticker, l_token_item); - pthread_rwlock_unlock(&l_ledger_priv->tokens_rwlock); - - if (!l_token_item) - return NULL; - dap_chain_ledger_token_emission_item_t * l_token_emission_item = NULL; - pthread_rwlock_rdlock(&l_token_item->token_emissions_rwlock); - HASH_FIND(hh, l_token_item->token_emissions, a_token_emission_hash, sizeof(*a_token_emission_hash), - l_token_emission_item); - pthread_rwlock_unlock(&l_token_item->token_emissions_rwlock); - return l_token_emission_item; - */ - - } - return 0; -} - /** * Checking a new transaction before adding to the cache * * return 1 OK, -1 error */ // Checking a new transaction before adding to the cache -int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, - bool a_from_threshold, dap_list_t **a_list_bound_items, dap_list_t **a_list_tx_out) +int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash, + bool a_from_threshold, dap_list_t **a_list_bound_items, dap_list_t **a_list_tx_out) { - /* - Steps of checking for current transaction tx2 and every previous transaction tx1: - 1. !is_used_out(tx1.dap_chain_datum_tx_out) - && - 2. valid(tx2.dap_chain_datum_tx_sig.pkey) - && - 3. hash(tx1) == tx2.dap_chain_datump_tx_in.tx_prev_hash - && - 4. tx1.dap_chain_datum_tx_out.addr.data.key == tx2.dap_chain_datum_tx_sig.pkey for unconditional output - \\ - 5a. tx1.dap_chain_datum_tx_sig.pkey == tx2.dap_chain_datum_tx_sig.pkey for conditional owner - \\ - 5b. tx1.dap_chain_datum_tx_out.condition == verify_svc_type(tx2) for conditional output - && - 6. sum( find (tx2.input.tx_prev_hash).output[tx2.input_tx_prev_idx].value ) == sum (tx2.outputs.value) per token - */ - + if (!PVT(a_ledger)->load_mode && !a_from_threshold) { + dap_chain_ledger_tx_item_t *l_ledger_item; + pthread_rwlock_rdlock(&PVT(a_ledger)->ledger_rwlock); + HASH_FIND(hh, PVT(a_ledger)->ledger_items, a_tx_hash, sizeof(dap_chain_hash_fast_t), l_ledger_item); + pthread_rwlock_unlock(&PVT(a_ledger)->ledger_rwlock); + if (l_ledger_item) { // transaction already present in the cache list + if (s_debug_more) { + char l_tx_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE]; + dap_chain_hash_fast_to_str(a_tx_hash, l_tx_hash_str, sizeof(l_tx_hash_str)); + log_it(L_WARNING, "Transaction %s already present in the cache", l_tx_hash_str); + } + return -1; + } + } +/* + * Steps of checking for current transaction tx2 and every previous transaction tx1: + * 1. valid(tx2.dap_chain_datum_tx_sig.pkey) + * && + * 2. !is_used_out(tx1.dap_chain_datum_tx_out) + * && + * 3. tx1.output != tx2.bound_items.outputs.used + * && + * 4. tx1.dap_chain_datum_tx_out.addr.data.key == tx2.dap_chain_datum_tx_sig.pkey for unconditional output + * \\ + * 5. tx1.dap_chain_datum_tx_out.condition == verify_svc_type(tx2) for conditional output + * && + * 6. sum( find (tx2.input.tx_prev_hash).output[tx2.input_tx_prev_idx].value ) == sum (tx2.outputs.value) per token + * && + * 7. valid(fee) +*/ dap_ledger_private_t *l_ledger_priv = PVT(a_ledger); if(!a_tx){ log_it(L_DEBUG, "NULL transaction, check broken"); @@ -2430,7 +2703,7 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t // sum of values in 'out' items from the previous transactions dap_chain_ledger_tokenizer_t *l_values_from_prev_tx = NULL, *l_values_from_cur_tx = NULL, *l_value_cur = NULL, *l_tmp = NULL, *l_res = NULL; - char *l_token = NULL; + char *l_token = NULL, *l_main_ticker = NULL; dap_chain_ledger_token_item_t * l_token_item = NULL; dap_chain_hash_fast_t *l_emission_hash = NULL; @@ -2438,24 +2711,22 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t int l_err_num = 0; int l_prev_tx_count = 0; + // 1. Verify signature in current transaction + if (!a_from_threshold && dap_chain_datum_tx_verify_sign(a_tx) != 1) + return -2; + // ---------------------------------------------------------------- - // find all 'in' items in current transaction - dap_list_t *l_list_in = dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_IN, - &l_prev_tx_count); - // find all conditional 'in' items in current transaction - dap_list_t *l_list_tmp = dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_IN_COND, + // find all 'in' & conditional 'in' items in current transaction + dap_list_t *l_list_in = dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_IN_ALL, &l_prev_tx_count); - if (l_list_tmp) { - // add conditional input to common list - l_list_in = dap_list_concat(l_list_in, l_list_tmp); - } - l_list_tmp = l_list_in; if (!l_list_in) { log_it(L_WARNING, "Tx check: no valid inputs found"); return -22; } dap_chain_ledger_tx_bound_t *bound_item; + dap_chain_hash_fast_t l_hash_pkey = {}; // find all previous transactions + dap_list_t *l_list_tmp = l_list_in; for (int l_list_tmp_num = 0; l_list_tmp; l_list_tmp = dap_list_next(l_list_tmp), l_list_tmp_num++) { bound_item = DAP_NEW_Z(dap_chain_ledger_tx_bound_t); dap_chain_tx_in_t *l_tx_in = NULL; @@ -2473,13 +2744,12 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t l_tx_prev_hash = l_tx_in_cond->header.tx_prev_hash; bound_item->in.tx_cur_in_cond = l_tx_in_cond; } - bound_item->tx_prev_hash_fast = l_tx_prev_hash; + bound_item->tx_prev_hash = l_tx_prev_hash; bool l_is_blank = dap_hash_fast_is_blank(&l_tx_prev_hash); char l_tx_prev_hash_str[70]={[0]='\0'}; if (l_is_blank){ - if(s_debug_more) - log_it(L_DEBUG, "Tx check: blank prev hash "); + debug_if(s_debug_more && !a_from_threshold, L_DEBUG, "Tx check: blank prev hash"); dap_snprintf(l_tx_prev_hash_str,sizeof( l_tx_prev_hash_str),"BLANK"); }else{ dap_chain_hash_fast_to_str(&l_tx_prev_hash,l_tx_prev_hash_str,sizeof(l_tx_prev_hash_str)); @@ -2501,20 +2771,22 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t l_token = l_tx_token->header.ticker; l_emission_hash = &l_tx_token->header.token_emission_hash; dap_chain_ledger_token_emission_item_t *l_emission_item = s_emission_item_find(a_ledger, l_token, l_emission_hash); - dap_chain_ledger_token_emission_for_stake_lock_item_t *stake_lock_emission = s_emission_for_stake_lock_item_find(a_ledger, l_emission_hash); + dap_chain_ledger_stake_lock_item_t *stake_lock_emission = s_emissions_for_stake_lock_item_find(a_ledger, l_emission_hash); if (!l_emission_item && stake_lock_emission) {//check emission for STAKE_LOCK dap_hash_fast_t cur_tx_hash; dap_hash_fast(a_tx, dap_chain_datum_tx_get_size(a_tx), &cur_tx_hash); - if (!dap_hash_fast_is_blank(&stake_lock_emission->tx_used_out) - && !dap_hash_fast_compare(&cur_tx_hash, &stake_lock_emission->tx_used_out)) { - debug_if(s_debug_more, L_WARNING, "stake_lock_emission is used out for tx_token [%s]", l_token); + if (!dap_hash_fast_is_blank(&stake_lock_emission->tx_used_out)) { + if (!dap_hash_fast_compare(&cur_tx_hash, &stake_lock_emission->tx_used_out)) + debug_if(s_debug_more, L_WARNING, "stake_lock_emission already present in cache for tx_token [%s]", l_token); + else + debug_if(s_debug_more, L_WARNING, "stake_lock_emission is used out for tx_token [%s]", l_token); l_err_num = -22; break; } dap_tsd_t *l_tsd; dap_chain_datum_token_t *l_datum_token = dap_chain_ledger_token_ticker_check(a_ledger, l_token); if (l_datum_token - && l_datum_token->type == DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL + && (l_datum_token->type == DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL || l_datum_token->type == DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_UPDATE) && l_datum_token->header_native_decl.tsd_total_size && NULL != (l_tsd = dap_tsd_find(l_datum_token->data_n_tsd, l_datum_token->header_native_decl.tsd_total_size, DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DELEGATE_EMISSION_FROM_STAKE_LOCK))) { dap_chain_datum_token_tsd_delegate_from_stake_lock_t l_tsd_section = dap_tsd_get_scalar(l_tsd, dap_chain_datum_token_tsd_delegate_from_stake_lock_t); @@ -2531,10 +2803,15 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t break; } dap_chain_datum_tx_t *l_tx_stake_lock = dap_chain_ledger_tx_find_by_hash(a_ledger, l_emission_hash); + if (!l_tx_stake_lock) { + debug_if(s_debug_more, L_WARNING, "Not found stake_lock transaction"); + l_err_num = DAP_CHAIN_CS_VERIFY_CODE_TX_NO_EMISSION; + break; + } dap_chain_tx_out_cond_t *l_tx_stake_lock_out_cond = (dap_chain_tx_out_cond_t*)dap_chain_datum_tx_item_get(l_tx_stake_lock, 0, TX_ITEM_TYPE_OUT_COND, 0);//TODO: ADD CHECK COUNT TX if (!l_tx_stake_lock_out_cond) { debug_if(s_debug_more, L_WARNING, "No OUT_COND to for tx_token [%s]", l_tx_token->header.ticker); - l_err_num = -30; + l_err_num = -32; break; } if (l_tx_stake_lock_out_cond->header.subtype != DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK) { @@ -2555,7 +2832,27 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t l_err_num = -26; break; } - + l_token_item = NULL; + pthread_rwlock_rdlock(&l_ledger_priv->tokens_rwlock); + HASH_FIND_STR(l_ledger_priv->tokens, l_token, l_token_item); + pthread_rwlock_unlock(&l_ledger_priv->tokens_rwlock); + if (!l_token_item){ + if(s_debug_more) + log_it(L_WARNING, "No token item found for token %s", l_token); + l_err_num = -15; + break; + } + if (!IS_ZERO_256(l_token_item->total_supply) && + compare256(l_token_item->current_supply, l_tx_out->header.value) < 0) { + char *l_balance = dap_chain_balance_print(l_token_item->current_supply); + char *l_value = dap_chain_balance_print(l_tx_out->header.value); + log_it(L_WARNING, "Token current supply %s lower, than emission value = %s", + l_balance, l_value); + DAP_DEL_Z(l_balance); + DAP_DEL_Z(l_value); + l_err_num = -30; + break; + } if (!EQUAL_256(l_value_expected, l_tx_out->header.value)) { char * l_value_expected_str = dap_chain_balance_print(l_value_expected); char * l_locked_value_str = dap_chain_balance_print(l_tx_out->header.value); @@ -2571,54 +2868,19 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t // check tiker const char *tx_tiker = dap_chain_ledger_tx_get_token_ticker_by_hash(a_ledger, l_emission_hash); if (!tx_tiker) { - debug_if(s_debug_more, L_WARNING, "No tiker stake_lock to for tx_token [%s]", l_tx_token->header.ticker); + debug_if(s_debug_more, L_WARNING, "No ticker stake_lock to for tx_token [%s]", l_tx_token->header.ticker); l_err_num = -33; break; } if (strcmp(tx_tiker, l_tsd_section.ticker_token_from)) { - debug_if(s_debug_more, L_WARNING, "Tikers not equal for [%s]", l_tx_token->header.ticker); + debug_if(s_debug_more, L_WARNING, "Tickers not equal for [%s]", l_tx_token->header.ticker); l_err_num = -35; break; } - - //Update value in ledger memory object - if (dap_hash_fast_is_blank(&stake_lock_emission->tx_used_out)) { - l_token_item = NULL; - pthread_rwlock_rdlock(&l_ledger_priv->tokens_rwlock); - HASH_FIND_STR(l_ledger_priv->tokens, l_token, l_token_item); - pthread_rwlock_unlock(&l_ledger_priv->tokens_rwlock); - if (!l_token_item){ - if(s_debug_more) - log_it(L_WARNING, "No token item found for token %s", l_token); - l_err_num = -15; - break; - } - if (!IS_ZERO_256(l_token_item->total_supply)) { - if (compare256(l_token_item->current_supply, l_tx_out->header.value) >= 0){ - SUBTRACT_256_256(l_token_item->current_supply, l_tx_out->header.value, &l_token_item->current_supply); - char *l_balance = dap_chain_balance_print(l_token_item->current_supply); - log_it(L_DEBUG, "New current supply %s for token %s", l_balance, l_token_item->ticker); - DAP_DEL_Z(l_balance); - } else { - char *l_balance = dap_chain_balance_print(l_token_item->current_supply); - char *l_value = dap_chain_balance_print(l_tx_out->header.value); - log_it(L_WARNING, "Token current supply %s lower, than emission value = %s", - l_balance, l_value); - DAP_DEL_Z(l_balance); - DAP_DEL_Z(l_value); - l_err_num = -30; - break; - } - stake_lock_emission->tx_used_out = cur_tx_hash; - //update current_supply in ledger cache and ledger memory object - s_update_token_cache(a_ledger, l_token_item); - } else { - log_it(L_DEBUG, "Total supply for token %s not found", l_token_item->ticker); - l_err_num = -32; - break; - } - } debug_if(s_debug_more, L_NOTICE, "Check emission passed for tx_token [%s]", l_tx_token->header.ticker); + bound_item->tx_prev = l_tx_stake_lock; + bound_item->stake_lock_item = stake_lock_emission; + l_list_bound_items = dap_list_append(l_list_bound_items, bound_item); break; } else { debug_if(s_debug_more, L_WARNING, "tx_token [%s] not valid for stake_lock transaction", l_token); @@ -2627,7 +2889,7 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t } } if (!l_emission_item) { - debug_if(s_debug_more, L_WARNING, "Emission for tx_token [%s] wasn't found", l_tx_token->header.ticker); + debug_if(s_debug_more && !a_from_threshold, L_WARNING, "Emission for tx_token [%s] wasn't found", l_tx_token->header.ticker); l_err_num = DAP_CHAIN_CS_VERIFY_CODE_TX_NO_EMISSION; break; } @@ -2668,12 +2930,9 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t } // Get previous transaction in the cache by hash dap_chain_ledger_tx_item_t *l_item_out = NULL; - dap_chain_datum_tx_t *l_tx_prev = - s_find_datum_tx_by_hash(a_ledger, &l_tx_prev_hash, &l_item_out); // dap_chain_datum_tx_t *l_tx_prev = (dap_chain_datum_tx_t*) dap_chain_node_datum_tx_cache_find(&tx_prev_hash); - bound_item->item_out = l_item_out; - if(!l_tx_prev) { // Unchained transaction - if (s_debug_more && !a_from_threshold) - log_it(L_DEBUG, "No previous transaction was found for hash %s", l_tx_prev_hash_str); + dap_chain_datum_tx_t *l_tx_prev = s_find_datum_tx_by_hash(a_ledger, &l_tx_prev_hash, &l_item_out); + if (!l_tx_prev) { // Unchained transaction + debug_if(s_debug_more && !a_from_threshold, L_DEBUG, "No previous transaction was found for hash %s", l_tx_prev_hash_str); l_err_num = DAP_CHAIN_CS_VERIFY_CODE_TX_NO_PREVIOUS; break; } @@ -2681,54 +2940,54 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t log_it(L_INFO,"Previous transaction was found for hash %s",l_tx_prev_hash_str); bound_item->tx_prev = l_tx_prev; - // 1. Check if out in previous transaction has spent + // 2. Check if out in previous transaction has spent int l_idx = (l_cond_type == TX_ITEM_TYPE_IN) ? l_tx_in->header.tx_out_prev_idx : l_tx_in_cond->header.tx_out_prev_idx; if (dap_chain_ledger_item_is_used_out(l_item_out, l_idx)) { l_err_num = -6; break; } - // 2. Verify signature in current transaction - if(dap_chain_datum_tx_verify_sign(a_tx) != 1) { - l_err_num = -2; - break; - } - - // 3. Compare hash in previous transaction with hash inside 'in' item - // calculate hash of previous transaction anew - dap_chain_hash_fast_t *l_hash_prev = dap_chain_node_datum_tx_calc_hash(l_tx_prev); - int l_res_hash = dap_hash_fast_compare(l_hash_prev, &l_tx_prev_hash); - - DAP_DELETE(l_hash_prev); - if (l_res_hash != 1) { - l_err_num = -7; - break; - } - uint256_t l_value; - // Get list of all 'out' items from previous transaction - dap_list_t *l_list_prev_out = dap_chain_datum_tx_items_get(l_tx_prev, TX_ITEM_TYPE_OUT_ALL, NULL); // Get one 'out' item in previous transaction bound with current 'in' item - void *l_tx_prev_out = dap_list_nth_data(l_list_prev_out, l_idx); - dap_list_free(l_list_prev_out); + void *l_tx_prev_out = dap_chain_datum_tx_item_get_nth(l_tx_prev, TX_ITEM_TYPE_OUT_ALL, l_idx); if(!l_tx_prev_out) { l_err_num = -8; break; } + // 3. Compare out in previous transaction with currently used out + for (dap_list_t *it = l_list_bound_items; it; it = it->next) { + dap_chain_ledger_tx_bound_t *l_bound_tmp = it->data; + if (l_tx_prev_out == l_bound_tmp->out.tx_prev_out) { + debug_if(s_debug_more, L_ERROR, "Previous transaction output already used in current tx"); + l_err_num = -7; + break; + } + } + if (l_err_num) + break; + if (l_cond_type == TX_ITEM_TYPE_IN) { dap_chain_tx_item_type_t l_type = *(uint8_t *)l_tx_prev_out; + dap_hash_fast_t *l_prev_out_addr_key = NULL; switch (l_type) { case TX_ITEM_TYPE_OUT_OLD: bound_item->out.tx_prev_out = l_tx_prev_out; l_tx_in_from = bound_item->out.tx_prev_out->addr; + l_prev_out_addr_key = &bound_item->out.tx_prev_out->addr.data.hash_fast; + l_value = dap_chain_uint256_from(bound_item->out.tx_prev_out->header.value); break; case TX_ITEM_TYPE_OUT: // 256 bound_item->out.tx_prev_out_256 = l_tx_prev_out; l_tx_in_from = bound_item->out.tx_prev_out_256->addr; + l_prev_out_addr_key = &bound_item->out.tx_prev_out_256->addr.data.hash_fast; + l_value = bound_item->out.tx_prev_out_256->header.value; break; case TX_ITEM_TYPE_OUT_EXT: // 256 bound_item->out.tx_prev_out_ext_256 = l_tx_prev_out; l_tx_in_from = bound_item->out.tx_prev_out_ext_256->addr; + l_prev_out_addr_key = &bound_item->out.tx_prev_out_ext_256->addr.data.hash_fast; + l_value = bound_item->out.tx_prev_out_ext_256->header.value; + l_token = bound_item->out.tx_prev_out_ext_256->token; break; default: l_err_num = -8; @@ -2737,48 +2996,20 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t if (l_err_num) break; - // calculate hash of public key in current transaction - dap_chain_hash_fast_t l_hash_pkey; - // Get sign item - dap_chain_tx_sig_t *l_tx_sig = (dap_chain_tx_sig_t*) dap_chain_datum_tx_item_get(a_tx, NULL, - TX_ITEM_TYPE_SIG, NULL); - // Get sign from sign item - dap_sign_t *l_sign = dap_chain_datum_tx_item_sign_get_sig((dap_chain_tx_sig_t*) l_tx_sig); - // Get public key from sign - size_t l_pkey_ser_size = 0; - const uint8_t *l_pkey_ser = dap_sign_get_pkey(l_sign, &l_pkey_ser_size); - // calculate hash from public key - dap_hash_fast(l_pkey_ser, l_pkey_ser_size, &l_hash_pkey); - // hash of public key in 'out' item of previous transaction - - uint8_t *l_prev_out_addr_key = NULL; - switch (l_type) { - case TX_ITEM_TYPE_OUT: - l_prev_out_addr_key = bound_item->out.tx_prev_out_256->addr.data.key; break; - case TX_ITEM_TYPE_OUT_OLD: - l_prev_out_addr_key = bound_item->out.tx_prev_out->addr.data.key; break; - case TX_ITEM_TYPE_OUT_EXT: - l_prev_out_addr_key = bound_item->out.tx_prev_out_ext_256->addr.data.key; break; - default: break; - } - // 4. compare public key hashes in the signature of the current transaction and in the 'out' item of the previous transaction - if(memcmp(&l_hash_pkey, l_prev_out_addr_key, sizeof(dap_chain_hash_fast_t))) { + if (dap_hash_fast_is_blank(&l_hash_pkey)) { + // Get sign item + dap_chain_tx_sig_t *l_tx_sig = (dap_chain_tx_sig_t*) dap_chain_datum_tx_item_get(a_tx, NULL, + TX_ITEM_TYPE_SIG, NULL); + // Get sign from sign item + dap_sign_t *l_sign = dap_chain_datum_tx_item_sign_get_sig(l_tx_sig); + // calculate hash from sign public key + dap_sign_get_pkey_hash(l_sign, &l_hash_pkey); + } + if (!dap_hash_fast_compare(&l_hash_pkey, l_prev_out_addr_key)) { l_err_num = -9; break; } - - switch (l_type) { - case TX_ITEM_TYPE_OUT: // 256 - l_value = bound_item->out.tx_prev_out_256->header.value; break; - case TX_ITEM_TYPE_OUT_OLD: - l_value = dap_chain_uint256_from(bound_item->out.tx_prev_out->header.value); break; - case TX_ITEM_TYPE_OUT_EXT: // 256 - l_value = bound_item->out.tx_prev_out_ext_256->header.value; - l_token = bound_item->out.tx_prev_out_ext_256->token; - break; - default: break; - } } else { // TX_ITEM_TYPE_IN_COND if(*(uint8_t *)l_tx_prev_out != TX_ITEM_TYPE_OUT_COND) { l_err_num = -8; @@ -2796,6 +3027,8 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t dap_chain_tx_out_cond_t *l_tx_prev_out_cond = NULL; l_tx_prev_out_cond = (dap_chain_tx_out_cond_t *)l_tx_prev_out; + if (l_tx_prev_out_cond->header.subtype != DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE) + l_main_ticker = l_token; bool l_owner = false; if (l_pkey_ser_size == l_prev_pkey_ser_size && @@ -2815,17 +3048,17 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t l_err_num = -13; break; } - if (l_verificator->callback(a_ledger, l_tx_prev_out_cond, a_tx, l_owner) == false) { - l_err_num = -14; + if (l_verificator->callback(a_ledger, &l_tx_prev_hash, l_tx_prev_out_cond, a_tx, l_owner) == false) { + if (l_sub_tmp == DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK) { + l_err_num = DAP_CHAIN_CS_VERIFY_CODE_TX_NO_PREVIOUS; + } else { + l_err_num = -14; + } break; } // calculate sum of values from previous transactions bound_item->out.tx_prev_out_cond_256 = l_tx_prev_out_cond; l_value = l_tx_prev_out_cond->header.value; - l_token = NULL; - } - if (!l_token || !*l_token) { - l_token = l_item_out->cache_data.token_ticker; } if (! l_token || !*l_token ) { log_it(L_WARNING, "No token ticker found in previous transaction"); @@ -2901,6 +3134,13 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t bool l_multichannel = false; if (HASH_COUNT(l_values_from_prev_tx) > 1) { l_multichannel = true; + if (HASH_COUNT(l_values_from_prev_tx) == 2 && !l_main_ticker) { + HASH_FIND_STR(l_values_from_cur_tx, PVT(a_ledger)->net->pub.native_ticker, l_value_cur); + if (l_value_cur) { + l_value_cur = l_value_cur->hh.next ? l_value_cur->hh.next : l_value_cur->hh.prev; + l_main_ticker = l_value_cur->token_ticker; + } + } } else { l_value_cur = DAP_NEW_Z(dap_chain_ledger_tokenizer_t); if(l_token) @@ -2910,7 +3150,9 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t // find 'out' items dap_list_t *l_list_out = dap_chain_datum_tx_items_get((dap_chain_datum_tx_t*) a_tx, TX_ITEM_TYPE_OUT_ALL, NULL); - uint256_t l_value = {}; + uint256_t l_value = {}, l_fee_value = {}, l_fee_sum = {}; + dap_chain_addr_t l_fee_addr = {}; + bool l_fee_check = dap_chain_net_tx_get_fee(PVT(a_ledger)->net->pub.id, &l_fee_value, &l_fee_addr); int l_item_idx = 0; for (l_list_tmp = l_list_out; l_list_tmp; l_list_tmp = dap_list_next(l_list_tmp), l_item_idx++) { dap_chain_tx_item_type_t l_type = *(uint8_t *)l_list_tmp->data; @@ -2929,8 +3171,12 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t case TX_ITEM_TYPE_OUT: { // 256 dap_chain_tx_out_t *l_tx_out = (dap_chain_tx_out_t *)l_list_tmp->data; if (l_multichannel) { // token ticker is mandatory for multichannel transactions - l_err_num = -16; - break; + if (l_main_ticker) + l_token = l_main_ticker; + else { + l_err_num = -16; + break; + } } l_value = l_tx_out->header.value; l_tx_out_to = l_tx_out->addr; @@ -2949,14 +3195,19 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t } break; case TX_ITEM_TYPE_OUT_COND: { dap_chain_tx_out_cond_t *l_tx_out = (dap_chain_tx_out_cond_t *)l_list_tmp->data; - if (l_multichannel) { // out_cond have no field .token - log_it(L_WARNING, "No conditional output support for multichannel transaction"); - l_err_num = -18; - break; + if (l_multichannel) { + if (l_main_ticker) + l_token = l_main_ticker; + else if (l_tx_out->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE) + l_token = (char *)PVT(a_ledger)->net->pub.native_ticker; + else { + log_it(L_WARNING, "No conditional output support for multichannel transaction"); + l_err_num = -18; + break; + } } l_value = l_tx_out->header.value; l_list_tx_out = dap_list_append(l_list_tx_out, l_tx_out); - l_list_tx_out_cond = dap_list_append(l_list_tx_out_cond, l_tx_out); } break; default: {} } @@ -2968,7 +3219,12 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t HASH_ADD_STR(l_values_from_cur_tx, token_ticker, l_value_cur); } } - SUM_256_256(l_value_cur->sum, l_value, &l_value_cur->sum); + if (SUM_256_256(l_value_cur->sum, l_value, &l_value_cur->sum)) { + debug_if(s_debug_more, L_WARNING, "Sum result overflow for tx_add_check with ticker %s", + l_value_cur->token_ticker); + l_err_num = -77; + break; + } // Get permissions for token l_token_item = NULL; @@ -3009,8 +3265,12 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t break; } } - } + if (l_fee_check && !memcmp(&l_tx_out_to, &l_fee_addr, sizeof(dap_chain_addr_t)) && + !dap_strcmp(l_value_cur->token_ticker, PVT(a_ledger)->net->pub.native_ticker)) { + SUM_256_256(l_fee_sum, l_value, &l_fee_sum); + } + } if ( l_list_out ) dap_list_free(l_list_out); @@ -3020,10 +3280,10 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t HASH_ITER(hh, l_values_from_prev_tx, l_value_cur, l_tmp) { HASH_FIND_STR(l_values_from_cur_tx, l_value_cur->token_ticker, l_res); if (!l_res || !EQUAL_256(l_res->sum, l_value_cur->sum) ) { - if(s_debug_more) { - char *l_balance = dap_chain_balance_print(l_res ? l_res->sum : uint256_0); - char *l_balance_cur = dap_chain_balance_print(l_value_cur->sum); - log_it(L_ERROR, "Sum of values of out items from current tx 256 (%s) is not equal outs from previous tx (%s) for token %s", + if (s_debug_more) { + char *l_balance = dap_chain_balance_to_coins(l_res ? l_res->sum : uint256_0); + char *l_balance_cur = dap_chain_balance_to_coins(l_value_cur->sum); + log_it(L_ERROR, "Sum of values of out items from current tx (%s) is not equal outs from previous tx (%s) for token %s", l_balance, l_balance_cur, l_value_cur->token_ticker); DAP_DELETE(l_balance); DAP_DELETE(l_balance_cur); @@ -3034,6 +3294,16 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t } } + // 7. Check the network fee + if (l_fee_check && compare256(l_fee_sum, l_fee_value) == -1) { + char *l_current_fee = dap_chain_balance_to_coins(l_fee_sum); + char *l_expected_fee = dap_chain_balance_to_coins(l_fee_value); + log_it(L_ERROR, "Fee value is invalid, expected %s pointed %s", l_expected_fee, l_current_fee); + l_err_num = -55; + DAP_DEL_Z(l_current_fee); + DAP_DEL_Z(l_expected_fee); + } + HASH_ITER(hh, l_values_from_prev_tx, l_value_cur, l_tmp) { HASH_DEL(l_values_from_prev_tx, l_value_cur); DAP_DELETE(l_value_cur); @@ -3047,10 +3317,7 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t } else { *a_list_bound_items = l_list_bound_items; } - if (l_list_tx_out_cond && !l_err_num) { - l_err_num = s_check_out_cond_verificator_added(a_ledger, a_tx, l_list_tx_out_cond); - dap_list_free(l_list_tx_out_cond); - } + if (!a_list_tx_out || l_err_num) { dap_list_free(l_list_tx_out); } else { @@ -3072,19 +3339,20 @@ int dap_chain_ledger_tx_add_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t * return -2; dap_list_t *l_list_bound_items = NULL; dap_list_t *l_list_tx_out = NULL; + dap_hash_fast_t l_tx_hash; + dap_hash_fast(a_tx, dap_chain_datum_tx_get_size(a_tx), &l_tx_hash); int l_ret_check; - if( (l_ret_check = dap_chain_ledger_tx_cache_check( - a_ledger, a_tx, false, &l_list_bound_items, &l_list_tx_out)) < 0){ - if(s_debug_more) - log_it (L_DEBUG, "dap_chain_ledger_tx_add_check() tx not passed the check: code %d ",l_ret_check); + if( (l_ret_check = dap_chain_ledger_tx_cache_check(a_ledger, a_tx, &l_tx_hash, false, + &l_list_bound_items, &l_list_tx_out)) < 0) { + debug_if(s_debug_more, L_DEBUG, "dap_chain_ledger_tx_add_check() tx not passed the check: code %d ", l_ret_check); return l_ret_check; } - dap_chain_hash_fast_t *l_tx_hash = dap_chain_node_datum_tx_calc_hash(a_tx); - char l_tx_hash_str[70]; - dap_chain_hash_fast_to_str(l_tx_hash,l_tx_hash_str,sizeof(l_tx_hash_str)); - if(s_debug_more) - log_it ( L_INFO, "dap_chain_ledger_tx_add_check() check passed for tx %s",l_tx_hash_str); + if(s_debug_more) { + char l_tx_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE]; + dap_chain_hash_fast_to_str(&l_tx_hash, l_tx_hash_str, sizeof(l_tx_hash_str)); + log_it ( L_INFO, "dap_chain_ledger_tx_add_check() check passed for tx %s", l_tx_hash_str); + } return 0; } @@ -3096,15 +3364,14 @@ int dap_chain_ledger_tx_add_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t * */ static int s_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, DAP_CHAIN_LEDGER_BALANCES_STR); - - if ( dap_global_db_set(l_gdb_group, a_balance->key, &a_balance->balance, sizeof(uint256_t), false, NULL, NULL) ) { - if(s_debug_more) - log_it(L_WARNING, "Ledger cache mismatch"); - return -1; + if (PVT(a_ledger)->cached) { + char *l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, DAP_CHAIN_LEDGER_BALANCES_STR); + if (!dap_global_db_set(l_gdb_group, a_balance->key, &a_balance->balance, sizeof(uint256_t), false, NULL, NULL)) { + debug_if(s_debug_more, L_WARNING, "Ledger cache mismatch"); + return -1; + } + DAP_DELETE(l_gdb_group); } - - DAP_DELETE(l_gdb_group); /* Notify the world*/ struct json_object *l_json = wallet_info_json_collect(a_ledger, a_balance); dap_notify_server_send_mt(json_object_get_string(l_json)); @@ -3112,7 +3379,7 @@ static int s_balance_cache_update(dap_ledger_t *a_ledger, dap_ledger_wallet_bala return 0; } -int sort_ledger_tx_item(dap_chain_ledger_tx_item_t* a, dap_chain_ledger_tx_item_t* b) +static int s_sort_ledger_tx_item(dap_chain_ledger_tx_item_t* a, dap_chain_ledger_tx_item_t* b) { return a->tx->header.ts_created == b->tx->header.ts_created ? 0 : a->tx->header.ts_created < b->tx->header.ts_created ? -1 : 1; @@ -3179,29 +3446,18 @@ static inline int s_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, d l_ledger_priv->tps_timer = NULL; } bool l_from_threshold = a_from_threshold; - if (!l_ledger_priv->load_mode && !a_from_threshold) { - HASH_VALUE(a_tx_hash, sizeof(*a_tx_hash), l_hash_value); - if(a_safe_call) pthread_rwlock_rdlock(&l_ledger_priv->ledger_rwlock); - HASH_FIND_BYHASHVALUE(hh, l_ledger_priv->ledger_items, a_tx_hash, sizeof(dap_chain_hash_fast_t), l_hash_value, l_item_tmp); - if(a_safe_call) pthread_rwlock_unlock(&l_ledger_priv->ledger_rwlock); - } - char l_tx_hash_str[70]; + char l_tx_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE]; dap_chain_hash_fast_to_str(a_tx_hash, l_tx_hash_str, sizeof(l_tx_hash_str)); - if (l_item_tmp) { // transaction already present in the cache list - if(s_debug_more) - log_it(L_WARNING, "Transaction %s already present in the cache", l_tx_hash_str); - return -1; - } int l_ret_check; l_item_tmp = NULL; - if( (l_ret_check = dap_chain_ledger_tx_cache_check( - a_ledger, a_tx, a_from_threshold, &l_list_bound_items, &l_list_tx_out)) < 0) { + if( (l_ret_check = dap_chain_ledger_tx_cache_check(a_ledger, a_tx, a_tx_hash, a_from_threshold, + &l_list_bound_items, &l_list_tx_out)) < 0) { if (l_ret_check == DAP_CHAIN_CS_VERIFY_CODE_TX_NO_PREVIOUS || l_ret_check == DAP_CHAIN_CS_VERIFY_CODE_TX_NO_EMISSION) { if (!l_from_threshold) { - if (!l_hash_value) - HASH_VALUE(a_tx_hash, sizeof(*a_tx_hash), l_hash_value); + unsigned l_hash_value = 0; + HASH_VALUE(a_tx_hash, sizeof(*a_tx_hash), l_hash_value); pthread_rwlock_rdlock(&l_ledger_priv->threshold_txs_rwlock); HASH_FIND_BYHASHVALUE(hh, l_ledger_priv->threshold_txs, a_tx_hash, sizeof(*a_tx_hash), l_hash_value, l_item_tmp); unsigned long long l_threshold_txs_count = HASH_COUNT(l_ledger_priv->threshold_txs); @@ -3230,11 +3486,6 @@ static inline int s_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, d if(s_debug_more) log_it ( L_DEBUG, "dap_chain_ledger_tx_add() check passed for tx %s",l_tx_hash_str); - char l_token_ticker[DAP_CHAIN_TICKER_SIZE_MAX] = { '\0'}, - l_token_ticker_old[DAP_CHAIN_TICKER_SIZE_MAX] = { '\0'}; - - //char *l_token_ticker = NULL, *l_token_ticker_old = NULL; - bool l_multichannel = false; // Mark 'out' items in cache if they were used & delete previous transactions from cache if it need // find all bound pairs 'in' and 'out' dap_list_t *l_list_tmp = l_list_bound_items; @@ -3242,10 +3493,10 @@ static inline int s_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, d size_t l_cache_size = sizeof(dap_store_obj_t) * (l_outs_used + 1); dap_store_obj_t *l_cache_used_outs = DAP_NEW_Z_SIZE(dap_store_obj_t, l_cache_size); char *l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, DAP_CHAIN_LEDGER_TXS_STR); - char *l_ticker_trl = NULL, *l_ticker_old_trl = NULL; - bool l_stake_updated = false; - // Update balance: deducts + char *l_main_token_ticker = NULL, *l_cur_token_ticker = NULL; + bool l_ticker_in_heap = false; + // Update balance: deducts for (int i = 1; l_list_tmp; i++) { dap_chain_ledger_tx_bound_t *bound_item = l_list_tmp->data; void *l_item_in = *(void **)&bound_item->in; @@ -3253,22 +3504,43 @@ static inline int s_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, d if (l_type == TX_ITEM_TYPE_IN) { dap_chain_tx_in_t *l_tx_in = bound_item->in.tx_cur_in; if (dap_hash_fast_is_blank(&l_tx_in->header.tx_prev_hash)) { // It's the emission behind - // Mark it as used with base tx hash - bound_item->item_emission->tx_used_out = *a_tx_hash; - // Mirror it in cache - char *l_hash_str = dap_chain_hash_fast_to_str_new(&bound_item->item_emission->datum_token_emission_hash); - size_t l_emission_size = bound_item->item_emission->datum_token_emission_size; - char *l_ems_group = dap_chain_ledger_get_gdb_group(a_ledger, DAP_CHAIN_LEDGER_EMISSIONS_STR); - size_t l_cache_size = l_emission_size + sizeof(dap_hash_fast_t); - uint8_t *l_cache = DAP_NEW_Z_SIZE(uint8_t, l_cache_size); - memcpy(l_cache, a_tx_hash, sizeof(dap_hash_fast_t)); - memcpy(l_cache + sizeof(dap_hash_fast_t), bound_item->item_emission->datum_token_emission, l_emission_size); - if ( dap_global_db_set(l_ems_group, l_hash_str, l_cache, l_cache_size, false, NULL, NULL) ) { - log_it(L_WARNING, "Ledger cache mismatch"); + // Find token ticker for emission + dap_chain_tx_token_t * l_tx_token = (dap_chain_tx_token_t *) dap_chain_datum_tx_item_get(a_tx, NULL, TX_ITEM_TYPE_TOKEN, NULL); + if (l_tx_token) + l_main_token_ticker = l_tx_token->header.ticker; + else { + log_it(L_ERROR, "No token item with blank prev tx hash"); + break; + } + if (bound_item->tx_prev) { // It's the stake lock emission + dap_chain_ledger_token_item_t *l_token_item = NULL; + pthread_rwlock_rdlock(&l_ledger_priv->tokens_rwlock); + HASH_FIND_STR(l_ledger_priv->tokens, l_main_token_ticker, l_token_item); + pthread_rwlock_unlock(&l_ledger_priv->tokens_rwlock); + if (!l_token_item){ + log_it(L_ERROR, "No token item found for token %s", l_main_token_ticker); + break; + } + if (!IS_ZERO_256(l_token_item->total_supply)) { + dap_chain_tx_out_t *l_tx_out = (dap_chain_tx_out_t*)dap_chain_datum_tx_item_get(a_tx, 0, TX_ITEM_TYPE_OUT, 0); + SUBTRACT_256_256(l_token_item->current_supply, l_tx_out->header.value, &l_token_item->current_supply); + char *l_balance = dap_chain_balance_print(l_token_item->current_supply); + log_it(L_DEBUG, "New current supply %s for token %s", l_balance, l_token_item->ticker); + DAP_DEL_Z(l_balance); + if (PVT(a_ledger)->cached) + s_ledger_token_cache_update(a_ledger, l_token_item); + } + bound_item->stake_lock_item->tx_used_out = *a_tx_hash; + if (PVT(a_ledger)->cached) + // Mirror it in cache + s_ledger_stake_lock_cache_update(a_ledger, bound_item->stake_lock_item); + } else { // It's the general emission + // Mark it as used with base tx hash + bound_item->item_emission->tx_used_out = *a_tx_hash; + if (PVT(a_ledger)->cached) + // Mirror it in cache + s_ledger_emission_cache_update(a_ledger, bound_item->item_emission); } - DAP_DELETE(l_hash_str); - DAP_DELETE(l_cache); - DAP_DELETE(l_ems_group); l_list_tmp = dap_list_next(l_list_tmp); i--; // Do not calc this output with tx used items l_outs_used--; @@ -3276,16 +3548,9 @@ static inline int s_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, d } } dap_chain_ledger_tx_item_t *l_prev_item_out = bound_item->item_out; - - if ( *l_prev_item_out->cache_data.token_ticker ) - l_ticker_trl = dap_stpcpy(l_token_ticker, l_prev_item_out->cache_data.token_ticker); - else - l_ticker_trl = dap_stpcpy(l_token_ticker, bound_item->out.tx_prev_out_ext_256->token); - - if (!l_multichannel && l_ticker_old_trl && strcmp(l_token_ticker, l_token_ticker_old)) { - l_multichannel = true; - } - l_ticker_old_trl = dap_stpcpy(l_token_ticker_old, l_token_ticker); + l_cur_token_ticker = l_prev_item_out->cache_data.token_ticker; + if (!l_main_token_ticker) + l_main_token_ticker = l_cur_token_ticker; int l_tx_prev_out_used_idx; if (l_type == TX_ITEM_TYPE_IN) { dap_chain_tx_in_t *l_tx_in = bound_item->in.tx_cur_in; @@ -3295,41 +3560,40 @@ static inline int s_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, d void *l_item_out = *(void **)&bound_item->out; dap_chain_tx_item_type_t l_out_type = *(uint8_t *)l_item_out; switch (l_out_type) { - case TX_ITEM_TYPE_OUT: l_addr = &bound_item->out.tx_prev_out_256->addr; break; - case TX_ITEM_TYPE_OUT_OLD: l_addr = &bound_item->out.tx_prev_out->addr; break; - case TX_ITEM_TYPE_OUT_EXT: l_addr = &bound_item->out.tx_prev_out_ext_256->addr; break; - default: - log_it(L_DEBUG, "Unknown item type %d", l_out_type); - break; + case TX_ITEM_TYPE_OUT: + l_addr = &bound_item->out.tx_prev_out_256->addr; + l_value = bound_item->out.tx_prev_out_256->header.value; + break; + case TX_ITEM_TYPE_OUT_OLD: + l_addr = &bound_item->out.tx_prev_out->addr; + l_value = GET_256_FROM_64(bound_item->out.tx_prev_out->header.value); + break; + case TX_ITEM_TYPE_OUT_EXT: + l_addr = &bound_item->out.tx_prev_out_ext_256->addr; + l_value = bound_item->out.tx_prev_out_ext_256->header.value; + l_cur_token_ticker = bound_item->out.tx_prev_out_ext_256->token; + break; + default: + log_it(L_DEBUG, "Unknown item type %d", l_out_type); + break; } char *l_addr_str = dap_chain_addr_to_str(l_addr); - char *l_wallet_balance_key = dap_strjoin(" ", l_addr_str, l_token_ticker, (char*)NULL); + char *l_wallet_balance_key = dap_strjoin(" ", l_addr_str, l_cur_token_ticker, (char*)NULL); pthread_rwlock_rdlock(&PVT(a_ledger)->balance_accounts_rwlock); HASH_FIND_STR(PVT(a_ledger)->balance_accounts, l_wallet_balance_key, wallet_balance); pthread_rwlock_unlock(&PVT(a_ledger)->balance_accounts_rwlock); if (wallet_balance) { - switch (l_out_type) { - case TX_ITEM_TYPE_OUT: l_value = bound_item->out.tx_prev_out_256->header.value; break; - case TX_ITEM_TYPE_OUT_OLD: l_value = GET_256_FROM_64(bound_item->out.tx_prev_out->header.value); break; - case TX_ITEM_TYPE_OUT_EXT: l_value = bound_item->out.tx_prev_out_ext_256->header.value; break; - default: - log_it(L_DEBUG, "Unknown item type %d", l_out_type); - break; - } - if(s_debug_more) { char *l_balance = dap_chain_balance_print(l_value); log_it(L_DEBUG,"SPEND %s from addr: %s", l_balance, l_wallet_balance_key); DAP_DELETE(l_balance); } - SUBTRACT_256_256(wallet_balance->balance, l_value, &wallet_balance->balance); - // Update the cache s_balance_cache_update(a_ledger, wallet_balance); } else { if(s_debug_more) - log_it(L_ERROR,"!!! Attempt to SPEND from some non-existent balance !!!: %s %s", l_addr_str, l_token_ticker); + log_it(L_ERROR,"!!! Attempt to SPEND from some non-existent balance !!!: %s %s", l_addr_str, l_cur_token_ticker); } DAP_DELETE(l_addr_str); DAP_DELETE(l_wallet_balance_key); @@ -3340,19 +3604,19 @@ static inline int s_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, d 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_out_used_idx = l_tx_in_cond->header.tx_out_prev_idx; - // Update stakes if any dap_chain_tx_out_cond_t *l_cond = bound_item->out.tx_prev_out_cond_256; - if (l_cond->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE) { - dap_chain_ledger_verificator_t *l_verificator; - int l_tmp = (int)DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE_UPDATE; - pthread_rwlock_rdlock(&s_verificators_rwlock); - HASH_FIND_INT(s_verificators, &l_tmp, l_verificator); - pthread_rwlock_unlock(&s_verificators_rwlock); - if (l_verificator && l_verificator->callback) { - l_verificator->callback(a_ledger, l_cond, a_tx, true); - } - l_stake_updated = true; - } + if (l_cond->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE) + l_main_token_ticker = l_prev_item_out->cache_data.token_ticker; + if (l_cond->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE) + l_cur_token_ticker = (char *)PVT(a_ledger)->net->pub.native_ticker; + // Update service items if any + dap_chain_ledger_verificator_t *l_verificator; + int l_tmp = l_cond->header.subtype; + pthread_rwlock_rdlock(&s_verificators_rwlock); + HASH_FIND_INT(s_verificators, &l_tmp, l_verificator); + pthread_rwlock_unlock(&s_verificators_rwlock); + if (l_verificator && l_verificator->callback_added) + l_verificator->callback_added(a_ledger, a_tx, l_cond); } // add a used output l_prev_item_out->cache_data.tx_hash_spent_fast[l_tx_prev_out_used_idx] = *a_tx_hash; @@ -3363,8 +3627,9 @@ static inline int s_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, d uint8_t *l_tx_cache = DAP_NEW_Z_SIZE(uint8_t, l_tx_cache_sz); memcpy(l_tx_cache, &l_prev_item_out->cache_data, sizeof(l_prev_item_out->cache_data)); memcpy(l_tx_cache + sizeof(l_prev_item_out->cache_data), l_prev_item_out->tx, l_tx_size); + char *l_tx_i_hash = dap_chain_hash_fast_to_str_new(&l_prev_item_out->tx_hash_fast); l_cache_used_outs[i] = (dap_store_obj_t) { - .key = dap_chain_hash_fast_to_str_new(&l_prev_item_out->tx_hash_fast), + .key = l_tx_i_hash, .value = l_tx_cache, .value_len = l_tx_cache_sz, .group = l_gdb_group @@ -3372,9 +3637,13 @@ static inline int s_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, d // delete previous transactions from cache because all out is used 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; + if (l_main_token_ticker == l_prev_item_out->cache_data.token_ticker) { + l_main_token_ticker = dap_strdup(l_prev_item_out->cache_data.token_ticker); + l_ticker_in_heap = true; + } + dap_chain_hash_fast_t l_tx_prev_hash_to_del = bound_item->tx_prev_hash; // remove from memory ledger - int res = dap_chain_ledger_tx_remove(a_ledger, &l_tx_prev_hash_to_del); + int res = dap_chain_ledger_tx_remove(a_ledger, &l_tx_prev_hash_to_del, a_tx->header.ts_created); if(res == -2) { if(s_debug_more) { char * l_tx_prev_hash_str = dap_chain_hash_fast_to_str_new(&l_tx_prev_hash_to_del); @@ -3400,108 +3669,86 @@ static inline int s_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, d l_list_tmp = dap_list_next(l_list_tmp); } - // Try to find token ticker if wasn't - if (!l_ticker_trl){ - //int l_base_tx_count = 0; - //dap_list_t *l_base_tx_list = dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_TOKEN, &l_base_tx_count ); - //if (l_base_tx_count >=1 && l_base_tx_list){ - dap_chain_tx_token_t * l_tx_token = (dap_chain_tx_token_t *) dap_chain_datum_tx_item_get(a_tx, NULL, TX_ITEM_TYPE_TOKEN, NULL); - if (l_tx_token) - l_ticker_trl = dap_stpcpy(l_token_ticker, l_tx_token->header.ticker); - //} - } - //Update balance : raise + bool l_multichannel = false; for (dap_list_t *l_tx_out = l_list_tx_out; l_tx_out; l_tx_out = dap_list_next(l_tx_out)) { + if (!l_tx_out->data) { + debug_if(s_debug_more, L_WARNING, "Can't detect tx ticker or matching output, can't append balances cache"); + continue; + } dap_chain_tx_item_type_t l_type = *(uint8_t *)l_tx_out->data; if (l_type == TX_ITEM_TYPE_OUT_COND) { - // Update stakes if any + // Update service items if any dap_chain_tx_out_cond_t *l_cond = (dap_chain_tx_out_cond_t *)l_tx_out->data; - if (l_cond->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE && !l_stake_updated) { - dap_chain_ledger_verificator_t *l_verificator; - int l_tmp = (int)DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE_UPDATE; - pthread_rwlock_rdlock(&s_verificators_rwlock); - HASH_FIND_INT(s_verificators, &l_tmp, l_verificator); - pthread_rwlock_unlock(&s_verificators_rwlock); - if (l_verificator && l_verificator->callback) { - l_verificator->callback(a_ledger, NULL, a_tx, true); - } - } + dap_chain_ledger_verificator_t *l_verificator; + int l_tmp = l_cond->header.subtype; + pthread_rwlock_rdlock(&s_verificators_rwlock); + HASH_FIND_INT(s_verificators, &l_tmp, l_verificator); + pthread_rwlock_unlock(&s_verificators_rwlock); + if (l_verificator && l_verificator->callback_added) + l_verificator->callback_added(a_ledger, a_tx, NULL); continue; // balance raise will be with next conditional transaction } - dap_chain_tx_out_old_t *l_out_item = NULL; - dap_chain_tx_out_t *l_out_item_256 = NULL; - dap_chain_tx_out_ext_t *l_out_item_ext_256 = NULL; + dap_chain_addr_t *l_addr; + uint256_t l_value = {}; switch (l_type) { - case TX_ITEM_TYPE_OUT: l_out_item_256 = (dap_chain_tx_out_t *)l_tx_out->data; break; - case TX_ITEM_TYPE_OUT_OLD: l_out_item = (dap_chain_tx_out_old_t *)l_tx_out->data; break; - case TX_ITEM_TYPE_OUT_EXT: l_out_item_ext_256 = (dap_chain_tx_out_ext_t *)l_tx_out->data; break; - default: - log_it(L_DEBUG, "Unknown item type %d", l_type); - break; + case TX_ITEM_TYPE_OUT: { + dap_chain_tx_out_t *l_out_item_256 = (dap_chain_tx_out_t *)l_tx_out->data; + l_addr = &l_out_item_256->addr; + l_value = l_out_item_256->header.value; + l_cur_token_ticker = l_main_token_ticker; + } break; + case TX_ITEM_TYPE_OUT_OLD: { + dap_chain_tx_out_old_t *l_out_item = (dap_chain_tx_out_old_t *)l_tx_out->data; + l_addr = &l_out_item->addr; + l_value = GET_256_FROM_64(l_out_item->header.value); + l_cur_token_ticker = l_main_token_ticker; + } break; + case TX_ITEM_TYPE_OUT_EXT: { + dap_chain_tx_out_ext_t *l_out_item_ext_256 = (dap_chain_tx_out_ext_t *)l_tx_out->data; + l_addr = &l_out_item_ext_256->addr; + l_value = l_out_item_ext_256->header.value; + l_cur_token_ticker = l_out_item_ext_256->token; + l_multichannel = true; + } break; + default: + log_it(L_DEBUG, "Unknown item type %d", l_type); + break; } - - if ((l_out_item||l_out_item_256||l_out_item_ext_256) && l_ticker_trl) { - dap_chain_addr_t *l_addr; - switch (l_type) { - case TX_ITEM_TYPE_OUT: l_addr = &l_out_item_256->addr; break; - case TX_ITEM_TYPE_OUT_OLD: l_addr = &l_out_item->addr; break; - case TX_ITEM_TYPE_OUT_EXT: l_addr = &l_out_item_ext_256->addr; break; - default: - log_it(L_DEBUG, "Unknown item type %d", l_type); - break; - } - char *l_addr_str = dap_chain_addr_to_str(l_addr); - dap_ledger_wallet_balance_t *wallet_balance = NULL; - if (l_multichannel) { - l_ticker_trl = dap_stpcpy(l_token_ticker, l_out_item_ext_256->token); - } - char *l_wallet_balance_key = dap_strjoin(" ", l_addr_str, l_token_ticker, (char*)NULL); - uint256_t l_value_256 = {}; - switch (l_type) { - case TX_ITEM_TYPE_OUT: l_value_256 = l_out_item_256->header.value; break; // _256 - case TX_ITEM_TYPE_OUT_OLD: l_value_256 = GET_256_FROM_64(l_out_item->header.value); break; - case TX_ITEM_TYPE_OUT_EXT: l_value_256 = l_out_item_ext_256->header.value; break; // _256 - default: - log_it(L_DEBUG, "Unknown item type %d", l_type); - break; - } - - if(s_debug_more) { - char *l_balance = dap_chain_balance_print(l_value_256); - log_it(L_DEBUG, "GOT %s to addr: %s", l_balance, l_wallet_balance_key); - DAP_DELETE(l_balance); - } - pthread_rwlock_rdlock(&l_ledger_priv->balance_accounts_rwlock); - HASH_FIND_STR(PVT(a_ledger)->balance_accounts, l_wallet_balance_key, wallet_balance); - pthread_rwlock_unlock(&l_ledger_priv->balance_accounts_rwlock); - if (wallet_balance) { - //if(s_debug_more) - // log_it(L_DEBUG, "Balance item is present in cache"); - SUM_256_256(wallet_balance->balance, l_value_256, &wallet_balance->balance); - DAP_DELETE (l_wallet_balance_key); - // Update the cache - s_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; - strcpy(wallet_balance->token_ticker, l_token_ticker); - SUM_256_256(wallet_balance->balance, l_value_256, &wallet_balance->balance); - if(s_debug_more) - log_it(L_DEBUG, "Create new balance item: %s %s", l_addr_str, l_token_ticker); - pthread_rwlock_wrlock(&l_ledger_priv->balance_accounts_rwlock); - HASH_ADD_KEYPTR(hh, PVT(a_ledger)->balance_accounts, wallet_balance->key, - strlen(l_wallet_balance_key), wallet_balance); - pthread_rwlock_unlock(&l_ledger_priv->balance_accounts_rwlock); - // Add it to cache - s_balance_cache_update(a_ledger, wallet_balance); - } - DAP_DELETE (l_addr_str); + char *l_addr_str = dap_chain_addr_to_str(l_addr); + dap_ledger_wallet_balance_t *wallet_balance = NULL; + char *l_wallet_balance_key = dap_strjoin(" ", l_addr_str, l_cur_token_ticker, (char*)NULL); + if(s_debug_more) { + char *l_balance = dap_chain_balance_print(l_value); + log_it(L_DEBUG, "GOT %s to addr: %s", l_balance, l_wallet_balance_key); + DAP_DELETE(l_balance); + } + pthread_rwlock_rdlock(&l_ledger_priv->balance_accounts_rwlock); + HASH_FIND_STR(PVT(a_ledger)->balance_accounts, l_wallet_balance_key, wallet_balance); + pthread_rwlock_unlock(&l_ledger_priv->balance_accounts_rwlock); + if (wallet_balance) { + //if(s_debug_more) + // log_it(L_DEBUG, "Balance item is present in cache"); + SUM_256_256(wallet_balance->balance, l_value, &wallet_balance->balance); + DAP_DELETE (l_wallet_balance_key); + // Update the cache + s_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; + strcpy(wallet_balance->token_ticker, l_cur_token_ticker); + SUM_256_256(wallet_balance->balance, l_value, &wallet_balance->balance); if(s_debug_more) - log_it(L_WARNING, "Can't detect tx ticker or matching output, can't append balances cache"); + log_it(L_DEBUG, "Create new balance item: %s %s", l_addr_str, l_cur_token_ticker); + pthread_rwlock_wrlock(&l_ledger_priv->balance_accounts_rwlock); + HASH_ADD_KEYPTR(hh, PVT(a_ledger)->balance_accounts, wallet_balance->key, + strlen(l_wallet_balance_key), wallet_balance); + pthread_rwlock_unlock(&l_ledger_priv->balance_accounts_rwlock); + // Add it to cache + s_balance_cache_update(a_ledger, wallet_balance); } + DAP_DELETE (l_addr_str); } // add transaction to the cache list @@ -3510,57 +3757,43 @@ static inline int s_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, d size_t l_tx_size = dap_chain_datum_tx_get_size(a_tx); l_tx_item->tx = DAP_DUP_SIZE(a_tx, l_tx_size); l_tx_item->cache_data.ts_created = dap_time_now(); // Time of transasction added to ledger - dap_list_t *l_tist_tmp = dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_OUT_ALL, &l_tx_item->cache_data.n_outs); - // If debug mode dump the UTXO - if (dap_log_level_get() == L_DEBUG && s_debug_more) { - dap_list_t *it = l_tist_tmp; - for (int i = 0; i < l_tx_item->cache_data.n_outs; i++) { - dap_chain_tx_out_old_t *l_tx_out = it->data; - if (l_tx_out->header.type != TX_ITEM_TYPE_OUT_OLD) - continue; - char * l_tx_out_addr_str = dap_chain_addr_to_str( &l_tx_out->addr ); - log_it(L_DEBUG, "Added tx out to %s", l_tx_out_addr_str); - DAP_DELETE (l_tx_out_addr_str); - it = it->next; - } - } + int l_outs_count = 0; + dap_list_t *l_tist_tmp = dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_OUT_ALL, &l_outs_count); + l_tx_item->cache_data.n_outs = l_outs_count; + // TODO: dump the UTXO in debug mode if need + if(l_tist_tmp) dap_list_free(l_tist_tmp); - if (!l_ticker_trl) { //No token ticker in previous txs - if(s_debug_more) - log_it(L_DEBUG, "No token ticker in previous txs"); - dap_chain_tx_token_t *l_token = (dap_chain_tx_token_t *)dap_chain_datum_tx_item_get(a_tx, NULL, TX_ITEM_TYPE_TOKEN, NULL); - l_ticker_trl = l_token - ? dap_stpcpy(l_token_ticker, l_token->header.ticker) - : NULL; - } - if (l_ticker_trl && !l_multichannel) - dap_stpcpy(l_tx_item->cache_data.token_ticker, l_token_ticker); - - if (!l_hash_value) - HASH_VALUE(a_tx_hash, sizeof(*a_tx_hash), l_hash_value); + if (l_main_token_ticker) { + dap_stpcpy(l_tx_item->cache_data.token_ticker, l_main_token_ticker); + if (l_ticker_in_heap) + DAP_DELETE(l_main_token_ticker); + } + else + debug_if(s_debug_more, L_ERROR, "No token ticker in previous txs"); + l_tx_item->cache_data.multichannel = l_multichannel; if(a_safe_call) pthread_rwlock_wrlock(&l_ledger_priv->ledger_rwlock); - HASH_ADD_BYHASHVALUE_INORDER(hh, l_ledger_priv->ledger_items, tx_hash_fast, sizeof(dap_chain_hash_fast_t), - l_hash_value, l_tx_item, sort_ledger_tx_item); // tx_hash_fast: name of key field + HASH_ADD_INORDER(hh, l_ledger_priv->ledger_items, tx_hash_fast, sizeof(dap_chain_hash_fast_t), + l_tx_item, s_sort_ledger_tx_item); // tx_hash_fast: name of key field if(a_safe_call) pthread_rwlock_unlock(&l_ledger_priv->ledger_rwlock); // Count TPS clock_gettime(CLOCK_REALTIME, &l_ledger_priv->tps_end_time); l_ledger_priv->tps_count++; - // Add it to cache - size_t l_tx_cache_sz = l_tx_size + sizeof(l_tx_item->cache_data); - uint8_t *l_tx_cache = DAP_NEW_STACK_SIZE(uint8_t, l_tx_cache_sz); - memcpy(l_tx_cache, &l_tx_item->cache_data, sizeof(l_tx_item->cache_data)); - memcpy(l_tx_cache + sizeof(l_tx_item->cache_data), a_tx, l_tx_size); - l_cache_used_outs[0] = (dap_store_obj_t) { - .key = l_tx_hash_str, - .value = l_tx_cache, - .value_len = l_tx_cache_sz, - .group = l_gdb_group - }; - // Apply it with single DB transaction - if ( dap_global_db_set_raw(l_cache_used_outs, l_outs_used + 1,NULL,NULL) != 0) { - if(s_debug_more) - log_it(L_WARNING, "Ledger cache mismatch"); + if (PVT(a_ledger)->cached) { + // Add it to cache + size_t l_tx_cache_sz = l_tx_size + sizeof(l_tx_item->cache_data); + uint8_t *l_tx_cache = DAP_NEW_STACK_SIZE(uint8_t, l_tx_cache_sz); + memcpy(l_tx_cache, &l_tx_item->cache_data, sizeof(l_tx_item->cache_data)); + memcpy(l_tx_cache + sizeof(l_tx_item->cache_data), a_tx, l_tx_size); + l_cache_used_outs[0] = (dap_store_obj_t) { + .key = l_tx_hash_str, + .value = l_tx_cache, + .value_len = l_tx_cache_sz, + .group = l_gdb_group + }; + // Apply it with single DB transaction + if (dap_global_db_set_raw(l_cache_used_outs, l_outs_used + 1, NULL, NULL)) + debug_if(s_debug_more, L_WARNING, "Ledger cache mismatch"); } if (!a_from_threshold) s_threshold_txs_proc(a_ledger); @@ -3627,7 +3860,7 @@ int dap_chain_ledger_tx_load(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, * * return 1 OK, -1 error, -2 tx_hash not found */ -int dap_chain_ledger_tx_remove(dap_ledger_t *a_ledger, dap_chain_hash_fast_t *a_tx_hash) +int dap_chain_ledger_tx_remove(dap_ledger_t *a_ledger, dap_chain_hash_fast_t *a_tx_hash, dap_time_t a_spent_time) { if(!a_tx_hash) return -1; @@ -3640,12 +3873,14 @@ int dap_chain_ledger_tx_remove(dap_ledger_t *a_ledger, dap_chain_hash_fast_t *a_ HASH_FIND_BYHASHVALUE(hh, l_ledger_priv->ledger_items, a_tx_hash, sizeof(dap_chain_hash_fast_t), l_hash_value, l_item_tmp); if(l_item_tmp != NULL) { HASH_DEL(l_ledger_priv->ledger_items, l_item_tmp); - // Remove it from cache - char *l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, DAP_CHAIN_LEDGER_TXS_STR); - char *l_tx_hash_str = dap_chain_hash_fast_to_str_new(a_tx_hash); - dap_global_db_del(l_gdb_group, l_tx_hash_str, NULL, NULL); - DAP_DELETE(l_tx_hash_str); - DAP_DELETE(l_gdb_group); + if (PVT(a_ledger)->cached) { + // Remove it from cache + char *l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, DAP_CHAIN_LEDGER_TXS_STR); + char *l_tx_hash_str = dap_chain_hash_fast_to_str_new(a_tx_hash); + dap_global_db_del(l_gdb_group, l_tx_hash_str, NULL, NULL); + DAP_DELETE(l_tx_hash_str); + DAP_DELETE(l_gdb_group); + } l_ret = 1; dap_chain_ledger_tx_spent_item_t *l_item_used; HASH_FIND_BYHASHVALUE(hh, l_ledger_priv->spent_items, a_tx_hash, sizeof(dap_chain_hash_fast_t), l_hash_value, l_item_used); @@ -3653,19 +3888,22 @@ int dap_chain_ledger_tx_remove(dap_ledger_t *a_ledger, dap_chain_hash_fast_t *a_ l_item_used = DAP_NEW_Z(dap_chain_ledger_tx_spent_item_t); l_item_used->tx_hash_fast = *a_tx_hash; int l_len = strnlen(l_item_tmp->cache_data.token_ticker, DAP_CHAIN_TICKER_SIZE_MAX); - strncpy(l_item_used->token_ticker, l_item_tmp->cache_data.token_ticker, l_len); + l_item_used->cache_data.spent_time = a_spent_time; + strncpy(l_item_used->cache_data.token_ticker, l_item_tmp->cache_data.token_ticker, DAP_CHAIN_TICKER_SIZE_MAX); + int l_out_num = -1; + dap_chain_datum_tx_out_cond_get(l_item_tmp->tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_ALL, &l_out_num); + if (l_out_num != -1 && l_out_num < MAX_OUT_ITEMS) + l_item_used->cache_data.tx_hash_spent_fast = l_item_tmp->cache_data.tx_hash_spent_fast[l_out_num]; HASH_ADD_BYHASHVALUE(hh, l_ledger_priv->spent_items, tx_hash_fast, sizeof(dap_chain_hash_fast_t), l_hash_value, l_item_used); - - // Add it to cache - l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, DAP_CHAIN_LEDGER_SPENT_TXS_STR); - char *l_tx_hash_str = dap_hash_fast_to_str_new(a_tx_hash); - if ( dap_global_db_set(l_gdb_group, l_tx_hash_str, l_item_used->token_ticker, l_len, false, NULL, NULL)) { - if(s_debug_more) - log_it(L_WARNING, "Ledger cache mismatch"); - } - - DAP_DELETE(l_tx_hash_str); - DAP_DELETE(l_gdb_group); + if (PVT(a_ledger)->cached) { + // Add it to cache + char *l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, DAP_CHAIN_LEDGER_SPENT_TXS_STR); + char *l_tx_hash_str = dap_hash_fast_to_str_new(a_tx_hash); + if (dap_global_db_set(l_gdb_group, l_tx_hash_str, &l_item_used->cache_data, sizeof(l_item_used->cache_data), false, NULL, NULL)) + debug_if(s_debug_more, L_WARNING, "Ledger cache mismatch"); + DAP_DELETE(l_tx_hash_str); + DAP_DELETE(l_gdb_group); + } } // delete tx & its item DAP_DELETE(l_item_tmp->tx); @@ -3689,6 +3927,7 @@ void dap_chain_ledger_purge(dap_ledger_t *a_ledger, bool a_preserve_db) pthread_rwlock_wrlock(&l_ledger_priv->threshold_emissions_rwlock); pthread_rwlock_wrlock(&l_ledger_priv->threshold_txs_rwlock); pthread_rwlock_wrlock(&l_ledger_priv->balance_accounts_rwlock); + pthread_rwlock_wrlock(&l_ledger_priv->stake_lock_rwlock); /* Delete regular transactions */ dap_chain_ledger_tx_item_t *l_item_current, *l_item_tmp; @@ -3760,6 +3999,18 @@ void dap_chain_ledger_purge(dap_ledger_t *a_ledger, bool a_preserve_db) DAP_DELETE(l_gdb_group); } + /* Delete stake-lock items */ + dap_chain_ledger_stake_lock_item_t *l_stake_item_current, *l_stake_item_tmp; + HASH_ITER(hh, l_ledger_priv->emissions_for_stake_lock, l_stake_item_current, l_stake_item_tmp) { + HASH_DEL(l_ledger_priv->emissions_for_stake_lock, l_stake_item_current); + DAP_DELETE(l_stake_item_current); + } + if (!a_preserve_db) { + l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, DAP_CHAIN_LEDGER_STAKE_LOCK_STR); + dap_global_db_del(l_gdb_group, NULL, NULL, NULL); + DAP_DELETE(l_gdb_group); + } + /* Delete threshold emissions */ HASH_ITER(hh, l_ledger_priv->threshold_emissions, l_emission_current, l_emission_tmp) { HASH_DEL(l_ledger_priv->threshold_emissions, l_emission_current); @@ -3785,6 +4036,7 @@ void dap_chain_ledger_purge(dap_ledger_t *a_ledger, bool a_preserve_db) pthread_rwlock_unlock(&l_ledger_priv->threshold_emissions_rwlock); pthread_rwlock_unlock(&l_ledger_priv->threshold_txs_rwlock); pthread_rwlock_unlock(&l_ledger_priv->balance_accounts_rwlock); + pthread_rwlock_unlock(&l_ledger_priv->stake_lock_rwlock); } /** @@ -4010,7 +4262,8 @@ static dap_chain_ledger_tx_item_t* tx_item_find_by_addr(dap_ledger_t *a_ledger, { // If a_token is setup we check if its not our token - miss it if (a_token && *l_iter_current->cache_data.token_ticker && - dap_strcmp(l_iter_current->cache_data.token_ticker, a_token)) + dap_strcmp(l_iter_current->cache_data.token_ticker, a_token) && + !l_iter_current->cache_data.multichannel) continue; // Now work with it dap_chain_datum_tx_t *l_tx = l_iter_current->tx; @@ -4148,14 +4401,13 @@ dap_list_t* dap_chain_ledger_tx_cache_find_out_cond_all(dap_ledger_t *a_ledger,d dap_chain_ledger_tx_item_t *l_iter_current = NULL, *l_item_tmp = NULL; HASH_ITER(hh, l_ledger_priv->ledger_items, l_iter_current, l_item_tmp) { dap_chain_datum_tx_t *l_tx = l_iter_current->tx; - dap_chain_hash_fast_t *l_tx_hash = &l_iter_current->tx_hash_fast; - int l_tx_out_cond_idx = 0; - dap_chain_tx_out_cond_t *l_tx_out_cond = dap_chain_datum_tx_out_cond_get(l_tx, &l_tx_out_cond_idx); - if(l_tx_out_cond){ // Is present cond out - if(l_tx_out_cond->header.srv_uid.uint64 == a_srv_uid.uint64 ) // is srv uid is same as we're searching for? + dap_list_t *l_list_out_items = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_OUT_COND, NULL); + for (dap_list_t *it = l_list_out_items; it; it = it->next) { + // Is present cond out + dap_chain_tx_out_cond_t *l_tx_out_cond = it->data; + if (l_tx_out_cond->header.srv_uid.uint64 == a_srv_uid.uint64) // is srv uid is same as we're searching for? l_ret = dap_list_append(l_ret,l_tx); } - } return l_ret; } @@ -4166,7 +4418,7 @@ dap_list_t* dap_chain_ledger_tx_cache_find_out_cond_all(dap_ledger_t *a_ledger,d * * a_addr[in] wallet address, whose owner can use the service */ -dap_chain_datum_tx_t* dap_chain_ledger_tx_cache_find_out_cond(dap_ledger_t *a_ledger, +dap_chain_datum_tx_t* dap_chain_ledger_tx_cache_find_out_cond(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_subtype_t a_cond_type, dap_chain_hash_fast_t *a_tx_first_hash, dap_chain_tx_out_cond_t **a_out_cond, int *a_out_cond_idx, char *a_token_ticker) { if (!a_tx_first_hash) @@ -4189,7 +4441,7 @@ dap_chain_datum_tx_t* dap_chain_ledger_tx_cache_find_out_cond(dap_ledger_t *a_le continue; } // Get out_cond item from transaction - l_tx_out_cond = dap_chain_datum_tx_out_cond_get(l_tx_tmp, &l_tx_out_cond_idx); + l_tx_out_cond = dap_chain_datum_tx_out_cond_get(l_tx_tmp, a_cond_type, &l_tx_out_cond_idx); if(l_tx_out_cond) { l_cur_tx = l_tx_tmp; @@ -4220,8 +4472,9 @@ dap_chain_datum_tx_t* dap_chain_ledger_tx_cache_find_out_cond(dap_ledger_t *a_le * a_public_key[in] public key that signed the transaction * a_public_key_size[in] public key size */ -uint256_t dap_chain_ledger_tx_cache_get_out_cond_value(dap_ledger_t *a_ledger, dap_chain_addr_t *a_addr, - dap_chain_tx_out_cond_t **tx_out_cond) +uint256_t dap_chain_ledger_tx_cache_get_out_cond_value(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_subtype_t a_cond_type, + dap_chain_addr_t *a_addr, dap_chain_tx_out_cond_t **tx_out_cond) + { uint256_t l_ret_value = {}; @@ -4232,14 +4485,11 @@ uint256_t dap_chain_ledger_tx_cache_get_out_cond_value(dap_ledger_t *a_ledger, d dap_chain_tx_out_cond_t *l_tx_out_cond; // Find all transactions do { - - l_tx_tmp = dap_chain_ledger_tx_cache_find_out_cond(a_ledger, &l_tx_first_hash, &l_tx_out_cond, NULL, NULL); - + l_tx_tmp = dap_chain_ledger_tx_cache_find_out_cond(a_ledger, a_cond_type, &l_tx_first_hash, &l_tx_out_cond, NULL, NULL); // Get out_cond item from transaction if(l_tx_tmp) { UNUSED(a_addr); // TODO check relations a_addr with cond_data and public key - if(l_tx_out_cond) { l_ret_value = l_tx_out_cond->header.value; if(tx_out_cond) @@ -4358,7 +4608,8 @@ int dap_chain_ledger_verificator_add(dap_chain_tx_out_cond_subtype_t a_subtype, return 0; } -dap_list_t * dap_chain_ledger_get_txs(dap_ledger_t *a_ledger, size_t a_count, size_t a_page){ +dap_list_t * dap_chain_ledger_get_txs(dap_ledger_t *a_ledger, size_t a_count, size_t a_page, bool a_reverse) +{ dap_ledger_private_t *l_ledger_priv = PVT(a_ledger); size_t l_offset = a_count * (a_page - 1); size_t l_count = HASH_COUNT(l_ledger_priv->ledger_items); @@ -4373,18 +4624,30 @@ dap_list_t * dap_chain_ledger_get_txs(dap_ledger_t *a_ledger, size_t a_count, si if (!l_ledger_priv->ledger_items) { return NULL; } - dap_chain_ledger_tx_item_t *l_ptr = l_ledger_priv->ledger_items->hh.tbl->tail->prev; - if (!l_ptr) - l_ptr = l_ledger_priv->ledger_items; - else - l_ptr = l_ptr->hh.next; - for (dap_chain_ledger_tx_item_t *ptr = l_ptr; ptr != NULL && l_counter < l_end; ptr = ptr->hh.prev){ - if (l_counter >= l_offset){ - dap_chain_datum_tx_t *l_tx = ptr->tx; - l_list = dap_list_append(l_list, l_tx); + if (a_reverse) { + dap_chain_ledger_tx_item_t *l_ptr = l_ledger_priv->ledger_items->hh.tbl->tail->prev; + if (!l_ptr) + l_ptr = l_ledger_priv->ledger_items; + else + l_ptr = l_ptr->hh.next; + for (dap_chain_ledger_tx_item_t *ptr = l_ptr; ptr != NULL && l_counter < l_end; ptr = ptr->hh.prev) { + if (l_counter >= l_offset) { + dap_chain_datum_tx_t *l_tx = ptr->tx; + l_list = dap_list_append(l_list, l_tx); + } + l_counter++; + } + } else { + dap_chain_ledger_tx_item_t *l_ptr = l_ledger_priv->ledger_items; + for (dap_chain_ledger_tx_item_t *ptr = l_ptr; ptr != NULL && l_counter < l_end; ptr = ptr->hh.next) { + if (l_counter >= l_offset) { + dap_chain_datum_tx_t *l_tx = ptr->tx; + l_list = dap_list_append(l_list, l_tx); + } + l_counter++; } - l_counter++; } + return l_list; } @@ -4456,8 +4719,3 @@ dap_list_t *dap_chain_ledger_get_list_tx_cond_outs_with_val(dap_ledger_t *a_ledg } return l_list_used_out; } - -bool dap_chain_ledger_fee_verificator(dap_ledger_t* a_ledger, dap_chain_tx_out_cond_t* a_cond, dap_chain_datum_tx_t* a_tx, bool a_owner) -{ - return false; -} diff --git a/modules/chain/dap_chain_pvt.c b/modules/chain/dap_chain_pvt.c index 33f233562ae7ce9bfef0557b0cc30ed9bcce6040..8481a4be4ff56762082c69e42a6f728aa3a58ca6 100644 --- a/modules/chain/dap_chain_pvt.c +++ b/modules/chain/dap_chain_pvt.c @@ -41,7 +41,3 @@ void dap_chain_add_mempool_notify_callback(dap_chain_t *a_chain, dap_global_db_o l_notifier->cb_arg = a_cb_arg; DAP_CHAIN_PVT(a_chain)->mempool_notifires = dap_list_append(DAP_CHAIN_PVT(a_chain)->mempool_notifires, l_notifier); } - - - - diff --git a/modules/chain/dap_chain_tx.c b/modules/chain/dap_chain_tx.c new file mode 100644 index 0000000000000000000000000000000000000000..b5d3441d6d24add54e3c744f70ec604c3f0ae851 --- /dev/null +++ b/modules/chain/dap_chain_tx.c @@ -0,0 +1,90 @@ +/* + * Authors: + * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net> + * DeM Labs Inc. https://demlabs.net + * Cellframe Network https://cellframe.net + * Copyright (c) 2022 + * 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_chain_tx.h" +#include "dap_chain_datum_tx.h" +#include "dap_chain_ledger.h" +#include "dap_common.h" +#include "uthash.h" +#define LOG_TAG "dap_chain_tx" + +/** + * @brief Wrap without deep copy the datum tx into the deserialed tx + * @param a_tx_packed + * @return + */ +dap_chain_tx_t * dap_chain_tx_wrap_packed(dap_chain_datum_tx_t * a_tx_packed) +{ + dap_chain_tx_t * l_tx = DAP_NEW_Z(dap_chain_tx_t); + dap_hash_fast(a_tx_packed, dap_chain_datum_tx_get_size(a_tx_packed), &l_tx->hash); + l_tx->datum_tx = a_tx_packed; + return l_tx; +} + +/** + * @brief Delete TX. IMPORTANT, doesn't delete wrapped packed tx if it has its store type + * @param a_tx + */ +void dap_chain_tx_delete(dap_chain_tx_t * a_tx) +{ + if(a_tx->prev) + DAP_DELETE(a_tx->prev); + if( a_tx->prev_hash ) + DAP_DELETE(a_tx->prev_hash); + + DAP_DELETE(a_tx); +} + +/** + * @brief dap_chain_tx_dup + * @param a_tx + * @return + */ +dap_chain_tx_t* dap_chain_tx_dup(dap_chain_tx_t * a_tx) +{ + dap_chain_tx_t * l_ret = DAP_DUP(a_tx); + if(a_tx->prev) + l_ret->prev = DAP_DUP_SIZE(a_tx->prev, sizeof(*a_tx->prev)* a_tx->prev_count ); + if(a_tx->prev_hash) + l_ret->prev_hash = DAP_DUP_SIZE(a_tx->prev_hash,sizeof(*a_tx->prev_hash)* a_tx->prev_count ); + return l_ret; +} + +/** + * @brief Add TX in hash table and updated prev/next links + * @param a_tx_hh + * @param a_tx + */ +void dap_chain_tx_hh_add (dap_chain_tx_t * a_tx_hh, dap_chain_tx_t * a_tx) +{ + HASH_ADD(hh,a_tx_hh,hash, sizeof(a_tx->hash),a_tx); +} + +void dap_chain_tx_hh_free (dap_chain_tx_t * a_tx_hh) +{ + dap_chain_tx_t * l_tx = NULL, *l_tmp = NULL; + HASH_ITER(hh, a_tx_hh, l_tx, l_tmp){ + HASH_DELETE(hh, a_tx_hh, l_tx); + dap_chain_tx_delete(l_tx); + } +} diff --git a/modules/chain/dap_chain_vf.c b/modules/chain/dap_chain_vf.c deleted file mode 100644 index d6797bea0775e50c21584eb53e66e6e6c62a54d8..0000000000000000000000000000000000000000 --- a/modules/chain/dap_chain_vf.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Authors: - * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net> - * DeM Labs Inc. https://demlabs.net - * CellFrame https://cellframe.net - * Sources https://gitlab.demlabs.net/cellframe - * Copyright (c) 2017-2019 - * All rights reserved. - - This file is part of CellFrame SDK - - CellFrame SDK is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - CellFrame SDK is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with any DAP based project. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "dap_chain_vf.h" - -#define LOG_TAG "dap_chain_vf" - -/** - * @brief - * empty function - * return 0 - * @return - */ -int dap_chain_vf_init() -{ - return 0; -} - -/** - * @brief - * empty function - */ -void dap_chain_vf_deinit() -{ - -} - -/** - * @brief - * empty function - * return 0 - * @param a_vf_id - * @param a_callback - * @return - */ -int dap_chain_vf_add(dap_chain_vf_id_t a_vf_id, dap_chain_vf_callback_t a_callback) -{ - return 0; -} - -/** - * @brief dap_chain_vf_check - * empty function - * return true - * @param a_vf_id - * @param a_ledger - * @param a_receipt - * @param a_arg - * @param a_arg_size - * @param a_param_value - * @param a_param_value_size - * @return - */ -bool dap_chain_vf_check(dap_chain_vf_id_t a_vf_id, dap_ledger_t * a_ledger, dap_chain_datum_tx_receipt_t * a_receipt, - void *a_arg , size_t a_arg_size, const char * a_param_value, const char * a_param_value_size ) -{ - return true; -} diff --git a/modules/chain/include/dap_chain.h b/modules/chain/include/dap_chain.h index 9b508ea967aa15045aba56c9ad7894d77e9fa4fe..537062aae2216d2e14816b82373c53d76a7099a1 100644 --- a/modules/chain/include/dap_chain.h +++ b/modules/chain/include/dap_chain.h @@ -83,13 +83,11 @@ typedef dap_chain_atom_ptr_t (*dap_chain_callback_atom_iter_find_by_hash_t)(dap_ typedef dap_chain_datum_tx_t* (*dap_chain_callback_tx_find_by_hash_t)(dap_chain_t * ,dap_chain_hash_fast_t *); typedef dap_chain_atom_ptr_t * (*dap_chain_callback_atom_iter_get_atoms_t)(dap_chain_atom_iter_t * ,size_t* ,size_t**); +typedef size_t (*dap_chain_callback_add_datums_t)(dap_chain_t * , dap_chain_datum_t **, size_t ); 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_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 typedef size_t(*dap_chain_callback_get_count)(dap_chain_t *a_chain); @@ -111,7 +109,7 @@ typedef struct dap_chain { dap_chain_id_t id; dap_chain_net_id_t net_id; - uint16_t load_priority; + uint16_t load_priority; char * name; char * net_name; dap_ledger_t * ledger; // If present - pointer to associated ledger @@ -122,12 +120,12 @@ typedef struct dap_chain { uint16_t datum_types_count; dap_chain_type_t *datum_types; - uint16_t default_datum_types_count; - dap_chain_type_t *default_datum_types; + uint16_t default_datum_types_count; + dap_chain_type_t *default_datum_types; uint16_t autoproc_datum_types_count; uint16_t *autoproc_datum_types; - uint256_t minimum_commission; + uint256_t minimum_commission; // To hold it in double-linked lists struct dap_chain * next; @@ -146,8 +144,6 @@ typedef struct dap_chain { dap_chain_callback_atom_verify_t callback_atom_verify; 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 dap_chain_callback_atom_iter_create_t callback_atom_iter_create; diff --git a/modules/chain/include/dap_chain_cell.h b/modules/chain/include/dap_chain_cell.h index 2c5f9246e746be0de3c0f5a1d83eae1d4f1a3267..8ca6a758cbf198c7b5cb1f060090c1dcf868270f 100644 --- a/modules/chain/include/dap_chain_cell.h +++ b/modules/chain/include/dap_chain_cell.h @@ -24,6 +24,7 @@ #pragma once #include <stdint.h> #include <stdio.h> +#include <pthread.h> #include "uthash.h" #include "dap_chain_common.h" diff --git a/modules/chain/include/dap_chain_ledger.h b/modules/chain/include/dap_chain_ledger.h index a77164a96de9ca51c6f50b2e861dc0f88250adde..d53d5452898a902a1e42ce9a6802cf103258ccff 100644 --- a/modules/chain/include/dap_chain_ledger.h +++ b/modules/chain/include/dap_chain_ledger.h @@ -26,9 +26,8 @@ #pragma once #include <stdint.h> #include <stdbool.h> - -//#include "dap_enc_key.h" #include "dap_common.h" +#include "dap_hash.h" #include "dap_list.h" #include "dap_math_ops.h" #include "dap_chain_common.h" @@ -42,7 +41,8 @@ typedef struct dap_ledger { void *_internal; } dap_ledger_t; -typedef bool (*dap_chain_ledger_verificator_callback_t)(dap_ledger_t* a_ledger, dap_chain_tx_out_cond_t* a_cond, dap_chain_datum_tx_t* a_tx, bool a_owner); +typedef bool (* dap_chain_ledger_verificator_callback_t)(dap_ledger_t * a_ledger, dap_hash_fast_t *a_tx_out_hash, dap_chain_tx_out_cond_t *a_tx_out_cond, + dap_chain_datum_tx_t *a_tx_in, bool a_owner); typedef bool (*dap_chain_ledger_verificator_callback_out_t)(dap_ledger_t* a_ledger, dap_chain_datum_tx_t* a_tx, dap_chain_tx_out_cond_t* a_cond); typedef struct dap_chain_net dap_chain_net_t; @@ -65,14 +65,13 @@ typedef struct dap_chain_net dap_chain_net_t; #define DAP_CHAIN_LEDGER_TOKENS_STR "tokens" #define DAP_CHAIN_LEDGER_EMISSIONS_STR "emissions" +#define DAP_CHAIN_LEDGER_STAKE_LOCK_STR "stake_lock" #define DAP_CHAIN_LEDGER_TXS_STR "txs" #define DAP_CHAIN_LEDGER_SPENT_TXS_STR "spent_txs" -#define DAP_CHAIN_LEDGER_SPENT_TXS_TIME_STR "spent_txs_time" #define DAP_CHAIN_LEDGER_BALANCES_STR "balances" int dap_chain_ledger_init(); void dap_chain_ledger_deinit(); -bool dap_chain_global_rwlocks_and_verificators_init(void); dap_ledger_t* dap_chain_ledger_create(uint16_t a_check_flags, char *a_net_name); @@ -145,6 +144,9 @@ int dap_chain_ledger_token_emission_load(dap_ledger_t *a_ledger, byte_t *a_token // Check if it addable int dap_chain_ledger_token_emission_add_check(dap_ledger_t *a_ledger, byte_t *a_token_emission, size_t a_token_emission_size); +/* Add stake-lock item */ +int dap_chain_ledger_emission_for_stake_lock_item_add(dap_ledger_t *a_ledger, const dap_chain_hash_fast_t *a_tx_hash); + dap_chain_datum_token_emission_t *dap_chain_ledger_token_emission_find(dap_ledger_t *a_ledger, const char *a_token_ticker, const dap_chain_hash_fast_t *a_token_emission_hash); @@ -157,16 +159,15 @@ void dap_chain_ledger_addr_get_token_ticker_all(dap_ledger_t *a_ledger, dap_chai char *** a_tickers, size_t * a_tickers_size); // Checking a new transaction before adding to the cache -int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, bool a_from_threshold, - dap_list_t **a_list_bound_items, dap_list_t **a_list_tx_out); - +int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash, + bool a_from_threshold, dap_list_t **a_list_bound_items, dap_list_t **a_list_tx_out); /** * Delete transaction from the cache * * return 1 OK, -1 error, -2 tx_hash not found */ -int dap_chain_ledger_tx_remove(dap_ledger_t *a_ledger, dap_chain_hash_fast_t *a_tx_hash); +int dap_chain_ledger_tx_remove(dap_ledger_t *a_ledger, dap_chain_hash_fast_t *a_tx_hash, dap_time_t a_spent_time); /** * Delete all transactions from the cache @@ -208,6 +209,7 @@ uint256_t dap_chain_ledger_calc_balance_full(dap_ledger_t *a_ledger, const dap_c */ dap_chain_datum_tx_t* dap_chain_ledger_tx_find_by_hash(dap_ledger_t *a_ledger, dap_chain_hash_fast_t *a_tx_hash); bool dap_chain_ledger_tx_spent_find_by_hash(dap_ledger_t *a_ledger, dap_chain_hash_fast_t *a_tx_hash); +dap_hash_fast_t *dap_chain_ledger_get_final_chain_tx_hash(dap_ledger_t *a_ledger, dap_chain_tx_item_type_t a_cond_type, dap_chain_hash_fast_t *a_tx_hash); // Get the transaction in the cache by the addr in out item dap_chain_datum_tx_t* dap_chain_ledger_tx_find_by_addr(dap_ledger_t *a_ledger, const char * a_token, @@ -218,28 +220,31 @@ const dap_chain_datum_tx_t* dap_chain_ledger_tx_find_by_pkey(dap_ledger_t *a_led char *a_public_key, size_t a_public_key_size, dap_chain_hash_fast_t *a_tx_first_hash); // Get the transaction in the cache with the out_cond item -dap_chain_datum_tx_t* dap_chain_ledger_tx_cache_find_out_cond(dap_ledger_t *a_ledger, dap_chain_hash_fast_t *a_tx_first_hash, - dap_chain_tx_out_cond_t **a_out_cond, int *a_out_cond_idx, char *a_token_ticker); +dap_chain_datum_tx_t* dap_chain_ledger_tx_cache_find_out_cond(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_subtype_t a_cond_type, + dap_chain_hash_fast_t *a_tx_first_hash, dap_chain_tx_out_cond_t **a_out_cond, + int *a_out_cond_idx, char *a_token_ticker); // Get all transactions from the cache with the specified out_cond items dap_list_t* dap_chain_ledger_tx_cache_find_out_cond_all(dap_ledger_t *a_ledger, dap_chain_net_srv_uid_t a_srv_uid); // Get the value from all transactions in the cache with out_cond item -uint256_t dap_chain_ledger_tx_cache_get_out_cond_value(dap_ledger_t *a_ledger, dap_chain_addr_t *a_addr, - dap_chain_tx_out_cond_t **tx_out_cond); +uint256_t dap_chain_ledger_tx_cache_get_out_cond_value(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_subtype_t a_cond_type, dap_chain_addr_t *a_addr, + dap_chain_tx_out_cond_t **tx_out_cond); // Get the list of 'out' items from previous transactions with summary value >= than a_value_need // Put this summary value to a_value_transfer dap_list_t *dap_chain_ledger_get_list_tx_outs_with_val(dap_ledger_t *a_ledger, const char *a_token_ticker, const dap_chain_addr_t *a_addr_from, uint256_t a_value_need, uint256_t *a_value_transfer); + // Get the list of 'out_cond' items with summary value >= than a_value_need dap_list_t *dap_chain_ledger_get_list_tx_cond_outs_with_val(dap_ledger_t *a_ledger, const char *a_token_ticker, const dap_chain_addr_t *a_addr_from, dap_chain_tx_out_cond_subtype_t a_subtype, uint256_t a_value_need, uint256_t *a_value_transfer); + // Add new verificator callback with associated subtype. Returns 1 if callback replaced, overwise returns 0 -int dap_chain_ledger_verificator_add(dap_chain_tx_out_cond_subtype_t a_subtype, dap_chain_ledger_verificator_callback_t a_callback, +int dap_chain_ledger_verificator_add(dap_chain_tx_out_cond_subtype_t a_subtype, dap_chain_ledger_verificator_callback_t a_callback, dap_chain_ledger_verificator_callback_out_t a_callback_added); // Getting a list of transactions from the ledger. -dap_list_t * dap_chain_ledger_get_txs(dap_ledger_t *a_ledger, size_t a_count, size_t a_page); +dap_list_t * dap_chain_ledger_get_txs(dap_ledger_t *a_ledger, size_t a_count, size_t a_page, bool a_reverse); -bool dap_chain_ledger_fee_verificator(dap_ledger_t* a_ledger, dap_chain_tx_out_cond_t* a_cond, dap_chain_datum_tx_t* a_tx, bool a_owner); +//bool dap_chain_ledger_fee_verificator(dap_ledger_t* a_ledger, dap_chain_tx_out_cond_t* a_cond, dap_chain_datum_tx_t* a_tx, bool a_owner); diff --git a/modules/chain/include/dap_chain_tx.h b/modules/chain/include/dap_chain_tx.h new file mode 100644 index 0000000000000000000000000000000000000000..fbae57c57cf1bf10389fd5224e63fb006e8aa3c7 --- /dev/null +++ b/modules/chain/include/dap_chain_tx.h @@ -0,0 +1,87 @@ +/* + * Authors: + * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net> + * DeM Labs Inc. https://demlabs.net + * Cellframe Network https://cellframe.net + * Copyright (c) 2022 + * 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_common.h" +#include "dap_chain_datum_token.h" +#include "dap_hash.h" +#include "uthash.h" +#include "dap_chain_datum_tx.h" +#include "dap_chain_datum_tx_items.h" +#include "dap_chain_datum_tx_in.h" +#include "dap_chain_datum_tx_in_cond.h" +#include "dap_chain_datum_tx_out_cond.h" +#include "dap_chain_datum_tx_out_ext.h" +#include "dap_chain_datum_tx_out.h" + +typedef struct dap_chain_tx +{ + enum {CHAIN_TX_STORE_TYPE_PACKED, CHAIN_TX_STORE_TYPE_UNPACKED} store_type; + dap_chain_datum_tx_t * datum_tx; + // Owner + dap_chain_addr_t owner; + const char * token_ticker[DAP_CHAIN_TICKER_SIZE_MAX]; + dap_hash_fast_t token_hash; + dap_chain_datum_token_t *token; + + // Inputs + dap_chain_datum_tx_item_t * in; + dap_chain_tx_in_cond_t * in_cond; + // Outputs + dap_chain_datum_tx_item_t * out; + dap_chain_tx_out_cond_t * out_cond; + + // Previous + struct dap_chain_tx ** prev; + size_t prev_count; + dap_hash_fast_t * prev_hash; + + struct dap_chain_tx ** next; + size_t next_count; + dap_hash_fast_t * next_hash; + + // Hash and UT hash handle + dap_hash_fast_t hash; + UT_hash_handle hh; +} dap_chain_tx_t; + +dap_chain_tx_t * dap_chain_tx_wrap_packed(dap_chain_datum_tx_t * a_tx_packed); +void dap_chain_tx_hh_add (dap_chain_tx_t * a_tx_hh, dap_chain_tx_t * a_tx); + +/** + * @brief Find tx in hashtable by its datum_tx hash + * @param a_tx_hh + * @param a_tx_hash + * @return + */ +static inline dap_chain_tx_t * dap_chain_tx_hh_find (dap_chain_tx_t * a_tx_hh, dap_hash_fast_t* a_tx_hash) +{ + dap_chain_tx_t * l_ret = NULL; + HASH_FIND(hh, a_tx_hh, a_tx_hash, sizeof(*a_tx_hash), l_ret); + return l_ret; +} + +void dap_chain_tx_hh_free (dap_chain_tx_t * a_tx_hh); +dap_chain_tx_t* dap_chain_tx_dup(dap_chain_tx_t * a_tx); + +void dap_chain_tx_delete(dap_chain_tx_t * a_tx); diff --git a/modules/chain/include/dap_chain_vf.h b/modules/chain/include/dap_chain_vf.h deleted file mode 100644 index 75f479004d47ed7025fab470541b03b14d0fd6ec..0000000000000000000000000000000000000000 --- a/modules/chain/include/dap_chain_vf.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Authors: - * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net> - * DeM Labs Inc. https://demlabs.net - * CellFrame https://cellframe.net - * Sources https://gitlab.demlabs.net/cellframe - * Copyright (c) 2017-2019 - * All rights reserved. - - This file is part of CellFrame SDK - - CellFrame SDK is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - CellFrame SDK is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with any DAP based project. If not, see <http://www.gnu.org/licenses/>. -*/ -#pragma once -#include <stdint.h> -#include "dap_chain_common.h" -#include "dap_chain_ledger.h" -#include "dap_chain_datum_tx_receipt.h" -#include "dap_chain_datum_tx_in_cond.h" -#include "dap_chain_datum_tx_out.h" - -typedef uint64_t dap_chain_vf_id_t; -typedef bool (*dap_chain_vf_callback_t) (dap_ledger_t *, dap_chain_datum_tx_receipt_t*, void * ,size_t ); - - - -// Verificator TX_CHECK argument structure -typedef struct dap_chain_vf_tx_check { - dap_chain_hash_fast_t tx_hash; // Transaction hash that should exists, if not null - uint64_t value; // Total tx value that should be exactly same, if not null - uint64_t value_max; // Total tx value not more or equal, if not null - uint64_t value_min; // Total tx value not less or equal, if not null - char token_ticker[DAP_CHAIN_TICKER_SIZE_MAX]; // Tocken ticker is exactly same, if not null -} dap_chain_vf_tx_check_t; - -typedef struct dap_chain_vf_tx_cond_in_check { - /// General TX check - dap_chain_vf_tx_check_t tx_check; - /// If any field is not null it must be equal to receipt info in the input item. - /// Checks first input. TODO: make able to check more than one inputs and input receipts - dap_chain_receipt_info_t receipt_info; -} dap_chain_vf_tx_cond_in_check_t; - - -typedef struct dap_chain_vf_tx_cond_out_srv_pay_check { - /// Do the general tx checks if some of them are not null - dap_chain_vf_tx_check_t tx_check; - /// Check if public key hash its not null - dap_chain_hash_fast_t pkey_hash; - /// Check for service uid if its not null - dap_chain_net_srv_uid_t srv_uid; - /// Check for units if not null - dap_chain_net_srv_price_unit_uid_t unit; - /// Check for maximum price per unit if not null - uint64_t unit_price_max_datoshi; - /// Chek if params are exactly - uint32_t params_size; -} dap_chain_vf_tx_cond_out_check_t; - - -/// General usage verificators IDs - -#define DAP_CHAIN_VF_ID_TX_CHECK 0x0000000000000010 -#define DAP_CHAIN_VF_ID_TX_IN_COND_CHECK 0x0000000000000020 -#define DAP_CHAIN_VF_ID_TX_OUT_COND_SRV_PAY_CHECK 0x0000000000000030 - -#ifdef __cplusplus -extern "C" { -#endif - -// Init general usage verificators -int dap_chain_vf_init(); -void dap_chain_vf_deinit(); - -// Add custom verificator -int dap_chain_vf_add(dap_chain_vf_id_t a_vf_id, dap_chain_vf_callback_t a_callback); - -// Check if verificator pass receipt -bool dap_chain_vf_check(dap_chain_vf_id_t a_vf_id, dap_ledger_t * a_ledger, dap_chain_datum_tx_receipt_t * a_receipt, - void *a_arg , size_t a_arg_size, const char * a_param_value, const char * a_param_value_size ); - -#ifdef __cplusplus -} -#endif diff --git a/modules/channel/chain-net/dap_stream_ch_chain_net.c b/modules/channel/chain-net/dap_stream_ch_chain_net.c index 820ea683a4e0f59526aff15fcb60a7ce23a425ec..335eef1d45485778cafcb3b3296d4b5ab9ab4947 100644 --- a/modules/channel/chain-net/dap_stream_ch_chain_net.c +++ b/modules/channel/chain-net/dap_stream_ch_chain_net.c @@ -198,22 +198,30 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) pthread_mutex_lock(&l_ch_chain_net->mutex); dap_stream_ch_pkt_t *l_ch_pkt = (dap_stream_ch_pkt_t *) a_arg; dap_stream_ch_chain_net_pkt_t *l_ch_chain_net_pkt = (dap_stream_ch_chain_net_pkt_t *) l_ch_pkt->data; - uint16_t l_acl_idx = dap_chain_net_acl_idx_by_id(l_ch_chain_net_pkt->hdr.net_id); + dap_chain_net_t *l_net = dap_chain_net_by_id(l_ch_chain_net_pkt->hdr.net_id); bool l_error = false; char l_err_str[64]; - if (l_acl_idx == (uint16_t)-1) { + if (!l_net) { log_it(L_ERROR, "Invalid net id in packet"); strcpy(l_err_str, "ERROR_NET_INVALID_ID"); l_error = true; } - uint8_t l_acl = a_ch->stream->session->acl ? a_ch->stream->session->acl[l_acl_idx] : 1; - if (!l_error && !l_acl) { - log_it(L_WARNING, "Unauthorized request attempt to network %s", - dap_chain_net_by_id(l_ch_chain_net_pkt->hdr.net_id)->pub.name); - strcpy(l_err_str, "ERROR_NET_NOT_AUTHORIZED"); + if (!l_error && dap_chain_net_get_state(l_net) == NET_STATE_OFFLINE) { + log_it(L_ERROR, "Invalid net id in packet"); + strcpy(l_err_str, "ERROR_NET_IS_OFFLINE"); l_error = true; } - if (l_error) { + if (!l_error) { + uint16_t l_acl_idx = dap_chain_net_get_acl_idx(l_net); + uint8_t l_acl = a_ch->stream->session->acl ? a_ch->stream->session->acl[l_acl_idx] : 1; + if (!l_acl) { + log_it(L_WARNING, "Unauthorized request attempt to network %s", + dap_chain_net_by_id(l_ch_chain_net_pkt->hdr.net_id)->pub.name); + strcpy(l_err_str, "ERROR_NET_NOT_AUTHORIZED"); + l_error = true; + } + } else { + dap_stream_ch_chain_net_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_ERROR , l_ch_chain_net_pkt->hdr.net_id, l_err_str, strlen(l_err_str) + 1); dap_stream_ch_set_ready_to_write_unsafe(a_ch, true); diff --git a/modules/channel/chain-voting/dap_stream_ch_chain_voting.c b/modules/channel/chain-voting/dap_stream_ch_chain_voting.c index ab49b11f39f2216463c69d232bdbce76c6191ba1..7295d303f976b69cbb335c685900f486d6433dd0 100644 --- a/modules/channel/chain-voting/dap_stream_ch_chain_voting.c +++ b/modules/channel/chain-voting/dap_stream_ch_chain_voting.c @@ -18,28 +18,22 @@ typedef struct voting_pkt_in_callback{ voting_ch_callback_t packet_in_callback; } voting_pkt_in_callback_t; -typedef struct voting_pkt_addr -{ - //dap_client_t *client; +typedef struct voting_pkt_addr { dap_chain_node_addr_t node_addr; - //dap_chain_node_client_t *node_client; dap_stream_ch_chain_voting_pkt_t *voting_pkt; } voting_pkt_addr_t; -typedef struct voting_pkt_items -{ - //size_t count; - // dap_stream_ch_chain_voting_pkt_t * pkts_out[]; +typedef struct voting_pkt_items { pthread_rwlock_t rwlock_out; pthread_rwlock_t rwlock_in; dap_list_t * pkts_out; // voting_pkt_addr_t dap_list_t * pkts_in; // dap_stream_ch_chain_voting_pkt_t - // dap_timerfd_t * timer_in; } voting_pkt_items_t; typedef struct voting_node_client_list { dap_chain_node_info_t *node_info; dap_chain_node_client_t *node_client; + dap_events_socket_uuid_t uuid; dap_chain_node_addr_t node_addr; UT_hash_handle hh; } voting_node_client_list_t; @@ -145,16 +139,18 @@ void dap_stream_ch_chain_voting_pkt_broadcast(dap_chain_net_t *a_net, dap_list_t voting_node_client_list_t *l_node_item = NULL; if ( l_remote_node_addr->uint64 != dap_chain_net_get_cur_addr_int(a_net) ) { HASH_FIND(hh, s_node_client_list, l_remote_node_addr, sizeof(dap_chain_node_addr_t), l_node_item); - if ( l_node_item - && l_node_item->node_client - && !dap_client_get_stream(l_node_item->node_client->client) ) { - dap_chain_node_client_close(l_node_item->node_client); - // DAP_DELETE(l_node_item->node_client); - char l_channels[] = {dap_stream_ch_chain_voting_get_id(),0}; - l_node_item->node_client = dap_chain_node_client_connect_channels(a_net, l_node_item->node_info, l_channels); - } - - if (!l_node_item) { + if (l_node_item) { + dap_chain_node_client_t *l_usable = dap_chain_node_client_find(l_node_item->uuid); + if (l_usable && !dap_client_get_stream(l_usable->client)) { + dap_chain_node_client_close(l_node_item->uuid); + l_usable = NULL; + } + if (!l_usable) { + char l_channels[] = {dap_stream_ch_chain_voting_get_id(),0}; + l_node_item->node_client = dap_chain_node_client_connect_channels(a_net, l_node_item->node_info, l_channels); + l_node_item->uuid = l_node_item->node_client->uuid; + } + } else { size_t node_info_size = 0; char *l_key = dap_chain_node_addr_to_hash_str(l_remote_node_addr); dap_chain_node_info_t *l_node_info = @@ -173,6 +169,7 @@ void dap_stream_ch_chain_voting_pkt_broadcast(dap_chain_net_t *a_net, dap_list_t l_node_client_item->node_addr = *l_remote_node_addr; l_node_client_item->node_info = l_node_info; l_node_client_item->node_client = l_node_client; + l_node_client_item->uuid = l_node_client->uuid; HASH_ADD(hh, s_node_client_list, node_addr, sizeof(dap_chain_node_addr_t), l_node_client_item); l_node_item = l_node_client_item; } @@ -303,7 +300,6 @@ static bool s_packet_in_callback_handler(void *a_arg) s_pkt_items->pkts_in = NULL; pthread_rwlock_unlock(&s_pkt_items->rwlock_in); while(l_list_pkts) { - dap_list_t *l_list_next = l_list_pkts->next; dap_stream_ch_chain_voting_pkt_t * l_voting_pkt = (dap_stream_ch_chain_voting_pkt_t *)l_list_pkts->data; for (size_t i=0; i<s_pkt_in_callback_count; i++) { voting_pkt_in_callback_t * l_callback = s_pkt_in_callback+i; @@ -313,7 +309,7 @@ static bool s_packet_in_callback_handler(void *a_arg) } } DAP_DELETE(l_voting_pkt); - l_list_pkts = l_list_next; + l_list_pkts = l_list_pkts->next; } dap_list_free(l_list_pkts); } else { @@ -323,12 +319,16 @@ static bool s_packet_in_callback_handler(void *a_arg) } -static void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) { +static void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) +{ dap_stream_ch_pkt_t * l_ch_pkt = (dap_stream_ch_pkt_t *) a_arg; + if (!l_ch_pkt) + return; pthread_rwlock_wrlock(&s_pkt_items->rwlock_in); - uint32_t l_voting_pkt_size = l_ch_pkt->hdr.size; - dap_stream_ch_chain_voting_pkt_t * l_voting_pkt = DAP_NEW_SIZE(dap_stream_ch_chain_voting_pkt_t, l_voting_pkt_size); - memcpy(l_voting_pkt, &l_ch_pkt->data, l_voting_pkt_size); + size_t l_voting_pkt_size = l_ch_pkt->hdr.size; + if (!l_voting_pkt_size || l_voting_pkt_size > UINT16_MAX) + return; + dap_stream_ch_chain_voting_pkt_t *l_voting_pkt = DAP_DUP_SIZE(&l_ch_pkt->data, l_voting_pkt_size); s_pkt_items->pkts_in = dap_list_append(s_pkt_items->pkts_in, l_voting_pkt); pthread_rwlock_unlock(&s_pkt_items->rwlock_in); } @@ -355,4 +355,4 @@ size_t dap_stream_ch_chain_voting_pkt_write_unsafe(dap_stream_ch_t *a_ch, uint8_ size_t l_ret = dap_stream_ch_pkt_write_unsafe(a_ch, a_type , l_chain_pkt, l_chain_pkt_size); DAP_DELETE(l_chain_pkt); return l_ret; -} \ No newline at end of file +} diff --git a/modules/channel/chain/dap_stream_ch_chain.c b/modules/channel/chain/dap_stream_ch_chain.c index 2ffbd5892e77417dc2f0a6f148f9658bb9b34493..5203deaab1d82a03e72d505176dd9363cfa84390 100644 --- a/modules/channel/chain/dap_stream_ch_chain.c +++ b/modules/channel/chain/dap_stream_ch_chain.c @@ -320,9 +320,8 @@ static bool s_sync_out_chains_proc_callback(dap_proc_thread_t *a_thread, void *a (void ) l_chain->callback_atom_find_by_hash(l_sync_request->chain.request_atom_iter, &l_hash_from, &l_first_size); } - - //pthread_rwlock_unlock(&l_chain->atoms_rwlock); + l_sync_request->chain.request_atom_iter = NULL; dap_proc_thread_worker_exec_callback_inter(a_thread, l_sync_request->worker->id, s_sync_out_chains_first_worker_callback, l_sync_request ); } else { //pthread_rwlock_unlock(&l_chain->atoms_rwlock); @@ -476,7 +475,7 @@ static bool s_sync_update_gdb_proc_callback(dap_proc_thread_t *a_thread, void *a DAP_DELETE(l_sync_request); return true; } - dap_chain_net_add_downlink(l_net, l_ch->stream_worker, l_ch->uuid); + dap_chain_net_add_downlink(l_net, l_ch->stream_worker, l_ch->uuid, l_ch->stream->esocket_uuid); dap_stream_ch_chain_t *l_ch_chain = DAP_STREAM_CH_CHAIN(l_ch); int l_flags = 0; if (dap_chain_net_get_extra_gdb_group(l_net, l_sync_request->request.node_addr)) @@ -632,11 +631,11 @@ static void s_gdb_sync_tsd_worker_callback(dap_worker_t *a_worker, void *a_arg) } /** - * @brief - * - * @param net_id - * @param group_name - * @return dap_chain_t* + * @brief + * + * @param net_id + * @param group_name + * @return dap_chain_t* */ dap_chain_t *dap_chain_get_chain_from_group_name(dap_chain_net_id_t a_net_id, const char *a_group_name) { @@ -720,12 +719,11 @@ static void s_gdb_in_pkt_proc_callback_get_ts_callback(dap_global_db_context_t * dap_chain_t *l_chain = dap_chain_get_chain_from_group_name(l_sync_request->request_hdr.net_id, l_obj->group); - if (l_chain && l_chain->callback_add_datums_with_group) { + if (l_chain && l_chain->callback_add_datums) { log_it(L_WARNING, "New data goes to GDB chain"); const void * restrict l_store_obj_value = l_obj->value; - l_chain->callback_add_datums_with_group(l_chain, - (dap_chain_datum_t** restrict) &l_store_obj_value, 1, - l_obj->group); + l_chain->callback_add_datums(l_chain, + (dap_chain_datum_t** restrict) &l_store_obj_value, 1); } else { // save data to global_db if( dap_global_db_set_raw(l_obj, 1,s_gdb_in_pkt_proc_set_raw_callback, l_sync_request) != 0) { @@ -941,7 +939,7 @@ static bool s_chain_timer_callback(void *a_arg) DAP_DELETE(a_arg); l_ch_chain->activity_timer = NULL; return false; - } + } if (l_ch_chain->state != CHAIN_STATE_WAITING && l_ch_chain->sent_breaks) s_stream_ch_packet_out(l_ch, NULL); // Sending dumb packet with nothing to inform remote thats we're just skiping atoms of GDB's, nothing freezed @@ -1004,18 +1002,15 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) sizeof(l_chain_pkt->hdr)); return; } - s_chain_timer_reset(l_ch_chain); - - size_t l_chain_pkt_data_size = l_ch_pkt->hdr.size-sizeof (l_chain_pkt->hdr) ; - uint16_t l_acl_idx = dap_chain_net_acl_idx_by_id(l_chain_pkt->hdr.net_id ); - if (l_acl_idx == (uint16_t)-1) { + size_t l_chain_pkt_data_size = l_ch_pkt->hdr.size-sizeof (l_chain_pkt->hdr); + dap_chain_net_t *l_net = dap_chain_net_by_id(l_chain_pkt->hdr.net_id); + if (!l_net) { if (l_ch_pkt->hdr.type == DAP_STREAM_CH_CHAIN_PKT_TYPE_ERROR) { if(l_ch_chain->callback_notify_packet_in) { l_ch_chain->callback_notify_packet_in(l_ch_chain, l_ch_pkt->hdr.type, l_chain_pkt, l_chain_pkt_data_size, l_ch_chain->callback_notify_arg); } } else { - log_it(L_ERROR, "Invalid request from %s with ext_id %016"DAP_UINT64_FORMAT_x" net id 0x%016"DAP_UINT64_FORMAT_x" chain id 0x%016"DAP_UINT64_FORMAT_x" cell_id 0x%016"DAP_UINT64_FORMAT_x" in packet", a_ch->stream->esocket->remote_addr_str? a_ch->stream->esocket->remote_addr_str: "<unknown>", l_chain_pkt->hdr.ext_id, l_chain_pkt->hdr.net_id.uint64, l_chain_pkt->hdr.chain_id.uint64, @@ -1028,6 +1023,14 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) } return; } + if (dap_chain_net_get_state(l_net) == NET_STATE_OFFLINE) { + s_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id.uint64, + l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64, + "ERROR_NET_IS_OFFLINE"); + a_ch->stream->esocket->flags |= DAP_SOCK_SIGNAL_CLOSE; + return; + } + uint16_t l_acl_idx = dap_chain_net_get_acl_idx(l_net); uint8_t l_acl = a_ch->stream->session->acl ? a_ch->stream->session->acl[l_acl_idx] : 1; if (!l_acl) { log_it(L_WARNING, "Unauthorized request attempt from %s to network %s", a_ch->stream->esocket->remote_addr_str? @@ -1038,6 +1041,7 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) "ERROR_NET_NOT_AUTHORIZED"); return; } + s_chain_timer_reset(l_ch_chain); switch (l_ch_pkt->hdr.type) { /// --- GDB update --- // Request for gdbs list update @@ -1583,8 +1587,8 @@ static void s_ch_chain_go_idle(dap_stream_ch_chain_t *a_ch_chain) memset(&a_ch_chain->request_hdr, 0, sizeof(a_ch_chain->request_hdr)); if (a_ch_chain->request_atom_iter && a_ch_chain->request_atom_iter->chain && a_ch_chain->request_atom_iter->chain->callback_atom_iter_delete) { - a_ch_chain->request_atom_iter->chain->callback_atom_iter_delete(a_ch_chain->request_atom_iter); - a_ch_chain->request_atom_iter = NULL; + a_ch_chain->request_atom_iter->chain->callback_atom_iter_delete(a_ch_chain->request_atom_iter); + a_ch_chain->request_atom_iter = NULL; } dap_stream_ch_chain_hash_item_t *l_hash_item = NULL, *l_tmp = NULL; @@ -1631,7 +1635,8 @@ static void s_stream_ch_io_complete(dap_events_socket_t *a_es, void *a_arg, int return; if (a_arg) { struct chain_io_complete *l_arg = (struct chain_io_complete *)a_arg; - DAP_STREAM_CH_CHAIN(l_ch)->state = l_arg->state; + if (DAP_STREAM_CH_CHAIN(l_ch)->state == CHAIN_STATE_WAITING) + DAP_STREAM_CH_CHAIN(l_ch)->state = l_arg->state; dap_stream_ch_chain_pkt_write_unsafe(l_ch, l_arg->type, l_arg->net_id, l_arg->chain_id, l_arg->cell_id, l_arg->data, l_arg->data_size); a_es->callbacks.arg = NULL; diff --git a/modules/common/dap_chain_common.c b/modules/common/dap_chain_common.c index fc613668244d38ff576d2b8a2f12b0d151ef95e3..17033619a799a78f5df5fd13544550d0618251f4 100644 --- a/modules/common/dap_chain_common.c +++ b/modules/common/dap_chain_common.c @@ -42,10 +42,9 @@ const dap_chain_net_srv_uid_t c_dap_chain_net_srv_uid_null = {0}; /* * Forward declarations */ -#define DAP_CHAIN$SZ_MAX128DEC DATOSHI_POW /* "340282366920938463463374607431768211455" */ -#define DAP_CHAIN$SZ_MAX256DEC DATOSHI_POW256 /* 2 ^ "340282366920938463463374607431768211455" */ -#define SZ_MAX256SCINOT 83 //1.15792089237316195423570985008687907853269984665640564039457584007913129639935e77 - +#define DAP_CHAIN$SZ_MAX128DEC DATOSHI_POW /* "340282366920938463463374607431768211455" */ +#define DAP_CHAIN$SZ_MAX256DEC DATOSHI_POW256 /* 2 ^ 256 = 1.15792089237316195423570985008687907853269984665640564039457584007913129639935e77*/ +#define DAP_SZ_MAX256SCINOT (DATOSHI_POW256 + 5) char *dap_cvt_uint256_to_str (uint256_t a_uint256); uint256_t dap_cvt_str_to_uint256 (const char *a_256bit_num); @@ -115,25 +114,6 @@ dap_chain_addr_t* dap_chain_addr_from_str(const char *a_str) return NULL; } -#if 0 -/** - * @brief dap_chain_net_id_from_str - * @param a_net_str - * @return - */ -dap_chain_net_id_t dap_chain_net_id_from_str(const char * a_net_str) -{ - dap_chain_net_id_t l_ret={ 0 }; - log_it(L_DEBUG, "net id: %s", a_net_str); - - if (!(l_ret.uint64 = strtoll(a_net_str, NULL, 0))) { - log_it(L_ERROR, "Wrong input string \"%s\" not recognized as network id", a_net_str); - return l_ret; - } - return l_ret; -} -#endif - /** * @brief dap_chain_net_srv_uid_from_str * @param a_net_str @@ -387,7 +367,7 @@ char *dap_chain_balance_to_coins256(uint256_t a_balance) l_strlen = l_len; /* Adjust string len in the buffer */ } - for ( l_cp = l_buf + strlen(l_buf) - 1; *l_cp == '0'; l_cp--) + for ( l_cp = l_buf + strlen(l_buf) - 1; *l_cp == '0' && l_cp >= l_buf; l_cp--) if (*(l_cp - 1) != '.') *l_cp = '\0'; @@ -569,23 +549,22 @@ uint256_t dap_chain_coins_to_balance256(const char *a_coins) { int l_len, l_pos; char l_buf [DAP_CHAIN$SZ_MAX256DEC + 8] = {0}, *l_point; - uint256_t l_nul = {0}; /* "12300000000.0000456" */ - if ( (l_len = strnlen(a_coins, DATOSHI_POW256 + 1)) > DATOSHI_POW256)/* Check for legal length */ /* 1 symbol for \0, one for '.', if more, there is an error */ + if ( (l_len = strnlen(a_coins, DATOSHI_POW256 + 2)) > DATOSHI_POW256 + 1)/* Check for legal length */ /* 1 symbol for \0, one for '.', if more, there is an error */ return log_it(L_WARNING, "Incorrect balance format of '%s' - too long (%d > %d)", a_coins, - l_len, DATOSHI_POW256), l_nul; + l_len, DATOSHI_POW256 + 1), uint256_0; /* Find , check and remove 'precision' dot symbol */ memcpy (l_buf, a_coins, l_len); /* Make local copy */ if ( !(l_point = memchr(l_buf, '.', l_len)) ) /* Is there 'dot' ? */ return log_it(L_WARNING, "Incorrect balance format of '%s' - no precision mark", a_coins), - l_nul; + uint256_0; l_pos = l_len - (l_point - l_buf); /* Check number of decimals after dot */ l_pos--; if ( (l_pos ) > DATOSHI_DEGREE ) - return log_it(L_WARNING, "Incorrect balance format of '%s' - too much precision", l_buf), l_nul; + return log_it(L_WARNING, "Incorrect balance format of '%s' - too much precision", l_buf), uint256_0; /* "123.456" -> "123456" */ memmove(l_point, l_point + 1, l_pos); /* Shift left a right part of the decimal string @@ -608,26 +587,19 @@ uint256_t dap_chain_coins_to_balance256(const char *a_coins) char *dap_cvt_uint256_to_str(uint256_t a_uint256) { - char *l_buf = DAP_NEW_Z_SIZE(char, DATOSHI_POW256 + 1); -#ifdef DAP_GLOBAL_IS_INT128 + char *l_buf = DAP_NEW_Z_SIZE(char, DATOSHI_POW256 + 2); // for decimal dot and trailing zero int l_pos = 0; uint256_t l_value = a_uint256; uint256_t uint256_ten = GET_256_FROM_64(10); uint256_t rem; do { divmod_impl_256(l_value, uint256_ten, &l_value, &rem); +#ifdef DAP_GLOBAL_IS_INT128 l_buf[l_pos++] = rem.lo + '0'; - } while (!IS_ZERO_256(l_value)); #else - int l_pos = 0; - uint256_t l_value = a_uint256; - uint256_t uint256_ten = GET_256_FROM_64(10); - uint256_t rem; - do { - divmod_impl_256(l_value, uint256_ten, &l_value, &rem); l_buf[l_pos++] = rem.lo.lo + (unsigned long long) '0'; - } while (!IS_ZERO_256(l_value)); #endif + } while (!IS_ZERO_256(l_value)); int l_strlen = strlen(l_buf) - 1; for (int i = 0; i < (l_strlen + 1) / 2; i++) { char c = l_buf[i]; @@ -806,7 +778,6 @@ const union __c_pow10_double__ { /* * DESCRIPTION: Convert decimal text string into the uint256_t binary representative. - * We calling twice 128 bit variant of convertors * * INPUTS: * a_256bit_num: Decimal string to be converted @@ -826,20 +797,19 @@ uint256_t dap_cvt_str_to_uint256(const char *a_256bit_num) char l_256bit_num[DAP_CHAIN$SZ_MAX256DEC + 1]; int overflow_flag = 0; - if (!a_256bit_num) { return log_it(L_ERROR, "NULL as an argument"), l_nul; } - /* Compute & check length */ - if ( (l_strlen = strnlen(a_256bit_num, SZ_MAX256SCINOT + 1) ) > SZ_MAX256SCINOT) - return log_it(L_ERROR, "Too many digits in `%s` (%d > %d)", a_256bit_num, l_strlen, SZ_MAX256SCINOT), l_nul; - /* Convert number from xxx.yyyyE+zz to xxxyyyy0000... */ char *l_eptr = strchr(a_256bit_num, 'e'); if (!l_eptr) l_eptr = strchr(a_256bit_num, 'E'); if (l_eptr) { + /* Compute & check length */ + if ( (l_strlen = strnlen(a_256bit_num, DAP_SZ_MAX256SCINOT + 1) ) > DAP_SZ_MAX256SCINOT) + return log_it(L_ERROR, "Too many digits in `%s` (%d > %d)", a_256bit_num, l_strlen, DAP_SZ_MAX256SCINOT), l_nul; + char *l_exp_ptr = l_eptr + 1; if (*l_exp_ptr == '+') l_exp_ptr++; @@ -850,33 +820,34 @@ uint256_t dap_cvt_str_to_uint256(const char *a_256bit_num) if (!l_dot_ptr || l_dot_ptr > l_eptr) return log_it(L_ERROR, "Invalid number format with exponent %d", l_exp), uint256_0; int l_dot_len = l_dot_ptr - a_256bit_num; - if (l_dot_len >= SZ_MAX256SCINOT) + if (l_dot_len >= DATOSHI_POW256) return log_it(L_ERROR, "Too many digits in '%s'", a_256bit_num), uint256_0; int l_exp_len = l_eptr - a_256bit_num - l_dot_len - 1; - if (l_exp_len + l_dot_len + 1 >= SZ_MAX256SCINOT) + if (l_exp_len + l_dot_len + 1 >= DATOSHI_POW256) return log_it(L_ERROR, "Too many digits in '%s'", a_256bit_num), uint256_0; if (l_exp < l_exp_len) { //todo: we need to handle numbers like 1.23456789000000e9 - return log_it(L_ERROR, "Invalid number format with exponent %d and nuber coun after dot %d", l_exp, + return log_it(L_ERROR, "Invalid number format with exponent %d and number count after dot %d", l_exp, l_exp_len), uint256_0; } memcpy(l_256bit_num, a_256bit_num, l_dot_len); memcpy(l_256bit_num + l_dot_len, a_256bit_num + l_dot_len + 1, l_exp_len); int l_zero_cnt = l_exp - l_exp_len; - if (l_zero_cnt > DAP_CHAIN$SZ_MAX256DEC) { + if (l_zero_cnt > DATOSHI_POW256) { //todo: need to handle leading zeroes, like 0.000...123e100 return log_it(L_ERROR, "Too long number for 256 bit: `%s` (%d > %d)", a_256bit_num, l_strlen, DAP_CHAIN$SZ_MAX256DEC), l_nul; } size_t l_pos = l_dot_len + l_exp_len; - for (int i = l_zero_cnt; i && l_pos < DAP_CHAIN$SZ_MAX256DEC; i--) + for (int i = l_zero_cnt; i && l_pos < DATOSHI_POW256; i--) l_256bit_num[l_pos++] = '0'; l_256bit_num[l_pos] = '\0'; l_strlen = l_pos; } else { - //we ahve an decimal string, not sci notation - if ( (l_strlen = strnlen(a_256bit_num, DAP_CHAIN$SZ_MAX256DEC + 1) ) > DAP_CHAIN$SZ_MAX256DEC) - return log_it(L_ERROR, "Too many digits in `%s` (%d > %d)", a_256bit_num, l_strlen, DAP_CHAIN$SZ_MAX256DEC), l_nul; + // We have a decimal string, not sci notation + /* Compute & check length */ + if ( (l_strlen = strnlen(a_256bit_num, DATOSHI_POW256 + 1) ) > DATOSHI_POW256) + return log_it(L_ERROR, "Too many digits in `%s` (%d > %d)", a_256bit_num, l_strlen, DATOSHI_POW256), l_nul; memcpy(l_256bit_num, a_256bit_num, l_strlen); l_256bit_num[l_strlen] = '\0'; } @@ -962,7 +933,7 @@ uint256_t dap_cvt_str_to_uint256(const char *a_256bit_num) } -uint256_t dap_chain_coins_to_balance(const char *a_coins) +inline uint256_t dap_chain_coins_to_balance(const char *a_coins) { return dap_chain_coins_to_balance256(a_coins); // return GET_256_FROM_128(dap_chain_coins_to_balance128(a_coins)); @@ -970,14 +941,14 @@ uint256_t dap_chain_coins_to_balance(const char *a_coins) -char *dap_chain_balance_to_coins(uint256_t a_balance) +inline char *dap_chain_balance_to_coins(uint256_t a_balance) { return dap_chain_balance_to_coins256(a_balance); /* @RRL */ //return dap_chain_balance_to_coins128(a_balance.lo); } -#define __NEW_STARLET__ "BMF" +//#define __NEW_STARLET__ "BMF" #ifdef __NEW_STARLET__ diff --git a/modules/common/dap_chain_datum.c b/modules/common/dap_chain_datum.c index 68eb357f2dff9b129fcaef22cd45443d0912a274..7240e64b6c64e7ca89568132c3ab978830ba167d 100644 --- a/modules/common/dap_chain_datum.c +++ b/modules/common/dap_chain_datum.c @@ -30,7 +30,6 @@ #include "dap_chain_datum_token.h" #include "dap_chain_datum_tx_items.h" #include "dap_chain_datum_hashtree_roots.h" -#include "dap_chain_datum_token.h" #include "dap_enc_base58.h" #define LOG_TAG "dap_chain_datum" @@ -399,13 +398,13 @@ bool dap_chain_datum_dump_tx(dap_chain_datum_tx_t *a_datum, case TX_ITEM_TYPE_OUT_COND: { char *l_value_str = dap_chain_balance_print(((dap_chain_tx_out_cond_t*)item)->header.value); char *l_coins_str = dap_chain_balance_to_coins(((dap_chain_tx_out_cond_t*)item)->header.value); + dap_time_t l_ts_exp = ((dap_chain_tx_out_cond_t*)item)->header.ts_expires; dap_string_append_printf(a_str_out, "\t OUT COND:\n" "\t Header:\n" - "\t\t\t ts_expires: %s\t" - "\t\t\t value: %s (%s)\n" - "\t\t\t subtype: %s\n" - "\t\t SubType:\n", - dap_ctime_r((dap_time_t*)((dap_chain_tx_out_cond_t*)item)->header.ts_expires, l_tmp_buf), + "\t\t ts_expires: %s" + "\t\t value: %s (%s)\n" + "\t\t subtype: %s\n", + l_ts_exp ? dap_ctime_r(&l_ts_exp, l_tmp_buf) : "never\n", l_coins_str, l_value_str, dap_chain_tx_out_cond_subtype_to_str(((dap_chain_tx_out_cond_t*)item)->header.subtype)); @@ -460,6 +459,20 @@ bool dap_chain_datum_dump_tx(dap_chain_datum_tx_t *a_datum, DAP_DELETE(l_value_str); DAP_DELETE(l_coins_str); } break; + case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK: { + dap_time_t l_ts_exp = ((dap_chain_tx_out_cond_t*)item)->subtype.srv_stake_lock.time_unlock; + char *l_value_str = dap_chain_balance_print(((dap_chain_tx_out_cond_t*)item)->header.value); + char *l_coins_str = dap_chain_balance_to_coins(((dap_chain_tx_out_cond_t*)item)->header.value); + dap_string_append_printf(a_str_out, "\t\t\t uid: 0x%016"DAP_UINT64_FORMAT_x"\n" + "\t\t\t value: %s (%s)\n" + "\t\t\t time_unlock %s\n", + ((dap_chain_tx_out_cond_t*)item)->header.srv_uid.uint64, + l_coins_str, + l_value_str, + dap_ctime_r(&l_ts_exp, l_tmp_buf)); + DAP_DELETE(l_value_str); + DAP_DELETE(l_coins_str); + } break; default: break; } } break; @@ -544,8 +557,18 @@ void dap_chain_datum_dump(dap_string_t *a_str_out, dap_chain_datum_t *a_datum, c DAP_DEL_Z(l_value_str); }break; case DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_UPDATE:{ + char *l_value_str = dap_chain_balance_print(l_token->total_supply); dap_string_append(a_str_out,"type: PRIVATE_UPDATE\n"); + dap_string_append(a_str_out, "decimals: 18\n"); + dap_string_append_printf(a_str_out, "auth signs (valid/total) %u/%u\n", l_token->signs_valid, l_token->signs_total); + dap_string_append_printf(a_str_out, "total_supply: %s\n", l_value_str); + dap_string_append(a_str_out,"flags: "); + dap_chain_datum_token_flags_dump(a_str_out, l_token->header_private_update.flags); s_datum_token_dump_tsd(a_str_out, l_token, l_token_size, a_hash_out_type); + size_t l_certs_field_size = l_token_size - sizeof(*l_token) - l_token->header_private_update.tsd_total_size; + dap_chain_datum_token_certs_dump(a_str_out, l_token->data_n_tsd + l_token->header_private_update.tsd_total_size, + l_certs_field_size, a_hash_out_type); + DAP_DEL_Z(l_value_str); }break; case DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL:{ char *l_value_str = dap_chain_balance_print(l_token->total_supply); @@ -562,8 +585,18 @@ void dap_chain_datum_dump(dap_string_t *a_str_out, dap_chain_datum_t *a_datum, c DAP_DEL_Z(l_value_str); }break; case DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_UPDATE:{ + char *l_value_str = dap_chain_balance_print(l_token->total_supply); dap_string_append_printf(a_str_out,"type: CF20_UPDATE\n"); + dap_string_append(a_str_out, "decimals: 18\n"); + dap_string_append_printf(a_str_out, "auth signs (valid/total) %u/%u\n", l_token->signs_valid, l_token->signs_total); + dap_string_append_printf(a_str_out, "total_supply: %s\n", l_value_str); + dap_string_append(a_str_out, "flags: "); + dap_chain_datum_token_flags_dump(a_str_out, l_token->header_native_update.flags); s_datum_token_dump_tsd(a_str_out, l_token, l_token_size, a_hash_out_type); + size_t l_certs_field_size = l_token_size - sizeof(*l_token) - l_token->header_native_update.tsd_total_size; + dap_chain_datum_token_certs_dump(a_str_out, l_token->data_n_tsd + l_token->header_native_update.tsd_total_size, + l_certs_field_size, a_hash_out_type); + DAP_DEL_Z(l_value_str); }break; case DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL:{ char *l_value_str = dap_chain_balance_print(l_token->total_supply); diff --git a/modules/common/dap_chain_datum_token.c b/modules/common/dap_chain_datum_token.c index a2e464d01027e6f220b8441fea3964bcab9a2ba4..87b17712b23fda755554c268b1ec95011ac4e5cb 100644 --- a/modules/common/dap_chain_datum_token.c +++ b/modules/common/dap_chain_datum_token.c @@ -38,12 +38,6 @@ const char *c_dap_chain_datum_token_emission_type_str[]={ [DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_ALGO] = "ALGO", [DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_ATOM_OWNER] = "OWNER", [DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_SMART_CONTRACT] = "SMART_CONTRACT" -// 256 types - // [DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_256_UNDEFINED] = "UNDEFINED", - // [DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_256_AUTH] = "AUTH", - // [DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_256_ALGO] = "ALGO", - // [DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_256_ATOM_OWNER] = "OWNER", - // [DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_256_SMART_CONTRACT] = "SMART_CONTRACT" }; const char *c_dap_chain_datum_token_flag_str[] = { @@ -182,18 +176,27 @@ dap_sign_t ** dap_chain_datum_token_signs_parse(dap_chain_datum_token_t * a_datu size_t l_offset = 0; size_t l_signs_offset = 0; switch (a_datum_token->type) { - case DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_SIMPLE: - l_signs_offset = sizeof(dap_chain_datum_token_old_t); - break; - case DAP_CHAIN_DATUM_TOKEN_TYPE_SIMPLE: - l_signs_offset = sizeof(dap_chain_datum_token_t); - break; - case DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL: - case DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL: - l_signs_offset = sizeof(dap_chain_datum_token_t) + a_datum_token->header_native_decl.tsd_total_size; - break; - default: - break; + case DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_SIMPLE: + l_signs_offset = sizeof(dap_chain_datum_token_old_t); + break; + case DAP_CHAIN_DATUM_TOKEN_TYPE_SIMPLE: + l_signs_offset = sizeof(dap_chain_datum_token_t); + break; + case DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL: + l_signs_offset = sizeof(dap_chain_datum_token_t) + a_datum_token->header_native_decl.tsd_total_size; + break; + case DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL: + l_signs_offset = sizeof(dap_chain_datum_token_t) + a_datum_token->header_private_decl.tsd_total_size; + break; + case DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_UPDATE: + l_signs_offset = sizeof(dap_chain_datum_token_t) + a_datum_token->header_native_update.tsd_total_size; + break; + case DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_UPDATE: + l_signs_offset = sizeof(dap_chain_datum_token_t) + a_datum_token->header_private_update.tsd_total_size; + break; + default: + l_signs_offset = sizeof(dap_chain_datum_token_t); + break; } dap_sign_t **l_ret = DAP_NEW_Z_SIZE(dap_sign_t*, sizeof(dap_sign_t*) * a_datum_token->signs_total); if (!l_ret) { diff --git a/modules/common/dap_chain_datum_tx.c b/modules/common/dap_chain_datum_tx.c index 927f078cfba81dbea2dc87fb3175c4ea2a78c973..82d01e2becb1f3d12096024e8f6cf51838ae1097 100644 --- a/modules/common/dap_chain_datum_tx.c +++ b/modules/common/dap_chain_datum_tx.c @@ -158,22 +158,6 @@ int dap_chain_datum_tx_add_fee_item(dap_chain_datum_tx_t **a_tx, uint256_t a_val return -1; } -/** - * Create 'out_cond' item with fee stake value and insert to transaction - * - * return 1 Ok, -1 Error - */ -int dap_chain_datum_tx_add_fee_stake_item(dap_chain_datum_tx_t **a_tx, uint256_t a_value) -{ - dap_chain_tx_out_cond_t *l_tx_out_fee_stake = dap_chain_datum_tx_item_out_cond_create_fee_stake(a_value); - if(l_tx_out_fee_stake) { - dap_chain_datum_tx_add_item(a_tx, (const uint8_t*) l_tx_out_fee_stake); - DAP_DELETE(l_tx_out_fee_stake); - return 1; - } - return -1; -} - /** * Create 'out' item and insert to transaction * @@ -270,7 +254,7 @@ int dap_chain_datum_tx_verify_sign(dap_chain_datum_tx_t *tx) log_it(L_WARNING,"Incorrect signature's header, possible corrupted data"); return -4; } - if (!dap_sign_verify_size(l_sign, tx_items_size) || dap_sign_verify(l_sign, tx->tx_items, tx_items_pos) != 1) { + if (dap_sign_verify_all(l_sign, tx_items_size, tx->tx_items, tx_items_pos)) { // invalid signature ret = 0; tx_items_pos += l_item_tx_size; diff --git a/modules/common/dap_chain_datum_tx_items.c b/modules/common/dap_chain_datum_tx_items.c index ddf05b010414d73285fed2a3962e011dc283fb51..ddbd99d53b56f1879b8135d13dbf1a31877f38f5 100644 --- a/modules/common/dap_chain_datum_tx_items.c +++ b/modules/common/dap_chain_datum_tx_items.c @@ -76,7 +76,8 @@ static size_t dap_chain_tx_out_ext_get_size(const dap_chain_tx_out_ext_t *a_item static size_t dap_chain_tx_out_cond_get_size(const dap_chain_tx_out_cond_t *a_item) { - return sizeof(dap_chain_tx_out_cond_t) + a_item->params_size; + size_t size = sizeof(dap_chain_tx_out_cond_t) + a_item->tsd_size; + return size; } static size_t dap_chain_tx_pkey_get_size(const dap_chain_tx_pkey_t *a_item) @@ -149,8 +150,6 @@ dap_chain_tx_out_cond_subtype_t dap_chain_tx_out_cond_subtype_from_str(const cha return DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE; else if (!dap_strcmp(a_subtype_str, "srv_stake_lock")) return DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK; - else if(!dap_strcmp(a_subtype_str, "srv_stake_update")) - return DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE_UPDATE; else if(!dap_strcmp(a_subtype_str, "fee")) return DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE; return DAP_CHAIN_TX_OUT_COND_SUBTYPE_UNDEFINED; @@ -228,7 +227,7 @@ dap_chain_tx_token_t *dap_chain_datum_tx_item_token_create(dap_chain_id_t a_id, dap_chain_tx_token_t *l_item = DAP_NEW_Z(dap_chain_tx_token_t); l_item->header.type = TX_ITEM_TYPE_TOKEN; l_item->header.token_emission_chain_id.uint64 = a_id.uint64; - memcpy (& l_item->header.token_emission_hash, a_datum_token_hash, sizeof ( *a_datum_token_hash ) ); + l_item->header.token_emission_hash = *a_datum_token_hash;; strncpy(l_item->header.ticker, a_ticker, sizeof(l_item->header.ticker) - 1); return l_item; } @@ -310,22 +309,6 @@ dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_fee(uint256_t a return l_item; } -/** - * Create item dap_chain_tx_out_cond_t with fee stake subtype - * - * return item, NULL Error - */ -dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_fee_stake(uint256_t a_value) -{ - if (IS_ZERO_256(a_value)) - return NULL; - dap_chain_tx_out_cond_t *l_item = DAP_NEW_Z(dap_chain_tx_out_cond_t); - l_item->header.item_type = TX_ITEM_TYPE_OUT_COND; - l_item->header.value = a_value; - l_item->header.subtype = DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE_STAKE; - return l_item; -} - /** * Create item dap_chain_tx_out_cond_t * @@ -352,8 +335,8 @@ dap_chain_tx_out_cond_t* dap_chain_datum_tx_item_out_cond_create_srv_pay(dap_pke l_item->subtype.srv_pay.unit_price_max_datoshi = a_value_max_per_unit; dap_hash_fast(a_key->pkey, a_key->header.size, &l_item->subtype.srv_pay.pkey_hash); if (a_params && a_params_size) { - l_item->params_size = (uint32_t)a_params_size; - memcpy(l_item->params, a_params, a_params_size); + l_item->tsd_size = (uint32_t)a_params_size; + memcpy(l_item->tsd, a_params, a_params_size); } return l_item; } @@ -361,6 +344,7 @@ dap_chain_tx_out_cond_t* dap_chain_datum_tx_item_out_cond_create_srv_pay(dap_pke dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_xchange(dap_chain_net_srv_uid_t a_srv_uid, dap_chain_net_id_t a_sell_net_id, uint256_t a_value_sell, dap_chain_net_id_t a_buy_net_id, const char *a_token, uint256_t a_value_buy, + const dap_chain_addr_t *a_seller_addr, const void *a_params, uint32_t a_params_size) { if (!a_token) @@ -376,9 +360,10 @@ dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_xchange(dap l_item->subtype.srv_xchange.sell_net_id = a_sell_net_id; strncpy(l_item->subtype.srv_xchange.buy_token, a_token, DAP_CHAIN_TICKER_SIZE_MAX); l_item->subtype.srv_xchange.buy_value = a_value_buy; - l_item->params_size = a_params_size; + l_item->subtype.srv_xchange.seller_addr = *a_seller_addr; + l_item->tsd_size = a_params_size; if (a_params_size) { - memcpy(l_item->params, a_params, a_params_size); + memcpy(l_item->tsd, a_params, a_params_size); } return l_item; } @@ -441,12 +426,12 @@ dap_sign_t* dap_chain_datum_tx_item_sign_get_sig(dap_chain_tx_sig_t *a_tx_sig) * Get item from transaction * * a_tx [in] transaction - * a_item_idx_start[in/out] start index / found index of item in transaction, if 0 then from beginning + * a_item_idx[in/out] start index / found index of item in transaction, if 0 then from beginning * a_type[in] type of item being find, if TX_ITEM_TYPE_ANY - any item * a_item_out_size size[out] size of returned item * return item data, NULL Error index or bad format transaction */ -uint8_t* dap_chain_datum_tx_item_get( dap_chain_datum_tx_t *a_tx, int *a_item_idx_start, +uint8_t* dap_chain_datum_tx_item_get( dap_chain_datum_tx_t *a_tx, int *a_item_idx, dap_chain_tx_item_type_t a_type, int *a_item_out_size) { if(!a_tx) @@ -459,7 +444,7 @@ uint8_t* dap_chain_datum_tx_item_get( dap_chain_datum_tx_t *a_tx, int *a_item_id if(!l_item_size) return NULL; // check index - if(!a_item_idx_start || l_item_idx >= *a_item_idx_start) { + if(!a_item_idx || l_item_idx >= *a_item_idx) { // check type dap_chain_tx_item_type_t l_type = dap_chain_datum_tx_item_get_type(l_item); if (a_type == TX_ITEM_TYPE_ANY || a_type == l_type || @@ -467,8 +452,8 @@ uint8_t* dap_chain_datum_tx_item_get( dap_chain_datum_tx_t *a_tx, int *a_item_id (a_type == TX_ITEM_TYPE_OUT_ALL && l_type == TX_ITEM_TYPE_OUT_OLD) || (a_type == TX_ITEM_TYPE_OUT_ALL && l_type == TX_ITEM_TYPE_OUT_COND) || (a_type == TX_ITEM_TYPE_OUT_ALL && l_type == TX_ITEM_TYPE_OUT_EXT)) { - if(a_item_idx_start) - *a_item_idx_start = l_item_idx; + if(a_item_idx) + *a_item_idx = l_item_idx; if(a_item_out_size) *a_item_out_size = l_item_size; return l_item; @@ -494,7 +479,7 @@ dap_list_t* dap_chain_datum_tx_items_get(dap_chain_datum_tx_t *a_tx, dap_chain_t int l_items_count = 0, l_item_idx_start = 0; uint8_t *l_tx_item; - // Get a_type item from transaction + // Get a_type items from transaction while ((l_tx_item = dap_chain_datum_tx_item_get(a_tx, &l_item_idx_start, a_type, NULL)) != NULL) { items_list = dap_list_append(items_list, l_tx_item); @@ -508,29 +493,44 @@ dap_list_t* dap_chain_datum_tx_items_get(dap_chain_datum_tx_t *a_tx, dap_chain_t return items_list; } +uint8_t *dap_chain_datum_tx_item_get_nth(dap_chain_datum_tx_t *a_tx, dap_chain_tx_item_type_t a_type, int a_item_idx) +{ + uint8_t *l_tx_item; + int l_item_idx = 0; + for (int l_type_idx = 0; l_type_idx <= a_item_idx; l_type_idx++) { + l_tx_item = dap_chain_datum_tx_item_get(a_tx, &l_item_idx, a_type, NULL); + if (!l_tx_item) + break; + l_item_idx++; + } + return l_tx_item; +} + /** * Get tx_out_cond item from transaction * * a_tx [in] transaction - * a_out_num[in/out] start index / found index of item in transaction, if 0 then from beginning + * a_cond_type [in] type of condition to find + * a_out_num[out] found index of item in transaction, -1 if not found * return tx_out_cond, or NULL */ -dap_chain_tx_out_cond_t *dap_chain_datum_tx_out_cond_get(dap_chain_datum_tx_t *a_tx, int *a_out_num) +dap_chain_tx_out_cond_t *dap_chain_datum_tx_out_cond_get(dap_chain_datum_tx_t *a_tx, dap_chain_tx_item_type_t a_cond_type, int *a_out_num) { dap_list_t *l_list_out_items = dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_OUT_ALL, NULL); - int l_prev_cond_idx = l_list_out_items ? 0 : -1; + int l_prev_cond_idx = l_list_out_items ? (a_out_num ? *a_out_num : 0) : -1; dap_chain_tx_out_cond_t *l_res = NULL; for (dap_list_t *l_list_tmp = l_list_out_items; l_list_tmp; l_list_tmp = dap_list_next(l_list_tmp), l_prev_cond_idx++) { // Start from *a_out_num item if a_out_num != NULL if(a_out_num && *a_out_num && l_prev_cond_idx <= *a_out_num) continue; - if (*(uint8_t *)l_list_tmp->data == TX_ITEM_TYPE_OUT_COND) { + if (*(uint8_t *)l_list_tmp->data == TX_ITEM_TYPE_OUT_COND && + ((dap_chain_tx_out_cond_t *)l_list_tmp->data)->header.subtype == a_cond_type) { l_res = l_list_tmp->data; break; } } dap_list_free(l_list_out_items); - if (a_out_num) { + if (a_out_num && l_res) { *a_out_num = l_prev_cond_idx; } return l_res; diff --git a/modules/common/include/dap_chain_common.h b/modules/common/include/dap_chain_common.h index fe8c66d844b38fc22f4844d8c876ecd998491fdb..1ec63018bce6e77c14cd4e00360086a9b50c2ba3 100644 --- a/modules/common/include/dap_chain_common.h +++ b/modules/common/include/dap_chain_common.h @@ -214,10 +214,11 @@ enum dap_chain_tx_item_type { TX_ITEM_TYPE_RECEIPT = 0x70, + TX_ITEM_TYPE_IN_ALL = 0xfd, TX_ITEM_TYPE_OUT_ALL = 0xfe, - TX_ITEM_TYPE_ANY = 0xff, - TX_ITEM_TYPE_UNKNOWN = 0xff + TX_ITEM_TYPE_ANY = 0xff }; +#define TX_ITEM_TYPE_UNKNOWN TX_ITEM_TYPE_ANY typedef byte_t dap_chain_tx_item_type_t; typedef struct dap_chain_receipt_info { @@ -242,9 +243,6 @@ size_t dap_chain_hash_slow_to_str(dap_chain_hash_slow_t * a_hash, char * a_str, char* dap_chain_addr_to_str(const dap_chain_addr_t *a_addr); dap_chain_addr_t* dap_chain_addr_from_str(const char *str); -#if 0 -dap_chain_net_id_t dap_chain_net_id_from_str(const char* a_str); -#endif dap_chain_net_srv_uid_t dap_chain_net_srv_uid_from_str(const char* a_str); void dap_chain_addr_fill(dap_chain_addr_t *a_addr, dap_sign_type_t a_type, dap_chain_hash_fast_t *a_pkey_hash, dap_chain_net_id_t a_net_id); @@ -264,9 +262,7 @@ DAP_STATIC_INLINE uint64_t dap_chain_coins_to_datoshi(long double a_count) DAP_STATIC_INLINE uint128_t dap_chain_uint128_from(uint64_t a_from) { - uint128_t l_ret = uint128_0; - ADD_64_INTO_128(a_from, &l_ret ); - return l_ret; + return GET_128_FROM_64(a_from); } // 256 @@ -275,18 +271,12 @@ uint128_t dap_chain_uint128_from_uint256(uint256_t a_from); // 256 DAP_STATIC_INLINE uint256_t dap_chain_uint256_from(uint64_t a_from) { - uint128_t l_temp_128 = uint128_0; - uint256_t l_ret_256 = uint256_0; - ADD_64_INTO_128(a_from, &l_temp_128); - ADD_128_INTO_256(l_temp_128, &l_ret_256); - return l_ret_256; + return GET_256_FROM_64(a_from); } DAP_STATIC_INLINE uint256_t dap_chain_uint256_from_uint128(uint128_t a_from) { - uint256_t l_ret_256 = uint256_0; - ADD_128_INTO_256(a_from, &l_ret_256); - return l_ret_256; + return GET_256_FROM_128(a_from); } uint64_t dap_chain_uint128_to(uint128_t a_from); diff --git a/modules/common/include/dap_chain_datum.h b/modules/common/include/dap_chain_datum.h index 402ba868899b69f3f88d55b4fd9f8a1829df147a..6a61ea4b0eb4a032b7719d42f171dcdf4d336325 100644 --- a/modules/common/include/dap_chain_datum.h +++ b/modules/common/include/dap_chain_datum.h @@ -28,6 +28,7 @@ #include "dap_math_ops.h" #include "dap_chain_common.h" #include "dap_chain_datum_tx.h" +#include "dap_chain_datum_token.h" #define DAP_CHAIN_DATUM_VERSION 0x00 @@ -68,7 +69,7 @@ #define DAP_CHAIN_DATUM_CUSTOM 0xffff -#define DAP_DATUM_TYPE_STR(t, s) \ +#define DAP_DATUM_TYPE_STR(t, s) \ switch (t) { \ case DAP_CHAIN_DATUM_TX: \ s = "DATUM_TX"; break; \ @@ -84,7 +85,7 @@ s = "DATUM_EVM_DATA"; break; \ case DAP_CHAIN_DATUM_CA: \ s = "DATUM_CA"; break; \ - case DAP_CHAIN_DATUM_SIGNER: \ + case DAP_CHAIN_DATUM_SIGNER: \ s = "DATUM_SIGNER"; break; \ case DAP_CHAIN_DATUM_CUSTOM: \ s = "DATUM_CUSTOM"; break; \ @@ -162,6 +163,7 @@ static inline const char *dap_chain_datum_type_id_to_str(uint16_t a_type_id) return l_ret; } +void s_datum_token_dump_tsd(dap_string_t *a_str_out, dap_chain_datum_token_t *a_token, size_t a_token_size, const char *a_hash_out_type); void dap_chain_datum_dump(dap_string_t *a_str_out, dap_chain_datum_t *a_datum, const char *a_hash_out_type); bool dap_chain_datum_dump_tx(dap_chain_datum_tx_t *a_datum, const char *a_ticker, diff --git a/modules/common/include/dap_chain_datum_token.h b/modules/common/include/dap_chain_datum_token.h index cf3c2cc8b296524b59654e2eee8013b7363b6ada..ffbdd96a6d8b5c0359af575faf4ab89ff6e857c1 100644 --- a/modules/common/include/dap_chain_datum_token.h +++ b/modules/common/include/dap_chain_datum_token.h @@ -70,12 +70,13 @@ typedef struct dap_chain_datum_token{ union { // Simple token declaration. Useful for 100% premined emission without any plays with token and owners after that struct { - // Nothing here + uint16_t decimals; } DAP_ALIGN_PACKED header_simple; // Private token declarations, with flags, manipulations and updates struct { uint16_t flags; // Token declaration flags uint64_t tsd_total_size; // Data size section with values in key-length-value list trailing the signs section + uint16_t decimals; } DAP_ALIGN_PACKED header_private_decl; //native tokens struct { @@ -85,11 +86,15 @@ typedef struct dap_chain_datum_token{ } DAP_ALIGN_PACKED header_native_decl; // Private token update struct { - uint64_t tsd_total_size; // Data size section with extended values in key-length-value list. + uint16_t flags; // Token declaration flags + uint64_t tsd_total_size; // Data size section with values in key-length-value list trailing the signs section + uint16_t decimals; } DAP_ALIGN_PACKED header_private_update; // native token update struct { - uint64_t tsd_total_size; // Data size section with extended values in key-length-value list. + uint16_t flags; // Token declaration flags + uint64_t tsd_total_size; // Data size section with values in key-length-value list trailing the signs section + uint16_t decimals; } DAP_ALIGN_PACKED header_native_update; // Public token declaration struct { @@ -269,25 +274,25 @@ typedef struct { char *key; uint64_t val; } t_datum_token_flag_struct; // new__ static t_datum_token_flag_struct s_flags_table[] = { - { "NO_FLAGS", DAP_CHAIN_DATUM_TOKEN_FLAG_NONE}, - { "ALL_BLOCKED", DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_SENDER_BLOCKED | DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_RECEIVER_BLOCKED}, - { "ALL_FROZEN", DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_SENDER_FROZEN | DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_RECEIVER_FROZEN }, + { "NO_FLAGS", DAP_CHAIN_DATUM_TOKEN_FLAG_NONE}, + { "ALL_BLOCKED", DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_SENDER_BLOCKED | DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_RECEIVER_BLOCKED}, + { "ALL_FROZEN", DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_SENDER_FROZEN | DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_RECEIVER_FROZEN }, { "ALL_ALLOWED", DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_SENDER_ALLOWED | DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_RECEIVER_ALLOWED}, - { "ALL_UNFROZEN", DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_SENDER_UNFROZEN | DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_RECEIVER_UNFROZEN }, + { "ALL_UNFROZEN", DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_SENDER_UNFROZEN | DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_RECEIVER_UNFROZEN }, { "STATIC_ALL", DAP_CHAIN_DATUM_TOKEN_FLAG_STATIC_ALL}, - { "STATIC_FLAGS", DAP_CHAIN_DATUM_TOKEN_FLAG_STATIC_FLAGS }, - { "STATIC_PERMISSIONS_ALL", DAP_CHAIN_DATUM_TOKEN_FLAG_STATIC_PERMISSIONS_ALL }, - { "STATIC_PERMISSIONS_DATUM_TYPE", DAP_CHAIN_DATUM_TOKEN_FLAG_STATIC_PERMISSIONS_DATUM_TYPE }, + { "STATIC_FLAGS", DAP_CHAIN_DATUM_TOKEN_FLAG_STATIC_FLAGS }, + { "STATIC_PERMISSIONS_ALL", DAP_CHAIN_DATUM_TOKEN_FLAG_STATIC_PERMISSIONS_ALL }, + { "STATIC_PERMISSIONS_DATUM_TYPE", DAP_CHAIN_DATUM_TOKEN_FLAG_STATIC_PERMISSIONS_DATUM_TYPE }, { "STATIC_PERMISSIONS_TX_SENDER", DAP_CHAIN_DATUM_TOKEN_FLAG_STATIC_PERMISSIONS_TX_SENDER }, { "STATIC_PERMISSIONS_TX_RECEIVER", DAP_CHAIN_DATUM_TOKEN_FLAG_STATIC_PERMISSIONS_TX_RECEIVER }, - { "ALL_SENDER_BLOCKED", DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_SENDER_BLOCKED}, - { "ALL_SENDER_FROZEN", DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_SENDER_FROZEN}, + { "ALL_SENDER_BLOCKED", DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_SENDER_BLOCKED}, + { "ALL_SENDER_FROZEN", DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_SENDER_FROZEN}, { "ALL_SENDER_ALLOWED", DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_SENDER_ALLOWED}, - { "ALL_SENDER_UNFROZEN", DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_SENDER_UNFROZEN}, - { "ALL_RECEIVER_BLOCKED", DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_RECEIVER_BLOCKED}, - { "ALL_RECEIVER_FROZEN", DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_RECEIVER_FROZEN }, + { "ALL_SENDER_UNFROZEN", DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_SENDER_UNFROZEN}, + { "ALL_RECEIVER_BLOCKED", DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_RECEIVER_BLOCKED}, + { "ALL_RECEIVER_FROZEN", DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_RECEIVER_FROZEN }, { "ALL_RECEIVER_ALLOWED", DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_RECEIVER_ALLOWED}, - { "ALL_RECEIVER_UNFROZEN", DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_RECEIVER_UNFROZEN }, + { "ALL_RECEIVER_UNFROZEN", DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_RECEIVER_UNFROZEN }, }; @@ -329,7 +334,7 @@ static inline char* s_flag_str_from_code(uint64_t code) s_multiple_flag = dap_strjoin(";", s_multiple_flag, s_flags_table[i].key, (char*)NULL); else s_multiple_flag = dap_strjoin(NULL, s_multiple_flag, s_flags_table[i].key, (char*)NULL); - } + } } char* s_no_flags = "NO FLAGS"; @@ -346,7 +351,7 @@ static inline char* s_flag_str_from_code(uint64_t code) * @return */ static inline char* dap_chain_datum_str_token_flag_from_code(uint64_t code) -{ +{ return s_flag_str_from_code(code); } @@ -359,7 +364,7 @@ static inline uint16_t dap_chain_datum_token_flag_from_str(const char* a_str) { if (a_str == NULL) return DAP_CHAIN_DATUM_TOKEN_FLAG_NONE; - + return s_flag_code_from_str(a_str); } @@ -382,7 +387,7 @@ typedef struct dap_chain_datum_token_emission{ uint64_t value; uint256_t value_256; }; - uint8_t nonce[DAP_CHAIN_DATUM_NONCE_SIZE]; + uint8_t nonce[DAP_CHAIN_DATUM_NONCE_SIZE]; } DAP_ALIGN_PACKED hdr; union { struct { diff --git a/modules/common/include/dap_chain_datum_tx.h b/modules/common/include/dap_chain_datum_tx.h index 0b903b6761d9b3525b832029e5afa0659d3fb922..d4f53f1efcf6324d533891b827a4e3a2a0d8f742 100644 --- a/modules/common/include/dap_chain_datum_tx.h +++ b/modules/common/include/dap_chain_datum_tx.h @@ -109,13 +109,6 @@ int dap_chain_datum_tx_add_out_item(dap_chain_datum_tx_t **a_tx, const dap_chain */ int dap_chain_datum_tx_add_fee_item(dap_chain_datum_tx_t **a_tx, uint256_t a_value); -/** - * Create 'out_cond' item with fee stake value and insert to transaction - * - * return 1 Ok, -1 Error - */ -int dap_chain_datum_tx_add_fee_stake_item(dap_chain_datum_tx_t **a_tx, uint256_t a_value); - /** * Create 'out'_ext item and insert to transaction * diff --git a/modules/common/include/dap_chain_datum_tx_items.h b/modules/common/include/dap_chain_datum_tx_items.h index 6326b567f5a44f37f20658d3295ae95dc591eb10..afb2bae94cb72143c602341b56769d3c0876348d 100644 --- a/modules/common/include/dap_chain_datum_tx_items.h +++ b/modules/common/include/dap_chain_datum_tx_items.h @@ -49,6 +49,12 @@ */ dap_chain_tx_item_type_t dap_chain_datum_tx_item_get_type(const void *a_item); +typedef struct dap_chain_datum_tx_item +{ + dap_chain_tx_item_type_t type; + byte_t data[]; +} DAP_ALIGN_PACKED dap_chain_datum_tx_item_t; + /** * Get item name by item type * @@ -156,7 +162,7 @@ dap_chain_tx_out_cond_t* dap_chain_datum_tx_item_out_cond_create_srv_pay(dap_pke */ dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_xchange(dap_chain_net_srv_uid_t a_srv_uid, dap_chain_net_id_t a_sell_net_id, uint256_t a_value_sell, dap_chain_net_id_t a_buy_net_id, - const char *a_token, uint256_t a_value_buy, + const char *a_token, uint256_t a_value_buy, const dap_chain_addr_t *a_seller_addr, const void *a_params, uint32_t a_params_size); /** * Create item dap_chain_tx_out_cond_t for stake service @@ -191,8 +197,9 @@ dap_sign_t *dap_chain_datum_tx_item_sign_get_sig(dap_chain_tx_sig_t *a_tx_sig); */ uint8_t* dap_chain_datum_tx_item_get( dap_chain_datum_tx_t *a_tx, int *a_item_idx_start, dap_chain_tx_item_type_t a_type, int *a_item_out_size); - +// Get Nth item of pointed type +uint8_t *dap_chain_datum_tx_item_get_nth(dap_chain_datum_tx_t *a_tx, dap_chain_tx_item_type_t a_type, int a_item_idx); // Get all item from transaction by type dap_list_t* dap_chain_datum_tx_items_get(dap_chain_datum_tx_t *a_tx, dap_chain_tx_item_type_t a_type, int *a_item_count); // Get conditional out item with it's idx -dap_chain_tx_out_cond_t *dap_chain_datum_tx_out_cond_get(dap_chain_datum_tx_t *a_tx, int *a_out_num); +dap_chain_tx_out_cond_t *dap_chain_datum_tx_out_cond_get(dap_chain_datum_tx_t *a_tx, dap_chain_tx_item_type_t a_cond_type, int *a_out_num); diff --git a/modules/common/include/dap_chain_datum_tx_out_cond.h b/modules/common/include/dap_chain_datum_tx_out_cond.h index 8eb3989e115176ebf66e4d1b6adeb8915e226304..2e41d3497b6cb32aa59bb839a7c4bdda3fa101e6 100644 --- a/modules/common/include/dap_chain_datum_tx_out_cond.h +++ b/modules/common/include/dap_chain_datum_tx_out_cond.h @@ -30,27 +30,22 @@ #include "dap_chain_common.h" #include "dap_chain_datum_tx.h" -// Maximum fee stake, if the actual fee is less, the difference will be returned to the sender -#define MAX_FEE_STAKE GET_256_FROM_64(1000) - enum dap_chain_tx_out_cond_subtype { DAP_CHAIN_TX_OUT_COND_SUBTYPE_UNDEFINED = 0x0, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY = 0x01, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE = 0x02, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE = 0x3, - DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE_UPDATE = 0xFA, // Virtual type for stake update verificator //TODO change it to new type of callback for ledger tx add DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE = 0x04, - DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE_STAKE = 0x05, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK = 0x06, + DAP_CHAIN_TX_OUT_COND_SUBTYPE_ALL = 0xFF }; typedef byte_t dap_chain_tx_out_cond_subtype_t; DAP_STATIC_INLINE const char *dap_chain_tx_out_cond_subtype_to_str(dap_chain_tx_out_cond_subtype_t a_subtype){ switch (a_subtype) { case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY: return "DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY"; - case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE: return "DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE"; + case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE: return "DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE"; case DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE: return "DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE"; - case DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE_STAKE: return "DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE_STAKE"; case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE: return "DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE"; case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK: return "DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK"; default: {} @@ -70,6 +65,7 @@ typedef struct dap_chain_tx_out_cond { dap_chain_tx_out_cond_subtype_t subtype; /// Number of Datoshis ( DAP/10^18 ) to be reserved for service uint256_t value; + byte_t paddding_ext[6]; /// When time expires this output could be used only by transaction owner dap_time_t ts_expires; /// Service uid that only could be used for this out @@ -77,7 +73,7 @@ typedef struct dap_chain_tx_out_cond { #if DAP_CHAIN_NET_SRV_UID_SIZE == 8 byte_t padding[8]; #endif - } header; + } DAP_ALIGN_PACKED header; union { /// Structure with specific for service pay condition subtype struct { @@ -87,7 +83,7 @@ typedef struct dap_chain_tx_out_cond { dap_chain_net_srv_price_unit_uid_t unit; /// Maximum price per unit uint256_t unit_price_max_datoshi; - } srv_pay; + } DAP_ALIGN_PACKED srv_pay; struct { // Chain network to change from dap_chain_net_id_t sell_net_id; @@ -97,7 +93,9 @@ typedef struct dap_chain_tx_out_cond { uint256_t buy_value; // Token ticker to change to char buy_token[DAP_CHAIN_TICKER_SIZE_MAX]; - } srv_xchange; + // Seller address + dap_chain_addr_t seller_addr; + } DAP_ALIGN_PACKED srv_xchange; struct { // Stake holder address dap_chain_addr_t hldr_addr; @@ -109,14 +107,21 @@ typedef struct dap_chain_tx_out_cond { dap_chain_addr_t signing_addr; // Node address of signer with this stake dap_chain_node_addr_t signer_node_addr; - } srv_stake; + } DAP_ALIGN_PACKED srv_stake; + struct { + dap_time_t time_unlock; + dap_hash_fast_t pkey_delegated; + uint256_t reinvest_percent; + uint32_t flags; + byte_t padding[4]; + } DAP_ALIGN_PACKED srv_stake_lock; struct { // Nothing here - } fee; - byte_t free_space[128]; // for future changes - } subtype; - uint32_t params_size; // Condition parameters size - uint8_t params[]; // condition parameters, pkey, hash or smth like this + } DAP_ALIGN_PACKED fee; + byte_t free_space[272]; // TODO increase it to 512 with version update + } DAP_ALIGN_PACKED subtype; + uint32_t tsd_size; // Condition parameters size + uint8_t tsd[]; // condition parameters, pkey, hash or smth like this } DAP_ALIGN_PACKED dap_chain_tx_out_cond_t; diff --git a/modules/consensus/block-poa/dap_chain_cs_block_poa.c b/modules/consensus/block-poa/dap_chain_cs_block_poa.c index 5b105ac6608d646825a5cb4128b8cd5e71e4a19d..28ecf8f8dfbbc5bc2e7bb3ff261afe8f0d052307 100644 --- a/modules/consensus/block-poa/dap_chain_cs_block_poa.c +++ b/modules/consensus/block-poa/dap_chain_cs_block_poa.c @@ -310,8 +310,9 @@ static int s_callback_block_verify(dap_chain_cs_blocks_t * a_blocks, dap_chain_b } // Parse the rest signs size_t l_offset = (byte_t *)l_sign - a_block->meta_n_datum_n_sign; + size_t l_signs_section_size = a_block_size - dap_chain_block_get_sign_offset(a_block, a_block_size); while (l_offset < a_block_size - sizeof(a_block->hdr)) { - if (!dap_sign_verify_size(l_sign, a_block_size)) { + if (!dap_sign_verify_size(l_sign, l_signs_section_size)) { log_it(L_ERROR, "Corrupted block: sign size is bigger than block size"); return -3; } diff --git a/modules/consensus/block-pos/dap_chain_cs_block_pos.c b/modules/consensus/block-pos/dap_chain_cs_block_pos.c index b72b59ffe265654fb8cfa3f2604d1e89e8737a18..69f2a241ebff348536ec49b094da7b1b16072bbf 100644 --- a/modules/consensus/block-pos/dap_chain_cs_block_pos.c +++ b/modules/consensus/block-pos/dap_chain_cs_block_pos.c @@ -201,12 +201,12 @@ static size_t s_callback_block_sign(dap_chain_cs_blocks_t *a_blocks, dap_chain_b } /** - * @brief + * @brief * function makes block singing verification * @param a_block a_blocks dap_chain_cs_blocks_t * @param a_block dap_chain_block_t * @param a_block_size size_t size of block object - * @return int + * @return int */ static int s_callback_block_verify(dap_chain_cs_blocks_t *a_blocks, dap_chain_block_t *a_block, size_t a_block_size) { @@ -230,6 +230,7 @@ static int s_callback_block_verify(dap_chain_cs_blocks_t *a_blocks, dap_chain_bl } uint16_t l_verified_num = 0; + size_t l_signs_section_size = a_block_size - dap_chain_block_get_sign_offset(a_block, a_block_size); for (size_t l_sig_pos = 0; l_sig_pos < l_signs_count; l_sig_pos++) { dap_sign_t *l_sign = dap_chain_block_sign_get(a_block, a_block_size, l_sig_pos); if (l_sign == NULL) { @@ -237,7 +238,7 @@ static int s_callback_block_verify(dap_chain_cs_blocks_t *a_blocks, dap_chain_bl return -4; } - bool l_sign_size_correct = dap_sign_verify_size(l_sign, a_block_size); + bool l_sign_size_correct = dap_sign_verify_size(l_sign, l_signs_section_size); if (!l_sign_size_correct) { log_it(L_WARNING, "Block's sign #%zu size is incorrect", l_sig_pos); return -44; diff --git a/modules/consensus/block-ton/dap_chain_cs_block_ton.c b/modules/consensus/block-ton/dap_chain_cs_block_ton.c index 9d69a9a92d0908f784385b44980392843a06e278..e49adde197cb06184f206caf4b47a6907838f9d6 100644 --- a/modules/consensus/block-ton/dap_chain_cs_block_ton.c +++ b/modules/consensus/block-ton/dap_chain_cs_block_ton.c @@ -14,37 +14,32 @@ #define LOG_TAG "dap_chain_cs_blocks_ton" static int s_callback_new(dap_chain_t *a_chain, dap_config_t *a_chain_cfg); -static void s_session_packet_in(void * a_arg, dap_chain_node_addr_t * a_sender_node_addr, - dap_chain_hash_fast_t *a_data_hash, uint8_t *a_data, size_t a_data_size); +static void s_session_packet_in(void * a_arg, dap_chain_node_addr_t * a_sender_node_addr, + dap_chain_hash_fast_t *a_data_hash, uint8_t *a_data, size_t a_data_size); static void s_session_candidate_to_chain( dap_chain_cs_block_ton_session_t *a_session, dap_chain_hash_fast_t *a_candidate_hash, - dap_chain_block_t *a_candidate, size_t a_candidate_size); + dap_chain_block_t *a_candidate, size_t a_candidate_size); static void s_session_candidate_submit(dap_chain_cs_block_ton_session_t *a_session); -static bool s_session_timer(); +static void s_session_timer(void *a_arg); static int s_session_atom_validation(dap_chain_cs_blocks_t *a_blocks, dap_chain_block_t *a_block, size_t a_block_size); static uint8_t *s_message_data_sign(dap_chain_cs_block_ton_session_t *a_session, - dap_chain_cs_block_ton_message_t *a_message, size_t *a_sign_size); + dap_chain_cs_block_ton_message_t *a_message, size_t *a_sign_size); static void s_message_send(dap_chain_cs_block_ton_session_t *a_session, uint8_t a_message_type, - uint8_t *a_data, size_t a_data_size, dap_list_t *a_validators); + uint8_t *a_data, size_t a_data_size, dap_list_t *a_validators); static void s_message_chain_add(dap_chain_cs_block_ton_session_t * a_session, dap_chain_node_addr_t * a_sender_node_addr, - dap_chain_cs_block_ton_message_t * a_message, - size_t a_message_size, dap_chain_hash_fast_t *a_message_hash); - + dap_chain_cs_block_ton_message_t * a_message, + size_t a_message_size, dap_chain_hash_fast_t *a_message_hash); static void s_session_round_start(dap_chain_cs_block_ton_session_t *a_session); static bool s_session_send_startsync(dap_chain_cs_block_ton_session_t *a_session); static bool s_session_round_start_callback_load_session_store(dap_global_db_context_t * a_global_db_context,int a_rc, const char * a_group, const char * a_key, const size_t a_values_total, const size_t a_values_shift, const size_t a_values_count, dap_global_db_obj_t * a_values, void * a_arg); - - -static void s_session_block_new_delete(dap_chain_cs_block_ton_session_t *a_session); static void s_session_my_candidate_delete(dap_chain_cs_block_ton_session_t *a_session); -static void s_session_round_finish(dap_chain_cs_block_ton_session_t *a_session, bool a_is_time_proc_lock); +static void s_session_round_finish(dap_chain_cs_block_ton_session_t *a_session, bool a_failed); static dap_chain_node_addr_t *s_session_get_validator( dap_chain_cs_block_ton_session_t *a_session, dap_chain_node_addr_t *a_addr, - dap_list_t *a_validators); -static uint16_t s_session_message_count( - dap_chain_cs_block_ton_session_t *a_session, uint8_t a_round_name, uint8_t a_type, - dap_chain_hash_fast_t *a_candidate_hash, uint16_t *a_attempt_number); + dap_list_t *a_validators); +static uint16_t s_session_message_count(dap_chain_cs_block_ton_session_t *a_session, uint8_t a_type, + dap_chain_hash_fast_t *a_candidate_hash, uint16_t *a_attempt_number); static void s_callback_delete(dap_chain_cs_blocks_t *a_blocks); static int s_callback_created(dap_chain_t *a_chain, dap_config_t *a_chain_net_cfg); static size_t s_callback_block_sign(dap_chain_cs_blocks_t *a_blocks, dap_chain_block_t **a_block_ptr, size_t a_block_size); @@ -54,10 +49,8 @@ static int s_compare_validators_list_stake(const void * a_item1, const void * a_ static int s_compare_validators_list_addr(const void * a_item1, const void * a_item2, void *a_unused); static dap_list_t *s_get_validators_addr_list(dap_chain_cs_block_ton_session_t *a_session); //(dap_chain_t *a_chain); -static bool s_hash_is_null(dap_chain_hash_fast_t *a_hash); - static dap_chain_cs_block_ton_session_t * s_session_items; -static dap_timerfd_t * s_session_cs_timer = NULL; +static dap_interval_timer_t s_session_cs_timer = NULL; typedef struct dap_chain_cs_block_ton_pvt { @@ -72,22 +65,22 @@ typedef struct dap_chain_cs_block_ton_pvt uint16_t poa_validators_count; bool flag_sign_verify; - bool debug; - bool validators_list_by_stake; - uint16_t round_start_sync_timeout; - uint16_t round_start_multiple_of; - uint32_t allowed_clock_offset; - uint32_t session_idle_min; - uint16_t round_candidates_max; - uint16_t next_candidate_delay; - uint16_t round_attempts_max; - uint16_t round_attempt_duration; - uint16_t first_message_delay; - uint16_t my_candidate_attempts_max; - - dap_list_t *ton_nodes_addrs; // dap_chain_node_addr_t - - uint16_t auth_certs_count; + bool debug; + bool validators_list_by_stake; + uint16_t round_start_sync_timeout; + uint16_t round_start_multiple_of; + uint32_t allowed_clock_offset; + uint32_t session_idle_min; + uint16_t round_candidates_max; + uint16_t next_candidate_delay; + uint16_t round_attempts_max; + uint16_t round_attempt_duration; + uint16_t first_message_delay; + uint16_t my_candidate_attempts_max; + + dap_list_t *ton_nodes_addrs; // dap_chain_node_addr_t + + uint16_t auth_certs_count; char *auth_certs_prefix; dap_cert_t ** auth_certs; } dap_chain_cs_block_ton_pvt_t; @@ -95,8 +88,8 @@ typedef struct dap_chain_cs_block_ton_pvt #define PVT(a) ((dap_chain_cs_block_ton_pvt_t *)a->_pvt) int dap_chain_cs_block_ton_init() { - dap_stream_ch_chain_voting_init(); - dap_chain_cs_add("block_ton", s_callback_new); + dap_stream_ch_chain_voting_init(); + dap_chain_cs_add("block_ton", s_callback_new); return 0; } @@ -133,70 +126,70 @@ static int s_callback_new(dap_chain_t *a_chain, dap_config_t *a_chain_cfg) { l_ton_pvt->tokens_hold_size = l_tokens_hold_size; l_ton_pvt->tokens_hold = DAP_NEW_Z_SIZE(char *, sizeof(char *) * l_tokens_hold_size); l_ton_pvt->tokens_hold_value = DAP_NEW_Z_SIZE(uint64_t, l_tokens_hold_value_size * sizeof(uint64_t)); - l_ton_pvt->debug = dap_config_get_item_bool_default(a_chain_cfg,"block-ton","consensus_debug", true); - - l_ton_pvt->validators_list_by_stake = dap_config_get_item_bool_default(a_chain_cfg,"block-ton","validators_list_by_stake", false); - l_ton_pvt->round_start_sync_timeout = dap_config_get_item_uint16_default(a_chain_cfg,"block-ton", "round_start_sync_timeout", 10); - l_ton_pvt->round_start_multiple_of = dap_config_get_item_uint16_default(a_chain_cfg,"block-ton", "round_start_multiple_of", 30); - l_ton_pvt->allowed_clock_offset = dap_config_get_item_uint32_default(a_chain_cfg,"block-ton", "allowed_clock_offset", 5); - l_ton_pvt->session_idle_min = dap_config_get_item_uint32_default(a_chain_cfg,"block-ton", "session_idle_min", 15); - l_ton_pvt->round_candidates_max = dap_config_get_item_uint16_default(a_chain_cfg,"block-ton", "round_candidates_max", 3); - l_ton_pvt->next_candidate_delay = dap_config_get_item_uint16_default(a_chain_cfg,"block-ton", "next_candidate_delay", 2); - l_ton_pvt->round_attempts_max = dap_config_get_item_uint16_default(a_chain_cfg,"block-ton", "round_attempts_max", 4); - l_ton_pvt->round_attempt_duration = dap_config_get_item_uint16_default(a_chain_cfg,"block-ton", "round_attempt_duration", 10); - l_ton_pvt->first_message_delay = dap_config_get_item_uint16_default(a_chain_cfg,"block-ton", "first_message_delay", 3); - l_ton_pvt->my_candidate_attempts_max = dap_config_get_item_uint16_default(a_chain_cfg,"block-ton", "my_candidate_attempts_max", 2); - + l_ton_pvt->debug = dap_config_get_item_bool_default(a_chain_cfg,"block-ton","consensus_debug", true); + + l_ton_pvt->validators_list_by_stake = dap_config_get_item_bool_default(a_chain_cfg,"block-ton","validators_list_by_stake", false); + l_ton_pvt->round_start_sync_timeout = dap_config_get_item_uint16_default(a_chain_cfg,"block-ton", "round_start_sync_timeout", 10); + l_ton_pvt->round_start_multiple_of = dap_config_get_item_uint16_default(a_chain_cfg,"block-ton", "round_start_multiple_of", 30); + l_ton_pvt->allowed_clock_offset = dap_config_get_item_uint32_default(a_chain_cfg,"block-ton", "allowed_clock_offset", 5); + l_ton_pvt->session_idle_min = dap_config_get_item_uint32_default(a_chain_cfg,"block-ton", "session_idle_min", 15); + l_ton_pvt->round_candidates_max = dap_config_get_item_uint16_default(a_chain_cfg,"block-ton", "round_candidates_max", 3); + l_ton_pvt->next_candidate_delay = dap_config_get_item_uint16_default(a_chain_cfg,"block-ton", "next_candidate_delay", 2); + l_ton_pvt->round_attempts_max = dap_config_get_item_uint16_default(a_chain_cfg,"block-ton", "round_attempts_max", 4); + l_ton_pvt->round_attempt_duration = dap_config_get_item_uint16_default(a_chain_cfg,"block-ton", "round_attempt_duration", 10); + l_ton_pvt->first_message_delay = dap_config_get_item_uint16_default(a_chain_cfg,"block-ton", "first_message_delay", 3); + l_ton_pvt->my_candidate_attempts_max = dap_config_get_item_uint16_default(a_chain_cfg,"block-ton", "my_candidate_attempts_max", 2); + l_ton_pvt->ton_nodes_addrs = NULL; l_ton_pvt->auth_certs_prefix = strdup( dap_config_get_item_str_default(a_chain_cfg,"block-ton","auth_certs_prefix", "ton") ); - l_ton_pvt->auth_certs_count = dap_config_get_item_uint16_default(a_chain_cfg,"block-ton","auth_certs_number", 0); + l_ton_pvt->auth_certs_count = dap_config_get_item_uint16_default(a_chain_cfg,"block-ton","auth_certs_number", 0); if ( !l_ton_pvt->validators_list_by_stake ) { // auth by cert for PoA mode - if (l_ton_pvt->auth_certs_count) { + if (l_ton_pvt->auth_certs_count) { l_ton_pvt->auth_certs = DAP_NEW_Z_SIZE(dap_cert_t *, l_ton_pvt->auth_certs_count * sizeof(dap_cert_t*)); - char l_cert_name[512]; - for (size_t i = 0; i < l_ton_pvt->auth_certs_count; i++ ){ - dap_snprintf(l_cert_name, sizeof(l_cert_name), "%s.%zu", l_ton_pvt->auth_certs_prefix, i); - if ((l_ton_pvt->auth_certs[i] = dap_cert_find_by_name( l_cert_name)) == NULL) { - dap_snprintf(l_cert_name, sizeof(l_cert_name), "%s.%zu.pub", l_ton_pvt->auth_certs_prefix, i); - if ((l_ton_pvt->auth_certs[i] = dap_cert_find_by_name(l_cert_name)) == NULL) { - log_it(L_ERROR, "TON: Can't find cert \"%s\"", l_cert_name); - return -1; - } - } - log_it(L_NOTICE, "TON: Initialized auth cert \"%s\"", l_cert_name); - } - } - - uint16_t l_node_addrs_count; - char **l_addrs = dap_config_get_array_str(a_chain_cfg, "block-ton", "ton_nodes_addrs", &l_node_addrs_count); - l_ton_pvt->poa_validators_count = l_node_addrs_count; - for(size_t i = 0; i < l_node_addrs_count; i++) { - dap_chain_node_addr_t *l_node_addr = DAP_NEW_Z(dap_chain_node_addr_t); + char l_cert_name[512]; + for (size_t i = 0; i < l_ton_pvt->auth_certs_count; i++ ){ + dap_snprintf(l_cert_name, sizeof(l_cert_name), "%s.%zu", l_ton_pvt->auth_certs_prefix, i); + if ((l_ton_pvt->auth_certs[i] = dap_cert_find_by_name( l_cert_name)) == NULL) { + dap_snprintf(l_cert_name, sizeof(l_cert_name), "%s.%zu.pub", l_ton_pvt->auth_certs_prefix, i); + if ((l_ton_pvt->auth_certs[i] = dap_cert_find_by_name(l_cert_name)) == NULL) { + log_it(L_ERROR, "TON: Can't find cert \"%s\"", l_cert_name); + return -1; + } + } + log_it(L_NOTICE, "TON: Initialized auth cert \"%s\"", l_cert_name); + } + } + + uint16_t l_node_addrs_count; + char **l_addrs = dap_config_get_array_str(a_chain_cfg, "block-ton", "ton_nodes_addrs", &l_node_addrs_count); + l_ton_pvt->poa_validators_count = l_node_addrs_count; + for(size_t i = 0; i < l_node_addrs_count; i++) { + dap_chain_node_addr_t *l_node_addr = DAP_NEW_Z(dap_chain_node_addr_t); if (dap_sscanf(l_addrs[i],NODE_ADDR_FP_STR, NODE_ADDR_FPS_ARGS(l_node_addr) ) != 4 ){ - log_it(L_ERROR,"TON: Wrong address format, should be like 0123::4567::890AB::CDEF"); - DAP_DELETE(l_node_addr); - //DAP_DELETE(l_node_info); - l_node_addr = NULL; - continue; - } - if (l_node_addr) { - log_it(L_MSG, "TON: add validator addr:"NODE_ADDR_FP_STR"", NODE_ADDR_FP_ARGS(l_node_addr)); - l_ton_pvt->ton_nodes_addrs = dap_list_append(l_ton_pvt->ton_nodes_addrs, l_node_addr); - } - } - - } - else { // stake - for (size_t i = 0; i < l_tokens_hold_value_size; i++) { - l_ton_pvt->tokens_hold[i] = dap_strdup(l_tokens_hold[i]); - if ((l_ton_pvt->tokens_hold_value[i] = - strtoull(l_tokens_hold_value_str[i],NULL,10)) == 0) { - log_it(L_CRITICAL, "Token %s has inproper hold value %s", - l_ton_pvt->tokens_hold[i], l_tokens_hold_value_str[i]); - goto lb_err; - } - } - } + log_it(L_ERROR,"TON: Wrong address format, should be like 0123::4567::890AB::CDEF"); + DAP_DELETE(l_node_addr); + //DAP_DELETE(l_node_info); + l_node_addr = NULL; + continue; + } + if (l_node_addr) { + log_it(L_MSG, "TON: add validator addr:"NODE_ADDR_FP_STR"", NODE_ADDR_FP_ARGS(l_node_addr)); + l_ton_pvt->ton_nodes_addrs = dap_list_append(l_ton_pvt->ton_nodes_addrs, l_node_addr); + } + } + + } + else { // stake + for (size_t i = 0; i < l_tokens_hold_value_size; i++) { + l_ton_pvt->tokens_hold[i] = dap_strdup(l_tokens_hold[i]); + if ((l_ton_pvt->tokens_hold_value[i] = + strtoull(l_tokens_hold_value_str[i],NULL,10)) == 0) { + log_it(L_CRITICAL, "Token %s has inproper hold value %s", + l_ton_pvt->tokens_hold[i], l_tokens_hold_value_str[i]); + goto lb_err; + } + } + } // Save old callback if present and set the call of its own (chain callbacks) @@ -219,6 +212,7 @@ lb_err: } static void s_callback_delete(dap_chain_cs_blocks_t *a_blocks) { + dap_interval_timer_delete(s_session_cs_timer); dap_chain_cs_block_ton_t *l_ton = DAP_CHAIN_CS_BLOCK_TON(a_blocks); if (l_ton->_pvt) DAP_DELETE(l_ton->_pvt); @@ -250,37 +244,37 @@ static dap_list_t *s_get_validators_addr_list(dap_chain_cs_block_ton_session_t * dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(a_session->chain); dap_chain_cs_block_ton_t *l_ton = DAP_CHAIN_CS_BLOCK_TON(l_blocks); dap_chain_cs_block_ton_pvt_t *l_ton_pvt = PVT(l_ton); - dap_list_t *l_ret = NULL; - - if ( l_ton_pvt->validators_list_by_stake) { - dap_list_t *l_validators = dap_chain_net_srv_stake_get_validators(); - l_validators = dap_list_sort(l_validators, s_compare_validators_list_stake); - dap_list_t *l_list = dap_list_first(l_validators); - while (l_list){ - dap_list_t *l_next = l_list->next; - dap_chain_node_addr_t *l_addr = - (dap_chain_node_addr_t *)DAP_DUP_SIZE( - &((dap_chain_net_srv_stake_item_t * )l_list->data)->node_addr, - sizeof(dap_chain_node_addr_t)); - DAP_DELETE(l_list->data); - l_ret = dap_list_append(l_ret, l_addr); - l_list = l_next; - } - dap_list_free(l_list); - } - else { - // dap_chain_net_t *l_net = dap_chain_net_by_id(a_session->chain->net_id); - dap_list_t *l_list = dap_list_first(PVT(a_session->ton)->ton_nodes_addrs); - while (l_list) { - dap_chain_node_addr_t *l_addr = - (dap_chain_node_addr_t *)DAP_DUP_SIZE( - l_list->data, sizeof(dap_chain_node_addr_t)); - l_ret = dap_list_append(l_ret, l_addr); - l_list = l_list->next; - } - l_ret = dap_list_sort(l_ret, s_compare_validators_list_addr); - } - return l_ret; + dap_list_t *l_ret = NULL; + + if ( l_ton_pvt->validators_list_by_stake) { + dap_list_t *l_validators = dap_chain_net_srv_stake_get_validators(); + l_validators = dap_list_sort(l_validators, s_compare_validators_list_stake); + dap_list_t *l_list = dap_list_first(l_validators); + while (l_list){ + dap_list_t *l_next = l_list->next; + dap_chain_node_addr_t *l_addr = + (dap_chain_node_addr_t *)DAP_DUP_SIZE( + &((dap_chain_net_srv_stake_item_t * )l_list->data)->node_addr, + sizeof(dap_chain_node_addr_t)); + DAP_DELETE(l_list->data); + l_ret = dap_list_append(l_ret, l_addr); + l_list = l_next; + } + dap_list_free(l_list); + } + else { + // dap_chain_net_t *l_net = dap_chain_net_by_id(a_session->chain->net_id); + dap_list_t *l_list = dap_list_first(PVT(a_session->ton)->ton_nodes_addrs); + while (l_list) { + dap_chain_node_addr_t *l_addr = + (dap_chain_node_addr_t *)DAP_DUP_SIZE( + l_list->data, sizeof(dap_chain_node_addr_t)); + l_ret = dap_list_append(l_ret, l_addr); + l_list = l_list->next; + } + l_ret = dap_list_sort(l_ret, s_compare_validators_list_addr); + } + return l_ret; } static int s_callback_created(dap_chain_t *a_chain, dap_config_t *a_chain_net_cfg) { @@ -304,144 +298,67 @@ static int s_callback_created(dap_chain_t *a_chain, dap_config_t *a_chain_net_cf log_it(L_ERROR, "No sign certificate provided, can't sign any blocks"); } - dap_chain_net_t *l_net = dap_chain_net_by_id(a_chain->net_id); + dap_chain_net_t *l_net = dap_chain_net_by_id(a_chain->net_id); dap_chain_cs_block_ton_session_t *l_session = DAP_NEW_Z(dap_chain_cs_block_ton_session_t); - l_session->chain = a_chain; - l_session->ton = l_ton; + l_session->chain = a_chain; + l_session->ton = l_ton; l_session->my_candidate = NULL; l_session->my_candidate_size = 0; l_session->my_candidate_attempts_count = 0; - l_session->old_round.validators_list = - l_session->cur_round.validators_list = - s_get_validators_addr_list(l_session); - l_session->cur_round.validators_count = dap_list_length(l_session->cur_round.validators_list); + l_session->cur_round.validators_list = s_get_validators_addr_list(l_session); + l_session->cur_round.validators_count = dap_list_length(l_session->cur_round.validators_list); l_session->my_addr = DAP_NEW(dap_chain_node_addr_t); - l_session->my_addr->uint64 = dap_chain_net_get_cur_addr_int(l_net); - - l_session->cur_round.id.uint64 = 1000; - l_session->old_round.id.uint64 = 0; - l_session->gdb_group_store = dap_strdup_printf("local.ton.%s.%s.store", - a_chain->net_name, a_chain->name); - l_session->gdb_group_message = dap_strdup_printf("local.ton.%s.%s.message", - a_chain->net_name, a_chain->name); - l_session->state = DAP_STREAM_CH_CHAIN_SESSION_STATE_IDLE; - l_session->time_proc_lock = false; - - dap_time_t l_time = dap_time_now(); - while (true) { - l_time++; - if ( (l_time % PVT(l_session->ton)->round_start_multiple_of) == 0) { - l_session->ts_round_sync_start = l_time; - break; - } - } - pthread_rwlock_init(&l_session->rwlock, NULL); - - log_it(L_INFO, "TON: init session for net:%s, chain:%s", a_chain->net_name, a_chain->name); - DL_APPEND(s_session_items, l_session); + l_session->my_addr->uint64 = dap_chain_net_get_cur_addr_int(l_net); + + l_session->cur_round.id.uint64 = 1000; + l_session->gdb_group_store = dap_strdup_printf("local.ton.%s.%s.store", + a_chain->net_name, a_chain->name); + l_session->gdb_group_message = dap_strdup_printf("local.ton.%s.%s.message", + a_chain->net_name, a_chain->name); + l_session->state = DAP_STREAM_CH_CHAIN_SESSION_STATE_IDLE; + + dap_time_t l_time = dap_time_now(); + while (true) { + l_time++; + if ( (l_time % l_ton_pvt->round_start_multiple_of) == 0) { + l_session->ts_round_sync_start = l_time; + break; + } + } + pthread_rwlock_init(&l_session->rwlock, NULL); + + log_it(L_INFO, "TON: init session for net:%s, chain:%s", a_chain->net_name, a_chain->name); + DL_APPEND(s_session_items, l_session); dap_chain_node_role_t l_role = dap_chain_net_get_role(l_net); - if ( PVT(l_session->ton)->validators_list_by_stake || + if (l_ton_pvt->validators_list_by_stake || (l_role.enums == NODE_ROLE_MASTER || l_role.enums == NODE_ROLE_ROOT) ) { - if ( s_session_get_validator(l_session, l_session->my_addr, l_session->cur_round.validators_list) ) { - if (!s_session_cs_timer) { - s_session_cs_timer = dap_timerfd_start(1*1000, - (dap_timerfd_callback_t)s_session_timer, - NULL); - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: Consensus main timer is started"); - } - dap_stream_ch_chain_voting_in_callback_add(l_session, s_session_packet_in); - } - } - return 0; -} - -/** - * @brief s_session_round_start_callback_load_session_store - * @param a_global_db_context - * @param a_rc - * @param a_group - * @param a_key - * @param a_values_total - * @param a_values_shift - * @param a_values_count - * @param a_values - * @param a_arg - */ -static bool s_session_round_start_callback_load_session_store(dap_global_db_context_t * a_global_db_context,int a_rc, const char * a_group, const char * a_key, const size_t a_values_total, const size_t a_values_shift, - const size_t a_values_count, dap_global_db_obj_t * a_values, void * a_arg) -{ - dap_chain_cs_block_ton_session_t *l_session = (dap_chain_cs_block_ton_session_t*) a_arg; - if (a_values_count) { - dap_chain_cs_block_ton_store_t *l_store_candidate_ready = NULL; - for (size_t i = 0; i < a_values_count; i++) { - if (!a_values[i].value_len) - continue; - dap_chain_cs_block_ton_store_t *l_store = - (dap_chain_cs_block_ton_store_t *)a_values[i].value; - if ( l_store->hdr.round_id.uint64 != l_session->cur_round.id.uint64 ) { - // dap_chain_global_db_gr_del(dap_strdup(l_objs[i].key), a_session->gdb_group_store); - if ( l_store->hdr.sign_collected ) { - l_store_candidate_ready = l_store; - } + if ( s_session_get_validator(l_session, l_session->my_addr, l_session->cur_round.validators_list) ) { + if (!s_session_cs_timer) { + s_session_cs_timer = dap_interval_timer_create(1000, s_session_timer, NULL); + if (l_ton_pvt->debug) + log_it(L_MSG, "TON: Consensus main timer is started"); } - } - if (l_store_candidate_ready) { - s_session_candidate_to_chain(l_session, &l_store_candidate_ready->hdr.candidate_hash, - (dap_chain_block_t*)l_store_candidate_ready->candidate_n_signs, l_store_candidate_ready->hdr.candidate_size); + dap_stream_ch_chain_voting_in_callback_add(l_session, s_session_packet_in); } } - - dap_list_free_full(l_session->cur_round.validators_list, NULL); - l_session->cur_round.validators_list = s_get_validators_addr_list(l_session); - l_session->cur_round.validators_count = dap_list_length(l_session->cur_round.validators_list); - - dap_timerfd_start(PVT(l_session->ton)->first_message_delay*1000, - (dap_timerfd_callback_t)s_session_send_startsync, - l_session); - - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Start syncing validators ", - l_session->chain->net_name, l_session->chain->name, - l_session->cur_round.id.uint64, l_session->attempt_current_number); - - l_session->time_proc_lock = false; // unlock - pthread_rwlock_unlock(&l_session->rwlock); - return true; + return 0; } - /** * @brief s_session_round_start * @param a_session */ static void s_session_round_start(dap_chain_cs_block_ton_session_t *a_session) { - - a_session->cur_round.validators_start = NULL; - a_session->cur_round.validators_start_count = 0; - - a_session->cur_round.validators_list = NULL; - a_session->cur_round.validators_count = 0; - - a_session->cur_round.candidates_count = 0; - - a_session->ts_round_start = 0; - a_session->ts_round_state_commit = 0; - a_session->attempt_current_number = 1; - - a_session->cur_round.my_candidate_hash = NULL; - a_session->cur_round.last_message_hash = NULL; - a_session->cur_round.messages_count = 0; - a_session->cur_round.submit = false; - - a_session->ts_round_sync_start = dap_time_now(); - a_session->cur_round.id.uint64++; - - dap_global_db_get_all(a_session->gdb_group_store, 0, s_session_round_start_callback_load_session_store, a_session); + memset(&a_session->cur_round, 0, sizeof(a_session->cur_round)); + a_session->ts_round_start = 0; + a_session->ts_round_state_commit = 0; + a_session->attempt_current_number = 1; + a_session->ts_round_sync_start = dap_time_now(); + a_session->cur_round.id.uint64++; } /** @@ -451,36 +368,36 @@ static void s_session_round_start(dap_chain_cs_block_ton_session_t *a_session) */ static bool s_session_send_startsync(dap_chain_cs_block_ton_session_t *a_session) { - dap_chain_cs_block_ton_message_startsync_t *l_startsync = - DAP_NEW_Z(dap_chain_cs_block_ton_message_startsync_t); - l_startsync->ts = a_session->ts_round_sync_start; - l_startsync->round_id.uint64 = a_session->cur_round.id.uint64; - s_message_send(a_session, DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_START_SYNC, - (uint8_t*)l_startsync, sizeof(dap_chain_cs_block_ton_message_startsync_t), - a_session->cur_round.validators_list); - if (PVT(a_session->ton)->debug) + dap_chain_cs_block_ton_message_startsync_t *l_startsync = + DAP_NEW_Z(dap_chain_cs_block_ton_message_startsync_t); + l_startsync->ts = a_session->ts_round_sync_start; + l_startsync->round_id.uint64 = a_session->cur_round.id.uint64; + s_message_send(a_session, DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_START_SYNC, + (uint8_t*)l_startsync, sizeof(dap_chain_cs_block_ton_message_startsync_t), + a_session->cur_round.validators_list); + if (PVT(a_session->ton)->debug) log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U" Sent START_SYNC pkt", - a_session->chain->net_name, a_session->chain->name, a_session->cur_round.id.uint64); + a_session->chain->net_name, a_session->chain->name, a_session->cur_round.id.uint64); - DAP_DELETE(l_startsync); - return false; + DAP_DELETE(l_startsync); + return false; } typedef struct s_session_send_votefor_data { - dap_chain_cs_block_ton_message_votefor_t *votefor; + dap_chain_cs_block_ton_message_votefor_t *votefor; dap_chain_cs_block_ton_session_t *session; } DAP_ALIGN_PACKED s_session_send_votefor_data_t; static bool s_session_send_votefor(s_session_send_votefor_data_t *a_data){ - dap_chain_cs_block_ton_message_votefor_t *l_votefor = a_data->votefor; + dap_chain_cs_block_ton_message_votefor_t *l_votefor = a_data->votefor; dap_chain_cs_block_ton_session_t *l_session = a_data->session; - l_votefor->round_id.uint64 = l_session->cur_round.id.uint64; - s_message_send(l_session, DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE_FOR, - (uint8_t*)l_votefor, sizeof(dap_chain_cs_block_ton_message_votefor_t), - l_session->cur_round.validators_start); - DAP_DELETE(l_votefor); - DAP_DELETE(a_data); - return false; + l_votefor->round_id.uint64 = l_session->cur_round.id.uint64; + s_message_send(l_session, DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE_FOR, + (uint8_t*)l_votefor, sizeof(dap_chain_cs_block_ton_message_votefor_t), + l_session->cur_round.validators_start); + DAP_DELETE(l_votefor); + DAP_DELETE(a_data); + return false; } /** @@ -545,8 +462,6 @@ static bool s_session_round_start_callback_load_session_store_coordinator_state_ l_session->attempt_current_number, l_hash_str); DAP_DELETE(l_hash_str); } - - l_session->time_proc_lock = false; // unlock pthread_rwlock_unlock(&l_session->rwlock); return true; } @@ -581,6 +496,15 @@ static void s_session_proc_state( dap_chain_cs_block_ton_session_t * a_session) // round start a_session->state = DAP_STREAM_CH_CHAIN_SESSION_STATE_WAIT_START; s_session_round_start(a_session); + dap_list_free_full(a_session->cur_round.validators_list, free); + a_session->cur_round.validators_list = s_get_validators_addr_list(a_session); + a_session->cur_round.validators_count = dap_list_length(a_session->cur_round.validators_list); + dap_timerfd_start(PVT(a_session->ton)->first_message_delay*1000, + (dap_timerfd_callback_t)s_session_send_startsync, a_session); + if (PVT(a_session->ton)->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Start syncing validators ", + a_session->chain->net_name, a_session->chain->name, + a_session->cur_round.id.uint64, a_session->attempt_current_number); goto session_processed; // Unlock happens after round start in its callbacks } goto session_unlock; @@ -588,7 +512,7 @@ static void s_session_proc_state( dap_chain_cs_block_ton_session_t * a_session) case DAP_STREAM_CH_CHAIN_SESSION_STATE_WAIT_START: { if ( (l_time-a_session->ts_round_sync_start) >= PVT(a_session->ton)->round_start_sync_timeout ) { // timeout start sync uint16_t l_startsync_count = a_session->cur_round.validators_start_count; - if ( ((float)l_startsync_count/a_session->cur_round.validators_count) >= ((float)2/3) ) { + if (l_startsync_count * 3 >= a_session->cur_round.validators_count * 2) { // if sync more 2/3 validators then start round and submit candidate if (PVT(a_session->ton)->debug) log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu More than 2/3 of the validators are synchronized, so starting the round and send the candidate", @@ -721,13 +645,13 @@ session_processed: // Stay locked * @brief s_session_timer * @return */ -static bool s_session_timer() +static void s_session_timer(void *a_arg) { + UNUSED(a_arg); dap_chain_cs_block_ton_session_t *l_session = NULL; - DL_FOREACH(s_session_items, l_session) { + DL_FOREACH(s_session_items, l_session) { s_session_proc_state(l_session); - } - return true; + } } /** @@ -742,235 +666,179 @@ static void s_session_candidate_to_chain( dap_chain_block_t *a_candidate, size_t a_candidate_size) { - dap_list_t *l_commitsign_list = NULL; + dap_list_t *l_commitsign_list = NULL; + dap_chain_hash_fast_t *l_candidate_hash = NULL; dap_chain_cs_block_ton_message_item_t *l_message_item=NULL, *l_message_tmp=NULL; - HASH_ITER(hh, a_session->old_round.messages_items, l_message_item, l_message_tmp) { - uint8_t l_message_type = l_message_item->message->hdr.type; - if ( l_message_type == DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_COMMIT_SIGN ) { - dap_chain_hash_fast_t *l_candidate_hash = - &((dap_chain_cs_block_ton_message_commitsign_t *) - (l_message_item->message->sign_n_message+l_message_item->message->hdr.sign_size))->candidate_hash; - if ( memcmp(l_candidate_hash, a_candidate_hash, sizeof(dap_chain_hash_fast_t)) == 0) { - l_commitsign_list = dap_list_append(l_commitsign_list, (void*)l_message_item->message); - } - } + HASH_ITER(hh, a_session->cur_round.messages_items, l_message_item, l_message_tmp) { + uint8_t l_message_type = l_message_item->message->hdr.type; + if ( l_message_type == DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_COMMIT_SIGN ) { + l_candidate_hash = &((dap_chain_cs_block_ton_message_commitsign_t *) + (l_message_item->message->sign_n_message+l_message_item->message->hdr.sign_size))->candidate_hash; + if ( memcmp(l_candidate_hash, a_candidate_hash, sizeof(dap_chain_hash_fast_t)) == 0) { + l_commitsign_list = dap_list_append(l_commitsign_list, (void*)l_message_item->message); + } + } } if (!l_commitsign_list) { - return; + return; } - dap_chain_block_t *l_candidate = - (dap_chain_block_t *)DAP_DUP_SIZE(a_candidate, a_candidate_size); - - size_t l_signs_count = 0; - dap_list_t *l_validators_list = dap_list_first(a_session->old_round.validators_start); - while(l_validators_list) { - dap_chain_node_addr_t *l_validator = (dap_chain_node_addr_t *)l_validators_list->data; - l_validators_list = l_validators_list->next; - dap_list_t *l_submit_temp = dap_list_first(l_commitsign_list); - while(l_submit_temp) { - dap_chain_cs_block_ton_message_t *l_message = (dap_chain_cs_block_ton_message_t *)l_submit_temp->data; - dap_chain_cs_block_ton_message_commitsign_t *l_commitsign = - (dap_chain_cs_block_ton_message_commitsign_t *) - (l_message->sign_n_message+l_message->hdr.sign_size); - if( l_message->hdr.is_verified - && l_message->hdr.sender_node_addr.uint64 == l_validator->uint64) { - dap_sign_t *l_candidate_sign = (dap_sign_t *)l_commitsign->candidate_sign; - size_t l_candidate_sign_size = dap_sign_get_size(l_candidate_sign); - if (!l_candidate_sign_size) { - continue; - } - l_candidate = DAP_REALLOC(l_candidate, a_candidate_size+l_candidate_sign_size); - memcpy(((byte_t *)l_candidate)+a_candidate_size, l_candidate_sign, l_candidate_sign_size); - a_candidate_size += l_candidate_sign_size; - l_signs_count++; - } - l_submit_temp = l_submit_temp->next; - } - } - - if ( ((float)l_signs_count/a_session->old_round.validators_count) >= ((float)2/3) ) { - //dap_chain_t *l_chain = a_session->chain; - //dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(l_chain); - dap_chain_atom_verify_res_t l_res = a_session->chain->callback_atom_add(a_session->chain, l_candidate, a_candidate_size); - char *l_candidate_hash_str = dap_chain_hash_fast_to_str_new(a_candidate_hash); - switch (l_res) { - case ATOM_ACCEPT: { - // block save to chain - if (dap_chain_atom_save(a_session->chain, (uint8_t *)l_candidate, a_candidate_size, a_session->chain->cells->id) < 0) { - log_it(L_ERROR, "TON: Can't save atom %s to the file", l_candidate_hash_str); - } - else { - log_it(L_INFO, "TON: atom %s added in chain successfully", l_candidate_hash_str); - } - } break; - case ATOM_MOVE_TO_THRESHOLD: { - log_it(L_INFO, "TON: Thresholded atom with hash %s", l_candidate_hash_str); - } break; - case ATOM_PASS: { - log_it(L_WARNING, "TON: Atom with hash %s not accepted (code ATOM_PASS, already present)", l_candidate_hash_str); + dap_chain_block_t *l_candidate = + (dap_chain_block_t *)DAP_DUP_SIZE(a_candidate, a_candidate_size); + + size_t l_signs_count = 0; + dap_list_t *l_validators_list = dap_list_first(a_session->cur_round.validators_start); + while(l_validators_list) { + dap_chain_node_addr_t *l_validator = (dap_chain_node_addr_t *)l_validators_list->data; + l_validators_list = l_validators_list->next; + dap_list_t *l_submit_temp = dap_list_first(l_commitsign_list); + while(l_submit_temp) { + dap_chain_cs_block_ton_message_t *l_message = (dap_chain_cs_block_ton_message_t *)l_submit_temp->data; + dap_chain_cs_block_ton_message_commitsign_t *l_commitsign = + (dap_chain_cs_block_ton_message_commitsign_t *) + (l_message->sign_n_message+l_message->hdr.sign_size); + if( l_message->hdr.is_verified + && l_message->hdr.sender_node_addr.uint64 == l_validator->uint64) { + dap_sign_t *l_candidate_sign = (dap_sign_t *)l_commitsign->candidate_sign; + size_t l_candidate_sign_size = dap_sign_get_size(l_candidate_sign); + if (!l_candidate_sign_size) { + continue; + } + l_candidate = DAP_REALLOC(l_candidate, a_candidate_size+l_candidate_sign_size); + memcpy(((byte_t *)l_candidate)+a_candidate_size, l_candidate_sign, l_candidate_sign_size); + a_candidate_size += l_candidate_sign_size; + l_signs_count++; + } + l_submit_temp = l_submit_temp->next; + } + } + + if (l_signs_count * 3 >= a_session->cur_round.validators_count * 2) { + dap_chain_atom_verify_res_t l_res = a_session->chain->callback_atom_add(a_session->chain, l_candidate, a_candidate_size); + char *l_candidate_hash_str = dap_chain_hash_fast_to_str_new(a_candidate_hash); + switch (l_res) { + case ATOM_ACCEPT: { + // block save to chain + if (dap_chain_atom_save(a_session->chain, (uint8_t *)l_candidate, a_candidate_size, a_session->chain->cells->id) < 0) { + log_it(L_ERROR, "TON: Can't save atom %s to the file", l_candidate_hash_str); + } + else { + log_it(L_INFO, "TON: atom %s added in chain successfully", l_candidate_hash_str); + } + } break; + case ATOM_MOVE_TO_THRESHOLD: { + log_it(L_INFO, "TON: Thresholded atom with hash %s", l_candidate_hash_str); + } break; + case ATOM_PASS: { + log_it(L_WARNING, "TON: Atom with hash %s not accepted (code ATOM_PASS, already present)", l_candidate_hash_str); DAP_DELETE(l_candidate); - } break; - case ATOM_REJECT: { - log_it(L_WARNING,"TON: Atom with hash %s rejected", l_candidate_hash_str); + } break; + case ATOM_REJECT: { + log_it(L_WARNING,"TON: Atom with hash %s rejected", l_candidate_hash_str); DAP_DELETE(l_candidate); - } break; - default: + } break; + default: log_it(L_CRITICAL, "TON: Wtf is this ret code ? Atom hash %s code %d", l_candidate_hash_str, l_res); DAP_DELETE(l_candidate); - } - DAP_DELETE(l_candidate_hash_str); - dap_chain_hash_fast_t l_my_candidate_hash; - dap_hash_fast(a_session->my_candidate, a_session->my_candidate_size, &l_my_candidate_hash); - if (memcmp(&l_my_candidate_hash, a_candidate_hash, - sizeof(dap_chain_hash_fast_t)) == 0) { - s_session_my_candidate_delete(a_session); - } - } - //DAP_DELETE(l_candidate); -} - -/** - * @brief Callback in session state processing timer's context to process session state after GDB callback - * @param a_worker - * @param a_arg - */ -static void s_callback_worker_session_proc_state(dap_worker_t * a_worker, void * a_arg) -{ - dap_chain_cs_block_ton_session_t * l_session = (dap_chain_cs_block_ton_session_t*) a_arg; - s_session_proc_state(l_session); + } + DAP_DELETE(l_candidate_hash_str); + dap_chain_hash_fast_t l_my_candidate_hash; + dap_hash_fast(a_session->my_candidate, a_session->my_candidate_size, &l_my_candidate_hash); + if (dap_hash_fast_compare(&l_my_candidate_hash, a_candidate_hash)) + s_session_my_candidate_delete(a_session); + } } -/** - * @brief s_callback_block_new_add_datums_op_results - * @param a_cs_blocks - * @param a_rc - * @param a_arg - */ -static void s_callback_block_new_add_datums_op_results (dap_chain_cs_blocks_t * a_cs_blocks, int a_rc, void * a_arg) +static void s_session_candidate_submit(dap_chain_cs_block_ton_session_t *a_session) { - dap_chain_cs_block_ton_session_t * l_session = (dap_chain_cs_block_ton_session_t*) a_arg; - dap_chain_t *l_chain = l_session->chain; + dap_chain_t *l_chain = a_session->chain; + s_session_my_candidate_delete(a_session); + a_session->worker = dap_worker_get_current(); + assert (a_session->worker); // It must be called from worker's timer dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(l_chain); - - if ( l_blocks->block_new_size && l_blocks->block_new) { - l_session->my_candidate = (dap_chain_block_t *)DAP_DUP_SIZE(l_blocks->block_new, l_blocks->block_new_size); - l_session->my_candidate_size = l_blocks->block_new_size; - s_session_block_new_delete(l_session); - } - - size_t l_submit_size = l_session->my_candidate ? - sizeof(dap_chain_cs_block_ton_message_submit_t)+l_session->my_candidate_size + a_session->my_candidate = l_blocks->callback_new_block_move(l_blocks, &a_session->my_candidate_size); + size_t l_submit_size = a_session->my_candidate ? + sizeof(dap_chain_cs_block_ton_message_submit_t)+a_session->my_candidate_size : sizeof(dap_chain_cs_block_ton_message_submit_t); - dap_chain_cs_block_ton_message_submit_t *l_submit = DAP_NEW_SIZE(dap_chain_cs_block_ton_message_submit_t, l_submit_size); - l_submit->round_id.uint64 = l_session->cur_round.id.uint64; - l_submit->candidate_size = l_session->my_candidate_size; + l_submit->round_id.uint64 = a_session->cur_round.id.uint64; + l_submit->candidate_size = a_session->my_candidate_size; - bool l_candidate_exists = false; - if ( l_session->my_candidate ) { + if ( a_session->my_candidate ) { dap_chain_hash_fast_t l_candidate_hash; - dap_hash_fast(l_session->my_candidate, l_session->my_candidate_size, &l_candidate_hash); - // pass if this candidate participated in old round - if ( !l_session->old_round.my_candidate_hash - || memcmp(&l_candidate_hash, l_session->old_round.my_candidate_hash, - sizeof(dap_chain_hash_fast_t)) != 0 ) { - l_submit->candidate_hash = l_candidate_hash; - l_session->cur_round.my_candidate_hash = - (dap_chain_hash_fast_t*)DAP_DUP_SIZE(&l_candidate_hash, sizeof(dap_chain_hash_fast_t)); - memcpy(l_submit->candidate, l_session->my_candidate, l_session->my_candidate_size); - if (PVT(l_session->ton)->debug) { - char *l_hash_str = dap_chain_hash_fast_to_str_new(&l_candidate_hash); - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U" Submit my candidate:%s", - l_session->chain->net_name, l_session->chain->name, - l_session->cur_round.id.uint64, l_hash_str); - DAP_DELETE(l_hash_str); - } - l_session->my_candidate_attempts_count++; - l_candidate_exists = true; + dap_hash_fast(a_session->my_candidate, a_session->my_candidate_size, &l_candidate_hash); + a_session->cur_round.my_candidate_hash = l_submit->candidate_hash = l_candidate_hash; + memcpy(l_submit->candidate, a_session->my_candidate, a_session->my_candidate_size); + if (PVT(a_session->ton)->debug) { + char *l_hash_str = dap_chain_hash_fast_to_str_new(&l_candidate_hash); + log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U" Submit my candidate:%s", + a_session->chain->net_name, a_session->chain->name, + a_session->cur_round.id.uint64, l_hash_str); + DAP_DELETE(l_hash_str); } - } - - if (!l_candidate_exists) { // no my candidate, send null hash - l_submit->candidate_hash = (dap_chain_hash_fast_t) { }; - l_session->cur_round.my_candidate_hash = NULL; - if (PVT(l_session->ton)->debug) + a_session->my_candidate_attempts_count++; + } else { // no my candidate, send null hash + a_session->cur_round.my_candidate_hash = l_submit->candidate_hash = (dap_chain_hash_fast_t){}; + if (PVT(a_session->ton)->debug) log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu I don't have a candidate. I submit a null candidate.", - l_session->chain->net_name, l_session->chain->name, - l_session->cur_round.id.uint64, l_session->attempt_current_number); + a_session->chain->net_name, a_session->chain->name, + a_session->cur_round.id.uint64, a_session->attempt_current_number); } - s_message_send(l_session, DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_SUBMIT, - (uint8_t*)l_submit, l_submit_size, l_session->cur_round.validators_start); + s_message_send(a_session, DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_SUBMIT, + (uint8_t*)l_submit, l_submit_size, a_session->cur_round.validators_start); DAP_DELETE(l_submit); - - l_session->time_proc_lock = false; // unlock - l_session->state = DAP_STREAM_CH_CHAIN_SESSION_STATE_CS_PROC_AFTER_SUBMIT; // Seconds stage after candidate submitted - - dap_worker_t * l_worker = l_session->worker; - dap_global_db_context_t * l_gdb_context = (dap_global_db_context_t*) dap_context_current()->_inheritor; - assert(l_worker); - assert(l_gdb_context); - pthread_rwlock_unlock(&l_session->rwlock); - dap_worker_exec_callback_inter( l_gdb_context->queue_worker_callback_input[l_worker->id],s_callback_worker_session_proc_state, l_session ); -} - -static void s_session_candidate_submit(dap_chain_cs_block_ton_session_t *a_session) { - dap_chain_t *l_chain = a_session->chain; - s_session_my_candidate_delete(a_session); - a_session->worker = dap_worker_get_current(); - assert (a_session->worker); // It must be called from worker's timer - - dap_chain_cs_new_block_add_datums(l_chain, s_callback_block_new_add_datums_op_results, a_session); // add new datums from queue } static int s_session_atom_validation(dap_chain_cs_blocks_t *a_blocks, dap_chain_block_t *a_block, size_t a_block_size){ dap_chain_cs_block_ton_t *l_ton = DAP_CHAIN_CS_BLOCK_TON(a_blocks); - dap_chain_atom_verify_res_t l_res = ATOM_ACCEPT; - PVT(l_ton)->flag_sign_verify = false; - l_res = a_blocks->chain->callback_atom_verify(a_blocks->chain, a_block, a_block_size); - PVT(l_ton)->flag_sign_verify = true; - if(l_res == ATOM_ACCEPT){ - return 0; - } + dap_chain_atom_verify_res_t l_res = ATOM_ACCEPT; + PVT(l_ton)->flag_sign_verify = false; + l_res = a_blocks->chain->callback_atom_verify(a_blocks->chain, a_block, a_block_size); + PVT(l_ton)->flag_sign_verify = true; + if(l_res == ATOM_ACCEPT){ + return 0; + } return -1; } -static void s_session_block_new_delete(dap_chain_cs_block_ton_session_t *a_session) { - dap_chain_t *l_chain = a_session->chain; - dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(l_chain); - l_blocks->callback_new_block_del(l_blocks); -} - static void s_session_my_candidate_delete(dap_chain_cs_block_ton_session_t *a_session) { - if (a_session->my_candidate){ - if (PVT(a_session->ton)->debug) { - dap_chain_hash_fast_t l_candidate_hash; - dap_hash_fast(a_session->my_candidate, a_session->my_candidate_size, &l_candidate_hash); - char *l_hash_str = dap_chain_hash_fast_to_str_new(&l_candidate_hash); - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Delete my candidate %s", - a_session->chain->net_name, a_session->chain->name, a_session->cur_round.id.uint64, - a_session->attempt_current_number, l_hash_str ); - DAP_DELETE(l_hash_str); - } - DAP_DEL_Z(a_session->my_candidate); - } + if (a_session->my_candidate){ + if (PVT(a_session->ton)->debug) { + dap_chain_hash_fast_t l_candidate_hash; + dap_hash_fast(a_session->my_candidate, a_session->my_candidate_size, &l_candidate_hash); + char *l_hash_str = dap_chain_hash_fast_to_str_new(&l_candidate_hash); + log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Delete my candidate %s", + a_session->chain->net_name, a_session->chain->name, a_session->cur_round.id.uint64, + a_session->attempt_current_number, l_hash_str ); + DAP_DELETE(l_hash_str); + } + DAP_DEL_Z(a_session->my_candidate); + } a_session->my_candidate_size = 0; - a_session->my_candidate_attempts_count = 0; + a_session->my_candidate_attempts_count = 0; } -static bool s_hash_is_null(dap_chain_hash_fast_t *a_hash){ - if (!a_hash) - return true; - dap_chain_hash_fast_t l_candidate_hash_null={0}; - return (memcmp(&l_candidate_hash_null, a_hash, - sizeof(dap_chain_hash_fast_t)) == 0) - ? true : false; -} +static void s_session_round_clear(dap_chain_cs_block_ton_session_t *a_session) +{ + // Truncate this group + dap_global_db_del(a_session->gdb_group_store, NULL, NULL, NULL); + dap_chain_cs_block_ton_message_item_t *l_message_item=NULL, *l_message_tmp=NULL; + HASH_ITER(hh, a_session->cur_round.messages_items, l_message_item, l_message_tmp) { + HASH_DEL(a_session->cur_round.messages_items, l_message_item); + DAP_DELETE(l_message_item->message); + DAP_DELETE(l_message_item); + } -struct session_round_finish_args{ - dap_chain_cs_block_ton_session_t *session; - bool is_time_proc_lock; -}; + if (a_session->cur_round.validators_start) + // delete only links + dap_list_free(a_session->cur_round.validators_start); + if (a_session->cur_round.validators_list) + // delete validators + dap_list_free_full(a_session->cur_round.validators_list, free); + + dap_chain_cs_block_ton_round_id_t l_round_id = a_session->cur_round.id; + a_session->cur_round = (dap_chain_cs_block_ton_round_t){.id = l_round_id}; +} /** * @brief s_session_round_finish_callback_load_store @@ -988,119 +856,38 @@ static bool s_session_round_finish_callback_load_store(dap_global_db_context_t * const size_t a_values_count, dap_global_db_obj_t * a_values, void * a_arg) { - dap_chain_cs_block_ton_session_t *l_session = ((struct session_round_finish_args *)a_arg)->session; - bool l_is_time_proc_lock = ((struct session_round_finish_args *)a_arg)->is_time_proc_lock; - DAP_DELETE(a_arg); + dap_chain_cs_block_ton_session_t *l_session = (dap_chain_cs_block_ton_session_t *)a_arg; - if(! l_is_time_proc_lock){ // If its not locked we lock it by ourself for writting - pthread_rwlock_wrlock(&l_session->rwlock); // lock for writting - } + pthread_rwlock_wrlock(&l_session->rwlock); // lock for writting l_session->state = DAP_STREAM_CH_CHAIN_SESSION_STATE_IDLE; l_session->ts_round_finish = dap_time_now(); - if (a_values_count) { - dap_chain_cs_block_ton_store_t *l_store_candidate_ready = NULL; - size_t l_candidate_ready_size = 0; - for (size_t i = 0; i < a_values_count; i++) { - if (!a_values[i].value_len) - continue; - dap_chain_cs_block_ton_store_t *l_store = - (dap_chain_cs_block_ton_store_t *)a_values[i].value; - if ( l_store->hdr.round_id.uint64 != l_session->cur_round.id.uint64 - || (l_store->hdr.round_id.uint64 == l_session->cur_round.id.uint64 - && !l_store->hdr.sign_collected) ) { - dap_global_db_del_unsafe(a_global_db_context,l_session->gdb_group_store,a_values[i].key ); - if ( l_store->hdr.sign_collected ) { - l_store_candidate_ready = l_store; - } + for (size_t i = 0; i < a_values_count; i++) { + if (!a_values[i].value_len) + continue; + dap_chain_cs_block_ton_store_t *l_store = (dap_chain_cs_block_ton_store_t*)a_values[i].value; + if (l_store->hdr.round_id.uint64 != l_session->cur_round.id.uint64) + continue; + if (l_store->hdr.sign_collected) + s_session_candidate_to_chain(l_session, &l_store->hdr.candidate_hash, + (dap_chain_block_t*)l_store->candidate_n_signs, + l_store->hdr.candidate_size); + else if (dap_hash_fast_compare(&l_store->hdr.candidate_hash, &l_session->cur_round.my_candidate_hash)) { + if (PVT(l_session->ton)->debug) { + char *l_hash_str = dap_chain_hash_fast_to_str_new(&l_store->hdr.candidate_hash); + log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu My candidate:%s %s Delete block_new.", + l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, + l_session->attempt_current_number, l_hash_str, + (l_store->hdr.approve_collected ? "approved with consensus" : "didn't collect 2/3 approve.")); + DAP_DELETE(l_hash_str); } + s_session_my_candidate_delete(l_session); + memset(&l_session->cur_round.my_candidate_hash, 0, sizeof(l_session->cur_round.my_candidate_hash)); - if ( l_store->hdr.round_id.uint64 == l_session->cur_round.id.uint64 ) { - if ( l_session->cur_round.my_candidate_hash - //&& !l_store->hdr.approve_collected - && memcmp(&l_store->hdr.candidate_hash, - l_session->cur_round.my_candidate_hash, sizeof(dap_chain_hash_fast_t)) == 0) { - - // delete my candidate if it passed consensus or not collected 2/3 approve - if ( !l_store->hdr.approve_collected || l_store->hdr.sign_collected ) { - // s_session_my_candidate_delete(a_session); - // DAP_DELETE(a_session->cur_round.my_candidate_hash); - // a_session->cur_round.my_candidate_hash=NULL; - if (PVT(l_session->ton)->debug) { - char *l_hash_str = dap_chain_hash_fast_to_str_new(&l_store->hdr.candidate_hash); - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu My candidate:%s %s Delete block_new.", - l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, - l_session->attempt_current_number, l_hash_str, - (l_store->hdr.sign_collected ? "passed consensus!" : "didn't collected 2/3 approve.") ); - DAP_DELETE(l_hash_str); - } - } - } - } } - // if (l_store_candidate_ready) { - // s_session_candidate_to_chain(a_session, &l_store_candidate_ready->hdr.candidate_hash, - // (dap_chain_block_t*)l_store_candidate_ready->candidate_n_signs, l_store_candidate_ready->hdr.candidate_size); - // } - } - - dap_chain_cs_block_ton_message_item_t *l_message_item=NULL, *l_message_tmp=NULL; - HASH_ITER(hh, l_session->old_round.messages_items, l_message_item, l_message_tmp) { - // Clang bug at this, l_message_item should change at every loop cycle - DAP_DELETE(l_message_item->message); - HASH_DEL(l_session->old_round.messages_items, l_message_item); - DAP_DELETE(l_message_item); - } - - if ( l_session->old_round.validators_start ) { - // delete only links - dap_list_free(l_session->old_round.validators_start); - } - l_session->old_round.validators_start = NULL; - - if ( l_session->old_round.validators_list ) { - // delete validators - dap_list_free_full(l_session->old_round.validators_list, NULL); - } - l_session->old_round.validators_list = NULL; - - if ( l_session->old_round.last_message_hash ) { - DAP_DELETE(l_session->old_round.last_message_hash); - l_session->old_round.last_message_hash = NULL; } - - if ( l_session->old_round.my_candidate_hash ) { - DAP_DELETE(l_session->old_round.my_candidate_hash); - l_session->old_round.my_candidate_hash = NULL; - } - - // move cur round to old - l_session->old_round.id.uint64 = l_session->cur_round.id.uint64; - - l_session->old_round.messages_items = l_session->cur_round.messages_items; - l_session->cur_round.messages_items = NULL; - - l_session->old_round.validators_start_count = l_session->cur_round.validators_start_count; - l_session->old_round.validators_start = l_session->cur_round.validators_start; - l_session->cur_round.validators_start = NULL; - - l_session->old_round.validators_count = l_session->cur_round.validators_count; - l_session->old_round.validators_list = l_session->cur_round.validators_list; - l_session->cur_round.validators_list = NULL; - - l_session->old_round.candidates_count = l_session->cur_round.candidates_count; - - l_session->old_round.last_message_hash = l_session->cur_round.last_message_hash; - l_session->cur_round.last_message_hash = NULL; - l_session->old_round.messages_count = l_session->cur_round.messages_count; - - l_session->old_round.my_candidate_hash = l_session->cur_round.my_candidate_hash; - l_session->cur_round.my_candidate_hash = NULL; - - if(l_is_time_proc_lock) // If its time proc locked we have to drop the flag - l_session->time_proc_lock = false; // unlock - + s_session_round_clear(l_session); pthread_rwlock_unlock(&l_session->rwlock); // then unlock anyway return true; } @@ -1110,73 +897,69 @@ static bool s_session_round_finish_callback_load_store(dap_global_db_context_t * * @param a_is_time_proc_lock * @return */ -static void s_session_round_finish(dap_chain_cs_block_ton_session_t *a_session, bool a_is_time_proc_lock) +static void s_session_round_finish(dap_chain_cs_block_ton_session_t *a_session, bool a_failed) { - struct session_round_finish_args * l_args = DAP_NEW_Z(struct session_round_finish_args); - l_args->session = a_session; - l_args->is_time_proc_lock = a_is_time_proc_lock; - if (dap_global_db_get_all(a_session->gdb_group_store,0,s_session_round_finish_callback_load_store, l_args) != 0){ - DAP_DELETE(l_args); - log_it(L_ERROR,"Can't process get_all request for group \"%s\"", a_session->gdb_group_store); + if (a_failed) { + s_session_round_clear(a_session); + return; } + if (dap_global_db_get_all(a_session->gdb_group_store,0,s_session_round_finish_callback_load_store, a_session) != 0) + log_it(L_ERROR,"Can't process get_all request for group \"%s\"", a_session->gdb_group_store); } // this is planned for get validator addr if validator addr list to be changed to stakes, // but currently it using for check validator addr exists -static dap_chain_node_addr_t *s_session_get_validator( - dap_chain_cs_block_ton_session_t * a_session, dap_chain_node_addr_t * a_addr, - dap_list_t *a_validators) { - // dap_chain_cs_block_ton_round_t *l_round = a_round_name == DAP_TON$ROUND_CUR ? // 'c' or 'o' - // &a_session->cur_round : &a_session->old_round; - dap_list_t* l_list_validator = dap_list_first(a_validators); - while(l_list_validator) { - dap_list_t *l_list_validator_next = l_list_validator->next; - if ( ((dap_chain_node_addr_t *)l_list_validator->data)->uint64 == a_addr->uint64 ) - return l_list_validator->data; - l_list_validator = l_list_validator_next; - } - return NULL; +static dap_chain_node_addr_t *s_session_get_validator(dap_chain_cs_block_ton_session_t *a_session, + dap_chain_node_addr_t *a_addr, + dap_list_t *a_validators) +{ + + // dap_chain_cs_block_ton_round_t *l_round = a_round_name == DAP_TON$ROUND_CUR ? // 'c' or 'o' + // &a_session->cur_round : &a_session->old_round; + dap_list_t* l_list_validator = dap_list_first(a_validators); + while(l_list_validator) { + dap_list_t *l_list_validator_next = l_list_validator->next; + if ( ((dap_chain_node_addr_t *)l_list_validator->data)->uint64 == a_addr->uint64 ) + return l_list_validator->data; + l_list_validator = l_list_validator_next; + } + return NULL; } -static uint16_t s_session_message_count( - dap_chain_cs_block_ton_session_t *a_session, uint8_t a_round_name, uint8_t a_type, - dap_chain_hash_fast_t *a_candidate_hash, uint16_t *a_attempt_number) { - dap_chain_cs_block_ton_message_item_t *l_messages_items = NULL; - l_messages_items = a_round_name == DAP_TON$ROUND_CUR ? // 'c' or 'o' - a_session->cur_round.messages_items - : a_session->old_round.messages_items; - uint16_t l_message_count = 0; - dap_chain_cs_block_ton_message_item_t *l_chain_message=NULL, *l_chain_message_tmp=NULL; - HASH_ITER(hh, l_messages_items, l_chain_message, l_chain_message_tmp) { - dap_chain_cs_block_ton_message_getinfo_t *l_getinfo = - (dap_chain_cs_block_ton_message_getinfo_t *) - (l_chain_message->message->sign_n_message+l_chain_message->message->hdr.sign_size); - if ( - l_chain_message->message->hdr.type == a_type - && (!a_candidate_hash || memcmp(&l_getinfo->candidate_hash, a_candidate_hash, - sizeof(dap_chain_hash_fast_t)) == 0) - ) { - switch(a_type) { - // case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_PRE_COMMIT: - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE_FOR: - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE: { - if ( a_attempt_number && *a_attempt_number == l_getinfo->attempt_number) { - l_message_count++; - } - } break; - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_APPROVE: - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_COMMIT_SIGN: { - if (l_chain_message->message->hdr.is_verified){ - l_message_count++; - } - } break; - default: - l_message_count++; - break; - } - } - } - return l_message_count; +static uint16_t s_session_message_count(dap_chain_cs_block_ton_session_t *a_session, uint8_t a_type, + dap_chain_hash_fast_t *a_candidate_hash, uint16_t *a_attempt_number) +{ + dap_chain_cs_block_ton_message_item_t *l_messages_items = NULL; + l_messages_items = a_session->cur_round.messages_items; + uint16_t l_message_count = 0; + dap_chain_cs_block_ton_message_item_t *l_chain_message=NULL, *l_chain_message_tmp=NULL; + HASH_ITER(hh, l_messages_items, l_chain_message, l_chain_message_tmp) { + dap_chain_cs_block_ton_message_getinfo_t *l_getinfo = (dap_chain_cs_block_ton_message_getinfo_t *) + (l_chain_message->message->sign_n_message+l_chain_message->message->hdr.sign_size); + if (l_chain_message->message->hdr.type == a_type && + (!a_candidate_hash || memcmp(&l_getinfo->candidate_hash, a_candidate_hash, + sizeof(dap_chain_hash_fast_t)) == 0)) { + switch(a_type) { + // case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_PRE_COMMIT: + case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE_FOR: + case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE: { + if ( a_attempt_number && *a_attempt_number == l_getinfo->attempt_number) { + l_message_count++; + } + } break; + case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_APPROVE: + case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_COMMIT_SIGN: { + if (l_chain_message->message->hdr.is_verified){ + l_message_count++; + } + } break; + default: + l_message_count++; + break; + } + } + } + return l_message_count; } struct vote_for_load_store_args @@ -1282,26 +1065,6 @@ static bool s_session_packet_in_callback_vote_for_load_store (dap_global_db_cont return true; } -/** - * @brief s_session_packet_in_handler_finish_save - * @param l_session - * @param a_sender_node_addr - * @param a_message - * @param a_message_size - * @param a_finalize_consensus - */ -static void s_session_packet_in_handler_finish_save(dap_chain_cs_block_ton_session_t *l_session, dap_chain_node_addr_t *a_sender_node_addr, - dap_chain_cs_block_ton_message_t * a_message,size_t a_message_size, - bool a_finalize_consensus) -{ - // save to messages chain - dap_chain_hash_fast_t l_message_hash; - s_message_chain_add(l_session, a_sender_node_addr, a_message, a_message_size, &l_message_hash); - if (a_finalize_consensus) { - s_session_round_finish(l_session,false); - } -} - /** * @brief The proc_msg_type_commit_sign struct */ @@ -1348,7 +1111,6 @@ static void s_callback_get_candidate_block_and_commit_sign (dap_global_db_contex size_t l_store_size = a_value_size; dap_chain_cs_block_ton_store_t *l_store = (dap_chain_cs_block_ton_store_t *) a_value; - bool l_finalize_consensus = false; pthread_rwlock_rdlock(&l_session->rwlock); @@ -1367,30 +1129,26 @@ static void s_callback_get_candidate_block_and_commit_sign (dap_global_db_contex if (dap_global_db_set(l_session->gdb_group_store, l_candidate_hash_str, l_store, l_store_size, true, NULL, NULL) == 0 ) { uint16_t l_commitsign_count = s_session_message_count( - l_session, DAP_TON$ROUND_CUR, DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_COMMIT_SIGN, + l_session, DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_COMMIT_SIGN, &l_candidate_hash, NULL); l_commitsign_count++; - if ( 3* l_commitsign_count >= 2*l_round->validators_count ) { - // s_session_round_finish(l_session,false); - if (l_round_id.uint64 == l_session->cur_round.id.uint64) { - l_finalize_consensus = true; - } + if (l_commitsign_count * 3 >= l_round->validators_count * 2) { if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Candidate:%s collected COMMIT_SIGN more than 2/3 of the validators, so to finished this round", + log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Candidate:%s collected COMMIT_SIGN more than 2/3 of the validators, so finish this round", l_session->chain->net_name, l_session->chain->name, l_round->id.uint64, l_session->attempt_current_number, l_candidate_hash_str); + if (l_round_id.uint64 == l_session->cur_round.id.uint64) { + s_message_chain_add(l_session, &l_sender_node_addr, l_message, l_message_size, NULL); + s_session_round_finish(l_session, false); + } } } - } - else { + } else log_it(L_WARNING, "Candidate:%s sign is incorrect: code %d", l_candidate_hash_str, l_sign_verified); - } } pthread_rwlock_unlock(&l_session->rwlock); DAP_DELETE(l_store); DAP_DELETE(l_candidate_hash_str); - s_session_packet_in_handler_finish_save(l_session, &l_sender_node_addr,l_message, l_message_size, l_finalize_consensus); - } @@ -1513,15 +1271,13 @@ static void s_callback_get_candidate_block_and_vote (dap_global_db_context_t * a if (dap_global_db_set_unsafe(a_global_db_context, l_session->gdb_group_store, l_candidate_hash_str, l_store, l_store_size, true ) == 0 ) { // Send PreCommit - dap_chain_cs_block_ton_message_precommit_t *l_precommit = - DAP_NEW_Z(dap_chain_cs_block_ton_message_precommit_t); - l_precommit->round_id.uint64 = l_session->cur_round.id.uint64; -// memcpy(&l_precommit->candidate_hash, &l_candidate_hash, sizeof(dap_chain_hash_fast_t)); - l_precommit->candidate_hash = l_candidate_hash; - l_precommit->attempt_number = l_session->attempt_current_number; - s_message_send(l_session, DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_PRE_COMMIT, (uint8_t*)l_precommit, + dap_chain_cs_block_ton_message_precommit_t l_precommit = { + .round_id.uint64 = l_session->cur_round.id.uint64, + .candidate_hash = l_candidate_hash, + .attempt_number = l_session->attempt_current_number + }; + s_message_send(l_session, DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_PRE_COMMIT, (uint8_t*)&l_precommit, sizeof(dap_chain_cs_block_ton_message_precommit_t), l_session->cur_round.validators_start); - DAP_DELETE(l_precommit); if (PVT(l_session->ton)->debug) log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Candidate:%s collected VOTE more than 2/3 of the validators, so to sent a PRE_COMMIT", l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, @@ -1634,11 +1390,9 @@ static void s_callback_check_and_save_candidate_block (dap_global_db_context_t dap_chain_block_t * l_candidate = l_args->candidate; size_t l_candidate_size = l_args->candidate_size; dap_nanotime_t l_time = l_args->time; - dap_chain_hash_fast_t l_candidate_hash; - memcpy(&l_candidate_hash, &l_args->candidate_hash, sizeof(l_args->candidate_hash)); + dap_chain_hash_fast_t l_candidate_hash = l_args->candidate_hash; DAP_DELETE(l_args); - size_t l_store_temp_size = a_value_size; dap_chain_cs_block_ton_store_t *l_store_temp = (dap_chain_cs_block_ton_store_t *) a_value; if (l_store_temp) { log_it(L_WARNING, "TON: Duplicate candidate:%s", l_candidate_hash_str); @@ -1646,12 +1400,10 @@ static void s_callback_check_and_save_candidate_block (dap_global_db_context_t DAP_DELETE(l_candidate); return; } + // store for new candidate + size_t l_store_size = sizeof(dap_chain_cs_block_ton_store_hdr_t) + l_candidate_size; + dap_chain_cs_block_ton_store_t *l_store = DAP_NEW_Z_SIZE(dap_chain_cs_block_ton_store_t, l_store_size); - pthread_rwlock_rdlock(&l_session->rwlock); - // stor for new candidate - size_t l_store_size = sizeof(dap_chain_cs_block_ton_store_hdr_t)+l_candidate_size; - dap_chain_cs_block_ton_store_t *l_store = - DAP_NEW_Z_SIZE(dap_chain_cs_block_ton_store_t, l_store_size); l_store->hdr.sign_collected = false; l_store->hdr.approve_collected = false; l_store->hdr.vote_collected = false; @@ -1659,10 +1411,10 @@ static void s_callback_check_and_save_candidate_block (dap_global_db_context_t l_store->hdr.candidate_size = l_candidate_size; l_store->hdr.ts_candidate_submit = l_time; l_store->hdr.round_id.uint64 = l_session->cur_round.id.uint64; - memcpy( &l_store->hdr.candidate_hash, &l_candidate_hash, sizeof(dap_chain_hash_fast_t)); - memcpy( &l_store->candidate_n_signs, l_candidate, l_candidate_size); + l_store->hdr.candidate_hash = l_candidate_hash; + memcpy(&l_store->candidate_n_signs, l_candidate, l_candidate_size); - pthread_rwlock_rdlock(&l_session->rwlock); + pthread_rwlock_wrlock(&l_session->rwlock); // save new block candidate if (dap_global_db_set_unsafe(a_global_db_context, l_session->gdb_group_store, l_candidate_hash_str, l_store, l_store_size, true) == 0) { @@ -1727,18 +1479,18 @@ static void s_callback_check_and_save_candidate_block (dap_global_db_context_t * @param a_data * @param a_data_size */ -static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_node_addr, +static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_node_addr, dap_chain_hash_fast_t *a_data_hash, uint8_t *a_data, size_t a_data_size) { dap_chain_cs_block_ton_session_t *l_session = (dap_chain_cs_block_ton_session_t *)a_arg; - dap_chain_cs_block_ton_message_t *l_message = - (dap_chain_cs_block_ton_message_t *)DAP_DUP_SIZE(a_data, a_data_size); + dap_chain_cs_block_ton_message_t *l_message = + (dap_chain_cs_block_ton_message_t *)DAP_DUP_SIZE(a_data, a_data_size); - if (PVT(l_session->ton)->debug) + if (PVT(l_session->ton)->debug) log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Receive pkt type:%x from addr:"NODE_ADDR_FP_STR", my_addr:"NODE_ADDR_FP_STR"", - l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, - l_session->attempt_current_number, l_message->hdr.type, - NODE_ADDR_FP_ARGS(a_sender_node_addr), NODE_ADDR_FP_ARGS(l_session->my_addr)); + l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, + l_session->attempt_current_number, l_message->hdr.type, + NODE_ADDR_FP_ARGS(a_sender_node_addr), NODE_ADDR_FP_ARGS(l_session->my_addr)); if( sizeof(*l_message)+l_message->hdr.sign_size > a_data_size){ log_it(L_WARNING, "TON: incorrect message size in header is %zu when data size is only %zu and header size is %zu", @@ -1748,361 +1500,356 @@ static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_nod size_t l_message_data_size = a_data_size - sizeof(*l_message) - l_message->hdr.sign_size ; byte_t * l_message_data = l_message->sign_n_message + l_message->hdr.sign_size; - if ( !PVT(l_session->ton)->validators_list_by_stake ) { - size_t l_data_size = 0; - dap_sign_t *l_sign = (dap_sign_t*)l_message->sign_n_message; - uint8_t *l_data = s_message_data_sign(l_session, l_message, &l_data_size); - bool l_verify_passed = false; - for (uint16_t j = 0; j < PVT(l_session->ton)->auth_certs_count; j++) { - if ( dap_cert_compare_with_sign(PVT(l_session->ton)->auth_certs[j], l_sign) == 0 - && dap_sign_verify(l_sign, l_data, l_data_size) == 1 ) { - l_verify_passed = true; - break; - } - } - //DAP_DELETE(l_sign); - DAP_DELETE(l_data); - if (!l_verify_passed) { - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Message rejected from addr:"NODE_ADDR_FP_STR" not passed verification", - l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, - l_session->attempt_current_number, NODE_ADDR_FP_ARGS(a_sender_node_addr)); - goto handler_finish; - } - } - + if ( !PVT(l_session->ton)->validators_list_by_stake ) { + size_t l_data_size = 0; + dap_sign_t *l_sign = (dap_sign_t*)l_message->sign_n_message; + uint8_t *l_data = s_message_data_sign(l_session, l_message, &l_data_size); + bool l_verify_passed = false; + for (uint16_t j = 0; j < PVT(l_session->ton)->auth_certs_count; j++) { + if ( dap_cert_compare_with_sign(PVT(l_session->ton)->auth_certs[j], l_sign) == 0 + && dap_sign_verify(l_sign, l_data, l_data_size) == 1 ) { + l_verify_passed = true; + break; + } + } + //DAP_DELETE(l_sign); + DAP_DELETE(l_data); + if (!l_verify_passed) { + if (PVT(l_session->ton)->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Message rejected from addr:"NODE_ADDR_FP_STR" not passed verification", + l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, + l_session->attempt_current_number, NODE_ADDR_FP_ARGS(a_sender_node_addr)); + goto handler_finish; + } + } + if (l_message->hdr.chain_id.uint64 != l_session->chain->id.uint64 ) { - goto handler_finish; + goto handler_finish; } dap_time_t l_time = dap_time_now(); - l_message->hdr.is_verified=false; + l_message->hdr.is_verified=false; dap_chain_hash_fast_t l_data_hash = {}; dap_hash_fast(a_data, a_data_size, &l_data_hash); if (memcmp(a_data_hash, &l_data_hash, sizeof(dap_chain_hash_fast_t)) != 0) { - if (PVT(l_session->ton)->debug) + if (PVT(l_session->ton)->debug) log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Message rejected: message hash does not match", - l_session->chain->net_name, l_session->chain->name, - l_session->cur_round.id.uint64, l_session->attempt_current_number); - goto handler_finish; + l_session->chain->net_name, l_session->chain->name, + l_session->cur_round.id.uint64, l_session->attempt_current_number); + goto handler_finish; } - // consensus round start sync - if ( l_message->hdr.type == DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_START_SYNC ) { - // check time offset - dap_chain_cs_block_ton_message_startsync_t *l_startsync = - (dap_chain_cs_block_ton_message_startsync_t *) - (l_message->sign_n_message+l_message->hdr.sign_size); + // consensus round start sync + if ( l_message->hdr.type == DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_START_SYNC ) { + // check time offset + dap_chain_cs_block_ton_message_startsync_t *l_startsync = + (dap_chain_cs_block_ton_message_startsync_t *) + (l_message->sign_n_message+l_message->hdr.sign_size); - if (PVT(l_session->ton)->debug) + if (PVT(l_session->ton)->debug) log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Receive START_SYNC: from addr:"NODE_ADDR_FP_STR"", - l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, - l_session->attempt_current_number, NODE_ADDR_FP_ARGS(a_sender_node_addr)); - - dap_chain_node_addr_t *l_validator = - s_session_get_validator(l_session, a_sender_node_addr, l_session->cur_round.validators_list); - - if (!l_validator) { - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Message rejected: validator addr:"NODE_ADDR_FP_STR" not on the list.", - l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, - l_session->attempt_current_number, NODE_ADDR_FP_ARGS(a_sender_node_addr)); - goto handler_finish; - } - - if ( - (l_time>l_startsync->ts && (l_time-l_startsync->ts) > PVT(l_session->ton)->allowed_clock_offset ) - || (l_time<l_startsync->ts && (l_startsync->ts-l_time) > PVT(l_session->ton)->allowed_clock_offset ) - ) { - // offset is more than allowed_clock_offset - // skip this validator - if (PVT(l_session->ton)->debug) + l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, + l_session->attempt_current_number, NODE_ADDR_FP_ARGS(a_sender_node_addr)); + + dap_chain_node_addr_t *l_validator = + s_session_get_validator(l_session, a_sender_node_addr, l_session->cur_round.validators_list); + + if (!l_validator) { + if (PVT(l_session->ton)->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Message rejected: validator addr:"NODE_ADDR_FP_STR" not in the list.", + l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, + l_session->attempt_current_number, NODE_ADDR_FP_ARGS(a_sender_node_addr)); + goto handler_finish; + } + + if ( + (l_time>l_startsync->ts && (l_time-l_startsync->ts) > PVT(l_session->ton)->allowed_clock_offset ) + || (l_time<l_startsync->ts && (l_startsync->ts-l_time) > PVT(l_session->ton)->allowed_clock_offset ) + ) { + // offset is more than allowed_clock_offset + // skip this validator + if (PVT(l_session->ton)->debug) log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Message rejected: too much time difference: my time:%"DAP_UINT64_FORMAT_U" sender time:%"DAP_UINT64_FORMAT_U"", - l_session->chain->net_name, l_session->chain->name, - l_session->cur_round.id.uint64, l_session->attempt_current_number, l_time, l_startsync->ts); - goto handler_finish; - } - - // add check&save sender addr - dap_list_t *l_list_temp = dap_list_first(l_session->cur_round.validators_start); - while(l_list_temp) { - dap_list_t *l_list_next = l_list_temp->next; - if (((dap_chain_node_addr_t *)l_list_temp->data)->uint64 == l_validator->uint64) { - if (PVT(l_session->ton)->debug) + l_session->chain->net_name, l_session->chain->name, + l_session->cur_round.id.uint64, l_session->attempt_current_number, l_time, l_startsync->ts); + goto handler_finish; + } + + // add check&save sender addr + dap_list_t *l_list_temp = dap_list_first(l_session->cur_round.validators_start); + while(l_list_temp) { + dap_list_t *l_list_next = l_list_temp->next; + if (((dap_chain_node_addr_t *)l_list_temp->data)->uint64 == l_validator->uint64) { + if (PVT(l_session->ton)->debug) log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Message rejected: repeated sync message from addr:"NODE_ADDR_FP_STR"", - l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, - l_session->attempt_current_number, NODE_ADDR_FP_ARGS(a_sender_node_addr)); - goto handler_finish; - } - l_list_temp = l_list_next; - } - - //sync round_id - if ( l_session->cur_round.id.uint64 < l_startsync->round_id.uint64 ) { - l_session->cur_round.id.uint64 = l_startsync->round_id.uint64; - } - - l_session->cur_round.validators_start = dap_list_append(l_session->cur_round.validators_start, l_validator); - l_session->cur_round.validators_start_count = dap_list_length(l_session->cur_round.validators_start); - // if ( l_session->ts_round_start_pub < l_startsync->ts ) - // l_session->ts_round_start_pub = l_startsync->ts; - // l_session->ts_round_start = (dap_chain_time_t)time(NULL); // l_startsync->ts; // set max time of start consensus - goto handler_finish; - } - - // validator check - uint64_t l_round_id = - ((dap_chain_cs_block_ton_message_getinfo_t *) - (l_message->sign_n_message+l_message->hdr.sign_size))->round_id.uint64; - dap_chain_node_addr_t *l_validator = NULL; - l_validator = l_round_id == l_session->old_round.id.uint64 ? - s_session_get_validator(l_session, a_sender_node_addr, l_session->old_round.validators_start) - : s_session_get_validator(l_session, a_sender_node_addr, l_session->cur_round.validators_start); - if (!l_validator) { - if (PVT(l_session->ton)->debug) - log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Message rejected: validator addr:"NODE_ADDR_FP_STR" not on the list.", - l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, - l_session->attempt_current_number, NODE_ADDR_FP_ARGS(a_sender_node_addr)); - goto handler_finish; - } - - // round check - if ( l_message->hdr.type != DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_COMMIT_SIGN ) { - if ( l_session->state != DAP_STREAM_CH_CHAIN_SESSION_STATE_CS_PROC - && l_session->state != DAP_STREAM_CH_CHAIN_SESSION_STATE_WAIT_SIGNS ) { - goto handler_finish; - } - if ( l_round_id != l_session->cur_round.id.uint64) { - if (PVT(l_session->ton)->debug) + l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, + l_session->attempt_current_number, NODE_ADDR_FP_ARGS(a_sender_node_addr)); + goto handler_finish; + } + l_list_temp = l_list_next; + } + + //sync round_id + if ( l_session->cur_round.id.uint64 < l_startsync->round_id.uint64 ) { + l_session->cur_round.id.uint64 = l_startsync->round_id.uint64; + } + + l_session->cur_round.validators_start = dap_list_append(l_session->cur_round.validators_start, l_validator); + l_session->cur_round.validators_start_count = dap_list_length(l_session->cur_round.validators_start); + // if ( l_session->ts_round_start_pub < l_startsync->ts ) + // l_session->ts_round_start_pub = l_startsync->ts; + // l_session->ts_round_start = (dap_chain_time_t)time(NULL); // l_startsync->ts; // set max time of start consensus + goto handler_finish; + } + + // validator check + uint64_t l_round_id = + ((dap_chain_cs_block_ton_message_getinfo_t *) + (l_message->sign_n_message+l_message->hdr.sign_size))->round_id.uint64; + dap_chain_node_addr_t *l_validator = NULL; + if (l_round_id == l_session->cur_round.id.uint64) + l_validator = s_session_get_validator(l_session, a_sender_node_addr, l_session->cur_round.validators_start); + if (!l_validator) { + if (PVT(l_session->ton)->debug) + log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Message rejected: validator addr:"NODE_ADDR_FP_STR" not in the list.", + l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, + l_session->attempt_current_number, NODE_ADDR_FP_ARGS(a_sender_node_addr)); + goto handler_finish; + } + + // round check + if ( l_message->hdr.type != DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_COMMIT_SIGN ) { + if ( l_session->state != DAP_STREAM_CH_CHAIN_SESSION_STATE_CS_PROC + && l_session->state != DAP_STREAM_CH_CHAIN_SESSION_STATE_WAIT_SIGNS ) { + goto handler_finish; + } + if ( l_round_id != l_session->cur_round.id.uint64) { + if (PVT(l_session->ton)->debug) log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Message rejected: round in message does not match to current round", - l_session->chain->net_name, l_session->chain->name, - l_session->cur_round.id.uint64, l_session->attempt_current_number); - goto handler_finish; - } - } else { - if ( l_round_id != l_session->cur_round.id.uint64 - && l_round_id != l_session->old_round.id.uint64 ) { - if (PVT(l_session->ton)->debug) + l_session->chain->net_name, l_session->chain->name, + l_session->cur_round.id.uint64, l_session->attempt_current_number); + goto handler_finish; + } + } else { + if (l_round_id != l_session->cur_round.id.uint64) { + if (PVT(l_session->ton)->debug) log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Message rejected: round in message does not match to current round", - l_session->chain->net_name, l_session->chain->name, - l_session->cur_round.id.uint64, l_session->attempt_current_number); - goto handler_finish; - } - } - - if ( l_session->attempt_current_number != 1 ) { - switch (l_message->hdr.type) { // this types allow only in first attempt - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_SUBMIT: - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_APPROVE: - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_REJECT: { - if (PVT(l_session->ton)->debug) + l_session->chain->net_name, l_session->chain->name, + l_session->cur_round.id.uint64, l_session->attempt_current_number); + goto handler_finish; + } + } + + if ( l_session->attempt_current_number != 1 ) { + switch (l_message->hdr.type) { // this types allow only in first attempt + case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_SUBMIT: + case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_APPROVE: + case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_REJECT: { + if (PVT(l_session->ton)->debug) log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Message rejected: message type:%x allowed only in first attempt", - l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, - l_session->attempt_current_number, l_message->hdr.type); - goto handler_finish; - } - } - } - - dap_chain_cs_block_ton_message_item_t *l_messages_items = NULL; - l_messages_items = l_round_id == l_session->old_round.id.uint64 ? - l_session->old_round.messages_items : l_session->cur_round.messages_items; - - // check hash message dup - dap_chain_cs_block_ton_message_item_t *l_message_item_temp = NULL; - HASH_FIND(hh, l_messages_items, a_data_hash, sizeof(dap_chain_hash_fast_t), l_message_item_temp); - if (l_message_item_temp) { - if (PVT(l_session->ton)->debug) + l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, + l_session->attempt_current_number, l_message->hdr.type); + goto handler_finish; + } + } + } + + dap_chain_cs_block_ton_message_item_t *l_messages_items = l_session->cur_round.messages_items; + + // check hash message dup + dap_chain_cs_block_ton_message_item_t *l_message_item_temp = NULL; + HASH_FIND(hh, l_messages_items, a_data_hash, sizeof(dap_chain_hash_fast_t), l_message_item_temp); + if (l_message_item_temp) { + if (PVT(l_session->ton)->debug) log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Message rejected: message hash is exists in chain (duplicate?)", - l_session->chain->net_name, l_session->chain->name, - l_session->cur_round.id.uint64, l_session->attempt_current_number); - goto handler_finish; - } - - // check validator index in queue for event Submit - if ( l_message->hdr.type == DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_SUBMIT ) { - dap_list_t *l_validators_list = dap_list_first(l_session->cur_round.validators_start); - int l_validator_number = 0; - int i = 0; - while(l_validators_list) { - if( ((dap_chain_node_addr_t *)l_validators_list->data)->uint64 == a_sender_node_addr->uint64) { - l_validator_number = i; - break; - } - i++; - l_validators_list = l_validators_list->next; - } - if ( l_validator_number ) { // pass if I first validator - int l_submit_count = 0; - dap_chain_cs_block_ton_message_item_t *l_chain_message=NULL, *l_chain_message_tmp=NULL; - HASH_ITER(hh, l_messages_items, l_chain_message, l_chain_message_tmp) { - if ( l_chain_message->message->hdr.type == DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_SUBMIT ) { - l_submit_count++; - } - } - if ( l_validator_number < l_submit_count ) { - // Skip this SUBMIT. Validator must wait its queue. - if (PVT(l_session->ton)->debug) + l_session->chain->net_name, l_session->chain->name, + l_session->cur_round.id.uint64, l_session->attempt_current_number); + goto handler_finish; + } + + // check validator index in queue for event Submit + if ( l_message->hdr.type == DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_SUBMIT ) { + dap_list_t *l_validators_list = dap_list_first(l_session->cur_round.validators_start); + int l_validator_number = 0; + int i = 0; + while(l_validators_list) { + if( ((dap_chain_node_addr_t *)l_validators_list->data)->uint64 == a_sender_node_addr->uint64) { + l_validator_number = i; + break; + } + i++; + l_validators_list = l_validators_list->next; + } + if ( l_validator_number ) { // pass if I first validator + int l_submit_count = 0; + dap_chain_cs_block_ton_message_item_t *l_chain_message=NULL, *l_chain_message_tmp=NULL; + HASH_ITER(hh, l_messages_items, l_chain_message, l_chain_message_tmp) { + if ( l_chain_message->message->hdr.type == DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_SUBMIT ) { + l_submit_count++; + } + } + if ( l_validator_number < l_submit_count ) { + // Skip this SUBMIT. Validator must wait its queue. + if (PVT(l_session->ton)->debug) log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Message rejected: Validator must wait its queue for sent SUBMIT", - l_session->chain->net_name, l_session->chain->name, - l_session->cur_round.id.uint64, l_session->attempt_current_number); - goto handler_finish; - } - } - } + l_session->chain->net_name, l_session->chain->name, + l_session->cur_round.id.uint64, l_session->attempt_current_number); + goto handler_finish; + } + } + } uint32_t /* l_approve_count = 0, */ l_vote_count = 0, l_precommit_count = 0; - // check messages chain + // check messages chain dap_chain_cs_block_ton_message_item_t *l_chain_message=NULL, *l_chain_message_tmp=NULL; HASH_ITER(hh, l_messages_items, l_chain_message, l_chain_message_tmp) { - if (l_chain_message->message->hdr.sender_node_addr.uint64 == a_sender_node_addr->uint64) { - dap_chain_hash_fast_t *l_candidate_hash_cur = - &((dap_chain_cs_block_ton_message_getinfo_t *) - (l_message->sign_n_message+l_message->hdr.sign_size))->candidate_hash; - - dap_chain_hash_fast_t *l_candidate_hash = - &((dap_chain_cs_block_ton_message_getinfo_t *) - (l_chain_message->message->sign_n_message+l_chain_message->message->hdr.sign_size))->candidate_hash; - - bool l_candidate_hash_match = (memcmp(l_candidate_hash_cur, l_candidate_hash, - sizeof(dap_chain_hash_fast_t)) == 0); - - uint8_t l_chain_msg_type = l_chain_message->message->hdr.type; - - // search & check messages from this validator - switch (l_chain_msg_type) { - // check dup messages APPROVE, REJECT for one candidate - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_APPROVE: - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_REJECT: { - switch (l_message->hdr.type) { - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_APPROVE: - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_REJECT: - if (l_candidate_hash_match) { - if (PVT(l_session->ton)->debug) + if (l_chain_message->message->hdr.sender_node_addr.uint64 == a_sender_node_addr->uint64) { + dap_chain_hash_fast_t *l_candidate_hash_cur = + &((dap_chain_cs_block_ton_message_getinfo_t *) + (l_message->sign_n_message+l_message->hdr.sign_size))->candidate_hash; + + dap_chain_hash_fast_t *l_candidate_hash = + &((dap_chain_cs_block_ton_message_getinfo_t *) + (l_chain_message->message->sign_n_message+l_chain_message->message->hdr.sign_size))->candidate_hash; + + bool l_candidate_hash_match = (memcmp(l_candidate_hash_cur, l_candidate_hash, + sizeof(dap_chain_hash_fast_t)) == 0); + + uint8_t l_chain_msg_type = l_chain_message->message->hdr.type; + + // search & check messages from this validator + switch (l_chain_msg_type) { + // check dup messages APPROVE, REJECT for one candidate + case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_APPROVE: + case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_REJECT: { + switch (l_message->hdr.type) { + case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_APPROVE: + case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_REJECT: + if (l_candidate_hash_match) { + if (PVT(l_session->ton)->debug) log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Message rejected: duplicate messages APPROVE or REJECT for one candidate", - l_session->chain->net_name, l_session->chain->name, + l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, l_session->attempt_current_number); - goto handler_finish; - } - } - } break; - //check dup messages VOTE for one candidate in this attempt - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE: { - dap_chain_cs_block_ton_message_vote_t *l_vote = - (dap_chain_cs_block_ton_message_vote_t *) - (l_message->sign_n_message+l_message->hdr.sign_size); - dap_chain_cs_block_ton_message_vote_t *l_vote_item = - (dap_chain_cs_block_ton_message_vote_t *) - (l_chain_message->message->sign_n_message+l_chain_message->message->hdr.sign_size); - if ( l_chain_msg_type == l_message->hdr.type - && l_vote->attempt_number == l_vote_item->attempt_number ) { - if (PVT(l_session->ton)->debug) + goto handler_finish; + } + } + } break; + //check dup messages VOTE for one candidate in this attempt + case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE: { + dap_chain_cs_block_ton_message_vote_t *l_vote = + (dap_chain_cs_block_ton_message_vote_t *) + (l_message->sign_n_message+l_message->hdr.sign_size); + dap_chain_cs_block_ton_message_vote_t *l_vote_item = + (dap_chain_cs_block_ton_message_vote_t *) + (l_chain_message->message->sign_n_message+l_chain_message->message->hdr.sign_size); + if ( l_chain_msg_type == l_message->hdr.type + && l_vote->attempt_number == l_vote_item->attempt_number ) { + if (PVT(l_session->ton)->debug) log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Message rejected: duplicate messages VOTE for one candidate for one attempt", - l_session->chain->net_name, l_session->chain->name, + l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, l_session->attempt_current_number); - goto handler_finish; - } - } break; - // this messages should only appear once per round //attempt - // case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE: - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_PRE_COMMIT: - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_COMMIT_SIGN: - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_SUBMIT:{ - if ( l_chain_msg_type == l_message->hdr.type ){ - if (PVT(l_session->ton)->debug) + goto handler_finish; + } + } break; + // this messages should only appear once per round //attempt + // case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE: + case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_PRE_COMMIT: + case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_COMMIT_SIGN: + case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_SUBMIT:{ + if ( l_chain_msg_type == l_message->hdr.type ){ + if (PVT(l_session->ton)->debug) log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Message rejected: duplicate messages VOTE or PRE_COMMIT for one candidate for one attempt", - l_session->chain->net_name, l_session->chain->name, + l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, l_session->attempt_current_number); - goto handler_finish; - } - } - } - // count messages in chain for this candidate - if (l_candidate_hash_match) { - switch (l_chain_msg_type) { - // case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_APPROVE: { - // l_approve_count++; - // } break; - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE: { - l_vote_count++; - } break; - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_PRE_COMMIT: { - l_precommit_count++; - } break; - } - } - } + goto handler_finish; + } + } + } + // count messages in chain for this candidate + if (l_candidate_hash_match) { + switch (l_chain_msg_type) { + // case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_APPROVE: { + // l_approve_count++; + // } break; + case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE: { + l_vote_count++; + } break; + case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_PRE_COMMIT: { + l_precommit_count++; + } break; + } + } + } } - // check message chain is correct - switch (l_message->hdr.type) { - // case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE: { - // if (!l_approve_count) { // if this validator not sent Approve for this candidate - // goto handler_finish; - // } - // } break; - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_PRE_COMMIT: { - if (!l_vote_count) { // if this validator not sent Vote for this candidate - if (PVT(l_session->ton)->debug) + // check message chain is correct + switch (l_message->hdr.type) { + // case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE: { + // if (!l_approve_count) { // if this validator not sent Approve for this candidate + // goto handler_finish; + // } + // } break; + case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_PRE_COMMIT: { + if (!l_vote_count) { // if this validator not sent Vote for this candidate + if (PVT(l_session->ton)->debug) log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Message rejected: this validator can't send a PRE_COMMIT because it didn't send a VOTE for this candidate", - l_session->chain->net_name, l_session->chain->name, + l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, l_session->attempt_current_number); - goto handler_finish; - } - } break; - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_COMMIT_SIGN: { - if (!l_precommit_count) { // if this validator not sent PreCommit for this candidate - if (PVT(l_session->ton)->debug) + goto handler_finish; + } + } break; + case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_COMMIT_SIGN: { + if (!l_precommit_count) { // if this validator not sent PreCommit for this candidate + if (PVT(l_session->ton)->debug) log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Message rejected: this validator can't send a COMMIT_SIGN because it didn't send a PRE_COMMIT for this candidate", - l_session->chain->net_name, l_session->chain->name, - l_session->cur_round.id.uint64, l_session->attempt_current_number); - goto handler_finish; - } - } break; - } - - bool l_finalize_consensus = false; - switch (l_message->hdr.type) { - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_SUBMIT: { + l_session->chain->net_name, l_session->chain->name, + l_session->cur_round.id.uint64, l_session->attempt_current_number); + goto handler_finish; + } + } break; + } + + switch (l_message->hdr.type) { + case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_SUBMIT: { if( sizeof(dap_chain_cs_block_ton_message_submit_t) > l_message_data_size){ log_it(L_WARNING, "Wrong submit message size,have %zu bytes for data section when only a header requires %zu bytes", l_message_data_size,sizeof(dap_chain_cs_block_ton_message_submit_t)); goto handler_finish; } dap_chain_cs_block_ton_message_submit_t *l_submit = (dap_chain_cs_block_ton_message_submit_t *)l_message_data; - - size_t l_candidate_size = l_submit->candidate_size; + size_t l_candidate_size = l_submit->candidate_size; if( l_message_data_size < l_candidate_size + sizeof(*l_submit) ){ log_it(L_WARNING, "Wrong submit message size %zu when maximum is %zu for received message", l_candidate_size, l_message_data_size - sizeof(*l_submit)); goto handler_finish; } - if (!l_candidate_size || s_hash_is_null(&l_submit->candidate_hash)) { // null candidate - save chain and exit - if (PVT(l_session->ton)->debug) + if (!l_candidate_size || dap_hash_fast_is_blank(&l_submit->candidate_hash)) { // null candidate - save chain and exit + + if (PVT(l_session->ton)->debug) log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Receive SUBMIT: candidate: NULL", - l_session->chain->net_name, l_session->chain->name, - l_session->cur_round.id.uint64, l_session->attempt_current_number); - goto handler_finish_save; - } + l_session->chain->net_name, l_session->chain->name, + l_session->cur_round.id.uint64, l_session->attempt_current_number); + goto handler_finish_save; + } - dap_chain_hash_fast_t l_candidate_hash; + dap_chain_hash_fast_t l_candidate_hash; dap_hash_fast(l_submit->candidate, l_candidate_size, &l_candidate_hash); - - // check candidate hash - if (memcmp(&l_submit->candidate_hash, &l_candidate_hash, - sizeof(dap_chain_hash_fast_t)) != 0) { - goto handler_finish; - } + + // check candidate hash + if (memcmp(&l_submit->candidate_hash, &l_candidate_hash, + sizeof(dap_chain_hash_fast_t)) != 0) { + goto handler_finish; + } dap_chain_block_t *l_candidate = (dap_chain_block_t *) DAP_DUP_SIZE(l_submit->candidate, l_candidate_size); - char *l_candidate_hash_str = dap_chain_hash_fast_to_str_new(&l_candidate_hash); - if (PVT(l_session->ton)->debug) + char *l_candidate_hash_str = dap_chain_hash_fast_to_str_new(&l_candidate_hash); + if (PVT(l_session->ton)->debug) log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Receive SUBMIT: candidate:%s, size:%zu", - l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, - l_session->attempt_current_number, l_candidate_hash_str, l_candidate_size); + l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, + l_session->attempt_current_number, l_candidate_hash_str, l_candidate_size); - // check block exist in store + // check block exist in store //s_check_block_exist_in_store(,) struct proc_msg_type_submit * l_args = DAP_NEW_Z(struct proc_msg_type_submit); l_args->session = l_session; @@ -2117,59 +1864,54 @@ static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_nod DAP_DELETE(l_args); goto handler_finish; } - } break; - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_REJECT: { + } break; + case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_REJECT: { if ( sizeof(dap_chain_cs_block_ton_message_reject_t) >l_message_data_size ){ log_it(L_WARNING, "Wrong reject message size,have %zu bytes for data section when requires %zu bytes", l_message_data_size,sizeof(dap_chain_cs_block_ton_message_reject_t)); goto handler_finish; } dap_chain_cs_block_ton_message_reject_t *l_reject = (dap_chain_cs_block_ton_message_reject_t *) l_message_data; - - - dap_chain_hash_fast_t *l_candidate_hash = &l_reject->candidate_hash; + dap_chain_hash_fast_t *l_candidate_hash = &l_reject->candidate_hash; pthread_rwlock_rdlock(&l_session->rwlock); - if ( s_hash_is_null(l_candidate_hash) ) { - if (PVT(l_session->ton)->debug) + if (dap_hash_fast_is_blank(l_candidate_hash)) { + if (PVT(l_session->ton)->debug) log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Receive REJECT: NULL", - l_session->chain->net_name, l_session->chain->name, - l_session->cur_round.id.uint64, l_session->attempt_current_number); + l_session->chain->net_name, l_session->chain->name, + l_session->cur_round.id.uint64, l_session->attempt_current_number); pthread_rwlock_unlock(&l_session->rwlock); goto handler_finish_save; - } - char *l_candidate_hash_str = dap_chain_hash_fast_to_str_new(l_candidate_hash); + } + char *l_candidate_hash_str = dap_chain_hash_fast_to_str_new(l_candidate_hash); - if (PVT(l_session->ton)->debug) + if (PVT(l_session->ton)->debug) log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Receive REJECT: candidate:%s", - l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, - l_session->attempt_current_number, l_candidate_hash_str); + l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, + l_session->attempt_current_number, l_candidate_hash_str); + - pthread_rwlock_wrlock(&l_session->rwlock); - uint16_t l_reject_count = s_session_message_count( - l_session, DAP_TON$ROUND_CUR, DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_REJECT, - l_candidate_hash, NULL); - l_reject_count++; + uint16_t l_reject_count = s_session_message_count(l_session, DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_REJECT, + l_candidate_hash, NULL); + l_reject_count++; if (l_reject_count * 3 >= l_session->cur_round.validators_count * 2) { dap_global_db_del_sync(l_session->gdb_group_store, l_candidate_hash_str); - dap_chain_hash_fast_t l_my_candidate_hash; - dap_hash_fast(l_session->my_candidate, l_session->my_candidate_size, &l_my_candidate_hash); - if (memcmp(&l_my_candidate_hash, l_candidate_hash, - sizeof(dap_chain_hash_fast_t)) == 0) { - s_session_my_candidate_delete(l_session); - } - if (PVT(l_session->ton)->debug) + dap_chain_hash_fast_t l_my_candidate_hash; + dap_hash_fast(l_session->my_candidate, l_session->my_candidate_size, &l_my_candidate_hash); + if (dap_hash_fast_compare(&l_my_candidate_hash, l_candidate_hash)) + s_session_my_candidate_delete(l_session); + if (PVT(l_session->ton)->debug) log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Candidate:%s collected rejected more than 2/3 of the validators, so to removed this candidate", l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, - l_session->attempt_current_number, l_candidate_hash_str); - } - pthread_rwlock_unlock(&l_session->rwlock); - DAP_DELETE(l_candidate_hash_str); - } break; - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_APPROVE: { + l_session->attempt_current_number, l_candidate_hash_str); + } + pthread_rwlock_unlock(&l_session->rwlock); + DAP_DELETE(l_candidate_hash_str); + } break; + case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_APPROVE: { if ( sizeof(dap_chain_cs_block_ton_message_approve_t) >l_message_data_size ){ log_it(L_WARNING, "Wrong approve message size,have %zu bytes for data section when requires %zu bytes", l_message_data_size,sizeof(dap_chain_cs_block_ton_message_approve_t)); @@ -2185,39 +1927,39 @@ static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_nod goto handler_finish; } - dap_chain_hash_fast_t *l_candidate_hash = &l_approve->candidate_hash; - - if ( s_hash_is_null(l_candidate_hash) ) { - if (PVT(l_session->ton)->debug) + dap_chain_hash_fast_t *l_candidate_hash = &l_approve->candidate_hash; + + if (dap_hash_fast_is_blank(l_candidate_hash)) { + if (PVT(l_session->ton)->debug) log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Receive APPROVE: candidate: NULL", - l_session->chain->net_name, l_session->chain->name, - l_session->cur_round.id.uint64, l_session->attempt_current_number); - goto handler_finish_save; - } - char *l_candidate_hash_str = dap_chain_hash_fast_to_str_new(l_candidate_hash); + l_session->chain->net_name, l_session->chain->name, + l_session->cur_round.id.uint64, l_session->attempt_current_number); + goto handler_finish_save; + } + char *l_candidate_hash_str = dap_chain_hash_fast_to_str_new(l_candidate_hash); pthread_rwlock_rdlock(&l_session->rwlock); if (PVT(l_session->ton)->debug) log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Receive APPROVE: candidate:%s", - l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, - l_session->attempt_current_number, l_candidate_hash_str); - - int l_sign_verified=0; - // check candidate hash sign - if ( (l_sign_verified=dap_sign_verify( (dap_sign_t*)l_approve->candidate_hash_sign, - l_candidate_hash, sizeof(dap_chain_hash_fast_t))) == 1 ) { - l_message->hdr.is_verified=true; - - if ( l_session->attempt_current_number == 1 ) { // if this first attempt then send Vote event - uint16_t l_approve_count = s_session_message_count( - l_session, DAP_TON$ROUND_CUR, DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_APPROVE, - l_candidate_hash, NULL); - l_approve_count++; + l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, + l_session->attempt_current_number, l_candidate_hash_str); + + int l_sign_verified=0; + // check candidate hash sign + if ( (l_sign_verified=dap_sign_verify( (dap_sign_t*)l_approve->candidate_hash_sign, + l_candidate_hash, sizeof(dap_chain_hash_fast_t))) == 1 ) { + l_message->hdr.is_verified=true; + + if ( l_session->attempt_current_number == 1 ) { // if this first attempt then send Vote event + uint16_t l_approve_count = s_session_message_count( + l_session, DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_APPROVE, + l_candidate_hash, NULL); + l_approve_count++; if (l_approve_count * 3 >= l_session->cur_round.validators_count * 2) { - if (PVT(l_session->ton)->debug) + if (PVT(l_session->ton)->debug) log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U" attempt:%hu Candidate:%s collected approve more than 2/3 of the validators", - l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, - l_session->attempt_current_number, l_candidate_hash_str); + l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, + l_session->attempt_current_number, l_candidate_hash_str); struct proc_msg_type_approve * l_args = DAP_NEW_Z(struct proc_msg_type_approve); l_args->session = l_session; @@ -2235,13 +1977,13 @@ static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_nod }else{ DAP_DELETE(l_candidate_hash_str); } - } else { - log_it(L_WARNING, "Candidate hash sign is incorrect: code %d", l_sign_verified); + } else { + log_it(L_WARNING, "Candidate hash sign is incorrect: code %d", l_sign_verified); DAP_DELETE(l_candidate_hash_str); } pthread_rwlock_unlock(&l_session->rwlock); } break; - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE_FOR: { + case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE_FOR: { if ( sizeof(dap_chain_cs_block_ton_message_votefor_t) >l_message_data_size ){ log_it(L_WARNING, "Wrong vote_for message size,have %zu bytes for data section when requires %zu bytes", l_message_data_size,sizeof(dap_chain_cs_block_ton_message_votefor_t)); @@ -2249,45 +1991,45 @@ static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_nod } dap_chain_cs_block_ton_message_votefor_t *l_votefor = (dap_chain_cs_block_ton_message_votefor_t *) l_message_data; - dap_chain_hash_fast_t *l_candidate_hash = &l_votefor->candidate_hash; + dap_chain_hash_fast_t *l_candidate_hash = &l_votefor->candidate_hash; pthread_rwlock_rdlock(&l_session->rwlock); - uint16_t l_attempt_current = l_session->attempt_current_number; - if ( l_votefor->attempt_number != l_attempt_current) { + uint16_t l_attempt_current = l_session->attempt_current_number; + if ( l_votefor->attempt_number != l_attempt_current) { pthread_rwlock_unlock(&l_session->rwlock); - goto handler_finish; // wrong attempt number in message - } + goto handler_finish; // wrong attempt number in message + } - if (PVT(l_session->ton)->debug) { - char *l_candidate_hash_str = dap_chain_hash_fast_to_str_new(l_candidate_hash); + if (PVT(l_session->ton)->debug) { + char *l_candidate_hash_str = dap_chain_hash_fast_to_str_new(l_candidate_hash); log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Receive VOTE_FOR: candidate:%s", l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, l_session->attempt_current_number, l_candidate_hash_str); - DAP_DELETE(l_candidate_hash_str); - } + DAP_DELETE(l_candidate_hash_str); + } - if ( a_sender_node_addr->uint64 != l_session->attempt_coordinator->uint64 ) { + if ( a_sender_node_addr->uint64 != l_session->attempt_coordinator->uint64 ) { pthread_rwlock_unlock(&l_session->rwlock); goto handler_finish; // wrong coordinator addr - } + } - uint16_t l_votefor_count = s_session_message_count( - l_session, DAP_TON$ROUND_CUR, DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE_FOR, - NULL, &l_attempt_current); - if ( l_votefor_count != 0 ) { - if (PVT(l_session->ton)->debug) + uint16_t l_votefor_count = s_session_message_count( + l_session, DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE_FOR, + NULL, &l_attempt_current); + if ( l_votefor_count != 0 ) { + if (PVT(l_session->ton)->debug) log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Ignored because it's not the first VOTE_FOR in this attempt", - l_session->chain->net_name, l_session->chain->name, - l_session->cur_round.id.uint64, l_session->attempt_current_number); + l_session->chain->net_name, l_session->chain->name, + l_session->cur_round.id.uint64, l_session->attempt_current_number); pthread_rwlock_unlock(&l_session->rwlock); - goto handler_finish; - } + goto handler_finish; + } struct vote_for_load_store_args * l_args = DAP_NEW_Z(struct vote_for_load_store_args); l_args->session = l_session; - memcpy(&l_args->candidate_hash, l_candidate_hash, sizeof(l_args->candidate_hash)); - // search candidate with 2/3 vote + l_args->candidate_hash = *l_candidate_hash; + // search candidate with 2/3 vote if(dap_global_db_get_all(l_session->gdb_group_store, 0, s_session_packet_in_callback_vote_for_load_store, l_session) != 0 ){ @@ -2296,39 +2038,39 @@ static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_nod } pthread_rwlock_unlock(&l_session->rwlock); } break; - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE: { + case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE: { if ( sizeof(dap_chain_cs_block_ton_message_vote_t) >l_message_data_size ){ log_it(L_WARNING, "Wrong vote message size,have %zu bytes for data section when requires %zu bytes", l_message_data_size,sizeof(dap_chain_cs_block_ton_message_vote_t)); goto handler_finish; } dap_chain_cs_block_ton_message_vote_t *l_vote = (dap_chain_cs_block_ton_message_vote_t *) l_message_data; - dap_chain_hash_fast_t *l_candidate_hash = &l_vote->candidate_hash; - - if ( l_vote->attempt_number != l_session->attempt_current_number) { - goto handler_finish; - } - - if ( s_hash_is_null(l_candidate_hash) ) { - if (PVT(l_session->ton)->debug) + dap_chain_hash_fast_t *l_candidate_hash = &l_vote->candidate_hash; + + if ( l_vote->attempt_number != l_session->attempt_current_number) { + goto handler_finish; + } + + if (dap_hash_fast_is_blank(l_candidate_hash)) { + if (PVT(l_session->ton)->debug) log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Receive VOTE: candidate: NULL", - l_session->chain->net_name, l_session->chain->name, - l_session->cur_round.id.uint64, l_session->attempt_current_number); - goto handler_finish_save; - } + l_session->chain->net_name, l_session->chain->name, + l_session->cur_round.id.uint64, l_session->attempt_current_number); + goto handler_finish_save; + } - char *l_candidate_hash_str = dap_chain_hash_fast_to_str_new(l_candidate_hash); - if (PVT(l_session->ton)->debug) + char *l_candidate_hash_str = dap_chain_hash_fast_to_str_new(l_candidate_hash); + if (PVT(l_session->ton)->debug) log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Receive VOTE: candidate:%s", - l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, - l_session->attempt_current_number, l_candidate_hash_str); - - pthread_rwlock_rdlock(&l_session->rwlock); - uint16_t l_attempt_number = l_session->attempt_current_number; - uint16_t l_vote_count = s_session_message_count( - l_session, DAP_TON$ROUND_CUR, DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE, - l_candidate_hash, &l_attempt_number); - l_vote_count++; + l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, + l_session->attempt_current_number, l_candidate_hash_str); + + pthread_rwlock_rdlock(&l_session->rwlock); + uint16_t l_attempt_number = l_session->attempt_current_number; + uint16_t l_vote_count = s_session_message_count( + l_session, DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_VOTE, + l_candidate_hash, &l_attempt_number); + l_vote_count++; if (l_vote_count * 3 >= l_session->cur_round.validators_count * 2){ struct proc_msg_type_vote * l_args = DAP_NEW_Z(struct proc_msg_type_vote); l_args->session = l_session; @@ -2339,10 +2081,10 @@ static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_nod DAP_DELETE(l_candidate_hash_str); DAP_DELETE(l_args); } - } - pthread_rwlock_unlock(&l_session->rwlock); - } break; - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_PRE_COMMIT: { + } + pthread_rwlock_unlock(&l_session->rwlock); + } break; + case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_PRE_COMMIT: { if ( sizeof(dap_chain_cs_block_ton_message_precommit_t) >l_message_data_size ){ log_it(L_WARNING, "Wrong pre_commit message size,have %zu bytes for data section when requires %zu bytes", l_message_data_size,sizeof(dap_chain_cs_block_ton_message_precommit_t)); @@ -2350,34 +2092,33 @@ static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_nod } dap_chain_cs_block_ton_message_precommit_t *l_precommit = (dap_chain_cs_block_ton_message_precommit_t *) l_message_data; - dap_chain_hash_fast_t *l_candidate_hash = &l_precommit->candidate_hash; + dap_chain_hash_fast_t *l_candidate_hash = &l_precommit->candidate_hash; - pthread_rwlock_rdlock(&l_session->rwlock); + pthread_rwlock_wrlock(&l_session->rwlock); - if ( l_precommit->attempt_number != l_session->attempt_current_number) { + if ( l_precommit->attempt_number != l_session->attempt_current_number) { pthread_rwlock_unlock(&l_session->rwlock); - goto handler_finish; - } - if ( s_hash_is_null(l_candidate_hash) ) { - if (PVT(l_session->ton)->debug) + goto handler_finish; + } + if (dap_hash_fast_is_blank(l_candidate_hash)) { + if (PVT(l_session->ton)->debug) log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Receive PRE_COMMIT: candidate: NULL", - l_session->chain->net_name, l_session->chain->name, - l_session->cur_round.id.uint64, l_session->attempt_current_number); + l_session->chain->net_name, l_session->chain->name, + l_session->cur_round.id.uint64, l_session->attempt_current_number); pthread_rwlock_unlock(&l_session->rwlock); - goto handler_finish_save; - } + goto handler_finish_save; + } - char *l_candidate_hash_str = dap_chain_hash_fast_to_str_new(l_candidate_hash); - if (PVT(l_session->ton)->debug) + char *l_candidate_hash_str = dap_chain_hash_fast_to_str_new(l_candidate_hash); + if (PVT(l_session->ton)->debug) log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Receive PRE_COMMIT: candidate:%s", - l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, - l_session->attempt_current_number, l_candidate_hash_str); - - uint16_t l_attempt_number = l_session->attempt_current_number; - uint16_t l_precommit_count = s_session_message_count( - l_session, DAP_TON$ROUND_CUR, DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_PRE_COMMIT, - l_candidate_hash, &l_attempt_number); - l_precommit_count++; + l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id.uint64, + l_session->attempt_current_number, l_candidate_hash_str); + + uint16_t l_attempt_number = l_session->attempt_current_number; + uint16_t l_precommit_count = s_session_message_count(l_session, DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_PRE_COMMIT, + l_candidate_hash, &l_attempt_number); + l_precommit_count++; if ( 3* l_precommit_count >= 2*l_session->cur_round.validators_count ) { struct proc_msg_type_pre_commit * l_args = DAP_NEW_Z(struct proc_msg_type_pre_commit); l_args->session = l_session; @@ -2388,11 +2129,10 @@ static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_nod DAP_DELETE(l_candidate_hash_str); DAP_DELETE(l_args); } - } + } pthread_rwlock_unlock(&l_session->rwlock); - } break; - case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_COMMIT_SIGN: { + case DAP_STREAM_CH_CHAIN_MESSAGE_TYPE_COMMIT_SIGN: { if ( sizeof(dap_chain_cs_block_ton_message_commitsign_t) >l_message_data_size ){ log_it(L_WARNING, "Wrong commit_sign message size,have %zu bytes for data section when requires %zu bytes", l_message_data_size,sizeof(dap_chain_cs_block_ton_message_commitsign_t)); @@ -2412,26 +2152,22 @@ static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_nod } pthread_rwlock_rdlock(&l_session->rwlock); - - dap_chain_cs_block_ton_round_t *l_round = - l_commitsign->round_id.uint64 == l_session->old_round.id.uint64 ? - &l_session->old_round : &l_session->cur_round; - - if ( s_hash_is_null(l_candidate_hash) ) { - if (PVT(l_session->ton)->debug) + dap_chain_cs_block_ton_round_t *l_round = &l_session->cur_round; + if (dap_hash_fast_is_blank(l_candidate_hash)) { + if (PVT(l_session->ton)->debug) log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Receive COMMIT_SIGN: candidate: NULL", - l_session->chain->net_name, l_session->chain->name, - l_round->id.uint64, l_session->attempt_current_number); + l_session->chain->net_name, l_session->chain->name, + l_round->id.uint64, l_session->attempt_current_number); pthread_rwlock_unlock(&l_session->rwlock); - goto handler_finish_save; - } + goto handler_finish_save; + } - char *l_candidate_hash_str = dap_chain_hash_fast_to_str_new(l_candidate_hash); - if (PVT(l_session->ton)->debug) + char *l_candidate_hash_str = dap_chain_hash_fast_to_str_new(l_candidate_hash); + if (PVT(l_session->ton)->debug) log_it(L_MSG, "TON: net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hu Receive COMMIT_SIGN: candidate:%s", - l_session->chain->net_name, l_session->chain->name, l_round->id.uint64, - l_session->attempt_current_number, l_candidate_hash_str); + l_session->chain->net_name, l_session->chain->name, l_round->id.uint64, + l_session->attempt_current_number, l_candidate_hash_str); struct proc_msg_type_commit_sign * l_args = DAP_NEW_Z(struct proc_msg_type_commit_sign); l_args->session = l_session; @@ -2454,111 +2190,106 @@ static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_nod } pthread_rwlock_unlock(&l_session->rwlock); - } break; - default: - break; - } + } break; + default: + break; + } handler_finish_save: - s_session_packet_in_handler_finish_save(l_session, a_sender_node_addr,l_message, a_data_size, l_finalize_consensus); + if (l_session->state != DAP_STREAM_CH_CHAIN_SESSION_STATE_IDLE) + s_message_chain_add(l_session, a_sender_node_addr, l_message, a_data_size, NULL); return; handler_finish: DAP_DELETE(l_message); } static uint8_t *s_message_data_sign(dap_chain_cs_block_ton_session_t *a_session, - dap_chain_cs_block_ton_message_t *a_message, size_t *a_sign_size) { - size_t l_size[5] = {sizeof(a_message->hdr.id), sizeof(a_message->hdr.ts_created), - sizeof(a_message->hdr.type), sizeof(a_message->hdr.chain_id), - sizeof(a_message->hdr.sender_node_addr)}; - size_t l_data_size = 0; - for(int i=0;i<5;i++) l_data_size+=l_size[i]; - uint8_t *l_data = DAP_NEW_SIZE(uint8_t, l_data_size); - size_t l_offset = 0; - memcpy(l_data+l_offset, &a_message->hdr.id, l_size[0]); - l_offset+=l_size[0]; - memcpy(l_data+l_offset, &a_message->hdr.ts_created, l_size[1]); - l_offset+=l_size[1]; - memcpy(l_data+l_offset, &a_message->hdr.type, l_size[2]); - l_offset+=l_size[2]; - memcpy(l_data+l_offset, &a_message->hdr.chain_id, l_size[3]); - l_offset+=l_size[3]; - memcpy(l_data+l_offset, &a_message->hdr.sender_node_addr, l_size[4]); - *a_sign_size = l_data_size; - return l_data; + dap_chain_cs_block_ton_message_t *a_message, size_t *a_sign_size) +{ + struct ton_msg_signing_data { + dap_chain_cs_block_ton_msg_id_t id; + dap_time_t ts_created; + uint8_t type; + dap_chain_id_t chain_id; + dap_chain_node_addr_t sender_node_addr; + } DAP_ALIGN_PACKED; + + struct ton_msg_signing_data *l_data = DAP_NEW(struct ton_msg_signing_data); + l_data->id = a_message->hdr.id; + l_data->ts_created = a_message->hdr.ts_created; + l_data->type = a_message->hdr.type; + l_data->chain_id = a_message->hdr.chain_id; + l_data->sender_node_addr = a_message->hdr.sender_node_addr; + if (a_sign_size) + *a_sign_size = sizeof(l_data); + return (uint8_t *)l_data; } + static void s_message_send(dap_chain_cs_block_ton_session_t *a_session, uint8_t a_message_type, - uint8_t *a_data, size_t a_data_size, dap_list_t *a_validators) { - dap_chain_net_t *l_net = dap_chain_net_by_id(a_session->chain->net_id); - size_t l_message_size = sizeof(dap_chain_cs_block_ton_message_hdr_t)+a_data_size; - dap_chain_cs_block_ton_message_t *l_message = - DAP_NEW_SIZE(dap_chain_cs_block_ton_message_t, l_message_size); - l_message->hdr.id.uint64 = (uint64_t)a_session->cur_round.messages_count; - l_message->hdr.chain_id.uint64 = a_session->chain->id.uint64; - l_message->hdr.ts_created = dap_time_now(); - l_message->hdr.type = a_message_type; + uint8_t *a_data, size_t a_data_size, dap_list_t *a_validators) +{ + dap_chain_net_t *l_net = dap_chain_net_by_id(a_session->chain->net_id); + size_t l_message_size = sizeof(dap_chain_cs_block_ton_message_hdr_t)+a_data_size; + dap_chain_cs_block_ton_message_t *l_message = + DAP_NEW_SIZE(dap_chain_cs_block_ton_message_t, l_message_size); + l_message->hdr.id.uint64 = (uint64_t)a_session->cur_round.messages_count; + l_message->hdr.chain_id.uint64 = a_session->chain->id.uint64; + l_message->hdr.ts_created = dap_time_now(); + l_message->hdr.type = a_message_type; l_message->hdr.sender_node_addr = *dap_chain_net_get_cur_addr(l_net); - size_t l_sign_size = 0; - if ( !PVT(a_session->ton)->validators_list_by_stake ) { - size_t l_data_size = sizeof(l_message->hdr.sender_node_addr); - uint8_t *l_data = s_message_data_sign(a_session, l_message, &l_data_size); - dap_sign_t *l_sign = dap_sign_create(PVT(a_session->ton)->blocks_sign_key, l_data, l_data_size, 0); - l_sign_size = dap_sign_get_size(l_sign); - l_message_size += l_sign_size; - l_message = DAP_REALLOC(l_message, l_message_size); - memcpy(l_message->sign_n_message, l_sign, l_sign_size); - DAP_DELETE(l_sign); - DAP_DELETE(l_data); - } - l_message->hdr.sign_size = l_sign_size; - memcpy(l_message->sign_n_message+l_sign_size, a_data, a_data_size); - l_message->hdr.message_size = a_data_size; - - dap_chain_hash_fast_t l_message_hash; - dap_hash_fast(l_message, l_message_size, &l_message_hash); - - dap_stream_ch_chain_voting_message_write(l_net, a_validators, //a_session->cur_round.validators_start, - &l_message_hash, l_message, l_message_size); + size_t l_sign_size = 0; + if ( !PVT(a_session->ton)->validators_list_by_stake ) { + size_t l_data_size = sizeof(l_message->hdr.sender_node_addr); + uint8_t *l_data = s_message_data_sign(a_session, l_message, &l_data_size); + dap_sign_t *l_sign = dap_sign_create(PVT(a_session->ton)->blocks_sign_key, l_data, l_data_size, 0); + l_sign_size = dap_sign_get_size(l_sign); + l_message_size += l_sign_size; + l_message = DAP_REALLOC(l_message, l_message_size); + memcpy(l_message->sign_n_message, l_sign, l_sign_size); + DAP_DELETE(l_sign); + DAP_DELETE(l_data); + } + l_message->hdr.sign_size = l_sign_size; + memcpy(l_message->sign_n_message+l_sign_size, a_data, a_data_size); + l_message->hdr.message_size = a_data_size; + + dap_chain_hash_fast_t l_message_hash; + dap_hash_fast(l_message, l_message_size, &l_message_hash); + + dap_stream_ch_chain_voting_message_write(l_net, a_validators, //a_session->cur_round.validators_start, + &l_message_hash, l_message, l_message_size); DAP_DELETE(l_message); } static void s_message_chain_add(dap_chain_cs_block_ton_session_t *a_session, dap_chain_node_addr_t *a_sender_node_addr, - dap_chain_cs_block_ton_message_t *a_message, - size_t a_message_size, dap_chain_hash_fast_t *a_message_hash) { - - pthread_rwlock_wrlock(&a_session->rwlock); - dap_chain_cs_block_ton_message_t *l_message = a_message; - - dap_chain_cs_block_ton_message_getinfo_t *l_getinfo = - (dap_chain_cs_block_ton_message_getinfo_t *) - (l_message->sign_n_message+l_message->hdr.sign_size); - dap_chain_cs_block_ton_round_t *l_round = - l_getinfo->round_id.uint64 == a_session->old_round.id.uint64 ? - &a_session->old_round : &a_session->cur_round; + dap_chain_cs_block_ton_message_t *a_message, + size_t a_message_size, dap_chain_hash_fast_t *a_message_hash) { - l_message->hdr.is_genesis = !l_round->last_message_hash ? true : false; - if (!l_message->hdr.is_genesis) { - l_message->hdr.prev_message_hash = *l_round->last_message_hash; - } + pthread_rwlock_wrlock(&a_session->rwlock); + dap_chain_cs_block_ton_message_t *l_message = a_message; + dap_chain_cs_block_ton_round_t *l_round = &a_session->cur_round; + l_message->hdr.is_genesis = dap_hash_fast_is_blank(&l_round->last_message_hash); + if (!l_message->hdr.is_genesis) { + l_message->hdr.prev_message_hash = l_round->last_message_hash; + } - dap_chain_hash_fast_t l_message_hash; - dap_hash_fast(a_message, a_message_size, &l_message_hash); + dap_chain_hash_fast_t l_message_hash; + dap_hash_fast(a_message, a_message_size, &l_message_hash); - dap_chain_cs_block_ton_message_item_t *l_message_items = DAP_NEW_Z(dap_chain_cs_block_ton_message_item_t); - l_message_items->message = l_message; + dap_chain_cs_block_ton_message_item_t *l_message_items = DAP_NEW_Z(dap_chain_cs_block_ton_message_item_t); + l_message_items->message = l_message; - memcpy( &l_message_items->message_hash, &l_message_hash, sizeof(dap_chain_hash_fast_t)); - l_round->last_message_hash = - (dap_chain_hash_fast_t*)DAP_DUP_SIZE(&l_message_hash, sizeof(dap_chain_hash_fast_t)); - HASH_ADD(hh, l_round->messages_items, message_hash, sizeof(l_message_items->message_hash), l_message_items); + l_round->last_message_hash = l_message_items->message_hash = l_message_hash; + HASH_ADD(hh, l_round->messages_items, message_hash, sizeof(l_message_items->message_hash), l_message_items); - l_round->messages_count++; - memcpy( a_message_hash, &l_message_hash, sizeof(dap_chain_hash_fast_t)); + l_round->messages_count++; + if (a_message_hash) + *a_message_hash = l_message_hash; - pthread_rwlock_unlock(&a_session->rwlock); + pthread_rwlock_unlock(&a_session->rwlock); } static size_t s_callback_block_sign(dap_chain_cs_blocks_t *a_blocks, dap_chain_block_t **a_block_ptr, size_t a_block_size) @@ -2590,53 +2321,53 @@ static int s_callback_block_verify(dap_chain_cs_blocks_t *a_blocks, dap_chain_bl return -7; } - if ( l_ton_pvt->flag_sign_verify && !l_ton_pvt->validators_list_by_stake ) { // PoA mode - size_t l_offset = dap_chain_block_get_sign_offset(a_block, a_block_size); - size_t l_signs_count = 0; - dap_sign_t **l_signs = dap_sign_get_unique_signs(a_block->meta_n_datum_n_sign+l_offset, - a_block_size-sizeof(a_block->hdr)-l_offset, &l_signs_count); - if (!l_signs_count){ - log_it(L_ERROR, "No any signatures at all for block"); - DAP_DELETE(l_signs); - return -2; - } - - if ( ((float)l_signs_count/l_ton_pvt->poa_validators_count ) < ((float)2/3) ) { + if ( l_ton_pvt->flag_sign_verify && !l_ton_pvt->validators_list_by_stake ) { // PoA mode + size_t l_offset = dap_chain_block_get_sign_offset(a_block, a_block_size); + size_t l_signs_count = 0; + dap_sign_t **l_signs = dap_sign_get_unique_signs(a_block->meta_n_datum_n_sign+l_offset, + a_block_size-sizeof(a_block->hdr)-l_offset, &l_signs_count); + if (!l_signs_count){ + log_it(L_ERROR, "No any signatures at all for block"); + DAP_DELETE(l_signs); + return -2; + } + + if (l_signs_count * 3 < l_ton_pvt->poa_validators_count * 2) { log_it(L_ERROR, "Corrupted block: not enough signs: %zu of %hu", l_signs_count, l_ton_pvt->poa_validators_count); - DAP_DELETE(l_signs); - return -1; - } - - // Parse the rest signs - int l_ret = 0; - uint16_t l_signs_verified_count = 0; - size_t l_block_excl_sign_size = dap_chain_block_get_sign_offset(a_block, a_block_size)+sizeof(a_block->hdr); - for (size_t i=0; i<l_signs_count; i++) { - dap_sign_t *l_sign = (dap_sign_t *)l_signs[i]; - if (!dap_sign_verify_size(l_sign, a_block_size)) { - log_it(L_ERROR, "Corrupted block: sign size is bigger than block size"); - l_ret = -3; - break; - } - - // Compare signature with auth_certs - for (uint16_t j = 0; j < l_ton_pvt->auth_certs_count; j++) { - if (dap_cert_compare_with_sign( l_ton_pvt->auth_certs[j], l_sign) == 0 - && dap_sign_verify(l_sign, a_block, l_block_excl_sign_size) == 1 ){ - l_signs_verified_count++; - break; - } - } - } - DAP_DELETE(l_signs); - if ( l_ret != 0 ) { - return l_ret; - } - if ( ((float)l_signs_verified_count/l_ton_pvt->poa_validators_count ) < ((float)2/3) ) { - log_it(L_ERROR, "Corrupted block: not enough signs: %u of %u", l_signs_verified_count, l_ton_pvt->poa_validators_count); - return -1; - } - } + DAP_DELETE(l_signs); + return -1; + } + + // Parse the rest signs + int l_ret = 0; + uint16_t l_signs_verified_count = 0; + size_t l_block_excl_sign_size = dap_chain_block_get_sign_offset(a_block, a_block_size)+sizeof(a_block->hdr); + for (size_t i=0; i<l_signs_count; i++) { + dap_sign_t *l_sign = (dap_sign_t *)l_signs[i]; + if (!dap_sign_verify_size(l_sign, a_block_size - l_block_excl_sign_size + sizeof(a_block->hdr))) { + log_it(L_ERROR, "Corrupted block: sign size is bigger than block size"); + l_ret = -3; + break; + } + + // Compare signature with auth_certs + for (uint16_t j = 0; j < l_ton_pvt->auth_certs_count; j++) { + if (dap_cert_compare_with_sign( l_ton_pvt->auth_certs[j], l_sign) == 0 + && dap_sign_verify(l_sign, a_block, l_block_excl_sign_size) == 1 ){ + l_signs_verified_count++; + break; + } + } + } + DAP_DELETE(l_signs); + if ( l_ret != 0 ) { + return l_ret; + } + if (l_signs_verified_count * 3 < l_ton_pvt->poa_validators_count * 2) { + log_it(L_ERROR, "Corrupted block: not enough signs: %u of %u", l_signs_verified_count, l_ton_pvt->poa_validators_count); + return -1; + } + } return 0; } diff --git a/modules/consensus/block-ton/include/dap_chain_cs_block_ton.h b/modules/consensus/block-ton/include/dap_chain_cs_block_ton.h index c4a7f3a0d9856c9403f6061a870be6cbbba82ed7..686413fdad11a5b79c4d263a376b9993a77feeef 100644 --- a/modules/consensus/block-ton/include/dap_chain_cs_block_ton.h +++ b/modules/consensus/block-ton/include/dap_chain_cs_block_ton.h @@ -23,11 +23,6 @@ #define DAP_CHAIN_BLOCKS_SESSION_ROUND_ID_SIZE 8 #define DAP_CHAIN_BLOCKS_SESSION_MESSAGE_ID_SIZE 8 -enum { - DAP_TON$ROUND_CUR = 'c', - DAP_TON$ROUND_OLD = 'o', -}; - typedef struct dap_chain_cs_block_ton_message dap_chain_cs_block_ton_message_t; typedef struct dap_chain_cs_block_ton_message_item dap_chain_cs_block_ton_message_item_t; @@ -43,76 +38,71 @@ typedef union dap_chain_cs_block_ton_round_id { uint64_t uint64; } DAP_ALIGN_PACKED dap_chain_cs_block_ton_round_id_t; +typedef union dap_chain_cs_block_ton_msg_id { + uint8_t raw[DAP_CHAIN_BLOCKS_SESSION_MESSAGE_ID_SIZE]; + uint64_t uint64; +} DAP_ALIGN_PACKED dap_chain_cs_block_ton_msg_id_t; + typedef struct dap_chain_cs_block_ton_round { - dap_chain_cs_block_ton_round_id_t id; - dap_list_t *validators_start; // dap_chain_node_addr_t - uint16_t validators_start_count; - dap_chain_hash_fast_t *last_message_hash; - dap_chain_cs_block_ton_message_item_t *messages_items; - bool submit; - uint16_t messages_count; - dap_chain_hash_fast_t *my_candidate_hash; - dap_list_t *validators_list; // dap_chain_node_addr_t - uint16_t validators_count; - uint16_t candidates_count; + dap_chain_cs_block_ton_round_id_t id; + dap_list_t *validators_start; // dap_chain_node_addr_t + uint16_t validators_start_count; + dap_chain_hash_fast_t last_message_hash; + dap_chain_cs_block_ton_message_item_t *messages_items; + bool submit; + uint16_t messages_count; + dap_chain_hash_fast_t my_candidate_hash; + dap_list_t *validators_list; // dap_chain_node_addr_t + uint16_t validators_count; + uint16_t candidates_count; } dap_chain_cs_block_ton_round_t; typedef struct dap_chain_cs_block_ton_session { - dap_chain_t *chain; - dap_chain_cs_block_ton_t *ton; + dap_chain_t *chain; + dap_chain_cs_block_ton_t *ton; - dap_chain_node_addr_t *my_addr; + dap_chain_node_addr_t *my_addr; dap_chain_block_t *my_candidate; size_t my_candidate_size; - uint16_t my_candidate_attempts_count; + uint16_t my_candidate_attempts_count; + + uint8_t state; // session state + dap_chain_cs_block_ton_round_t cur_round; - uint8_t state; // session state - dap_chain_cs_block_ton_round_t cur_round; - dap_chain_cs_block_ton_round_t old_round; - - dap_chain_node_addr_t *attempt_coordinator; // validator-coordinator in current attempt - uint16_t attempt_current_number; + dap_chain_node_addr_t *attempt_coordinator; // validator-coordinator in current attempt + uint16_t attempt_current_number; - dap_time_t ts_round_sync_start; // time start sync - dap_time_t ts_round_start; // time round-start - dap_time_t ts_round_state_commit; - dap_time_t ts_round_finish; + dap_time_t ts_round_sync_start; // time start sync + dap_time_t ts_round_start; // time round-start + dap_time_t ts_round_state_commit; + dap_time_t ts_round_finish; - char * gdb_group_setup; - char * gdb_group_store; - char * gdb_group_message; + char * gdb_group_setup; + char * gdb_group_store; + char * gdb_group_message; - dap_enc_key_t *blocks_sign_key; + dap_enc_key_t *blocks_sign_key; struct dap_chain_cs_block_ton_session *next; struct dap_chain_cs_block_ton_session *prev; - bool time_proc_lock; // flag - skip check if prev check is not finish + bool time_proc_lock; // flag - skip check if prev check is not finish dap_worker_t * worker; // Worker where it was processed last time pthread_rwlock_t rwlock; } dap_chain_cs_block_ton_session_t; typedef struct dap_chain_cs_block_ton_message_hdr { - uint8_t type; - - union { - uint8_t raw[DAP_CHAIN_BLOCKS_SESSION_MESSAGE_ID_SIZE]; - uint64_t uint64; - } DAP_ALIGN_PACKED id; - - size_t sign_size; - size_t message_size; - - dap_time_t ts_created; - //dap_chain_cs_block_ton_round_id_t round_id; - - dap_chain_node_addr_t sender_node_addr; - - bool is_genesis; - bool is_verified; - dap_chain_hash_fast_t prev_message_hash; + uint8_t type; + dap_chain_cs_block_ton_msg_id_t id; + uint64_t sign_size; + uint64_t message_size; + dap_time_t ts_created; + dap_chain_node_addr_t sender_node_addr; + uint16_t is_genesis; + uint16_t is_verified; + dap_chain_hash_fast_t prev_message_hash; dap_chain_id_t chain_id; } DAP_ALIGN_PACKED dap_chain_cs_block_ton_message_hdr_t; @@ -129,15 +119,15 @@ typedef struct dap_chain_cs_block_ton_message_item { // struct for get info from any messages typedef struct dap_chain_cs_block_ton_message_getinfo { - dap_chain_hash_fast_t candidate_hash; - dap_chain_cs_block_ton_round_id_t round_id; - uint16_t attempt_number; + dap_chain_hash_fast_t candidate_hash; + dap_chain_cs_block_ton_round_id_t round_id; + uint16_t attempt_number; } DAP_ALIGN_PACKED dap_chain_cs_block_ton_message_getinfo_t; // technical messages typedef struct dap_chain_cs_block_ton_message_startsync { - dap_time_t ts; - dap_chain_cs_block_ton_round_id_t round_id; + dap_time_t ts; + dap_chain_cs_block_ton_round_id_t round_id; } DAP_ALIGN_PACKED dap_chain_cs_block_ton_message_startsync_t; /* @@ -153,61 +143,61 @@ in this round (even if the current process has another opinion) */ typedef struct dap_chain_cs_block_ton_message_submit { - dap_chain_hash_fast_t candidate_hash; - dap_chain_cs_block_ton_round_id_t round_id; - size_t candidate_size; - uint8_t candidate[]; + dap_chain_hash_fast_t candidate_hash; + dap_chain_cs_block_ton_round_id_t round_id; + size_t candidate_size; + uint8_t candidate[]; } DAP_ALIGN_PACKED dap_chain_cs_block_ton_message_submit_t; typedef struct dap_chain_cs_block_ton_message_approve { - dap_chain_hash_fast_t candidate_hash; - dap_chain_cs_block_ton_round_id_t round_id; - uint8_t candidate_hash_sign[]; + dap_chain_hash_fast_t candidate_hash; + dap_chain_cs_block_ton_round_id_t round_id; + uint8_t candidate_hash_sign[]; } DAP_ALIGN_PACKED dap_chain_cs_block_ton_message_approve_t; typedef struct dap_chain_cs_block_ton_message_reject { - dap_chain_hash_fast_t candidate_hash; - dap_chain_cs_block_ton_round_id_t round_id; + dap_chain_hash_fast_t candidate_hash; + dap_chain_cs_block_ton_round_id_t round_id; } DAP_ALIGN_PACKED dap_chain_cs_block_ton_message_reject_t; typedef struct dap_chain_cs_block_ton_message_votefor { - dap_chain_hash_fast_t candidate_hash; - dap_chain_cs_block_ton_round_id_t round_id; - uint16_t attempt_number; + dap_chain_hash_fast_t candidate_hash; + dap_chain_cs_block_ton_round_id_t round_id; + uint16_t attempt_number; } DAP_ALIGN_PACKED dap_chain_cs_block_ton_message_votefor_t; typedef struct dap_chain_cs_block_ton_message_vote { - dap_chain_hash_fast_t candidate_hash; - dap_chain_cs_block_ton_round_id_t round_id; - uint16_t attempt_number; + dap_chain_hash_fast_t candidate_hash; + dap_chain_cs_block_ton_round_id_t round_id; + uint16_t attempt_number; } DAP_ALIGN_PACKED dap_chain_cs_block_ton_message_vote_t; typedef struct dap_chain_cs_block_ton_message_precommit { - dap_chain_hash_fast_t candidate_hash; - dap_chain_cs_block_ton_round_id_t round_id; - uint16_t attempt_number; + dap_chain_hash_fast_t candidate_hash; + dap_chain_cs_block_ton_round_id_t round_id; + uint16_t attempt_number; } DAP_ALIGN_PACKED dap_chain_cs_block_ton_message_precommit_t; typedef struct dap_chain_cs_block_ton_message_commitsign { - dap_chain_hash_fast_t candidate_hash; - dap_chain_cs_block_ton_round_id_t round_id; - uint8_t candidate_sign[]; + dap_chain_hash_fast_t candidate_hash; + dap_chain_cs_block_ton_round_id_t round_id; + uint8_t candidate_sign[]; } DAP_ALIGN_PACKED dap_chain_cs_block_ton_message_commitsign_t; typedef struct dap_chain_cs_block_ton_store_hdr { - bool sign_collected; // cellect 2/3 min - bool approve_collected; - // bool reject_done; - bool vote_collected; - bool precommit_collected; - size_t candidate_size; - dap_chain_cs_block_ton_round_id_t round_id; - dap_chain_hash_fast_t candidate_hash; - dap_time_t ts_candidate_submit; + bool sign_collected; // collect 2/3 min + bool approve_collected; + // bool reject_done; + bool vote_collected; + bool precommit_collected; + size_t candidate_size; + dap_chain_cs_block_ton_round_id_t round_id; + dap_chain_hash_fast_t candidate_hash; + dap_time_t ts_candidate_submit; } DAP_ALIGN_PACKED dap_chain_cs_block_ton_store_hdr_t; typedef struct dap_chain_cs_block_ton_store { - dap_chain_cs_block_ton_store_hdr_t hdr; + dap_chain_cs_block_ton_store_hdr_t hdr; uint8_t candidate_n_signs[]; } DAP_ALIGN_PACKED dap_chain_cs_block_ton_store_t; diff --git a/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c b/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c index fd64efc4f3fdab214e06139939751a6833bb4a56..986cd1ee38545ecac54fa71db3031c35cbae89fc 100644 --- a/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c +++ b/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c @@ -55,7 +55,7 @@ #define LOG_TAG "dap_chain_cs_dag_poa" typedef struct dap_chain_cs_dag_poa_presign_callback{ - dap_chain_cs_dag_poa_callback_t callback; + dap_chain_cs_dag_poa_callback_t callback; void *arg; } dap_chain_cs_dag_poa_presign_callback_t; @@ -100,7 +100,7 @@ static void s_round_event_cs_done(dap_chain_cs_dag_t * a_dag, uint64_t a_round_i static int s_cli_dag_poa(int argc, char ** argv, char **str_reply); static bool s_seed_mode = false; -static dap_timerfd_t *s_poa_round_timer = NULL; +static dap_interval_timer_t s_poa_round_timer = NULL; /** * @brief @@ -130,7 +130,7 @@ void dap_chain_cs_dag_poa_deinit(void) /* // example -static int s_callback_presign_test(dap_chain_t *a_chain, +static int s_callback_presign_test(dap_chain_t *a_chain, dap_chain_cs_dag_event_t* a_event, size_t a_event_size, void *a_arg) { dap_chain_hash_fast_t l_event_hash; dap_chain_cs_dag_event_calc_hash(a_event, a_event_size, &l_event_hash); @@ -372,9 +372,7 @@ static int s_callback_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg) dap_chain_node_role_t l_role = dap_chain_net_get_role(l_net); if (l_role.enums == NODE_ROLE_ROOT_MASTER || l_role.enums == NODE_ROLE_ROOT) { if (!s_poa_round_timer) { - s_poa_round_timer = dap_interval_timer_create(10 * 1000, - s_poa_round_clean, - a_chain); + s_poa_round_timer = dap_interval_timer_create(10 * 1000, s_poa_round_clean, a_chain); log_it(L_MSG, "DAG-PoA: Round timer is started"); } } @@ -791,7 +789,7 @@ static int s_callback_event_round_sync(dap_chain_cs_dag_t * a_dag, const char a_ */ static int s_callback_event_verify(dap_chain_cs_dag_t * a_dag, dap_chain_cs_dag_event_t * a_event, size_t a_event_size) { - + dap_chain_cs_dag_poa_pvt_t * l_poa_pvt = PVT ( DAP_CHAIN_CS_DAG_POA( a_dag ) ); size_t l_offset_from_beginning = dap_chain_cs_dag_event_calc_size_excl_signs(a_event, a_event_size); if( l_offset_from_beginning >= a_event_size){ @@ -822,7 +820,7 @@ static int s_callback_event_verify(dap_chain_cs_dag_t * a_dag, dap_chain_cs_dag_ uint16_t l_event_signs_count = a_event->header.signs_count; for (size_t i=0; i<l_signs_count; i++) { dap_sign_t *l_sign = (dap_sign_t *)l_signs[i]; - if (!dap_sign_verify_size(l_sign, a_event_size)) { + if (!dap_sign_verify_size(l_sign, a_event_size - l_offset_from_beginning)) { log_it(L_WARNING,"Incorrect size with event %p", a_event); l_ret = -3; break; diff --git a/modules/consensus/dag-pos/dap_chain_cs_dag_pos.c b/modules/consensus/dag-pos/dap_chain_cs_dag_pos.c index 22312893f841d051ce10e0dfc4fccb3bf8d7918f..256a3219b1b42d8a7af0c94dd959ffa64487f53d 100644 --- a/modules/consensus/dag-pos/dap_chain_cs_dag_pos.c +++ b/modules/consensus/dag-pos/dap_chain_cs_dag_pos.c @@ -184,14 +184,14 @@ static void s_callback_delete(dap_chain_cs_dag_t * a_dag) } /** - * @brief + * @brief * create event - * @param a_dag - * @param a_datum - * @param a_hashes - * @param a_hashes_count - * @param a_dag_event_size - * @return dap_chain_cs_dag_event_t* + * @param a_dag + * @param a_datum + * @param a_hashes + * @param a_hashes_count + * @param a_dag_event_size + * @return dap_chain_cs_dag_event_t* */ static dap_chain_cs_dag_event_t * s_callback_event_create(dap_chain_cs_dag_t * a_dag, dap_chain_datum_t * a_datum, dap_chain_hash_fast_t * a_hashes, size_t a_hashes_count, @@ -213,12 +213,12 @@ static dap_chain_cs_dag_event_t * s_callback_event_create(dap_chain_cs_dag_t * a } /** - * @brief + * @brief * function makes event singing verification * @param a_dag dag object * @param a_dag_event dap_chain_cs_dag_event_t * @param a_dag_event_size size_t size of event object - * @return int + * @return int */ static int s_callback_event_verify(dap_chain_cs_dag_t * a_dag, dap_chain_cs_dag_event_t * a_dag_event, size_t a_dag_event_size) { @@ -233,6 +233,7 @@ static int s_callback_event_verify(dap_chain_cs_dag_t * a_dag, dap_chain_cs_dag_ log_it(L_WARNING,"Incorrect size with event %p on chain %s", a_dag_event, a_dag->chain->name); return -7; } + size_t l_offset_signs = dap_chain_cs_dag_event_calc_size_excl_signs(a_dag_event, a_dag_event_size); if ( a_dag_event->header.signs_count >= l_pos_pvt->confirmations_minimum ){ uint16_t l_verified_num = 0; @@ -243,7 +244,7 @@ static int s_callback_event_verify(dap_chain_cs_dag_t * a_dag, dap_chain_cs_dag_ return -4; } - bool l_sign_size_correct = dap_sign_verify_size(l_sign, a_dag_event_size); + bool l_sign_size_correct = dap_sign_verify_size(l_sign, a_dag_event_size - l_offset_signs); if (!l_sign_size_correct) { log_it(L_WARNING, "Event's sign size is incorrect"); return -41; diff --git a/modules/consensus/none/dap_chain_cs_none.c b/modules/consensus/none/dap_chain_cs_none.c index 030c1fea0ba503e6d624db2f76a76afd9880e9f9..c7c5e58d1f3bcdf8ce91bd0928630de0186a4dcc 100644 --- a/modules/consensus/none/dap_chain_cs_none.c +++ b/modules/consensus/none/dap_chain_cs_none.c @@ -25,11 +25,10 @@ #include <stdlib.h> #include <stdbool.h> #include <pthread.h> - -#include "dap_chain.h" #include "utlist.h" #include "dap_chain_net.h" +#include "dap_chain.h" #include "dap_common.h" #include "dap_strfuncs.h" #include "dap_config.h" @@ -95,16 +94,13 @@ static dap_chain_datum_t **s_chain_callback_atom_get_datum(dap_chain_atom_ptr_t static size_t s_chain_callback_datums_pool_proc(dap_chain_t * a_chain, dap_chain_datum_t ** a_datums, size_t a_datums_size); -static size_t s_chain_callback_datums_pool_proc_with_group(dap_chain_t * a_chain, dap_chain_datum_t ** a_datums, - size_t a_datums_size, const char *a_group); - /** * @brief stub for consensus - * + * * @param a_chain chain object * @param a_chain_cfg chain config object - * @return int + * @return int */ static int s_cs_callback_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg) { @@ -150,7 +146,7 @@ static void s_history_callback_notify(void * a_arg, const char a_op_code, const /** * @brief set PVT(DAP_CHAIN_GDB(a_chain))->is_load_mode = true - * + * * @param a_chain dap_chain_t object */ static void s_dap_chain_gdb_callback_purge(dap_chain_t *a_chain) @@ -162,8 +158,8 @@ static void s_dap_chain_gdb_callback_purge(dap_chain_t *a_chain) * @brief configure chain gdb * Set atom element callbacks * @param a_chain dap_chain_t chain object - * @param a_chain_cfg dap_config_t config object - * @return int + * @param a_chain_cfg dap_config_t config object + * @return int */ int dap_chain_gdb_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg) { @@ -211,7 +207,6 @@ int dap_chain_gdb_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg) a_chain->callback_atom_find_by_hash = s_chain_callback_atom_iter_find_by_hash; 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 @@ -226,7 +221,7 @@ int dap_chain_gdb_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg) /** * @brief clear dap_chain_gdb_t object - * + * * @param a_chain dap_chain_t chain object */ void dap_chain_gdb_delete(dap_chain_t * a_chain) @@ -242,7 +237,7 @@ void dap_chain_gdb_delete(dap_chain_t * a_chain) /** * @brief get group name for ledger - * + * * @param a_chain dap_chain_t * chain object * @return const char* */ @@ -310,7 +305,7 @@ static bool s_ledger_load_callback(dap_global_db_context_t * a_global_db_context /** * @brief Load ledger from mempool - * + * * @param a_gdb_group a_gdb_group char gdb group name * @param a_chain chain dap_chain_t object * @return int return 0 if OK otherwise negative error code @@ -331,11 +326,11 @@ int dap_chain_gdb_ledger_load(char *a_gdb_group, dap_chain_t *a_chain) /** * @brief call s_chain_callback_atom_add for every dap_chain_datum_t objects in a_datums array - * + * * @param a_chain dap_chain_t chain object (f.e. plasma) * @param a_datums dap_chain_datum array with dap_chain_datum objects * @param a_datums_count object counts in datums array - * @return size_t + * @return size_t */ static size_t s_chain_callback_datums_pool_proc(dap_chain_t * a_chain, dap_chain_datum_t ** a_datums, size_t a_datums_count) @@ -347,37 +342,20 @@ static size_t s_chain_callback_datums_pool_proc(dap_chain_t * a_chain, dap_chain return a_datums_count; } -/** - * @brief call s_chain_callback_atom_add for every dap_chain_datum_t objects in a_datums array only if chain contains specific group (chain-gdb.home21-network.chain-F) - * - * @param a_chain dap_chain_t chain object (f.e. plasma) - * @param a_datums dap_chain_datum array with dap_chain_datum objects - * @param a_datums_count object counts in datums array - * @param a_group group name - * @return size_t - */ -static size_t s_chain_callback_datums_pool_proc_with_group(dap_chain_t * a_chain, dap_chain_datum_t ** a_datums, - size_t a_datums_count, const char *a_group) -{ - if(dap_strcmp(dap_chain_gdb_get_group(a_chain), a_group)) - return 0; - return s_chain_callback_datums_pool_proc(a_chain, a_datums, a_datums_count); -} - /** * @brief add atom to DB - * + * * @param a_chain chaon object * @param a_atom pointer to atom * @param a_atom_size atom size - * @return dap_chain_atom_verify_res_t + * @return dap_chain_atom_verify_res_t */ static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_chain, dap_chain_atom_ptr_t a_atom, size_t a_atom_size) { dap_chain_gdb_t * l_gdb = DAP_CHAIN_GDB(a_chain); dap_chain_gdb_private_t *l_gdb_priv = PVT(l_gdb); dap_chain_datum_t *l_datum = (dap_chain_datum_t*) a_atom; - if(dap_chain_datum_add(a_chain, l_datum, a_atom_size)) + if(dap_chain_datum_add(a_chain, l_datum, a_atom_size, NULL)) return ATOM_REJECT; dap_chain_gdb_datum_hash_item_t * l_hash_item = DAP_NEW_Z(dap_chain_gdb_datum_hash_item_t); @@ -388,19 +366,24 @@ static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_cha dap_global_db_set(l_gdb_priv->group_datums, l_hash_item->key, l_datum, l_datum_size, false, NULL, NULL); } else log_it(L_DEBUG,"Load mode, doesn't save item %s:%s", l_hash_item->key, l_gdb_priv->group_datums); - DL_APPEND(l_gdb_priv->hash_items, l_hash_item); + if (!l_gdb_priv->is_load_mode && a_chain->atom_notifiers) { + for(dap_list_t *l_iter = a_chain->atom_notifiers; l_iter; l_iter = dap_list_next(l_iter)) { + dap_chain_atom_notifier_t *i = (dap_chain_atom_notifier_t *)l_iter->data; + i->callback(i->arg, a_chain, (dap_chain_cell_id_t){}, (void *)l_datum, l_datum_size); + } + } return ATOM_ACCEPT; } /** * @brief Verify atomic element (currently simply return ATOM_ACCEPT) - * + * * @param a_chain chain object * @param a_atom pointer to atom * @param a_atom_size size of atom - * @return dap_chain_atom_verify_res_t + * @return dap_chain_atom_verify_res_t */ static dap_chain_atom_verify_res_t s_chain_callback_atom_verify(dap_chain_t * a_chain, dap_chain_atom_ptr_t a_atom, size_t a_atom_size) { @@ -413,8 +396,8 @@ static dap_chain_atom_verify_res_t s_chain_callback_atom_verify(dap_chain_t * a_ /** * @brief return size of dap_chain_datum_t l_datum_null->header - * - * @return size_t + * + * @return size_t */ static size_t s_chain_callback_atom_get_static_hdr_size() { @@ -425,9 +408,9 @@ static size_t s_chain_callback_atom_get_static_hdr_size() /** * @brief Create atomic element iterator - * + * * @param a_chain dap_chain_t a_chain - * @return dap_chain_atom_iter_t* + * @return dap_chain_atom_iter_t* */ static dap_chain_atom_iter_t* s_chain_callback_atom_iter_create(dap_chain_t * a_chain, dap_chain_cell_id_t a_cell_id, bool a_with_treshold) { @@ -569,11 +552,11 @@ static dap_chain_atom_ptr_t s_chain_callback_atom_iter_get_next(dap_chain_atom_i /** * @brief return null in current implementation - * - * @param a_atom_iter - * @param a_links_size_ptr - * @param a_links_sizes_ptr - * @return dap_chain_atom_ptr_t* + * + * @param a_atom_iter + * @param a_links_size_ptr + * @param a_links_sizes_ptr + * @return dap_chain_atom_ptr_t* */ static dap_chain_atom_ptr_t* s_chain_callback_atom_iter_get_links(dap_chain_atom_iter_t * a_atom_iter, size_t * a_links_size_ptr, size_t **a_links_sizes_ptr) @@ -586,11 +569,11 @@ static dap_chain_atom_ptr_t* s_chain_callback_atom_iter_get_links(dap_chain_atom /** * @brief return null in current implementation - * - * @param a_atom_iter - * @param a_lasts_size_ptr - * @param a_links_sizes_ptr - * @return dap_chain_atom_ptr_t* + * + * @param a_atom_iter + * @param a_lasts_size_ptr + * @param a_links_sizes_ptr + * @return dap_chain_atom_ptr_t* */ static dap_chain_atom_ptr_t* s_chain_callback_atom_iter_get_lasts(dap_chain_atom_iter_t * a_atom_iter, size_t * a_lasts_size_ptr, size_t **a_links_sizes_ptr) @@ -603,11 +586,11 @@ static dap_chain_atom_ptr_t* s_chain_callback_atom_iter_get_lasts(dap_chain_atom /** * @brief get new datum object from atom - * + * * @param a_atom atom object * @param a_atom_size atom size * @param a_datums_count count of datums - * @return dap_chain_datum_t** + * @return dap_chain_datum_t** */ static dap_chain_datum_t **s_chain_callback_atom_get_datum(dap_chain_atom_ptr_t a_atom, size_t a_atom_size, size_t *a_datums_count) { diff --git a/modules/global-db/CMakeLists.txt b/modules/global-db/CMakeLists.txt index f83f426e737cecd870ba2874312d999147d6399c..72c9868c179e09de233703989c4ae2ea855d6e84 100644 --- a/modules/global-db/CMakeLists.txt +++ b/modules/global-db/CMakeLists.txt @@ -21,7 +21,12 @@ file(GLOB DAP_CHAIN_GLOBAL_DB_HDR include/dap_chain_global_db_driver_sqlite.h ) -set(DAP_CHAIN_GLOBAL_DB_LIBS dap_core dap_crypto dap_chain sqlite3 dap_cuttdb json-c) +add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../../3rdparty/cuttdb ${CMAKE_CURRENT_BINARY_DIR}/../../3rdparty/cuttdb) +if (BUILD_WITH_GDB_DRIVER_MDBX) +add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../../3rdparty/libmdbx ${CMAKE_CURRENT_BINARY_DIR}/../../3rdparty/libmdbx) +endif() + +set(DAP_CHAIN_GLOBAL_DB_LIBS dap_core dap_io dap_crypto dap_chain dap_chain_net sqlite3 dap_cuttdb json-c) if(BUILD_WITH_GDB_DRIVER_MDBX) file(GLOB DAP_CHAIN_GLOBAL_DB_SRC ${DAP_CHAIN_GLOBAL_DB_SRC} dap_chain_global_db_driver_mdbx.c) @@ -38,7 +43,7 @@ endif() add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_GLOBAL_DB_SRC} ${DAP_CHAIN_GLOBAL_DB_HDR}) -target_link_libraries(${PROJECT_NAME} ${DAP_CHAIN_GLOBAL_DB_LIBS}) +target_link_libraries(${PROJECT_NAME} ${DAP_CHAIN_GLOBAL_DB_LIBS}) target_include_directories(${PROJECT_NAME} INTERFACE .) target_include_directories(${PROJECT_NAME} PUBLIC include) diff --git a/modules/global-db/dap_chain_global_db_driver_mdbx.c b/modules/global-db/dap_chain_global_db_driver_mdbx.c index 8da7cc0b255febdb487393a2dc6f8f43610a5e0a..e307141db085afc17ce151622881b99f9954e1ed 100644 --- a/modules/global-db/dap_chain_global_db_driver_mdbx.c +++ b/modules/global-db/dap_chain_global_db_driver_mdbx.c @@ -821,12 +821,13 @@ size_t l_cnt = 0, l_count_out = 0; l_obj_arr = l_obj; l_obj = l_obj_arr + (l_cnt - 1); /* Point <l_obj> to last array's element */ + memset(l_obj, 0, sizeof(dap_store_obj_t)); if ( !(l_obj->key = DAP_CALLOC(1, l_key.iov_len + 1)) ) l_rc = MDBX_PROBLEM, log_it (L_ERROR, "Cannot allocate a memory for store object key, errno=%d", errno); else if ( (l_obj->value = DAP_CALLOC(1, (l_data.iov_len + 1) - sizeof(struct __record_suffix__))) ) - { + { /* Fill the <store obj> by data from the retreived record */ l_obj->key_len = l_key.iov_len; memcpy((char *) l_obj->key, l_key.iov_base, l_obj->key_len); @@ -834,14 +835,13 @@ size_t l_cnt = 0, l_count_out = 0; l_obj->value_len = l_data.iov_len - sizeof(struct __record_suffix__); memcpy(l_obj->value, l_data.iov_base, l_obj->value_len); - l_obj->id = l_suff->id; l_obj->timestamp = l_suff->ts; l_obj->flags = l_suff->flags; dap_assert ( (l_obj->group = dap_strdup(a_group)) ); l_obj->group_len = strlen(l_obj->group); - } + } else l_rc = MDBX_PROBLEM, log_it (L_ERROR, "Cannot allocate a memory for store object value, errno=%d", errno); } @@ -1005,8 +1005,7 @@ struct __record_suffix__ *l_suff; - if ( !(l_db_ctx = s_get_db_ctx_for_group(a_store_obj->group)) ) { /* Get a DB context for the group */ - log_it(L_WARNING, "No DB context for the group '%s', create it ...", a_store_obj->group); + if ( !(l_db_ctx = s_get_db_ctx_for_group(a_store_obj->group)) ) { /* Get a DB context for the group */ /* Group is not found ? Try to create table for new group */ if ( !(l_db_ctx = s_cre_db_ctx_for_group(a_store_obj->group, MDBX_CREATE)) ) return log_it(L_WARNING, "Cannot create DB context for the group '%s'", a_store_obj->group), -EIO; diff --git a/modules/global-db/dap_chain_global_db_driver_sqlite.c b/modules/global-db/dap_chain_global_db_driver_sqlite.c index 8f00e4283fb1af8171c47279c9203e84c26e5c1d..ed2772d08484b30627339b248d6660307a61bd94 100644 --- a/modules/global-db/dap_chain_global_db_driver_sqlite.c +++ b/modules/global-db/dap_chain_global_db_driver_sqlite.c @@ -611,7 +611,7 @@ int dap_db_driver_sqlite_apply_store_obj(dap_store_obj_t *a_store_obj) return -1; char *l_blob_value = s_dap_db_driver_get_string_from_blob(a_store_obj->value, (int)a_store_obj->value_len); //add one record - l_query = sqlite3_mprintf("REPLACE INTO '%s' values(NULL, '%s', x'', '%lld', x'%s')", + l_query = sqlite3_mprintf("INSERT INTO '%s' values(NULL, '%s', x'', '%lld', x'%s')", l_table_name, a_store_obj->key, a_store_obj->timestamp, l_blob_value); s_dap_db_driver_sqlite_free(l_blob_value); } @@ -650,17 +650,14 @@ int dap_db_driver_sqlite_apply_store_obj(dap_store_obj_t *a_store_obj) if(l_ret == SQLITE_CONSTRAINT) { s_dap_db_driver_sqlite_free(l_error_message); l_error_message = NULL; - //delete exist record - char *l_query_del = sqlite3_mprintf("DELETE FROM '%s' WHERE key = '%s'", l_table_name, a_store_obj->key); - l_ret = s_dap_db_driver_sqlite_exec(l_conn->conn, l_query_del, &l_error_message); - s_dap_db_driver_sqlite_free(l_query_del); - if(l_ret != SQLITE_OK) { - log_it(L_INFO, "Entry with the same key is already present and can't delete, %s", l_error_message); - s_dap_db_driver_sqlite_free(l_error_message); - l_error_message = NULL; - } - // repeat request - l_ret = s_dap_db_driver_sqlite_exec(l_conn->conn, l_query, &l_error_message); + //replace one record + char *l_blob_value = s_dap_db_driver_get_string_from_blob(a_store_obj->value, (int)a_store_obj->value_len); + char *l_query_replace = sqlite3_mprintf("REPLACE INTO '%s' values(NULL, '%s', x'', '%lld', x'%s')", + l_table_name, a_store_obj->key, a_store_obj->timestamp, l_blob_value); + s_dap_db_driver_sqlite_free(l_blob_value); + l_ret = s_dap_db_driver_sqlite_exec(l_conn->conn, l_query_replace, &l_error_message); + s_dap_db_driver_sqlite_free(l_query_replace); + } // missing database if(l_ret != SQLITE_OK) { diff --git a/modules/global-db/dap_chain_global_db_remote.c b/modules/global-db/dap_chain_global_db_remote.c index 7351eacc48eb32fa195fcf2ed94f9bd349a04f68..fae3fe9e0376659ed2406fe3e729f7ab276fd486 100644 --- a/modules/global-db/dap_chain_global_db_remote.c +++ b/modules/global-db/dap_chain_global_db_remote.c @@ -591,7 +591,7 @@ unsigned char *pdata; *( (uint64_t *) pdata) = a_store_obj->value_len; pdata += sizeof(uint64_t); memcpy(pdata, a_store_obj->value, a_store_obj->value_len); pdata += a_store_obj->value_len; - assert( (pdata - l_pkt->data) == l_data_size_out); + assert( (uint32_t)(pdata - l_pkt->data) == l_data_size_out); return l_pkt; } diff --git a/modules/global-db/dap_global_db.c b/modules/global-db/dap_global_db.c index 7d25fe500b502f86547e801d810a6c6bd2527c15..61f5a5baa6453c8890aa85fe53150e57768b2f76 100644 --- a/modules/global-db/dap_global_db.c +++ b/modules/global-db/dap_global_db.c @@ -208,7 +208,7 @@ int dap_global_db_init(const char * a_storage_path, const char * a_driver_name) s_driver_name = dap_strdup(a_driver_name); // Debug config - g_dap_global_db_debug_more = dap_config_get_item_bool(g_config, "global_db", "debug_more"); + g_dap_global_db_debug_more = dap_config_get_item_bool_default(g_config, "resources", "debug_more", false); // Driver initalization diff --git a/modules/global-db/include/dap_global_db.h b/modules/global-db/include/dap_global_db.h index d7d2e7afdbcc257ca4c393ad1d5537239ddb4e5c..e83c3d28ab5d5a5ae046ac4f426611f225ba6940 100644 --- a/modules/global-db/include/dap_global_db.h +++ b/modules/global-db/include/dap_global_db.h @@ -28,7 +28,7 @@ #include "dap_context.h" #include "dap_proc_queue.h" -#define DAP_GLOBAL_DB_VERSION 1 +#define DAP_GLOBAL_DB_VERSION 2 #define DAP_GLOBAL_DB_LOCAL_GENERAL "local.general" // GlobalDB own context custom extension diff --git a/modules/mempool/dap_chain_mempool.c b/modules/mempool/dap_chain_mempool.c index af666267f5ede774dbc1e13459b8d7b037b610dc..844d1d0e788654718b5d02bea7269024714783b2 100644 --- a/modules/mempool/dap_chain_mempool.c +++ b/modules/mempool/dap_chain_mempool.c @@ -59,6 +59,7 @@ #include "dap_list.h" #include "dap_chain.h" #include "dap_chain_net.h" +#include "dap_chain_net_tx.h" #include "dap_sign.h" #include "dap_chain_datum_tx.h" #include "dap_chain_datum_tx_items.h" @@ -117,19 +118,29 @@ dap_hash_fast_t* dap_chain_mempool_tx_create(dap_chain_t * a_chain, dap_enc_key_ !dap_chain_addr_check_sum(a_addr_from) || (a_addr_to && !dap_chain_addr_check_sum(a_addr_to)) || IS_ZERO_256(a_value)) return NULL; + const char *l_native_ticker = dap_chain_net_by_id(a_chain->net_id)->pub.native_ticker; + bool l_single_channel = !dap_strcmp(a_token_ticker, l_native_ticker); // find the transactions from which to take away coins uint256_t l_value_transfer = {}; // how many coins to transfer - uint256_t l_value_need; - // Full fee - uint256_t l_value_fee_full = {}; - // Add fee stake - SUM_256_256(a_value_fee, MAX_FEE_STAKE, &l_value_fee_full); - // Add full fee - SUM_256_256(a_value, l_value_fee_full, &l_value_need); + uint256_t l_value_need = a_value, l_net_fee = {}, l_total_fee = {}, l_fee_transfer = {}; + dap_chain_addr_t l_addr_fee = {}; + dap_list_t *l_list_fee_out = NULL; + bool l_net_fee_used = dap_chain_net_tx_get_fee(a_chain->net_id, &l_net_fee, &l_addr_fee); + SUM_256_256(l_net_fee, a_value_fee, &l_total_fee); + if (l_single_channel) + SUM_256_256(l_value_need, l_total_fee, &l_value_need); + else { + l_list_fee_out = dap_chain_ledger_get_list_tx_outs_with_val(a_chain->ledger, l_native_ticker, + a_addr_from, l_total_fee, &l_fee_transfer); + if (!l_list_fee_out) { + log_it(L_WARNING, "Not enough funds to pay fee"); + return NULL; + } + } dap_list_t *l_list_used_out = dap_chain_ledger_get_list_tx_outs_with_val(a_chain->ledger, a_token_ticker, a_addr_from, l_value_need, &l_value_transfer); if (!l_list_used_out) { - log_it(L_WARNING,"Not enough funds to transfer"); + log_it(L_WARNING, "Not enough funds to transfer"); return NULL; } // create empty transaction @@ -139,21 +150,38 @@ dap_hash_fast_t* dap_chain_mempool_tx_create(dap_chain_t * a_chain, dap_enc_key_ uint256_t l_value_to_items = dap_chain_datum_tx_add_in_item_list(&l_tx, l_list_used_out); assert(EQUAL_256(l_value_to_items, l_value_transfer)); dap_list_free_full(l_list_used_out, NULL); + if (l_list_fee_out) { + uint256_t l_value_fee_items = dap_chain_datum_tx_add_in_item_list(&l_tx, l_list_fee_out); + assert(EQUAL_256(l_value_fee_items, l_fee_transfer)); + dap_list_free_full(l_list_fee_out, NULL); + } + } - // add 'out' items - { + + if (l_single_channel) { // add 'out' items uint256_t l_value_pack = {}; // how much datoshi add to 'out' items - if(dap_chain_datum_tx_add_out_item(&l_tx, a_addr_to, a_value) == 1) { + if (dap_chain_datum_tx_add_out_item(&l_tx, a_addr_to, a_value) == 1) { SUM_256_256(l_value_pack, a_value, &l_value_pack); - // transaction fee - if (!IS_ZERO_256(a_value_fee)) { - if(dap_chain_datum_tx_add_fee_item(&l_tx, a_value_fee) == 1) - SUM_256_256(l_value_pack, a_value_fee, &l_value_pack); + } else { + dap_chain_datum_tx_delete(l_tx); + return NULL; + } + // Network fee + if (l_net_fee_used) { + if (dap_chain_datum_tx_add_out_item(&l_tx, &l_addr_fee, l_net_fee) == 1) + SUM_256_256(l_value_pack, l_net_fee, &l_value_pack); + else { + dap_chain_datum_tx_delete(l_tx); + return NULL; } - // Staker fee - if(!IS_ZERO_256(MAX_FEE_STAKE)) { - if(dap_chain_datum_tx_add_fee_stake_item(&l_tx, MAX_FEE_STAKE) == 1) - SUM_256_256(l_value_pack, MAX_FEE_STAKE, &l_value_pack); + } + // Validator's fee + if (!IS_ZERO_256(a_value_fee)) { + if (dap_chain_datum_tx_add_fee_item(&l_tx, a_value_fee) == 1) + SUM_256_256(l_value_pack, a_value_fee, &l_value_pack); + else { + dap_chain_datum_tx_delete(l_tx); + return NULL; } } // coin back @@ -165,6 +193,42 @@ dap_hash_fast_t* dap_chain_mempool_tx_create(dap_chain_t * a_chain, dap_enc_key_ return NULL; } } + } else { // add 'out_ext' items + if (dap_chain_datum_tx_add_out_ext_item(&l_tx, a_addr_to, a_value, a_token_ticker) != 1) { + dap_chain_datum_tx_delete(l_tx); + return NULL; + } + // coin back + uint256_t l_value_back; + SUBTRACT_256_256(l_value_transfer, a_value, &l_value_back); + if(!IS_ZERO_256(l_value_back)) { + if(dap_chain_datum_tx_add_out_item(&l_tx, a_addr_from, l_value_back) != 1) { + dap_chain_datum_tx_delete(l_tx); + return NULL; + } + } + // Network fee + if (l_net_fee_used) { + if (dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_addr_fee, l_net_fee, l_native_ticker) != 1) { + dap_chain_datum_tx_delete(l_tx); + return NULL; + } + } + // Validator's fee + if (!IS_ZERO_256(a_value_fee)) { + if (dap_chain_datum_tx_add_fee_item(&l_tx, a_value_fee) != 1) { + dap_chain_datum_tx_delete(l_tx); + return NULL; + } + } + // fee coin back + SUBTRACT_256_256(l_fee_transfer, l_total_fee, &l_value_back); + if(!IS_ZERO_256(l_value_back)) { + if(dap_chain_datum_tx_add_out_ext_item(&l_tx, a_addr_from, l_value_back, l_native_ticker) != 1) { + dap_chain_datum_tx_delete(l_tx); + return NULL; + } + } } // add 'sign' items @@ -209,18 +273,20 @@ int dap_chain_mempool_tx_create_massive( dap_chain_t * a_chain, dap_enc_key_t *a return -1; } - dap_global_db_obj_t * l_objs = DAP_NEW_Z_SIZE(dap_global_db_obj_t, (a_tx_num + 1) * sizeof (dap_global_db_obj_t)); - - + const char *l_native_ticker = dap_chain_net_by_id(a_chain->net_id)->pub.native_ticker; + if (dap_strcmp(a_token_ticker, l_native_ticker)) { + log_it(L_WARNING, "dap_chain_mempool_tx_create_massive() should only be used with native token"); + return -2; + } + dap_global_db_obj_t * l_objs = DAP_NEW_Z_SIZE(dap_global_db_obj_t, (a_tx_num + 1) * sizeof (dap_global_db_obj_t)); + uint256_t l_net_fee = {}, l_total_fee = {}; + dap_chain_addr_t l_addr_fee = {}; + bool l_net_fee_used = dap_chain_net_tx_get_fee(a_chain->net_id, &l_net_fee, &l_addr_fee); + SUM_256_256(l_net_fee, a_value_fee, &l_total_fee); // Search unused out: uint256_t l_single_val = {}; - // Full fee - uint256_t l_value_fee_full = {}; - // Add fee stake - SUM_256_256(a_value_fee, MAX_FEE_STAKE, &l_value_fee_full); - // Add full fee - SUM_256_256(a_value, l_value_fee_full, &l_single_val); + SUM_256_256(a_value, l_total_fee, &l_single_val); uint256_t l_value_need = {}; MULT_256_256(dap_chain_uint256_from(a_tx_num), l_single_val, &l_value_need); uint256_t l_value_transfer = {}; // how many coins to transfer @@ -254,7 +320,7 @@ int dap_chain_mempool_tx_create_massive( dap_chain_t * a_chain, dap_enc_key_t *a dap_chain_hash_fast_to_str(&l_item->tx_hash_fast,l_in_hash_str,sizeof (l_in_hash_str) ); char *l_balance = dap_chain_balance_print(l_item->value); - if(dap_chain_datum_tx_add_in_item(&l_tx_new, &l_item->tx_hash_fast, (uint32_t)l_item->num_idx_out) == 1) { + if (dap_chain_datum_tx_add_in_item(&l_tx_new, &l_item->tx_hash_fast, l_item->num_idx_out)) { SUM_256_256(l_value_to_items, l_item->value, &l_value_to_items); log_it(L_DEBUG, "Added input %s with %s datoshi", l_in_hash_str, l_balance); }else{ @@ -280,23 +346,36 @@ int dap_chain_mempool_tx_create_massive( dap_chain_t * a_chain, dap_enc_key_t *a // add 'out' items uint256_t l_value_pack = {}; // how much coin add to 'out' items - if(dap_chain_datum_tx_add_out_item(&l_tx_new, a_addr_to, a_value) == 1) { + if (dap_chain_datum_tx_add_out_item(&l_tx_new, a_addr_to, a_value) == 1) SUM_256_256(l_value_pack, a_value, &l_value_pack); - // Transaction fee - if (!IS_ZERO_256(a_value_fee)) { - if (dap_chain_datum_tx_add_fee_item(&l_tx_new, a_value_fee) == 1) - SUM_256_256(l_value_pack, a_value_fee, &l_value_pack); + else { + dap_chain_datum_tx_delete(l_tx_new); + DAP_DELETE(l_objs); + return -3; + } + // Network fee + if (l_net_fee_used) { + if (dap_chain_datum_tx_add_out_item(&l_tx_new, &l_addr_fee, l_net_fee) == 1) + SUM_256_256(l_value_pack, l_net_fee, &l_value_pack); + else { + dap_chain_datum_tx_delete(l_tx_new); + DAP_DELETE(l_objs); + return -3; } - // Staker fee - if(!IS_ZERO_256(MAX_FEE_STAKE)) { - if(dap_chain_datum_tx_add_fee_stake_item(&l_tx_new, MAX_FEE_STAKE) == 1) - SUM_256_256(l_value_pack, MAX_FEE_STAKE, &l_value_pack); + } + // Validator's fee + if (!IS_ZERO_256(a_value_fee)) { + if (dap_chain_datum_tx_add_fee_item(&l_tx_new, a_value_fee) == 1) + SUM_256_256(l_value_pack, a_value_fee, &l_value_pack); + else { + dap_chain_datum_tx_delete(l_tx_new); + DAP_DELETE(l_objs); + return -3; } } // coin back SUBTRACT_256_256(l_value_transfer, l_value_pack, &l_value_back); if (!IS_ZERO_256(l_value_back)) { - //log_it(L_DEBUG,"Change back %"DAP_UINT64_FORMAT_U"", l_value_back); if(dap_chain_datum_tx_add_out_item(&l_tx_new, a_addr_from, l_value_back) != 1) { dap_chain_datum_tx_delete(l_tx_new); DAP_DELETE(l_objs); @@ -308,7 +387,7 @@ int dap_chain_mempool_tx_create_massive( dap_chain_t * a_chain, dap_enc_key_t *a if(dap_chain_datum_tx_add_sign_item(&l_tx_new, a_key_from) != 1) { dap_chain_datum_tx_delete(l_tx_new); DAP_DELETE(l_objs); - return -1; + return -4; } // now tx is formed - calc size and hash size_t l_tx_size = dap_chain_datum_tx_get_size(l_tx_new); @@ -358,15 +437,13 @@ int dap_chain_mempool_tx_create_massive( dap_chain_t * a_chain, dap_enc_key_t *a //continue; l_objs[i].value = (uint8_t *)l_datum; l_objs[i].value_len = l_tx_size + sizeof(l_datum->header); - log_it(L_DEBUG, "Prepared obj with key %s (value_len = %zd)", + log_it(L_DEBUG, "Prepared obj with key %s (value_len = %"DAP_UINT64_FORMAT_U")", l_objs[i].key? l_objs[i].key :"NULL" , l_objs[i].value_len ); } - dap_list_free_full(l_list_used_out, NULL); + dap_list_free_full(l_list_used_out, free); char * l_gdb_group = dap_chain_net_get_gdb_group_mempool_new(a_chain); - - //return 0; dap_global_db_set_multiple_zc(l_gdb_group, l_objs,a_tx_num, s_tx_create_massive_gdb_save_callback , NULL ); DAP_DELETE(l_gdb_group); return 0; @@ -408,87 +485,83 @@ dap_chain_datum_t *dap_chain_tx_create_cond_input(dap_chain_net_t * a_net, dap_c log_it(L_ERROR, "Wrong address_to checksum"); return NULL; } - - // create empty transaction - dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create(); - - uint16_t pos = 0; - dap_chain_datum_tx_add_item(&l_tx, (byte_t*)a_receipt); - pos++; - uint256_t l_value_send = a_receipt->receipt_info.value_datoshi; - - // add 'in_cond' items - dap_chain_hash_fast_t *l_tx_prev_hash = a_tx_prev_hash; - dap_chain_datum_tx_t *l_tx_cond = dap_chain_ledger_tx_find_by_hash(l_ledger, l_tx_prev_hash); - int l_prev_cond_idx = 0; - dap_chain_tx_out_cond_t *l_out_cond = dap_chain_datum_tx_out_cond_get(l_tx_cond, &l_prev_cond_idx); + dap_chain_hash_fast_t *l_tx_final_hash = dap_chain_ledger_get_final_chain_tx_hash(l_ledger, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY, a_tx_prev_hash); + if (!l_tx_final_hash) { + log_it(L_WARNING, "Requested conditional transaction is already used out"); + return NULL; + } + if (dap_strcmp(a_net->pub.native_ticker, dap_chain_ledger_tx_get_token_ticker_by_hash(l_ledger, l_tx_final_hash))) { + log_it(L_WARNING, "Pay for service should be only in native token ticker"); + return NULL; + } + dap_chain_datum_tx_t *l_tx_cond = dap_chain_ledger_tx_find_by_hash(l_ledger, l_tx_final_hash); + int l_out_cond_idx; + dap_chain_tx_out_cond_t *l_out_cond = dap_chain_datum_tx_out_cond_get(l_tx_cond, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY, &l_out_cond_idx); if (!l_out_cond) { log_it(L_WARNING, "Requested conditioned transaction have no conditioned output"); return NULL; } - if (dap_chain_ledger_tx_hash_is_used_out_item(l_ledger, l_tx_prev_hash, l_prev_cond_idx)) { // TX already spent - dap_chain_datum_tx_t *l_tx_tmp = NULL; - dap_chain_hash_fast_t l_tx_cur_hash = { 0 }; // start hash - dap_chain_tx_out_cond_t *l_tmp_cond; - uint256_t l_value_cond = {}; - int l_tmp_cond_idx; - // Find all transactions - while (compare256(l_value_cond, l_value_send) == -1) { - l_tx_tmp = dap_chain_ledger_tx_cache_find_out_cond(l_ledger, &l_tx_cur_hash, &l_tmp_cond, &l_tmp_cond_idx, NULL); - if (!l_tx_tmp) { - break; - } - if (dap_chain_ledger_tx_hash_is_used_out_item(l_ledger, &l_tx_cur_hash, l_tmp_cond_idx)) - continue; - if (l_tmp_cond->header.subtype != l_out_cond->header.subtype) - continue; - if (!dap_chain_net_srv_uid_compare(l_tmp_cond->header.srv_uid, l_out_cond->header.srv_uid)) - continue; - if (l_tmp_cond->subtype.srv_pay.unit.uint32 != l_out_cond->subtype.srv_pay.unit.uint32) - continue; - if (!EQUAL_256(l_tmp_cond->subtype.srv_pay.unit_price_max_datoshi, l_out_cond->subtype.srv_pay.unit_price_max_datoshi)) - continue; - if (memcmp(&l_tmp_cond->subtype.srv_pay.pkey_hash, &l_out_cond->subtype.srv_pay.pkey_hash, sizeof(dap_chain_hash_fast_t))) - continue; - l_value_cond = l_tmp_cond->header.value; - } - if (compare256(l_value_cond, l_value_send) == -1) { - log_it(L_WARNING, "Requested conditional transaction is already used out"); - return NULL; - } - l_prev_cond_idx = l_tmp_cond_idx; - l_out_cond = l_tmp_cond; - l_tx_prev_hash = dap_chain_node_datum_tx_calc_hash(l_tx_tmp); + + dap_chain_tx_out_cond_t *l_out_fee = dap_chain_datum_tx_out_cond_get(l_tx_cond, DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE, NULL); + uint256_t l_fee = l_out_fee ? l_out_fee->header.value : uint256_0; + uint256_t l_value_send = a_receipt->receipt_info.value_datoshi; + uint256_t l_net_fee = {}; + dap_chain_addr_t l_addr_fee = {}; + bool l_net_fee_used = dap_chain_net_tx_get_fee(a_net->pub.id, &l_net_fee, &l_addr_fee); + SUM_256_256(l_value_send, l_net_fee, &l_value_send); + SUM_256_256(l_value_send, l_fee, &l_value_send); + if (compare256(l_out_cond->header.value, l_value_send) < 0) { + log_it(L_WARNING, "Requested conditioned transaction have no enough funds"); + return NULL; } - if (dap_chain_datum_tx_add_in_cond_item(&l_tx, l_tx_prev_hash, l_prev_cond_idx, pos - 1)) { + + // create empty transaction + dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create(); + dap_chain_datum_tx_add_item(&l_tx, (byte_t*)a_receipt); + // add 'in_cond' items + if (dap_chain_datum_tx_add_in_cond_item(&l_tx, l_tx_final_hash, l_out_cond_idx, 0)) { dap_chain_datum_tx_delete(l_tx); log_it( L_ERROR, "Cant add tx cond input"); return NULL; } - // add 'out' item - if (dap_chain_datum_tx_add_out_item(&l_tx, a_addr_to, l_value_send) != 1) { + if (dap_chain_datum_tx_add_out_item(&l_tx, a_addr_to, a_receipt->receipt_info.value_datoshi) != 1) { dap_chain_datum_tx_delete(l_tx); log_it( L_ERROR, "Cant add tx output"); return NULL; } - - uint256_t l_old_val = l_out_cond->header.value; - SUBTRACT_256_256(l_out_cond->header.value, l_value_send, &l_out_cond->header.value); - dap_chain_datum_tx_add_item(&l_tx, (const uint8_t *)l_out_cond); - l_out_cond->header.value = l_old_val; - - // add 'sign' items - if (a_key_tx_sign) { - if(dap_chain_datum_tx_add_sign_item(&l_tx, a_key_tx_sign) != 1) { + // add network fee + if (l_net_fee_used) { + if (dap_chain_datum_tx_add_out_item(&l_tx, &l_addr_fee, l_net_fee) != 1) { + dap_chain_datum_tx_delete(l_tx); + log_it( L_ERROR, "Cant add tx output"); + return NULL; + } + } + // add validator's fee + if (!IS_ZERO_256(l_fee)) { + if (dap_chain_datum_tx_add_fee_item(&l_tx, l_fee) != 1) { dap_chain_datum_tx_delete(l_tx); - log_it( L_ERROR, "Can't add sign output"); + log_it( L_ERROR, "Cant add tx output"); return NULL; } } + //add 'out_cond' item + uint256_t l_new_val = {}; + uint256_t l_value_cond = l_out_cond->header.value; + SUBTRACT_256_256(l_out_cond->header.value, l_value_send, &l_new_val); + l_out_cond->header.value = l_new_val; // Use old conditinal output to form the new one + dap_chain_datum_tx_add_item(&l_tx, (const uint8_t *)l_out_cond); + l_out_cond->header.value = l_value_cond; // Restore original value + // add 'sign' item + if(dap_chain_datum_tx_add_sign_item(&l_tx, a_key_tx_sign) != 1) { + dap_chain_datum_tx_delete(l_tx); + log_it( L_ERROR, "Can't add sign output"); + return NULL; + } size_t l_tx_size = dap_chain_datum_tx_get_size( l_tx ); dap_chain_datum_t *l_datum = dap_chain_datum_create( DAP_CHAIN_DATUM_TX, l_tx, l_tx_size ); - DAP_DELETE(l_tx); + dap_chain_datum_tx_delete(l_tx); return l_datum; } @@ -502,11 +575,7 @@ dap_chain_hash_fast_t* dap_chain_mempool_tx_create_cond_input(dap_chain_net_t * char * l_key_str = dap_chain_hash_fast_to_str_new( l_key_hash ); - char * l_gdb_group; - if(a_net->pub.default_chain) - l_gdb_group = dap_chain_net_get_gdb_group_mempool_new(a_net->pub.default_chain); - else - l_gdb_group = dap_chain_net_get_gdb_group_mempool_by_chain_type( a_net ,CHAIN_TYPE_TX); + char * l_gdb_group = dap_chain_net_get_gdb_group_mempool_by_chain_type(a_net, CHAIN_TYPE_TX); if( dap_global_db_set(l_gdb_group, l_key_str, l_datum, dap_chain_datum_size(l_datum), true, NULL, NULL ) == 0 ) { log_it(L_NOTICE, "Transaction %s placed in mempool", l_key_str); @@ -537,6 +606,14 @@ static dap_chain_datum_t* dap_chain_tx_create_cond(dap_chain_net_t *a_net, !a_key_from->priv_key_data || !a_key_from->priv_key_data_size || IS_ZERO_256(a_value)) return NULL; + if (dap_strcmp(a_net->pub.native_ticker, a_token_ticker)) { + log_it(L_WARNING, "Pay for service should be only in native token ticker"); + return NULL; + } + + uint256_t l_net_fee = {}; + dap_chain_addr_t l_addr_fee = {}; + bool l_net_fee_used = dap_chain_net_tx_get_fee(a_net->pub.id, &l_net_fee, &l_addr_fee); // find the transactions from which to take away coins uint256_t l_value_transfer = {}; // how many coins to transfer uint256_t l_value_need = {}; @@ -558,7 +635,7 @@ static dap_chain_datum_t* dap_chain_tx_create_cond(dap_chain_net_t *a_net, { uint256_t l_value_to_items = dap_chain_datum_tx_add_in_item_list(&l_tx, l_list_used_out); assert(EQUAL_256(l_value_to_items, l_value_transfer)); - dap_list_free_full(l_list_used_out, NULL); + dap_list_free_full(l_list_used_out, free); } // add 'out_cond' and 'out' items { @@ -566,9 +643,27 @@ static dap_chain_datum_t* dap_chain_tx_create_cond(dap_chain_net_t *a_net, if(dap_chain_datum_tx_add_out_cond_item(&l_tx, a_key_cond, a_srv_uid, a_value, a_value_per_unit_max, a_unit, a_cond, a_cond_size) == 1) { SUM_256_256(l_value_pack, a_value, &l_value_pack); - // transaction fee - if (!IS_ZERO_256(a_value_fee)) { - // TODO add condition with fee for mempool-as-service + } else { + dap_chain_datum_tx_delete(l_tx); + log_it( L_ERROR, "Cant add conditional output"); + return NULL; + } + // Network fee + if (l_net_fee_used) { + if (dap_chain_datum_tx_add_out_item(&l_tx, &l_addr_fee, l_net_fee) == 1) + SUM_256_256(l_value_pack, l_net_fee, &l_value_pack); + else { + dap_chain_datum_tx_delete(l_tx); + return NULL; + } + } + // Validator's fee + if (!IS_ZERO_256(a_value_fee)) { + if (dap_chain_datum_tx_add_fee_item(&l_tx, a_value_fee) == 1) + SUM_256_256(l_value_pack, a_value_fee, &l_value_pack); + else { + dap_chain_datum_tx_delete(l_tx); + return NULL; } } // coin back @@ -596,6 +691,7 @@ static dap_chain_datum_t* dap_chain_tx_create_cond(dap_chain_net_t *a_net, return l_datum; } + /** * Make transfer transaction & insert to cache * @@ -713,7 +809,7 @@ dap_chain_datum_token_emission_t *dap_chain_mempool_emission_get(dap_chain_t *a_ dap_chain_datum_token_emission_t *dap_chain_mempool_datum_emission_extract(dap_chain_t *a_chain, byte_t *a_data, size_t a_size) { - if (!a_chain || !a_data || !a_size) + if (!a_chain || !a_data || a_size < sizeof(dap_chain_datum_t)) return NULL; dap_chain_datum_t *l_datum = (dap_chain_datum_t *)a_data; if ((l_datum->header.version_id != DAP_CHAIN_DATUM_VERSION) || (l_datum->header.type_id != DAP_CHAIN_DATUM_TOKEN_EMISSION) || diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c index b3d28dc5ffbc84c68f6ff44fb260ae9ed754bdc9..eb378f0249924c0927f3156cde645779003eedf5 100644 --- a/modules/net/dap_chain_net.c +++ b/modules/net/dap_chain_net.c @@ -26,10 +26,6 @@ #ifndef _GNU_SOURCE #define _GNU_SOURCE -#include "dap_chain.h" -#include "dap_chain_datum_tx_out_cond.h" -#include "dap_list.h" -#include "dap_time.h" #endif #ifndef _XOPEN_SOURCE #define _XOPEN_SOURCE /* See feature_test_macros(7) */ @@ -65,7 +61,9 @@ #include "uthash.h" #include "utlist.h" - +#include "dap_chain.h" +#include "dap_list.h" +#include "dap_time.h" #include "dap_common.h" #include "dap_string.h" #include "dap_strfuncs.h" @@ -75,17 +73,22 @@ #include "dap_hash.h" #include "dap_cert.h" #include "dap_cert_file.h" - +#include "dap_chain_datum_tx.h" +#include "dap_chain_datum_tx_in_cond.h" +#include "dap_chain_datum_tx_items.h" +#include "dap_chain_datum_tx_out.h" +#include "dap_chain_datum_tx_out_cond.h" #include "dap_timerfd.h" #include "dap_stream_worker.h" #include "dap_worker.h" #include "dap_proc_queue.h" #include "dap_proc_thread.h" - #include "dap_enc_http.h" #include "dap_chain_common.h" #include "dap_chain_datum_decree.h" +#include "dap_chain_tx.h" #include "dap_chain_net.h" +#include "dap_chain_net_tx.h" #include "dap_chain_net_srv.h" #include "dap_chain_pvt.h" #include "dap_chain_node_client.h" @@ -135,11 +138,13 @@ struct link_dns_request { struct net_link { dap_chain_node_info_t *link_info; dap_chain_node_client_t *link; + dap_events_socket_uuid_t client_uuid; }; struct downlink { dap_stream_worker_t *worker; dap_stream_ch_uuid_t ch_uuid; + dap_events_socket_uuid_t esocket_uuid; UT_hash_handle hh; }; @@ -200,7 +205,7 @@ typedef struct dap_chain_net_pvt{ uint16_t acl_idx; // Main loop timer - dap_timerfd_t * main_timer; + dap_interval_timer_t main_timer; // General rwlock for structure pthread_rwlock_t rwlock; @@ -283,8 +288,7 @@ static int s_cli_net(int argc, char ** argv, char **str_reply); static bool s_seed_mode = false; -static uint8_t *dap_chain_net_set_acl(dap_chain_hash_fast_t *a_pkey_hash); - +static uint8_t *s_net_set_acl(dap_chain_hash_fast_t *a_pkey_hash); static bool s_start_dns_request(dap_chain_net_t *a_net, dap_chain_node_info_t *a_link_node_info); /** @@ -329,9 +333,7 @@ int dap_chain_net_init() s_required_links_count = dap_config_get_item_int32_default(g_config, "general", "require_links", s_required_links_count); s_debug_more = dap_config_get_item_bool_default(g_config,"chain_net","debug_more",false); - dap_chain_net_load_all(); - - dap_enc_http_set_acl_callback(dap_chain_net_set_acl); + dap_enc_http_set_acl_callback(s_net_set_acl); log_it(L_NOTICE,"Chain networks initialized"); return 0; } @@ -406,7 +408,7 @@ void dap_chain_net_add_gdb_notify_callback(dap_chain_net_t *a_net, dap_global_db PVT(a_net)->gdb_notifiers = dap_list_append(PVT(a_net)->gdb_notifiers, l_notifier); } -int dap_chain_net_add_downlink(dap_chain_net_t *a_net, dap_stream_worker_t *a_worker, dap_stream_ch_uuid_t a_ch_uuid) +int dap_chain_net_add_downlink(dap_chain_net_t *a_net, dap_stream_worker_t *a_worker, dap_stream_ch_uuid_t a_ch_uuid, dap_events_socket_uuid_t a_esocket_uuid) { if (!a_net || !a_worker) return -1; @@ -423,12 +425,12 @@ int dap_chain_net_add_downlink(dap_chain_net_t *a_net, dap_stream_worker_t *a_wo l_downlink = DAP_NEW_Z(struct downlink); l_downlink->worker = a_worker; l_downlink->ch_uuid = a_ch_uuid; + l_downlink->esocket_uuid = a_esocket_uuid; HASH_ADD_BYHASHVALUE(hh, l_net_pvt->downlinks, ch_uuid, sizeof(a_ch_uuid), a_hash_value, l_downlink); pthread_rwlock_unlock(&l_net_pvt->rwlock); return 0; } - struct send_records_args{ dap_chain_net_t * net; dap_proc_thread_t * proc_thread; @@ -518,7 +520,7 @@ static bool s_net_send_records_callback_get_raw (dap_global_db_context_t * a_glo static bool s_net_send_records(dap_proc_thread_t *a_thread, void *a_arg) { UNUSED(a_thread); - dap_store_obj_t *l_obj, *l_arg_obj = (dap_store_obj_t *)a_arg; + dap_store_obj_t *l_arg_obj = (dap_store_obj_t *)a_arg; dap_chain_net_t *l_net = (dap_chain_net_t *)l_arg_obj->callback_proc_thread_arg; struct send_records_args * l_args = DAP_NEW_Z(struct send_records_args); @@ -594,7 +596,7 @@ static bool s_net_send_atoms(dap_proc_thread_t *a_thread, void *a_arg) UNUSED(a_thread); dap_store_obj_t *l_arg = (dap_store_obj_t *)a_arg; dap_chain_net_t *l_net = (dap_chain_net_t *)l_arg->callback_proc_thread_arg; - pthread_rwlock_rdlock(&PVT(l_net)->rwlock); + pthread_rwlock_wrlock(&PVT(l_net)->rwlock); if (PVT(l_net)->state != NET_STATE_SYNC_CHAINS) { dap_list_t *it = NULL; do { @@ -822,99 +824,6 @@ static void s_fill_links_from_root_aliases(dap_chain_net_t * a_net) } } -/** - * @brief s_net_state_link_replace_error - * @param a_worker - * @param a_node_info - * @param a_arg - * @param a_errno - */ -/*static void s_net_state_link_replace_error(dap_worker_t *a_worker, dap_chain_node_info_t *a_node_info, void *a_arg, int a_errno) -{ - UNUSED(a_worker); - struct link_dns_request *l_dns_request = (struct link_dns_request *)a_arg; - dap_chain_net_t *l_net = l_dns_request->net; - char l_node_addr_str[INET_ADDRSTRLEN] = {}; - inet_ntop(AF_INET, &a_node_info->hdr.ext_addr_v4, l_node_addr_str, sizeof (a_node_info->hdr.ext_addr_v4)); - log_it(L_WARNING,"Link " NODE_ADDR_FP_STR " (%s) replace error with code %d", NODE_ADDR_FP_ARGS_S(a_node_info->hdr.address), - l_node_addr_str,a_errno ); - struct json_object *l_json = net_states_json_collect(l_net); - char l_err_str[128] = { }; - dap_snprintf(l_err_str, sizeof(l_err_str) - , "Link " NODE_ADDR_FP_STR " [%s] replace errno %d" - , NODE_ADDR_FP_ARGS_S(a_node_info->hdr.address), l_node_addr_str, a_errno); - json_object_object_add(l_json, "errorMessage", json_object_new_string(l_err_str)); - dap_notify_server_send_mt(json_object_get_string(l_json)); - json_object_put(l_json); - DAP_DELETE(a_node_info); - dap_chain_node_info_t *l_link_node_info = NULL; - for (int i = 0; i < 1000; i++) { - l_link_node_info = s_get_dns_link_from_cfg(l_net); - if (l_link_node_info) - break; - } - if (!l_link_node_info || PVT(l_net)->state == NET_STATE_OFFLINE) { // We have lost this link forever - DAP_DELETE(l_dns_request); - return; - } - if (dap_chain_node_info_dns_request(l_link_node_info->hdr.ext_addr_v4, - l_link_node_info->hdr.ext_port, - l_net->pub.name, - l_link_node_info, // use it twice - s_net_state_link_replace_success, - s_net_state_link_replace_error, - l_dns_request)) { - log_it(L_ERROR, "Can't process node info dns request"); - DAP_DELETE(l_link_node_info); - DAP_DELETE(l_dns_request); - } -}*/ - -/** - * @brief s_net_state_link_repace_success - * @param a_worker - * @param a_node_info - * @param a_arg - */ - -/*static void s_net_state_link_replace_success(dap_worker_t *a_worker, dap_chain_node_info_t *a_node_info, void *a_arg) -{ - if (s_debug_more) { - char l_node_addr_str[INET_ADDRSTRLEN] = {}; - inet_ntop(AF_INET, &a_node_info->hdr.ext_addr_v4, l_node_addr_str, INET_ADDRSTRLEN); - log_it(L_DEBUG,"Link " NODE_ADDR_FP_STR " (%s) replace success", NODE_ADDR_FP_ARGS_S(a_node_info->hdr.address), - l_node_addr_str); - } - - struct link_dns_request *l_dns_request = (struct link_dns_request *)a_arg; - dap_chain_net_t *l_net = l_dns_request->net; - dap_chain_net_pvt_t *l_net_pvt = PVT(l_net); - if (l_net_pvt->state == NET_STATE_OFFLINE) { - DAP_DELETE(l_dns_request); - return; - } - uint64_t l_own_addr = dap_chain_net_get_cur_addr_int(l_net); - if (a_node_info->hdr.address.uint64 == l_own_addr) { - s_net_state_link_replace_error(a_worker, a_node_info, a_arg, EWOULDBLOCK); - return; - } - struct net_link *l_new_link = DAP_NEW_Z(struct net_link); - l_new_link->link_info = a_node_info; - l_new_link->link = dap_chain_net_client_create_n_connect(l_net, a_node_info); - pthread_rwlock_wrlock(&l_net_pvt->rwlock); - l_net_pvt->net_links = dap_list_append(l_net_pvt->net_links, l_new_link); - pthread_rwlock_unlock(&l_net_pvt->rwlock); - struct json_object *l_json = net_states_json_collect(l_net); - char l_err_str[128] = { }; - dap_snprintf(l_err_str, sizeof(l_err_str) - , "Link " NODE_ADDR_FP_STR " replace success" - , NODE_ADDR_FP_ARGS_S(a_node_info->hdr.address)); - json_object_object_add(l_json, "errorMessage", json_object_new_string(l_err_str)); - dap_notify_server_send_mt(json_object_get_string(l_json)); - json_object_put(l_json); - DAP_DELETE(l_dns_request); -}*/ - /** * @brief s_node_link_callback_connected * @param a_node_client @@ -994,11 +903,13 @@ static void s_node_link_callback_disconnected(dap_chain_node_client_t *a_node_cl log_it(L_ERROR, "Links count is zero in disconnected callback, looks smbd decreased it twice or forget to increase on connect/reconnect"); } if (l_net_pvt->state_target != NET_STATE_OFFLINE) { - a_node_client->keep_connection = true; for (dap_list_t *it = l_net_pvt->net_links; it; it = it->next) { if (((struct net_link *)it->data)->link == NULL) { // We have a free prepared link - s_node_link_remove(l_net_pvt, a_node_client, true); - a_node_client->keep_connection = false; + s_node_link_remove(l_net_pvt, a_node_client, l_net_pvt->only_static_links); + dap_chain_node_client_t *l_client_new = dap_chain_net_client_create_n_connect(l_net, + ((struct net_link *)it->data)->link_info); + ((struct net_link *)it->data)->link = l_client_new; + ((struct net_link *)it->data)->client_uuid = l_client_new->uuid; ((struct net_link *)it->data)->link = dap_chain_net_client_create_n_connect(l_net, ((struct net_link *)it->data)->link_info); pthread_rwlock_unlock(&l_net_pvt->rwlock); @@ -1006,6 +917,7 @@ static void s_node_link_callback_disconnected(dap_chain_node_client_t *a_node_cl } } if (l_net_pvt->only_static_links) { + a_node_client->keep_connection = true; pthread_rwlock_unlock(&l_net_pvt->rwlock); return; } @@ -1022,16 +934,6 @@ static void s_node_link_callback_disconnected(dap_chain_node_client_t *a_node_cl if (l_link_node_info) { if(!s_start_dns_request(l_net, l_link_node_info)) { - /*struct link_dns_request *l_dns_request = DAP_NEW_Z(struct link_dns_request); - l_dns_request->net = l_net; - if (dap_chain_node_info_dns_request(l_link_node_info->hdr.ext_addr_v4, - l_link_node_info->hdr.ext_port, - l_net->pub.name, - l_link_node_info, // use it twice - s_net_state_link_prepare_success,//s_net_state_link_replace_success, - s_net_state_link_prepare_error,//s_net_state_link_replace_error, - l_dns_request)) { - */ log_it(L_ERROR, "Can't process node info dns request"); DAP_DELETE(l_link_node_info); } else { @@ -1113,7 +1015,9 @@ static void s_node_link_callback_delete(dap_chain_node_client_t * a_node_client, for ( dap_list_t * it = l_net_pvt->net_links; it; it=it->next ){ if (((struct net_link *)it->data)->link == a_node_client) { log_it(L_DEBUG,"Replace node client with new one"); - ((struct net_link *)it->data)->link = dap_chain_net_client_create_n_connect(l_net, a_node_client->info); + dap_chain_node_client_t *l_client = dap_chain_net_client_create_n_connect(l_net, a_node_client->info); + ((struct net_link *)it->data)->link = l_client; + ((struct net_link *)it->data)->client_uuid = l_client->uuid; } } pthread_rwlock_unlock(&l_net_pvt->rwlock); @@ -1332,15 +1236,16 @@ static bool s_net_states_proc(dap_proc_thread_t *a_thread, void *a_arg) { // delete all links dap_list_t *l_tmp = l_net_pvt->net_links; while (l_tmp) { - dap_list_t *l_next =l_tmp->next; - dap_chain_node_client_t *l_link = ((struct net_link *)l_tmp->data)->link; - if (l_link) { - l_link->keep_connection = false; - dap_chain_node_client_close(l_link); - } + dap_list_t *l_next = l_tmp->next; + dap_chain_node_client_close(((struct net_link *)l_tmp->data)->client_uuid); DAP_DEL_Z(((struct net_link *)l_tmp->data)->link_info); l_tmp = l_next; } + struct downlink *l_downlink, *l_dltmp; + HASH_ITER(hh, l_net_pvt->downlinks, l_downlink, l_dltmp) { + HASH_DEL(l_net_pvt->downlinks, l_downlink); + dap_events_socket_delete_mt(l_downlink->worker->worker, l_downlink->esocket_uuid); + } dap_list_free_full(l_net_pvt->net_links, NULL); l_net_pvt->net_links = NULL; if ( l_net_pvt->state_target != NET_STATE_OFFLINE ){ @@ -1453,6 +1358,7 @@ static bool s_net_states_proc(dap_proc_thread_t *a_thread, void *a_arg) { dap_chain_node_info_t *l_link_info = ((struct net_link *)l_tmp->data)->link_info; dap_chain_node_client_t *l_client = dap_chain_net_client_create_n_connect(l_net, l_link_info); ((struct net_link *)l_tmp->data)->link = l_client; + ((struct net_link *)l_tmp->data)->client_uuid = l_client->uuid; if (++l_used_links == s_required_links_count) break; } @@ -1774,7 +1680,7 @@ const char* dap_chain_net_get_type(dap_chain_t *l_chain) * @return true * @return false */ -void s_chain_net_ledger_cache_reload(dap_chain_net_t *l_net) +static void s_chain_net_ledger_cache_reload(dap_chain_net_t *l_net) { dap_chain_ledger_purge(l_net->pub.ledger, false); dap_chain_t *l_chain = NULL; @@ -1792,18 +1698,6 @@ void s_chain_net_ledger_cache_reload(dap_chain_net_t *l_net) debug_if(s_debug_more, L_DEBUG, "Added atom from treshold"); } } - /*bool l_processed; - do { - l_processed = false; - DL_FOREACH(l_net->pub.chains, l_chain) { - if (l_chain->callback_atom_add_from_treshold) { - while (l_chain->callback_atom_add_from_treshold(l_chain, NULL)) { - log_it(L_DEBUG, "Added atom from treshold"); - l_processed = true; - } - } - } - } while (l_processed); */ //TODO: Commented out in branch master and flagged as obscure code. } /** @@ -1814,7 +1708,7 @@ void s_chain_net_ledger_cache_reload(dap_chain_net_t *l_net) * @return true * @return false */ -bool s_chain_net_reload_ledger_cache_once(dap_chain_net_t *l_net) +static bool s_chain_net_reload_ledger_cache_once(dap_chain_net_t *l_net) { if (!l_net) return false; @@ -1826,7 +1720,7 @@ bool s_chain_net_reload_ledger_cache_once(dap_chain_net_t *l_net) return false; } // create file, if it not presented. If file exists, ledger cache operation is stopped - char *l_cache_file = dap_strdup_printf( "%s/%s.cache", l_cache_dir, "5B0FEEF6-B0D5-48A9-BFA2-32E8B294366D"); + char *l_cache_file = dap_strdup_printf( "%s/%s.cache", l_cache_dir, "e0fee993-54b7-4cbb-be94-f633cc17853f"); DAP_DELETE(l_cache_dir); if (dap_file_simple_test(l_cache_file)) { log_it(L_WARNING, "Cache file '%s' already exists", l_cache_file); @@ -1834,7 +1728,6 @@ bool s_chain_net_reload_ledger_cache_once(dap_chain_net_t *l_net) return false; } - log_it(L_WARNING,"Start one time ledger cache reloading"); static FILE *s_cache_file = NULL; s_cache_file = fopen(l_cache_file, "a"); if(!s_cache_file) { @@ -1846,9 +1739,6 @@ bool s_chain_net_reload_ledger_cache_once(dap_chain_net_t *l_net) return -1; } } - // reload ledger cache (same as net -net <network_name>> ledger reload command) - if (dap_file_simple_test(l_cache_file)) - s_chain_net_ledger_cache_reload(l_net); fclose(s_cache_file); DAP_DELETE(l_cache_file); return true; @@ -1861,21 +1751,21 @@ bool s_chain_net_reload_ledger_cache_once(dap_chain_net_t *l_net) * @return uint16_t */ static const char *s_chain_type_convert_to_string(dap_chain_type_t a_type) { - switch (a_type) { - case CHAIN_TYPE_TOKEN: - return ("token"); - case CHAIN_TYPE_EMISSION: - return ("emission"); - case CHAIN_TYPE_TX: - return ("transaction"); - case CHAIN_TYPE_CA: - return ("ca"); - case CHAIN_TYPE_SIGNER: - return ("signer"); - - default: - return ("custom"); - } + switch (a_type) { + case CHAIN_TYPE_TOKEN: + return ("token"); + case CHAIN_TYPE_EMISSION: + return ("emission"); + case CHAIN_TYPE_TX: + return ("transaction"); + case CHAIN_TYPE_CA: + return ("ca"); + case CHAIN_TYPE_SIGNER: + return ("signer"); + + default: + return ("custom"); + } } /** @@ -1933,13 +1823,13 @@ static int s_cli_net(int argc, char **argv, char **a_str_reply) dap_chain_t * l_chain = l_net->pub.chains; while (l_chain) { dap_string_append_printf(l_string_ret, "\t\t%s:\n", l_chain->name ); - if (l_chain->default_datum_types_count) - { - dap_string_append_printf(l_string_ret, "\t\t"); - for (uint16_t i = 0; i < l_chain->default_datum_types_count; i++) - dap_string_append_printf(l_string_ret, "| %s ", s_chain_type_convert_to_string(l_chain->default_datum_types[i]) ); - dap_string_append_printf(l_string_ret, "|\n"); - } + if (l_chain->default_datum_types_count) + { + dap_string_append_printf(l_string_ret, "\t\t"); + for (uint16_t i = 0; i < l_chain->default_datum_types_count; i++) + dap_string_append_printf(l_string_ret, "| %s ", s_chain_type_convert_to_string(l_chain->default_datum_types[i]) ); + dap_string_append_printf(l_string_ret, "|\n"); + } l_chain = l_chain->next; } } @@ -2269,12 +2159,13 @@ static int s_cli_net(int argc, char **argv, char **a_str_reply) "Subcommand 'ca' requires one of parameter: add, list, del\n"); l_ret = -5; } - } else if (l_ledger_str && !strcmp(l_ledger_str, "reload")) - { - s_chain_net_ledger_cache_reload(l_net); - } - else - { + } else if (l_ledger_str && !strcmp(l_ledger_str, "reload")) { + int l_return_state = dap_chain_net_stop(l_net); + sleep(1); // wait to net going offline + s_chain_net_ledger_cache_reload(l_net); + if (l_return_state) + dap_chain_net_start(l_net); + } else { dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'net' requires one of subcomands: sync, link, go, get, stats, ca, ledger"); l_ret = -1; @@ -2294,21 +2185,21 @@ static int s_cli_net(int argc, char **argv, char **a_str_reply) static void remove_duplicates_in_chain_by_priority(dap_chain_t *l_chain_1, dap_chain_t *l_chain_2) { - dap_chain_t *l_chain_high_priority = (l_chain_1->load_priority > l_chain_2->load_priority) ? l_chain_2 : l_chain_1; //such distribution is made for correct operation with the same priority - dap_chain_t *l_chain_low_priority = (l_chain_1->load_priority > l_chain_2->load_priority) ? l_chain_1 : l_chain_2; //...^...^...^... + dap_chain_t *l_chain_high_priority = (l_chain_1->load_priority > l_chain_2->load_priority) ? l_chain_2 : l_chain_1; //such distribution is made for correct operation with the same priority + dap_chain_t *l_chain_low_priority = (l_chain_1->load_priority > l_chain_2->load_priority) ? l_chain_1 : l_chain_2; //...^...^...^... - for (int i = 0; i < l_chain_high_priority->default_datum_types_count; i++) - { - for (int j = 0; j < l_chain_low_priority->default_datum_types_count; j++) - { - if (l_chain_high_priority->default_datum_types[i] == l_chain_low_priority->default_datum_types[j]) - { - l_chain_low_priority->default_datum_types[j] = l_chain_low_priority->default_datum_types[l_chain_low_priority->default_datum_types_count - 1]; - --l_chain_low_priority->default_datum_types_count; - --j; - } - } - } + for (int i = 0; i < l_chain_high_priority->default_datum_types_count; i++) + { + for (int j = 0; j < l_chain_low_priority->default_datum_types_count; j++) + { + if (l_chain_high_priority->default_datum_types[i] == l_chain_low_priority->default_datum_types[j]) + { + l_chain_low_priority->default_datum_types[j] = l_chain_low_priority->default_datum_types[l_chain_low_priority->default_datum_types_count - 1]; + --l_chain_low_priority->default_datum_types_count; + --j; + } + } + } } // for sequential loading chains @@ -2329,6 +2220,16 @@ static int callback_compare_prioritity_list(const void * a_item1, const void * a return -1; } +void s_main_timer_callback(void *a_arg) +{ + dap_chain_net_t *l_net = (dap_chain_net_t *)a_arg; + dap_chain_net_pvt_t *l_net_pvt = PVT(l_net); + if (l_net_pvt->state_target == NET_STATE_ONLINE && + l_net_pvt->state >= NET_STATE_LINKS_ESTABLISHED && + !l_net_pvt->links_connected_count) // restart network + dap_chain_net_start(l_net); +} + /** * @brief load network config settings from cellframe-node.cfg file * @@ -2548,87 +2449,69 @@ int s_net_load(const char * a_net_name, uint16_t a_acl_idx) ( l_seed_nodes_ipv4_len && i < l_seed_nodes_ipv4_len ) || ( l_seed_nodes_ipv6_len && i < l_seed_nodes_ipv6_len ) || ( l_seed_nodes_hostnames_len && i < l_seed_nodes_hostnames_len ) - ) - ; i++ ){ - dap_chain_node_addr_t *l_seed_node_addr; - dap_chain_node_info_t *l_node_info = NULL; - l_seed_node_addr = dap_chain_node_alias_find(l_net, l_net_pvt->seed_aliases[i]); - if (l_seed_node_addr) { - l_node_info = dap_chain_node_info_read(l_net, l_seed_node_addr); - DAP_DELETE(l_seed_node_addr); + ); i++) { + dap_chain_node_addr_t l_seed_node_addr = { 0 }, *l_seed_node_addr_gdb = NULL; + dap_chain_node_info_t l_node_info = { 0 }, *l_node_info_gdb = NULL; + + log_it(L_NOTICE, "Check alias %s in db", l_net_pvt->seed_aliases[i]); + dap_snprintf(l_node_info.hdr.alias,sizeof (l_node_info.hdr.alias),"%s", PVT(l_net)->seed_aliases[i]); + if (dap_sscanf(l_seed_nodes_addrs[i], NODE_ADDR_FP_STR, NODE_ADDR_FPS_ARGS_S(l_seed_node_addr)) != 4) { + log_it(L_ERROR,"Wrong address format, must be 0123::4567::890AB::CDEF"); + continue; } - if (!l_seed_node_addr || !l_node_info) { - log_it(L_NOTICE, "Update alias %s in database, prefill it",l_net_pvt->seed_aliases[i]); - l_node_info = DAP_NEW_Z(dap_chain_node_info_t); - l_seed_node_addr = DAP_NEW_Z(dap_chain_node_addr_t); - dap_snprintf( l_node_info->hdr.alias,sizeof ( l_node_info->hdr.alias),"%s",PVT(l_net)->seed_aliases[i]); - if (dap_sscanf(l_seed_nodes_addrs[i],NODE_ADDR_FP_STR, NODE_ADDR_FPS_ARGS(l_seed_node_addr) ) != 4 ){ - log_it(L_ERROR,"Wrong address format, should be like 0123::4567::890AB::CDEF"); - DAP_DELETE(l_seed_node_addr); - DAP_DELETE(l_node_info); - l_seed_node_addr = NULL; - continue; + if (l_seed_nodes_ipv4_len) + inet_pton(AF_INET, l_seed_nodes_ipv4[i], &l_node_info.hdr.ext_addr_v4); + if (l_seed_nodes_ipv6_len) + inet_pton(AF_INET6, l_seed_nodes_ipv6[i], &l_node_info.hdr.ext_addr_v6); + l_node_info.hdr.ext_port = l_seed_nodes_port_len && l_seed_nodes_port_len >= i ? + strtoul(l_seed_nodes_port[i], NULL, 10) : 8079; + + if (l_seed_nodes_hostnames_len) { + struct sockaddr l_sa = {}; + log_it(L_DEBUG, "Resolve %s addr", l_seed_nodes_hostnames[i]); + int l_ret_code = dap_net_resolve_host(l_seed_nodes_hostnames[i], AF_INET, &l_sa); + if (l_ret_code == 0) { + struct in_addr *l_res = (struct in_addr *)&l_sa; + log_it(L_NOTICE, "Resolved %s to %s (ipv4)", l_seed_nodes_hostnames[i], inet_ntoa(*l_res)); + l_node_info.hdr.ext_addr_v4.s_addr = l_res->s_addr; + } else { + log_it(L_ERROR, "%s", gai_strerror(l_ret_code)); } - if( l_seed_node_addr ){ - if ( l_seed_nodes_ipv4_len ) - inet_pton( AF_INET, l_seed_nodes_ipv4[i],&l_node_info->hdr.ext_addr_v4); - if ( l_seed_nodes_ipv6_len ) - inet_pton( AF_INET6, l_seed_nodes_ipv6[i],&l_node_info->hdr.ext_addr_v6); - if(l_seed_nodes_port_len && l_seed_nodes_port_len >= i) - l_node_info->hdr.ext_port = strtoul(l_seed_nodes_port[i], NULL, 10); - else - l_node_info->hdr.ext_port = 8079; - - if ( l_seed_nodes_hostnames_len ){ - struct addrinfo l_hints={0}; - - l_hints.ai_family = AF_UNSPEC ; /* Allow IPv4 or IPv6 */ - //l_hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */ - - log_it( L_DEBUG, "Resolve %s addr", l_seed_nodes_hostnames[i]); - struct hostent *l_he; - - if ( (l_he = gethostbyname (l_seed_nodes_hostnames[i]) ) != NULL ){ - struct in_addr **l_addr_list = (struct in_addr **) l_he->h_addr_list; - for(int i = 0; l_addr_list[i] != NULL; i++ ) { - log_it( L_NOTICE, "Resolved %s to %s (ipv4)", l_seed_nodes_hostnames[i] , - inet_ntoa( *l_addr_list[i] ) ); - l_node_info->hdr.ext_addr_v4.s_addr = l_addr_list[i]->s_addr; - } - } else { - herror("gethostname"); - } - } + } - l_node_info->hdr.address.uint64 = l_seed_node_addr->uint64; - if ( l_node_info->hdr.ext_addr_v4.s_addr || - #ifdef DAP_OS_BSD - l_node_info->hdr.ext_addr_v6.__u6_addr.__u6_addr32[0] - #else - l_node_info->hdr.ext_addr_v6.s6_addr32[0] - #endif - ){ - int l_ret; - if ( (l_ret = dap_chain_node_info_save(l_net, l_node_info)) ==0 ){ - if (dap_chain_node_alias_register(l_net,l_net_pvt->seed_aliases[i],l_seed_node_addr)) - log_it(L_NOTICE,"Seed node "NODE_ADDR_FP_STR" added to the curent list",NODE_ADDR_FP_ARGS(l_seed_node_addr) ); - else { - log_it(L_WARNING,"Cant register alias %s for address "NODE_ADDR_FP_STR, l_net_pvt->seed_aliases[i], NODE_ADDR_FP_ARGS(l_seed_node_addr)); - } - }else{ - log_it(L_WARNING,"Cant save node info for address "NODE_ADDR_FP_STR" return code %d", - NODE_ADDR_FP_ARGS(l_seed_node_addr), l_ret); - } + l_seed_node_addr_gdb = dap_chain_node_alias_find(l_net, l_net_pvt->seed_aliases[i]); + l_node_info_gdb = l_seed_node_addr_gdb ? dap_chain_node_info_read(l_net, l_seed_node_addr_gdb) : NULL; + + l_node_info.hdr.address = l_seed_node_addr; + if (l_node_info.hdr.ext_addr_v4.s_addr || +#ifdef DAP_OS_BSD + l_node_info.hdr.ext_addr_v6.__u6_addr.__u6_addr32[0] +#else + l_node_info.hdr.ext_addr_v6.s6_addr32[0] +#endif + ) { + /* Let's check if config was altered */ + int l_ret = l_node_info_gdb ? memcmp(&l_node_info, l_node_info_gdb, sizeof(dap_chain_node_info_t)) : 1; + if (!l_ret) { + log_it(L_NOTICE,"Seed node "NODE_ADDR_FP_STR" already in list", NODE_ADDR_FP_ARGS_S(l_seed_node_addr)); + } else { + /* Either not yet added or must be altered */ + l_ret = dap_chain_node_info_save(l_net, &l_node_info); + if (!l_ret) { + if (dap_chain_node_alias_register(l_net,l_net_pvt->seed_aliases[i], &l_seed_node_addr)) + log_it(L_NOTICE,"Seed node "NODE_ADDR_FP_STR" added to the curent list", NODE_ADDR_FP_ARGS_S(l_seed_node_addr)); + else + log_it(L_WARNING,"Cant register alias %s for address "NODE_ADDR_FP_STR, l_net_pvt->seed_aliases[i], NODE_ADDR_FP_ARGS_S(l_seed_node_addr)); + } else { + log_it(L_WARNING,"Cant save node info for address "NODE_ADDR_FP_STR" return code %d", NODE_ADDR_FP_ARGS_S(l_seed_node_addr), l_ret); } - DAP_DELETE(l_seed_node_addr); - }else - log_it(L_WARNING,"No address for seed node, can't populate global_db with it"); - DAP_DELETE( l_node_info); - } else { - log_it(L_DEBUG,"Seed alias %s is present", PVT(l_net)->seed_aliases[i]); - DAP_DELETE(l_node_info); - } + } + } else + log_it(L_WARNING,"No address for seed node, can't populate global_db with it"); + DAP_DEL_Z(l_seed_node_addr_gdb); + DAP_DEL_Z(l_node_info_gdb); } + PVT(l_net)->bootstrap_nodes_count = 0; PVT(l_net)->bootstrap_nodes_addrs = DAP_NEW_SIZE(struct in_addr, l_bootstrap_nodes_len * sizeof(struct in_addr)); PVT(l_net)->bootstrap_nodes_ports = DAP_NEW_SIZE(uint16_t, l_bootstrap_nodes_len * sizeof(uint16_t)); @@ -2755,6 +2638,12 @@ int s_net_load(const char * a_net_name, uint16_t a_acl_idx) } closedir(l_chains_dir); + // reload ledger cache at once + if (s_chain_net_reload_ledger_cache_once(l_net)) { + log_it(L_WARNING,"Start one time ledger cache reloading"); + dap_chain_ledger_purge(l_net->pub.ledger, false); + } + // sort list with chains names by priority l_prior_list = dap_list_sort(l_prior_list, callback_compare_prioritity_list); // load chains by priority @@ -2766,7 +2655,7 @@ int s_net_load(const char * a_net_name, uint16_t a_acl_idx) l_chain = dap_chain_load_from_cfg(l_net->pub.ledger, l_net->pub.name, l_net->pub.id, l_chain_prior->chains_path); if(l_chain) {//add minimum commission from to which the master node agrees. if present (default = 1.0) - l_chain->minimum_commission = dap_chain_coins_to_balance(dap_config_get_item_str_default(l_cfg , "general" ,"minimum_commission","1.0")); + l_chain->minimum_commission = dap_chain_coins_to_balance(dap_config_get_item_str_default(l_cfg , "general" ,"minimum_commission","1.0")); DL_APPEND(l_net->pub.chains, l_chain); if(l_chain->callback_created) l_chain->callback_created(l_chain, l_cfg); @@ -2797,7 +2686,7 @@ int s_net_load(const char * a_net_name, uint16_t a_acl_idx) log_it(L_ERROR, "Please, fix your configs and restart node"); return -2; } - remove_duplicates_in_chain_by_priority(l_chain, l_chain02); + remove_duplicates_in_chain_by_priority(l_chain, l_chain02); } } } @@ -2814,13 +2703,7 @@ int s_net_load(const char * a_net_name, uint16_t a_acl_idx) } } } while (l_processed); - - const char* l_default_chain_name = dap_config_get_item_str(l_cfg , "general" , "default_chain"); - if(l_default_chain_name) - l_net->pub.default_chain = dap_chain_net_get_chain_by_name(l_net, l_default_chain_name); - else - l_net->pub.default_chain = NULL; - + l_net->pub.native_ticker = dap_strdup(dap_config_get_item_str(l_cfg , "general" , "native_ticker")); } else { log_it(L_ERROR, "Can't find any chains for network %s", l_net->pub.name); l_net_pvt->load_mode = false; @@ -2854,7 +2737,8 @@ int s_net_load(const char * a_net_name, uint16_t a_acl_idx) char ** l_proc_chains = dap_config_get_array_str(l_cfg,"role-master" , "proc_chains", &l_proc_chains_count ); for ( size_t i = 0; i< l_proc_chains_count ; i++){ dap_chain_id_t l_chain_id = {{0}}; - if(dap_sscanf( l_proc_chains[i], "0x%16"DAP_UINT64_FORMAT_X, &l_chain_id.uint64) ==1 || dap_scanf("0x%16"DAP_UINT64_FORMAT_x, &l_chain_id.uint64) == 1){ + if (dap_sscanf( l_proc_chains[i], "0x%16"DAP_UINT64_FORMAT_X, &l_chain_id.uint64) ==1 || + dap_scanf("0x%16"DAP_UINT64_FORMAT_x, &l_chain_id.uint64) == 1) { dap_chain_t * l_chain = dap_chain_find_by_id(l_net->pub.id, l_chain_id ); if ( l_chain ){ l_chain->is_datum_pool_proc = true; @@ -2884,14 +2768,12 @@ int s_net_load(const char * a_net_name, uint16_t a_acl_idx) l_net_pvt->load_mode = false; dap_chain_ledger_load_end(l_net->pub.ledger); - // reload ledger cache at once - s_chain_net_reload_ledger_cache_once(l_net); - dap_chain_net_add_gdb_notify_callback(l_net, dap_chain_net_sync_gdb_broadcast, l_net); if (l_target_state != l_net_pvt->state_target) dap_chain_net_state_go_to(l_net, l_target_state); - // Start the proc thread + uint32_t l_timeout = dap_config_get_item_uint32_default(g_config, "node_client", "timer_update_states", 600); + PVT(l_net)->main_timer = dap_interval_timer_create(l_timeout * 1000, s_main_timer_callback, l_net); log_it(L_INFO, "Chain network \"%s\" initialized",l_net_item->name); DAP_DELETE(l_node_addr_str); @@ -2905,6 +2787,20 @@ int s_net_load(const char * a_net_name, uint16_t a_acl_idx) */ void dap_chain_net_deinit() { + pthread_rwlock_rdlock(&g_net_items_rwlock); + dap_chain_net_item_t *l_current_item, *l_tmp; + HASH_ITER(hh, s_net_items, l_current_item, l_tmp) { + dap_chain_net_t *l_net = l_current_item->chain_net; + dap_chain_net_pvt_t *l_net_pvt = PVT(l_net); + dap_interval_timer_delete(l_net_pvt->main_timer); + DAP_DEL_Z(l_net_pvt); + DAP_DEL_Z(l_net); + HASH_DEL(s_net_items, l_current_item); + DAP_DEL_Z(l_current_item); + } + pthread_rwlock_unlock(&g_net_items_rwlock); + pthread_rwlock_destroy(&g_net_items_rwlock); + } dap_chain_net_t **dap_chain_net_list(uint16_t *a_size) @@ -2974,10 +2870,9 @@ dap_chain_net_t * dap_chain_net_by_id( dap_chain_net_id_t a_id) * @param a_id * @return */ -uint16_t dap_chain_net_acl_idx_by_id(dap_chain_net_id_t a_id) +uint16_t dap_chain_net_get_acl_idx(dap_chain_net_t *a_net) { - dap_chain_net_t *l_net = dap_chain_net_by_id(a_id); - return l_net ? PVT(l_net)->acl_idx : (uint16_t)-1; + return a_net ? PVT(a_net)->acl_idx : (uint16_t)-1; } /** @@ -3015,15 +2910,16 @@ dap_chain_t * dap_chain_net_get_chain_by_name( dap_chain_net_t * l_net, const ch * @param a_datum_type * @return */ -dap_chain_t * dap_chain_net_get_chain_by_chain_type(dap_chain_net_t * l_net, dap_chain_type_t a_datum_type) +dap_chain_t *dap_chain_net_get_chain_by_chain_type(dap_chain_net_t *a_net, dap_chain_type_t a_datum_type) { - dap_chain_t * l_chain; - - if(!l_net) + if (!a_net) return NULL; - DL_FOREACH(l_net->pub.chains, l_chain) - { + dap_chain_t *l_chain = dap_chain_net_get_default_chain_by_chain_type(a_net, a_datum_type); + if (l_chain) + return l_chain; + + DL_FOREACH(a_net->pub.chains, l_chain) { for(int i = 0; i < l_chain->datum_types_count; i++) { if(l_chain->datum_types[i] == a_datum_type) return l_chain; @@ -3037,21 +2933,21 @@ dap_chain_t * dap_chain_net_get_chain_by_chain_type(dap_chain_net_t * l_net, dap * @param a_datum_type * @return */ -dap_chain_t * dap_chain_net_get_default_chain_by_chain_type(dap_chain_net_t * l_net, dap_chain_type_t a_datum_type) +dap_chain_t * dap_chain_net_get_default_chain_by_chain_type(dap_chain_net_t *a_net, dap_chain_type_t a_datum_type) { - dap_chain_t * l_chain; + dap_chain_t * l_chain; - if(!l_net) - return NULL; + if (!a_net) + return NULL; - DL_FOREACH(l_net->pub.chains, l_chain) - { - for(int i = 0; i < l_chain->default_datum_types_count; i++) { - if(l_chain->default_datum_types[i] == a_datum_type) - return l_chain; - } - } - return NULL; + DL_FOREACH(a_net->pub.chains, l_chain) + { + for(int i = 0; i < l_chain->default_datum_types_count; i++) { + if(l_chain->default_datum_types[i] == a_datum_type) + return l_chain; + } + } + return NULL; } /** @@ -3059,12 +2955,12 @@ dap_chain_t * dap_chain_net_get_default_chain_by_chain_type(dap_chain_net_t * l_ * @param a_datum_type * @return */ -char * dap_chain_net_get_gdb_group_mempool_by_chain_type(dap_chain_net_t * l_net, dap_chain_type_t a_datum_type) +char * dap_chain_net_get_gdb_group_mempool_by_chain_type(dap_chain_net_t *a_net, dap_chain_type_t a_datum_type) { - dap_chain_t * l_chain; - if(!l_net) + dap_chain_t *l_chain; + if (!a_net) return NULL; - DL_FOREACH(l_net->pub.chains, l_chain) + DL_FOREACH(a_net->pub.chains, l_chain) { for(int i = 0; i < l_chain->datum_types_count; i++) { if(l_chain->datum_types[i] == a_datum_type) @@ -3309,334 +3205,6 @@ void dap_chain_net_proc_mempool (dap_chain_net_t * a_net) } } -/** - * @brief For now it returns all COND_IN transactions - * @param a_net - * @param a_srv_uid - * @param a_search_type - * @return Hash lists of dap_chain_datum_tx_item_t with conditional transaction and it spending if present - */ -dap_chain_datum_tx_spends_items_t * dap_chain_net_get_tx_cond_all_with_spends_by_srv_uid(dap_chain_net_t * a_net, const dap_chain_net_srv_uid_t a_srv_uid, - const dap_time_t a_time_from, const dap_time_t a_time_to, - const dap_chain_net_tx_search_type_t a_search_type) -{ - dap_ledger_t * l_ledger = a_net->pub.ledger; - dap_chain_datum_tx_spends_items_t * l_ret = DAP_NEW_Z(dap_chain_datum_tx_spends_items_t); - - switch (a_search_type) { - case TX_SEARCH_TYPE_NET: - case TX_SEARCH_TYPE_CELL: - case TX_SEARCH_TYPE_LOCAL: - case TX_SEARCH_TYPE_CELL_SPENT: - case TX_SEARCH_TYPE_NET_UNSPENT: - case TX_SEARCH_TYPE_CELL_UNSPENT: - case TX_SEARCH_TYPE_NET_SPENT: { - // pass all chains - for ( dap_chain_t * l_chain = a_net->pub.chains; l_chain; l_chain = l_chain->next){ - dap_chain_cell_t * l_cell, *l_cell_tmp; - // Go through all cells - HASH_ITER(hh,l_chain->cells,l_cell, l_cell_tmp){ - dap_chain_atom_iter_t * l_atom_iter = l_chain->callback_atom_iter_create(l_chain,l_cell->id, false ); - // try to find transaction in chain ( inside shard ) - size_t l_atom_size = 0; - dap_chain_atom_ptr_t l_atom = l_chain->callback_atom_iter_get_first(l_atom_iter, &l_atom_size); - - // Check atoms in chain - while(l_atom && l_atom_size) { - size_t l_datums_count = 0; - dap_chain_datum_t **l_datums = l_chain->callback_atom_get_datums(l_atom, l_atom_size, &l_datums_count); - // transaction - dap_chain_datum_tx_t *l_tx = NULL; - - for (size_t i = 0; i < l_datums_count; i++) { - // Check if its transaction - if (l_datums && (l_datums[i]->header.type_id == DAP_CHAIN_DATUM_TX)) { - l_tx = (dap_chain_datum_tx_t *)l_datums[i]->data; - } - - // If found TX - if (l_tx){ - // Check for time from - if(a_time_from && l_tx->header.ts_created < a_time_from) - continue; - - // Check for time to - if(a_time_to && l_tx->header.ts_created > a_time_to) - continue; - - if(a_search_type == TX_SEARCH_TYPE_CELL_SPENT || a_search_type == TX_SEARCH_TYPE_NET_SPENT ){ - dap_hash_fast_t * l_tx_hash = dap_chain_node_datum_tx_calc_hash(l_tx); - bool l_is_spent = dap_chain_ledger_tx_spent_find_by_hash(l_ledger,l_tx_hash); - DAP_DELETE(l_tx_hash); - if(!l_is_spent) - continue; - } - - // Go through all items - uint32_t l_tx_items_pos = 0, l_tx_items_size = l_tx->header.tx_items_size; - int l_item_idx = 0; - while (l_tx_items_pos < l_tx_items_size) { - uint8_t *l_item = l_tx->tx_items + l_tx_items_pos; - int l_item_size = dap_chain_datum_item_tx_get_size(l_item); - if(!l_item_size) - break; - // check type - dap_chain_tx_item_type_t l_item_type = dap_chain_datum_tx_item_get_type(l_item); - switch (l_item_type){ - case TX_ITEM_TYPE_IN_COND:{ - dap_chain_tx_in_cond_t * l_tx_in_cond = (dap_chain_tx_in_cond_t *) l_item; - dap_chain_datum_tx_spends_item_t *l_tx_prev_out_item = NULL; - HASH_FIND(hh, l_ret->tx_outs, &l_tx_in_cond->header.tx_prev_hash,sizeof(l_tx_in_cond->header.tx_prev_hash), l_tx_prev_out_item); - - if (l_tx_prev_out_item){ // we found previous out_cond with target srv_uid - dap_chain_datum_tx_spends_item_t *l_item_in = DAP_NEW_Z(dap_chain_datum_tx_spends_item_t); - size_t l_tx_size = dap_chain_datum_tx_get_size(l_tx); - dap_chain_datum_tx_t * l_tx_dup = DAP_DUP_SIZE(l_tx,l_tx_size); - dap_hash_fast(l_tx_dup,l_tx_size, &l_item_in->tx_hash); - - l_item_in->tx = l_tx_dup; - // Calc same offset from tx duplicate - l_item_in->in_cond = (dap_chain_tx_in_cond_t*) (l_tx_dup->tx_items + l_tx_items_pos); - HASH_ADD_KEYPTR(hh,l_ret->tx_ins, &l_item_in->tx_hash, sizeof(l_item_in->tx_hash), l_item_in); - - // Link previous out with current in - l_tx_prev_out_item->tx_next = l_tx_dup; - } - }break; - case TX_ITEM_TYPE_OUT_COND:{ - dap_chain_tx_out_cond_t * l_tx_out_cond = (dap_chain_tx_out_cond_t *)l_item; - if(l_tx_out_cond->header.srv_uid.uint64 == a_srv_uid.uint64){ - dap_chain_datum_tx_spends_item_t * l_item = DAP_NEW_Z(dap_chain_datum_tx_spends_item_t); - size_t l_tx_size = dap_chain_datum_tx_get_size(l_tx); - dap_chain_datum_tx_t * l_tx_dup = DAP_DUP_SIZE(l_tx,l_tx_size); - dap_hash_fast(l_tx,l_tx_size, &l_item->tx_hash); - l_item->tx = l_tx_dup; - // Calc same offset from tx duplicate - l_item->out_cond = (dap_chain_tx_out_cond_t*) (l_tx_dup->tx_items + l_tx_items_pos); - - HASH_ADD_KEYPTR(hh,l_ret->tx_outs, &l_item->tx_hash, sizeof(l_item->tx_hash), l_item); - break; // We're seaching only for one specified OUT_COND output per transaction - } - } break; - default:; - } - - l_tx_items_pos += l_item_size; - l_item_idx++; - } - } - } - DAP_DEL_Z(l_datums); - // go to next atom - l_atom = l_chain->callback_atom_iter_get_next(l_atom_iter, &l_atom_size); - - } - } - } - } break; - - } - return l_ret; - -} - -/** - * @brief dap_chain_datum_tx_spends_items_free - * @param a_items - */ -void dap_chain_datum_tx_spends_items_free(dap_chain_datum_tx_spends_items_t * a_items) -{ - assert(a_items); - dap_chain_datum_tx_spends_item_free(a_items->tx_ins); - dap_chain_datum_tx_spends_item_free(a_items->tx_outs); - DAP_DELETE(a_items); -} - -/** - * @brief dap_chain_datum_tx_spends_item_free - * @param a_items - */ -void dap_chain_datum_tx_spends_item_free(dap_chain_datum_tx_spends_item_t * a_items) -{ - dap_chain_datum_tx_spends_item_t * l_item, *l_tmp; - HASH_ITER(hh,a_items,l_item,l_tmp){ - DAP_DELETE(l_item->tx); - HASH_DELETE(hh,a_items, l_item); - DAP_DELETE(l_item); - } -} - -/** - * @brief dap_chain_net_get_tx_cond_all_by_srv_uid - * @param a_net - * @param a_srv_uid - * @param a_search_type - * @return - */ -dap_list_t * dap_chain_net_get_tx_cond_all_by_srv_uid(dap_chain_net_t * a_net, const dap_chain_net_srv_uid_t a_srv_uid, - const dap_time_t a_time_from, const dap_time_t a_time_to, - const dap_chain_net_tx_search_type_t a_search_type) -{ - dap_ledger_t * l_ledger = a_net->pub.ledger; - dap_list_t * l_ret = NULL; - - switch (a_search_type) { - case TX_SEARCH_TYPE_NET: - case TX_SEARCH_TYPE_CELL: - case TX_SEARCH_TYPE_LOCAL: - case TX_SEARCH_TYPE_CELL_SPENT: - case TX_SEARCH_TYPE_NET_SPENT: { - // pass all chains - for ( dap_chain_t * l_chain = a_net->pub.chains; l_chain; l_chain = l_chain->next){ - dap_chain_cell_t * l_cell, *l_cell_tmp; - // Go through all cells - HASH_ITER(hh,l_chain->cells,l_cell, l_cell_tmp){ - dap_chain_atom_iter_t * l_atom_iter = l_chain->callback_atom_iter_create(l_chain,l_cell->id, false ); - // try to find transaction in chain ( inside shard ) - size_t l_atom_size = 0; - dap_chain_atom_ptr_t l_atom = l_chain->callback_atom_iter_get_first(l_atom_iter, &l_atom_size); - - // Check atoms in chain - while(l_atom && l_atom_size) { - dap_chain_datum_t *l_datum = (dap_chain_datum_t*) l_atom; - // transaction - dap_chain_datum_tx_t *l_tx = NULL; - - // Check if its transaction - if ( l_datum && (l_datum->header.type_id == DAP_CHAIN_DATUM_TX)) { - l_tx = (dap_chain_datum_tx_t*) l_datum->data; - } - - // If found TX - if (l_tx){ - // Check for time from - if(a_time_from && l_tx->header.ts_created < a_time_from) - continue; - - // Check for time to - if(a_time_to && l_tx->header.ts_created > a_time_to) - continue; - - if(a_search_type == TX_SEARCH_TYPE_CELL_SPENT || a_search_type == TX_SEARCH_TYPE_NET_SPENT ){ - dap_hash_fast_t * l_tx_hash = dap_chain_node_datum_tx_calc_hash(l_tx); - bool l_is_spent = dap_chain_ledger_tx_spent_find_by_hash(l_ledger,l_tx_hash); - DAP_DELETE(l_tx_hash); - if(!l_is_spent) - continue; - } - // Check for OUT_COND items - dap_list_t *l_list_out_cond_items = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_OUT_COND , NULL); - if(l_list_out_cond_items){ - dap_list_t *l_list_cur = l_list_out_cond_items; - while(l_list_cur){ // Go through all cond items - l_list_cur = dap_list_next(l_list_cur); - dap_chain_tx_out_cond_t * l_tx_out_cond = (dap_chain_tx_out_cond_t *)l_list_cur->data; - if(l_tx_out_cond) // If we found cond out with target srv_uid - if(l_tx_out_cond->header.srv_uid.uint64 == a_srv_uid.uint64) - l_ret = dap_list_append(l_ret,l_tx); - } - dap_list_free(l_list_out_cond_items); - } - } - - // go to next atom - l_atom = l_chain->callback_atom_iter_get_next(l_atom_iter, &l_atom_size); - - } - } - } - } break; - - case TX_SEARCH_TYPE_NET_UNSPENT: - case TX_SEARCH_TYPE_CELL_UNSPENT: - l_ret = dap_chain_ledger_tx_cache_find_out_cond_all(l_ledger, a_srv_uid); - break; - } - return l_ret; - -} - -/** - * @brief Summarize all tx inputs - * @param a_net - * @param a_tx - * @return - */ -uint256_t dap_chain_net_get_tx_total_value(dap_chain_net_t * a_net, dap_chain_datum_tx_t * a_tx) -{ - uint256_t l_ret = {0}; - int l_item_idx = 0; - dap_chain_tx_in_t *l_in_item = NULL; - do { - l_in_item = (dap_chain_tx_in_t*) dap_chain_datum_tx_item_get(a_tx, &l_item_idx, TX_ITEM_TYPE_IN , NULL); - l_item_idx++; - if(l_in_item ) { - //const char *token = l_out_cond_item->subtype.srv_xchange.token; - dap_chain_datum_tx_t * l_tx_prev = dap_chain_net_get_tx_by_hash(a_net,&l_in_item->header.tx_prev_hash, TX_SEARCH_TYPE_NET_SPENT); - if(l_tx_prev){ - int l_tx_prev_out_index = l_in_item->header.tx_out_prev_idx; - dap_chain_tx_out_t * l_tx_prev_out =(dap_chain_tx_out_t *) - dap_chain_datum_tx_item_get(l_tx_prev,&l_tx_prev_out_index, TX_ITEM_TYPE_OUT,NULL); - if( l_tx_prev_out_index == (int) l_in_item->header.tx_out_prev_idx && l_tx_prev_out){ - uint256_t l_in_value = l_tx_prev_out->header.value; - if(SUM_256_256(l_in_value,l_ret, &l_ret )!= 0) - log_it(L_ERROR, "Overflow on inputs values calculation (summing)"); - }else{ - log_it(L_WARNING, "Can't find item with index %d in prev tx hash", l_tx_prev_out_index); - } - }else - log_it(L_WARNING, "Can't find prev tx hash"); - } - } while(l_in_item); - return l_ret; -} - -/** - * @brief dap_chain_net_tx_get_by_hash - * @param a_net - * @param a_tx_hash - * @param a_search_type - * @return - */ -dap_chain_datum_tx_t * dap_chain_net_get_tx_by_hash(dap_chain_net_t * a_net, dap_chain_hash_fast_t * a_tx_hash, - dap_chain_net_tx_search_type_t a_search_type) -{ - dap_ledger_t * l_ledger = a_net->pub.ledger; - dap_chain_datum_tx_t * l_tx = NULL; - - switch (a_search_type) { - case TX_SEARCH_TYPE_NET: - case TX_SEARCH_TYPE_CELL: - case TX_SEARCH_TYPE_LOCAL: - case TX_SEARCH_TYPE_CELL_SPENT: - case TX_SEARCH_TYPE_NET_SPENT: { - - if ( ! l_tx ){ - // pass all chains - for ( dap_chain_t * l_chain = a_net->pub.chains; l_chain; l_chain = l_chain->next){ - if ( l_chain->callback_tx_find_by_hash ){ - // try to find transaction in chain ( inside shard ) - l_tx = l_chain->callback_tx_find_by_hash(l_chain, a_tx_hash); - if (l_tx) { - if ((a_search_type == TX_SEARCH_TYPE_CELL_SPENT || - a_search_type == TX_SEARCH_TYPE_NET_SPENT) && - (!dap_chain_ledger_tx_spent_find_by_hash(l_ledger, a_tx_hash))) - return NULL; - break; - } - } - } - } - } break; - - case TX_SEARCH_TYPE_NET_UNSPENT: - case TX_SEARCH_TYPE_CELL_UNSPENT: - l_tx = dap_chain_ledger_tx_find_by_hash(l_ledger, a_tx_hash); - break; - } - return l_tx; -} - /** * @brief dap_chain_net_get_extra_gdb_group * @param a_net @@ -3747,6 +3315,7 @@ static bool s_net_check_acl(dap_chain_net_t *a_net, dap_chain_hash_fast_t *a_pke } } } + dap_config_close(l_cfg); return l_authorized; } @@ -3756,7 +3325,7 @@ static bool s_net_check_acl(dap_chain_net_t *a_net, dap_chain_hash_fast_t *a_pke * @param a_pkey_hash dap_chain_hash_fast_t hash object * @return uint8_t* */ -static uint8_t *dap_chain_net_set_acl(dap_chain_hash_fast_t *a_pkey_hash) +static uint8_t *s_net_set_acl(dap_chain_hash_fast_t *a_pkey_hash) { uint16_t l_net_count; dap_chain_net_t **l_net_list = dap_chain_net_list(&l_net_count); @@ -3779,9 +3348,9 @@ static uint8_t *dap_chain_net_set_acl(dap_chain_hash_fast_t *a_pkey_hash) * @param a_filter_func * @param a_filter_func_param */ -dap_list_t* dap_chain_datum_list(dap_chain_net_t *a_net, dap_chain_t *a_chain, datum_filter_func_t *a_filter_func, void *a_filter_func_param) +dap_list_t* dap_chain_datum_list(dap_chain_net_t *a_net, dap_chain_t *a_chain, dap_chain_datum_filter_func_t *a_filter_func, void *a_filter_func_param) { - dap_list_t *l_list = NULL; + dap_list_t *l_list = NULL; if(!a_net) // return l_list; // void *l_chain_tmp = (void*) 0x1; @@ -3855,21 +3424,20 @@ dap_list_t* dap_chain_datum_list(dap_chain_net_t *a_net, dap_chain_t *a_chain, d * @param a_datum_size * @return */ -int dap_chain_datum_add(dap_chain_t * a_chain, dap_chain_datum_t *a_datum, size_t a_datum_size ) +int dap_chain_datum_add(dap_chain_t *a_chain, dap_chain_datum_t *a_datum, size_t a_datum_size, dap_hash_fast_t *a_tx_hash) { size_t l_datum_data_size = a_datum->header.data_size; if ( a_datum_size < l_datum_data_size+ sizeof (a_datum->header) ){ log_it(L_INFO,"Corrupted datum rejected: wrong size %zd not equel or less datum size %zd",a_datum->header.data_size+ sizeof (a_datum->header), a_datum_size ); - return -1; + return -101; } switch (a_datum->header.type_id) { case DAP_CHAIN_DATUM_DECREE:{ dap_chain_datum_decree_t * l_decree = (dap_chain_datum_decree_t *) a_datum->data; if( sizeof(l_decree->header)> l_datum_data_size ){ - log_it(L_WARNING, "Corrupted decree, size %zd is smaller than ever decree header's size %zd", l_datum_data_size, - sizeof(l_decree->header)); - break; + log_it(L_WARNING, "Corrupted decree, size %zd is smaller than ever decree header's size %zd", l_datum_data_size, sizeof(l_decree->header)); + return -102; } @@ -3883,42 +3451,34 @@ int dap_chain_datum_add(dap_chain_t * a_chain, dap_chain_datum_t *a_datum, size_ } }else{ log_it(L_WARNING,"Decree for unknown srv uid 0x%016"DAP_UINT64_FORMAT_X , l_decree->header.srv_id.uint64); + return -103; } - }break; + } default:; } - }break; + } break; + + case DAP_CHAIN_DATUM_TOKEN_DECL: + return dap_chain_ledger_token_load(a_chain->ledger, (dap_chain_datum_token_t *)a_datum->data, a_datum->header.data_size); + + case DAP_CHAIN_DATUM_TOKEN_EMISSION: + return dap_chain_ledger_token_emission_load(a_chain->ledger, a_datum->data, a_datum->header.data_size); - case DAP_CHAIN_DATUM_TOKEN_DECL:{ - if (dap_chain_ledger_token_load(a_chain->ledger, (dap_chain_datum_token_t *)a_datum->data, a_datum->header.data_size)) - return -2; - }break; - case DAP_CHAIN_DATUM_TOKEN_EMISSION: { - if (dap_chain_ledger_token_emission_load(a_chain->ledger, a_datum->data, a_datum->header.data_size)) - return -3; - }break; case DAP_CHAIN_DATUM_TX:{ dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t*) a_datum->data; // Check tx correcntess - size_t l_tx_size = dap_chain_datum_tx_get_size(l_tx); - if (l_tx_size > l_datum_data_size ){ - log_it(L_WARNING, "Corrupted transaction in datum, size %zd is greater than datum's size %zd", l_tx_size, l_datum_data_size); - return -1; - } + int res = dap_chain_ledger_tx_load(a_chain->ledger, l_tx, a_tx_hash); + return res == 1 ? 0 : res; + } + + case DAP_CHAIN_DATUM_CA: + return dap_cert_chain_file_save(a_datum, a_chain->net_name); - // TODO process with different codes from ledger to work with ledger thresholds - if (dap_chain_ledger_tx_load(a_chain->ledger, l_tx, NULL) != 1) - return -4; - }break; - case DAP_CHAIN_DATUM_CA:{ - if (dap_cert_chain_file_save(a_datum, a_chain->net_name) < 0) - return -5; - }break; case DAP_CHAIN_DATUM_SIGNER: - break; + break; case DAP_CHAIN_DATUM_CUSTOM: - break; + break; default: return -666; } diff --git a/modules/net/dap_chain_net_tx.c b/modules/net/dap_chain_net_tx.c new file mode 100644 index 0000000000000000000000000000000000000000..95e0c9c44f8c46ffe6b4d724f17381dc09f71d24 --- /dev/null +++ b/modules/net/dap_chain_net_tx.c @@ -0,0 +1,635 @@ +/* + * Authors: + * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net> + * DeM Labs Inc. https://demlabs.net + * Cellframe Network https://cellframe.net + * Copyright (c) 2022 + * 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_chain_net_tx.h" +#include "dap_chain_cell.h" +#include "dap_chain_common.h" +#include "dap_chain_datum_tx_in_cond.h" +#include "dap_chain_tx.h" +#include "dap_list.h" + +#define LOG_TAG "dap_chain_net_tx" + +/** + * @brief For now it returns all COND_IN transactions + * @param a_net + * @param a_srv_uid + * @param a_search_type + * @return Hash lists of dap_chain_datum_tx_item_t with conditional transaction and it spending if present + */ +dap_chain_datum_tx_spends_items_t * dap_chain_net_get_tx_cond_all_with_spends_by_srv_uid(dap_chain_net_t * a_net, const dap_chain_net_srv_uid_t a_srv_uid, + const dap_time_t a_time_from, const dap_time_t a_time_to, + const dap_chain_net_tx_search_type_t a_search_type) +{ + dap_ledger_t * l_ledger = a_net->pub.ledger; + dap_chain_datum_tx_spends_items_t * l_ret = DAP_NEW_Z(dap_chain_datum_tx_spends_items_t); + + switch (a_search_type) { + case TX_SEARCH_TYPE_NET: + case TX_SEARCH_TYPE_CELL: + case TX_SEARCH_TYPE_LOCAL: + case TX_SEARCH_TYPE_CELL_SPENT: + case TX_SEARCH_TYPE_NET_UNSPENT: + case TX_SEARCH_TYPE_CELL_UNSPENT: + case TX_SEARCH_TYPE_NET_SPENT: { + // pass all chains + for ( dap_chain_t * l_chain = a_net->pub.chains; l_chain; l_chain = l_chain->next){ + dap_chain_cell_t * l_cell, *l_cell_tmp; + // Go through all cells + HASH_ITER(hh,l_chain->cells,l_cell, l_cell_tmp){ + dap_chain_atom_iter_t * l_atom_iter = l_chain->callback_atom_iter_create(l_chain,l_cell->id, false ); + // try to find transaction in chain ( inside shard ) + size_t l_atom_size = 0; + dap_chain_atom_ptr_t l_atom = l_chain->callback_atom_iter_get_first(l_atom_iter, &l_atom_size); + + // Check atoms in chain + while(l_atom && l_atom_size) { + size_t l_datums_count = 0; + dap_chain_datum_t **l_datums = l_chain->callback_atom_get_datums(l_atom, l_atom_size, &l_datums_count); + // transaction + dap_chain_datum_tx_t *l_tx = NULL; + + for (size_t i = 0; i < l_datums_count; i++) { + // Check if its transaction + if (l_datums && (l_datums[i]->header.type_id == DAP_CHAIN_DATUM_TX)) { + l_tx = (dap_chain_datum_tx_t *)l_datums[i]->data; + } + + // If found TX + if (l_tx){ + // Check for time from + if(a_time_from && l_tx->header.ts_created < a_time_from) + continue; + + // Check for time to + if(a_time_to && l_tx->header.ts_created > a_time_to) + continue; + + if(a_search_type == TX_SEARCH_TYPE_CELL_SPENT || a_search_type == TX_SEARCH_TYPE_NET_SPENT ){ + dap_hash_fast_t * l_tx_hash = dap_chain_node_datum_tx_calc_hash(l_tx); + bool l_is_spent = dap_chain_ledger_tx_spent_find_by_hash(l_ledger,l_tx_hash); + DAP_DELETE(l_tx_hash); + if(!l_is_spent) + continue; + } + + // Go through all items + uint32_t l_tx_items_pos = 0, l_tx_items_size = l_tx->header.tx_items_size; + int l_item_idx = 0; + while (l_tx_items_pos < l_tx_items_size) { + uint8_t *l_item = l_tx->tx_items + l_tx_items_pos; + int l_item_size = dap_chain_datum_item_tx_get_size(l_item); + if(!l_item_size) + break; + // check type + dap_chain_tx_item_type_t l_item_type = dap_chain_datum_tx_item_get_type(l_item); + switch (l_item_type){ + case TX_ITEM_TYPE_IN_COND:{ + dap_chain_tx_in_cond_t * l_tx_in_cond = (dap_chain_tx_in_cond_t *) l_item; + dap_chain_datum_tx_spends_item_t *l_tx_prev_out_item = NULL; + HASH_FIND(hh, l_ret->tx_outs, &l_tx_in_cond->header.tx_prev_hash,sizeof(l_tx_in_cond->header.tx_prev_hash), l_tx_prev_out_item); + + if (l_tx_prev_out_item){ // we found previous out_cond with target srv_uid + dap_chain_datum_tx_spends_item_t *l_item_in = DAP_NEW_Z(dap_chain_datum_tx_spends_item_t); + size_t l_tx_size = dap_chain_datum_tx_get_size(l_tx); + dap_chain_datum_tx_t * l_tx_dup = DAP_DUP_SIZE(l_tx,l_tx_size); + dap_hash_fast(l_tx_dup,l_tx_size, &l_item_in->tx_hash); + + l_item_in->tx = l_tx_dup; + // Calc same offset from tx duplicate + l_item_in->in_cond = (dap_chain_tx_in_cond_t*) (l_tx_dup->tx_items + l_tx_items_pos); + HASH_ADD(hh,l_ret->tx_ins, tx_hash, sizeof(dap_chain_hash_fast_t), l_item_in); + + // Link previous out with current in + l_tx_prev_out_item->tx_next = l_tx_dup; + } + }break; + case TX_ITEM_TYPE_OUT_COND:{ + dap_chain_tx_out_cond_t * l_tx_out_cond = (dap_chain_tx_out_cond_t *)l_item; + if(l_tx_out_cond->header.srv_uid.uint64 == a_srv_uid.uint64){ + dap_chain_datum_tx_spends_item_t * l_item = DAP_NEW_Z(dap_chain_datum_tx_spends_item_t); + size_t l_tx_size = dap_chain_datum_tx_get_size(l_tx); + dap_chain_datum_tx_t * l_tx_dup = DAP_DUP_SIZE(l_tx,l_tx_size); + dap_hash_fast(l_tx,l_tx_size, &l_item->tx_hash); + l_item->tx = l_tx_dup; + // Calc same offset from tx duplicate + l_item->out_cond = (dap_chain_tx_out_cond_t*) (l_tx_dup->tx_items + l_tx_items_pos); + + HASH_ADD(hh,l_ret->tx_outs, tx_hash, sizeof(dap_chain_hash_fast_t), l_item); + break; // We're seaching only for one specified OUT_COND output per transaction + } + } break; + default:; + } + + l_tx_items_pos += l_item_size; + l_item_idx++; + } + } + } + DAP_DEL_Z(l_datums); + // go to next atom + l_atom = l_chain->callback_atom_iter_get_next(l_atom_iter, &l_atom_size); + + } + } + } + } break; + + } + return l_ret; + +} + +/** + * @brief dap_chain_datum_tx_spends_items_free + * @param a_items + */ +void dap_chain_datum_tx_spends_items_free(dap_chain_datum_tx_spends_items_t * a_items) +{ + assert(a_items); + dap_chain_datum_tx_spends_item_free(a_items->tx_ins); + dap_chain_datum_tx_spends_item_free(a_items->tx_outs); + DAP_DELETE(a_items); +} + +/** + * @brief dap_chain_datum_tx_spends_item_free + * @param a_items + */ +void dap_chain_datum_tx_spends_item_free(dap_chain_datum_tx_spends_item_t * a_items) +{ + dap_chain_datum_tx_spends_item_t * l_item, *l_tmp; + HASH_ITER(hh,a_items,l_item,l_tmp){ + DAP_DELETE(l_item->tx); + HASH_DELETE(hh,a_items, l_item); + DAP_DELETE(l_item); + } +} + +/** + * @brief dap_chain_net_get_tx_all + * @param a_net + * @param a_search_type + * @param a_tx_callback + * @param a_arg + */ +void dap_chain_net_get_tx_all(dap_chain_net_t * a_net, dap_chain_net_tx_search_type_t a_search_type ,dap_chain_net_tx_hash_callback_t a_tx_callback, void * a_arg) +{ + assert(a_tx_callback); + switch (a_search_type) { + case TX_SEARCH_TYPE_NET_UNSPENT: + case TX_SEARCH_TYPE_CELL_UNSPENT: + case TX_SEARCH_TYPE_NET: + case TX_SEARCH_TYPE_CELL: + case TX_SEARCH_TYPE_LOCAL: + case TX_SEARCH_TYPE_CELL_SPENT: + case TX_SEARCH_TYPE_NET_SPENT: { + // pass all chains + for ( dap_chain_t * l_chain = a_net->pub.chains; l_chain; l_chain = l_chain->next){ + dap_chain_cell_t * l_cell, *l_cell_tmp; + // Go through all cells + HASH_ITER(hh,l_chain->cells,l_cell, l_cell_tmp){ + dap_chain_atom_iter_t * l_atom_iter = l_chain->callback_atom_iter_create(l_chain,l_cell->id, false ); + // try to find transaction in chain ( inside shard ) + size_t l_atom_size = 0; + dap_chain_atom_ptr_t l_atom = l_chain->callback_atom_iter_get_first(l_atom_iter, &l_atom_size); + + // Check atoms in chain + while(l_atom && l_atom_size) { + size_t l_datums_count = 0; + dap_chain_datum_t **l_datums = l_chain->callback_atom_get_datums(l_atom, l_atom_size, &l_datums_count); + // transaction + dap_chain_datum_tx_t *l_tx = NULL; + + for (size_t i = 0; i < l_datums_count; i++) { + // Check if its transaction + if (l_datums && (l_datums[i]->header.type_id == DAP_CHAIN_DATUM_TX)) { + l_tx = (dap_chain_datum_tx_t *) l_datums[i]->data; + } + + // If found TX + if ( l_tx ) { + a_tx_callback(a_net, l_tx, a_arg); + } + } + DAP_DEL_Z(l_datums); + // go to next atom + l_atom = l_chain->callback_atom_iter_get_next(l_atom_iter, &l_atom_size); + } + } + } + } break; + + } +} + +/** + * @brief The get_tx_cond_all_from_tx struct + */ +struct get_tx_cond_all_from_tx +{ + dap_list_t * ret; + dap_hash_fast_t * tx_begin_hash; + dap_chain_datum_tx_t * tx_last; + dap_hash_fast_t tx_last_hash; + int tx_last_cond_idx; + dap_chain_net_srv_uid_t srv_uid; +}; + +/** + * @brief s_get_tx_cond_all_from_tx_callback + * @param a_net + * @param a_tx + * @param a_arg + */ +static void s_get_tx_cond_chain_callback(dap_chain_net_t* a_net, dap_chain_datum_tx_t *a_tx, void *a_arg) +{ + struct get_tx_cond_all_from_tx * l_args = (struct get_tx_cond_all_from_tx* ) a_arg; + dap_hash_fast_t * l_tx_hash = dap_chain_node_datum_tx_calc_hash(a_tx); + if( l_args->ret ){ + int l_item_idx = 0; + byte_t *l_tx_item; + + // Get items from transaction + while ((l_tx_item = dap_chain_datum_tx_item_get(a_tx, &l_item_idx, TX_ITEM_TYPE_IN_COND , NULL)) != NULL){ + dap_chain_tx_in_cond_t * l_in_cond = (dap_chain_tx_in_cond_t *) l_tx_item; + if(dap_hash_fast_compare(&l_in_cond->header.tx_prev_hash, &l_args->tx_last_hash) && + (uint32_t)l_args->tx_last_cond_idx == l_in_cond->header.tx_out_prev_idx ){ // Found output + // We're the next tx in tx cond chain + l_args->ret = dap_list_append(l_args->ret, a_tx); + } + l_item_idx++; + } + }else if(dap_hash_fast_compare(l_tx_hash,l_args->tx_begin_hash)){ + // Found condition + int l_item_idx = 0; + byte_t *l_tx_item; + + // Get items from transaction + while ((l_tx_item = dap_chain_datum_tx_item_get(a_tx, &l_item_idx, TX_ITEM_TYPE_OUT_COND , NULL)) != NULL){ + dap_chain_tx_out_cond_t * l_out_cond = (dap_chain_tx_out_cond_t *) l_tx_item; + if ( l_out_cond->header.srv_uid.uint64 == l_args->srv_uid.uint64 ){ // We found output with target service uuid + l_args->tx_last = a_tx; // Record current transaction as the last in tx chain + memcpy(&l_args->tx_last_hash, l_tx_hash, sizeof(*l_tx_hash)); // Record current hash + l_args->tx_last_cond_idx = l_item_idx; + l_args->ret = dap_list_append(NULL, a_tx); + break; + } + } + } + DAP_DELETE(l_tx_hash); +} + +/** + * @brief Return spends chain for conditioned transaction since beginning one + * @param a_net Network where to search for + * @param l_tx_hash TX hash of the Tx chain beginning + * @param a_srv_uid Service UID from witch cond output the chain begin + * @return List of conditioned transactions followin each other one by one as they do as spends + */ +dap_list_t * dap_chain_net_get_tx_cond_chain(dap_chain_net_t * a_net, dap_hash_fast_t * a_tx_hash, dap_chain_net_srv_uid_t a_srv_uid) +{ + struct get_tx_cond_all_from_tx * l_args = DAP_NEW_Z(struct get_tx_cond_all_from_tx); + l_args->tx_begin_hash = a_tx_hash; + l_args->srv_uid = a_srv_uid; + dap_chain_net_get_tx_all(a_net,TX_SEARCH_TYPE_NET,s_get_tx_cond_chain_callback, l_args); + dap_list_t * l_ret = l_args->ret; + DAP_DELETE(l_args); + return l_ret; +} + +/** + * @brief The get_tx_cond_all_for_addr struct + */ +struct get_tx_cond_all_for_addr +{ + dap_list_t * ret; + dap_chain_tx_t * tx_all_hh; // Transactions hash table for target address + const dap_chain_addr_t * addr; + dap_chain_net_srv_uid_t srv_uid; +}; + +/** + * @brief s_get_tx_cond_all_for_addr_callback + * @param a_net + * @param a_tx + * @param a_arg + */ +static void s_get_tx_cond_all_for_addr_callback(dap_chain_net_t* a_net, dap_chain_datum_tx_t *a_datum_tx, void *a_arg) +{ + struct get_tx_cond_all_for_addr * l_args = (struct get_tx_cond_all_for_addr* ) a_arg; + int l_item_idx = 0; + dap_chain_datum_tx_item_t *l_tx_item; + bool l_tx_for_addr = false; // TX with output related with our address + bool l_tx_from_addr = false; // TX with input that take assets from our address + //const char *l_tx_from_addr_token = NULL; + bool l_tx_collected = false; // We already collected this TX in return list + + // Get in items to detect is in or in_cond from target address + while ((l_tx_item = (dap_chain_datum_tx_item_t *) dap_chain_datum_tx_item_get(a_datum_tx, &l_item_idx, TX_ITEM_TYPE_ANY , NULL)) != NULL){ + switch (l_tx_item->type){ + case TX_ITEM_TYPE_IN:{ + dap_chain_tx_in_t * l_in = (dap_chain_tx_in_t *) l_tx_item; + if( l_tx_from_addr) // Already detected thats spends from addr + break; + dap_chain_tx_t * l_tx = dap_chain_tx_hh_find( l_args->tx_all_hh, &l_in->header.tx_prev_hash); + if( l_tx ){ // Its input thats closing output for target address - we note it + l_tx_from_addr = true; + //l_tx_from_addr_token = dap_chain_ledger_tx_get_token_ticker_by_hash(a_net->pub.ledger, &l_tx->hash); + } + }break; + case TX_ITEM_TYPE_IN_COND:{ + if(l_tx_collected) // Already collected + break; + dap_chain_tx_in_cond_t * l_in_cond = (dap_chain_tx_in_cond_t *) l_tx_item; + dap_chain_tx_t * l_tx = dap_chain_tx_hh_find( l_args->tx_all_hh, &l_in_cond->header.tx_prev_hash); + if( l_tx ){ // Its input thats closing conditioned tx related with target address, collect it + //dap_chain_tx_t *l_tx_add = dap_chain_tx_wrap_packed(a_datum_tx); + l_args->ret = dap_list_append(l_args->ret, a_datum_tx); + l_tx_collected = true; + } + }break; + } + l_item_idx++; + } + + // Get out items from transaction + while ((l_tx_item = (dap_chain_datum_tx_item_t *) dap_chain_datum_tx_item_get(a_datum_tx, &l_item_idx, TX_ITEM_TYPE_OUT_ALL , NULL)) != NULL){ + switch (l_tx_item->type){ + case TX_ITEM_TYPE_OUT:{ + if(l_tx_for_addr) // Its already added + break; + dap_chain_tx_out_t * l_out = (dap_chain_tx_out_t*) l_tx_item; + if ( memcmp(&l_out->addr, l_args->addr, sizeof(*l_args->addr)) == 0){ // Its our address tx + dap_chain_tx_t * l_tx = dap_chain_tx_wrap_packed(a_datum_tx); + dap_chain_tx_hh_add(l_args->tx_all_hh, l_tx); + l_tx_for_addr = true; + } + }break; + case TX_ITEM_TYPE_OUT_EXT:{ + if(l_tx_for_addr) // Its already added + break; + dap_chain_tx_out_ext_t * l_out = (dap_chain_tx_out_ext_t*) l_tx_item; + if ( memcmp(&l_out->addr, l_args->addr, sizeof(*l_args->addr)) == 0){ // Its our address tx + dap_chain_tx_t * l_tx = dap_chain_tx_wrap_packed(a_datum_tx); + dap_chain_tx_hh_add(l_args->tx_all_hh, l_tx); + l_tx_for_addr = true; + } + }break; + case TX_ITEM_TYPE_OUT_COND:{ + dap_chain_tx_out_cond_t * l_out_cond = (dap_chain_tx_out_cond_t*) l_tx_item; + if(l_tx_collected) // Already collected for return list + break; + + // If this output spends monies from our address + if(l_tx_from_addr && l_out_cond->header.srv_uid.uint64 == l_args->srv_uid.uint64){ + //dap_chain_tx_t *l_tx_add = dap_chain_tx_wrap_packed(a_datum_tx); + l_args->ret = dap_list_append(l_args->ret, a_datum_tx); + l_tx_collected = true; + } + } break; + } + l_item_idx++; + } + +} + +/** + * @brief Compose list of all cond transactions with target srv_uid for specified address + * @param a_net + * @param a_addr + * @param a_srv_uid + * @return List of dap_chain_tx_t (don't forget to free it) + */ +dap_list_t * dap_chain_net_get_tx_cond_all_for_addr(dap_chain_net_t * a_net, dap_chain_addr_t * a_addr, dap_chain_net_srv_uid_t a_srv_uid) +{ + struct get_tx_cond_all_for_addr * l_args = DAP_NEW_Z(struct get_tx_cond_all_for_addr); + l_args->addr = a_addr; + l_args->srv_uid = a_srv_uid; + dap_chain_net_get_tx_all(a_net,TX_SEARCH_TYPE_NET,s_get_tx_cond_all_for_addr_callback, l_args); + dap_chain_tx_hh_free(l_args->tx_all_hh); + dap_list_t * l_ret = l_args->ret; + DAP_DELETE(l_args); + return l_ret; +} + +/** + * @brief dap_chain_net_get_tx_cond_all_by_srv_uid + * @param a_net + * @param a_srv_uid + * @param a_search_type + * @return + */ +dap_list_t * dap_chain_net_get_tx_cond_all_by_srv_uid(dap_chain_net_t * a_net, const dap_chain_net_srv_uid_t a_srv_uid, + const dap_time_t a_time_from, const dap_time_t a_time_to, + const dap_chain_net_tx_search_type_t a_search_type) +{ + dap_ledger_t * l_ledger = a_net->pub.ledger; + dap_list_t * l_ret = NULL; + + switch (a_search_type) { + case TX_SEARCH_TYPE_NET: + case TX_SEARCH_TYPE_CELL: + case TX_SEARCH_TYPE_LOCAL: + case TX_SEARCH_TYPE_CELL_SPENT: + case TX_SEARCH_TYPE_NET_SPENT: { + // pass all chains + for ( dap_chain_t * l_chain = a_net->pub.chains; l_chain; l_chain = l_chain->next){ + dap_chain_cell_t * l_cell, *l_cell_tmp; + // Go through all cells + HASH_ITER(hh,l_chain->cells,l_cell, l_cell_tmp){ + dap_chain_atom_iter_t * l_atom_iter = l_chain->callback_atom_iter_create(l_chain,l_cell->id, false ); + // try to find transaction in chain ( inside shard ) + size_t l_atom_size = 0; + dap_chain_atom_ptr_t l_atom = l_chain->callback_atom_iter_get_first(l_atom_iter, &l_atom_size); + + // Check atoms in chain + while(l_atom && l_atom_size) { + size_t l_datums_count = 0; + dap_chain_datum_t **l_datums = l_chain->callback_atom_get_datums(l_atom, l_atom_size, &l_datums_count); + // transaction + dap_chain_datum_tx_t *l_tx = NULL; + + for (size_t i = 0; i < l_datums_count; i++) { + // Check if its transaction + if (l_datums && (l_datums[i]->header.type_id == DAP_CHAIN_DATUM_TX)) { + l_tx = (dap_chain_datum_tx_t *)l_datums[i]->data; + } + + // If found TX + if (l_tx){ + // Check for time from + if(a_time_from && l_tx->header.ts_created < a_time_from) + continue; + + // Check for time to + if(a_time_to && l_tx->header.ts_created > a_time_to) + continue; + + if(a_search_type == TX_SEARCH_TYPE_CELL_SPENT || a_search_type == TX_SEARCH_TYPE_NET_SPENT ){ + dap_hash_fast_t * l_tx_hash = dap_chain_node_datum_tx_calc_hash(l_tx); + bool l_is_spent = dap_chain_ledger_tx_spent_find_by_hash(l_ledger,l_tx_hash); + DAP_DELETE(l_tx_hash); + if(!l_is_spent) + continue; + } + // Check for OUT_COND items + dap_list_t *l_list_out_cond_items = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_OUT_COND , NULL); + if(l_list_out_cond_items){ + dap_list_t *l_list_cur = l_list_out_cond_items; + while(l_list_cur){ // Go through all cond items + dap_chain_tx_out_cond_t * l_tx_out_cond = (dap_chain_tx_out_cond_t *)l_list_cur->data; + if(l_tx_out_cond) // If we found cond out with target srv_uid + if(l_tx_out_cond->header.srv_uid.uint64 == a_srv_uid.uint64) + l_ret = dap_list_append(l_ret, + DAP_DUP_SIZE(l_tx, dap_chain_datum_tx_get_size(l_tx))); + l_list_cur = dap_list_next(l_list_cur); + } + dap_list_free(l_list_out_cond_items); + } + } + } + DAP_DEL_Z(l_datums); + // go to next atom + l_atom = l_chain->callback_atom_iter_get_next(l_atom_iter, &l_atom_size); + + } + } + } + } break; + + case TX_SEARCH_TYPE_NET_UNSPENT: + case TX_SEARCH_TYPE_CELL_UNSPENT: + l_ret = dap_chain_ledger_tx_cache_find_out_cond_all(l_ledger, a_srv_uid); + break; + } + return l_ret; + +} + + +/** + * @brief Summarize all tx inputs + * @param a_net + * @param a_tx + * @return + */ +uint256_t dap_chain_net_get_tx_total_value(dap_chain_net_t * a_net, dap_chain_datum_tx_t * a_tx) +{ + uint256_t l_ret = {0}; + int l_item_idx = 0; + dap_chain_tx_in_t *l_in_item = NULL; + do { + l_in_item = (dap_chain_tx_in_t*) dap_chain_datum_tx_item_get(a_tx, &l_item_idx, TX_ITEM_TYPE_IN , NULL); + l_item_idx++; + if(l_in_item ) { + //const char *token = l_out_cond_item->subtype.srv_xchange.token; + dap_chain_datum_tx_t * l_tx_prev = dap_chain_net_get_tx_by_hash(a_net,&l_in_item->header.tx_prev_hash, TX_SEARCH_TYPE_NET_SPENT); + if(l_tx_prev){ + int l_tx_prev_out_index = l_in_item->header.tx_out_prev_idx; + dap_chain_tx_out_t * l_tx_prev_out =(dap_chain_tx_out_t *) + dap_chain_datum_tx_item_get(l_tx_prev,&l_tx_prev_out_index, TX_ITEM_TYPE_OUT,NULL); + if ((uint32_t)l_tx_prev_out_index == l_in_item->header.tx_out_prev_idx && l_tx_prev_out) { + uint256_t l_in_value = l_tx_prev_out->header.value; + if(SUM_256_256(l_in_value,l_ret, &l_ret )!= 0) + log_it(L_ERROR, "Overflow on inputs values calculation (summing)"); + }else{ + log_it(L_WARNING, "Can't find item with index %d in prev tx hash", l_tx_prev_out_index); + } + }else + log_it(L_WARNING, "Can't find prev tx hash"); + } + } while(l_in_item); + return l_ret; +} + + +/** + * @brief dap_chain_net_tx_get_by_hash + * @param a_net + * @param a_tx_hash + * @param a_search_type + * @return + */ +dap_chain_datum_tx_t * dap_chain_net_get_tx_by_hash(dap_chain_net_t * a_net, dap_chain_hash_fast_t * a_tx_hash, + dap_chain_net_tx_search_type_t a_search_type) +{ + dap_ledger_t * l_ledger = a_net->pub.ledger; + dap_chain_datum_tx_t * l_tx = NULL; + + switch (a_search_type) { + case TX_SEARCH_TYPE_NET: + case TX_SEARCH_TYPE_CELL: + case TX_SEARCH_TYPE_LOCAL: + case TX_SEARCH_TYPE_CELL_SPENT: + case TX_SEARCH_TYPE_NET_SPENT: { + + if ( ! l_tx ){ + // pass all chains + for ( dap_chain_t * l_chain = a_net->pub.chains; l_chain; l_chain = l_chain->next){ + if ( l_chain->callback_tx_find_by_hash ){ + // try to find transaction in chain ( inside shard ) + l_tx = l_chain->callback_tx_find_by_hash(l_chain, a_tx_hash); + if (l_tx) { + if ((a_search_type == TX_SEARCH_TYPE_CELL_SPENT || + a_search_type == TX_SEARCH_TYPE_NET_SPENT) && + (!dap_chain_ledger_tx_spent_find_by_hash(l_ledger, a_tx_hash))) + return NULL; + break; + } + } + } + } + } break; + + case TX_SEARCH_TYPE_NET_UNSPENT: + case TX_SEARCH_TYPE_CELL_UNSPENT: + l_tx = dap_chain_ledger_tx_find_by_hash(l_ledger, a_tx_hash); + break; + } + return l_tx; +} + +static struct net_fee { + dap_chain_net_id_t net_id; + uint256_t value; // Network fee value + dap_chain_addr_t fee_addr; // Addr collector + UT_hash_handle hh; +} *s_net_fees = NULL; // Governance statements for networks +static pthread_rwlock_t s_net_fees_rwlock = PTHREAD_RWLOCK_INITIALIZER; + +bool dap_chain_net_tx_get_fee(dap_chain_net_id_t a_net_id, uint256_t *a_value, dap_chain_addr_t *a_addr) +{ + struct net_fee *l_net_fee; + HASH_FIND(hh, s_net_fees, &a_net_id, sizeof(a_net_id), l_net_fee); + if (!l_net_fee || IS_ZERO_256(l_net_fee->value)) + return false; + if (a_value) + *a_value = l_net_fee->value; + if (a_addr) + *a_addr = l_net_fee->fee_addr; + return true; +} diff --git a/modules/net/dap_chain_node.c b/modules/net/dap_chain_node.c index 02402d03ad58f3e23a31fe80da06c9b5678f27e6..6aa7e06e55c50383ae330e151d42ce649c9a7bb7 100644 --- a/modules/net/dap_chain_node.c +++ b/modules/net/dap_chain_node.c @@ -198,83 +198,55 @@ dap_chain_node_info_t* dap_chain_node_info_read( dap_chain_net_t * a_net,dap_cha return l_node_info; } +bool dap_chain_node_mempool_need_process(dap_chain_t *a_chain, dap_chain_datum_t *a_datum) { + for (uint16_t j = 0; j < a_chain->autoproc_datum_types_count; j++) + if (a_datum->header.type_id == a_chain->autoproc_datum_types[j]) + return true; + return false; +} -/** - * Serialize dap_chain_node_info_t - * size[out] - length of output string - * return data or NULL if error - */ -/*uint8_t* dap_chain_node_info_serialize(dap_chain_node_info_t *node_info, size_t *size) -{ - if(!node_info) - return NULL; - size_t node_info_size = dap_chain_node_info_get_size(node_info); - size_t node_info_str_size = 2 * node_info_size + 1; - uint8_t *node_info_str = DAP_NEW_Z_SIZE(uint8_t, node_info_str_size); - if(bin2hex(node_info_str, (const unsigned char *) node_info, node_info_size) == -1) { - DAP_DELETE(node_info_str); - return NULL; - } - - if(size) - *size = node_info_str_size; - return node_info_str; -}*/ - -/** - * Deserialize dap_chain_node_info_t - * size[in] - length of input string - * return data or NULL if error - */ -/*dap_chain_node_info_t* dap_chain_node_info_deserialize(uint8_t *node_info_str, size_t size) -{ - if(!node_info_str || size<=0) - return NULL; - dap_chain_node_info_t *node_info = DAP_NEW_Z_SIZE(dap_chain_node_info_t, (size / 2 + 1)); - if(hex2bin((char*) node_info, (const unsigned char *) node_info_str, size) == -1 || - (size / 2) != dap_chain_node_info_get_size(node_info)) { - log_it(L_ERROR, "node_info_deserialize - incorrect node_info size (%ld!=%ld)", - size / 2, dap_chain_node_info_get_size(node_info)); - DAP_DELETE(node_info); - return NULL; - } - return node_info; -}*/ - -int dap_chain_node_mempool_process(dap_chain_t *a_chain, dap_chain_datum_t *a_datum) -{ - bool l_need_process = false; - for (uint16_t j = 0; j < a_chain->autoproc_datum_types_count; j++) { - if (a_datum->header.type_id == a_chain->autoproc_datum_types[j]) { - l_need_process = true; - break; - } - } - if (!l_need_process) - return -1; - // Auth signs for emissions already verified by this callback - return (int)a_chain->callback_add_datums(a_chain, &a_datum, 1); +// Return true if processed datum should be deleted from mempool +bool dap_chain_node_mempool_process(dap_chain_t *a_chain, dap_chain_datum_t *a_datum) { + if (!a_chain->callback_add_datums) + return false; + // Verify for correctness + dap_chain_net_t *l_net = dap_chain_net_by_id(a_chain->net_id); + int l_verify_datum = dap_chain_net_verify_datum_for_add(l_net, a_datum); + if (l_verify_datum != 0 && + l_verify_datum != DAP_CHAIN_CS_VERIFY_CODE_TX_NO_PREVIOUS && + l_verify_datum != DAP_CHAIN_CS_VERIFY_CODE_TX_NO_EMISSION && + l_verify_datum != DAP_CHAIN_CS_VERIFY_CODE_TX_NO_TOKEN) + return true; + if (!l_verify_datum) + a_chain->callback_add_datums(a_chain, &a_datum, 1); + return false; } -static void s_chain_node_mempool_autoproc_notify(void *a_arg, const char a_op_code, const char *a_group, - const char *a_key, const void *a_value, const size_t a_value_len) -{ - UNUSED(a_value_len); - if (!a_arg || !a_value || a_op_code != 'a') { - return; - } - dap_chain_t *l_chain =(dap_chain_t *)a_arg; - dap_chain_net_t *l_net = dap_chain_net_by_id(l_chain->net_id); +void dap_chain_node_mempool_process_all(dap_chain_t *a_chain) { + dap_chain_net_t *l_net = dap_chain_net_by_id(a_chain->net_id); if (!l_net->pub.mempool_autoproc) return; - dap_chain_datum_t *l_datum = (dap_chain_datum_t *)a_value; - if (dap_chain_node_mempool_process(l_chain, l_datum) >= 0) { - dap_global_db_context_t * l_gdb_context = dap_global_db_context_current(); - assert(l_gdb_context); - dap_global_db_del_unsafe(l_gdb_context,a_group, a_key); + char *l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool_new(a_chain); + size_t l_objs_size = 0; + dap_global_db_obj_t *l_objs = dap_global_db_get_all_sync(l_gdb_group_mempool, &l_objs_size); + if (l_objs_size) { + for (size_t i = 0; i < l_objs_size; i++) { + if (!l_objs[i].value_len) + continue; + dap_chain_datum_t *l_datum = (dap_chain_datum_t *)l_objs[i].value; + if (dap_chain_node_mempool_need_process(a_chain, l_datum)) { + if (dap_chain_node_mempool_process(a_chain, l_datum)) { + // Delete processed objects + dap_global_db_del(l_gdb_group_mempool, l_objs[i].key, NULL, NULL); + } + } + } + dap_global_db_objs_delete(l_objs, l_objs_size); } + DAP_DELETE(l_gdb_group_mempool); } + /** * @brief * get automatic mempool processing, when network config contains mempool_auto_types for specific datums @@ -302,27 +274,8 @@ bool dap_chain_node_mempool_autoproc_init() } dap_chain_t *l_chain; DL_FOREACH(l_net_list[i]->pub.chains, l_chain) { - if (!l_chain) { - continue; - } - char *l_gdb_group_mempool = NULL; - l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool_new(l_chain); - size_t l_objs_size = 0; - dap_global_db_obj_t *l_objs = dap_global_db_get_all_sync(l_gdb_group_mempool, &l_objs_size); - if (l_objs_size) { - for (size_t i = 0; i < l_objs_size; i++) { - if (!l_objs[i].value_len) - continue; - dap_chain_datum_t *l_datum = (dap_chain_datum_t *)l_objs[i].value; - if (dap_chain_node_mempool_process(l_chain, l_datum) >= 0) { - // Delete processed objects - dap_global_db_del_sync(l_gdb_group_mempool, l_objs[i].key ); - } - } - dap_global_db_objs_delete(l_objs, l_objs_size); - } - DAP_DELETE(l_gdb_group_mempool); - dap_chain_add_mempool_notify_callback(l_chain, s_chain_node_mempool_autoproc_notify, l_chain); + if (l_chain) + dap_chain_node_mempool_process_all(l_chain); } } DAP_DELETE(l_net_list); diff --git a/modules/net/dap_chain_node_cli.c b/modules/net/dap_chain_node_cli.c index 11dcbf7cabce78e04f8d3680dd6f74c96f67cb38..6529f934aff7f3c1cd0366a1072562e27690582b 100644 --- a/modules/net/dap_chain_node_cli.c +++ b/modules/net/dap_chain_node_cli.c @@ -131,66 +131,66 @@ int dap_chain_node_cli_init(dap_config_t * g_config) // Token commands dap_cli_server_cmd_add ("token_update", com_token_update, "Token update", - "\nPrivate token update\n" - "token_update -net <net_name> -chain <chain_name> -token <token_ticker> [-type private] [-<Param name 1> <Param Value 1>] [-Param name 2> <Param Value 2>] ...[-<Param Name N> <Param Value N>]\n" - "\t Update private token <token_ticker> for <netname>:<chain_name> with" - "\t custom parameters list <Param 1>, <Param 2>...<Param N>." - "\n" - "==Params==\n" - "General:\n" - "\t -flags_set <value>:\t Set list of flags from <value> to token declaration\n" - "\t -flags_unset <value>:\t Unset list of flags from <value> from token declaration\n" - "\t -total_supply <value>:\t Set total supply - emission's maximum - to the <value>\n" - "\t -total_signs_valid <value>:\t Set valid signatures count's minimum\n" - "\t -signs_add <value>:\t Add signature's pkey fingerprint to the list of owners\n" - "\t -signs_remove <value>:\t Remove signature's pkey fingerprint from the owners\n" - "\nDatum type allowed/blocked updates:\n" - "\t -datum_type_allowed_add <value>:\t Add allowed datum type(s)\n" - "\t -datum_type_allowed_remove <value>:\t Remove datum type(s) from allowed\n" - "\t -datum_type_allowed_clear:\t Remove all datum types from allowed\n" - "\t -datum_type_blocked_add <value>:\t Add blocked datum type(s)\n" - "\t -datum_type_blocked_remove <value>:\t Remove datum type(s) from blocked\n" - "\t -datum_type_blocked_clear:\t Remove all datum types from blocked\n" - "\nTx receiver addresses allowed/blocked updates:\n" - "\t -tx_receiver_allowed_add <value>:\t Add allowed tx receiver(s)\n" - "\t -tx_receiver_allowed_remove <value>:\t Remove tx receiver(s) from allowed\n" - "\t -tx_receiver_allowed_clear:\t Remove all tx receivers from allowed\n" - "\t -tx_receiver_blocked_add <value>:\t Add blocked tx receiver(s)\n" - "\t -tx_receiver_blocked_remove <value>:\t Remove tx receiver(s) from blocked\n" - "\t -tx_receiver_blocked_clear:\t Remove all tx receivers from blocked\n" - "\nTx sender addresses allowed/blocked updates:\n" - "\t -tx_sender_allowed_add <value>:\t Add allowed tx sender(s)\n" - "\t -tx_sender_allowed_remove <value>:\t Remove tx sender(s) from allowed\n" - "\t -tx_sender_allowed_clear:\t Remove all tx senders from allowed\n" - "\t -tx_sender_blocked_add <value>:\t Add allowed tx sender(s)\n" - "\t -tx_sender_blocked_remove <value>:\t Remove tx sender(s) from blocked\n" - "\t -tx_sender_blocked_clear:\t Remove all tx sender(s) from blocked\n" - "\n" - "==Flags==" - "\t ALL_BLOCKED:\t Blocked all permissions, usefull add it first and then add allows what you want to allow\n" - "\t ALL_ALLOWED:\t Allowed all permissions if not blocked them. Be careful with this mode\n" - "\t ALL_FROZEN:\t All permissions are temprorary frozen\n" - "\t ALL_UNFROZEN:\t Unfrozen permissions\n" - "\t STATIC_ALL:\t No token manipulations after declarations at all. Token declares staticly and can't variabed after\n" - "\t STATIC_FLAGS:\t No token manipulations after declarations with flags\n" - "\t STATIC_PERMISSIONS_ALL:\t No all permissions lists manipulations after declarations\n" - "\t STATIC_PERMISSIONS_DATUM_TYPE:\t No datum type permissions lists manipulations after declarations\n" - "\t STATIC_PERMISSIONS_TX_SENDER:\t No tx sender permissions lists manipulations after declarations\n" - "\t STATIC_PERMISSIONS_TX_RECEIVER:\t No tx receiver permissions lists manipulations after declarations\n" - "\n" - ); + "\nPrivate or CF20 token update\n" + "\nPrivate token update\n" + "token_update -net <net_name> -chain <chain_name> -token <existing token_ticker> -type private -total_supply <the same or more> -decimals <18>\n" + "-signs_total <the same total as the token you are updating> -signs_emission <the same total as the token you are updating> -certs <use the certificates of the token you are update>\n" + "-flags [<Flag 1>][,<Flag 2>]...[,<Flag N>]...\n" + "\t [-<Param name 1> <Param Value 1>] [-Param name 2> <Param Value 2>] ...[-<Param Name N> <Param Value N>]\n" + "\t Update token for <netname>:<chain name> with ticker <token ticker>, flags <Flag 1>,<Flag2>...<Flag N>\n" + "\t and custom parameters list <Param 1>, <Param 2>...<Param N>.\n" + "\nCF20 token update\n" + "token_update -net <net_name> -chain <chain_name> -token <existing token_ticker> -type CF20 -total_supply <the same or more/if 0 = endless> -decimals <18>\n" + "-signs_total <the same total as the token you are updating> -signs_emission <the same total as the token you are updating> -certs <use the certificates of the token you are update>\n" + "\t -flags [<Flag 1>][,<Flag 2>]...[,<Flag N>]...\n" + "\t [-<Param name 1> <Param Value 1>] [-Param name 2> <Param Value 2>] ...[-<Param Name N> <Param Value N>]\n" + "\t Update token for <netname>:<chain name> with ticker <token ticker>, flags <Flag 1>,<Flag2>...<Flag N>\n" + "\t and custom parameters list <Param 1>, <Param 2>...<Param N>.\n" + "\n" + "==Flags==" + "\t ALL_BLOCKED:\t Blocked all permissions, usefull add it first and then add allows what you want to allow\n" + "\t ALL_ALLOWED:\t Allowed all permissions if not blocked them. Be careful with this mode\n" + "\t ALL_FROZEN:\t All permissions are temprorary frozen\n" + "\t ALL_UNFROZEN:\t Unfrozen permissions\n" + "\t STATIC_ALL:\t No token manipulations after declarations at all. Token declares staticly and can't variabed after\n" + "\t STATIC_FLAGS:\t No token manipulations after declarations with flags\n" + "\t STATIC_PERMISSIONS_ALL:\t No all permissions lists manipulations after declarations\n" + "\t STATIC_PERMISSIONS_DATUM_TYPE:\t No datum type permissions lists manipulations after declarations\n" + "\t STATIC_PERMISSIONS_TX_SENDER:\t No tx sender permissions lists manipulations after declarations\n" + "\t STATIC_PERMISSIONS_TX_RECEIVER:\t No tx receiver permissions lists manipulations after declarations\n" + "\n" + "==Params==\n" + "General:\n" + "\t -flags <value>:\t List of flags from <value> to token declaration or update\n" + "\t -total_supply <value>:\t Set total supply - emission's maximum - to the <value>\n" + "\t -total_signs_valid <value>:\t Set valid signatures count's minimum\n" + "\nDatum type allowed/blocked:\n" + "\t -datum_type_allowed <value>:\t Set allowed datum type(s)\n" + "\t -datum_type_blocked <value>:\t Set blocked datum type(s)\n" + "\nTx receiver addresses allowed/blocked:\n" + "\t -tx_receiver_allowed <value>:\t Set allowed tx receiver(s)\n" + "\t -tx_receiver_blocked <value>:\t Set blocked tx receiver(s)\n" + "\nTx sender addresses allowed/blocked:\n" + "\t -tx_sender_allowed <value>:\t Set allowed tx sender(s)\n" + "\t -tx_sender_blocked <value>:\t Set allowed tx sender(s)\n" + "\n" + ); + + // Token commands dap_cli_server_cmd_add ("token_decl", com_token_decl, "Token declaration", "Simple token declaration:\n" "token_decl -net <net_name> -chain <chain_name> -token <token_ticker> -total_supply <total supply> -signs_total <sign total> -signs_emission <signs for emission> -certs <certs list>\n" "\t Declare new simple token for <netname>:<chain_name> with ticker <token_ticker>, maximum emission <total supply> and <signs for emission> from <signs total> signatures on valid emission\n" "\nExtended private token declaration\n" - "token_decl -net <net_name> -chain <chain_name> -token <token_ticker> -type private -flags [<Flag 1>][,<Flag 2>]...[,<Flag N>]...\n" + "token_decl -net <net_name> -chain <chain_name> -token <token_ticker> -type private -total_supply <total supply> " + "-decimals <18> -signs_total <sign total> -signs_emission <signs for emission> -certs <certs list> -flags [<Flag 1>][,<Flag 2>]...[,<Flag N>]...\n" "\t [-<Param name 1> <Param Value 1>] [-Param name 2> <Param Value 2>] ...[-<Param Name N> <Param Value N>]\n" "\t Declare new token for <netname>:<chain_name> with ticker <token_ticker>, flags <Flag 1>,<Flag2>...<Flag N>\n" "\t and custom parameters list <Param 1>, <Param 2>...<Param N>.\n" "\nExtended CF20 token declaration\n" - "token_decl -net <net_name> -chain <chain_name> -token <token_ticker> -type CF20 -decimals <18> -signs_total <sign total> -signs_emission <signs for emission> -certs <certs list>" + "token_decl -net <net_name> -chain <chain_name> -token <token_ticker> -type CF20 " + "-total_supply <total supply/if 0 = endless> -decimals <18> -signs_total <sign total> -signs_emission <signs for emission> -certs <certs list>\n" "\t -flags [<Flag 1>][,<Flag 2>]...[,<Flag N>]...\n" "\t [-<Param name 1> <Param Value 1>] [-Param name 2> <Param Value 2>] ...[-<Param Name N> <Param Value N>]\n" "\t Declare new token for <netname>:<chain_name> with ticker <token_ticker>, flags <Flag 1>,<Flag2>...<Flag N>\n" @@ -213,7 +213,6 @@ int dap_chain_node_cli_init(dap_config_t * g_config) "\t -flags <value>:\t List of flags from <value> to token declaration\n" "\t -total_supply <value>:\t Set total supply - emission's maximum - to the <value>\n" "\t -total_signs_valid <value>:\t Set valid signatures count's minimum\n" - "\t -signs <value>:\t Signature's fingerprint list\n" "\nDatum type allowed/blocked:\n" "\t -datum_type_allowed <value>:\t Set allowed datum type(s)\n" "\t -datum_type_blocked <value>:\t Set blocked datum type(s)\n" @@ -232,11 +231,17 @@ int dap_chain_node_cli_init(dap_config_t * g_config) ); dap_cli_server_cmd_add ("token_emit", com_token_emit, "Token emission", - "token_emit {sign | -token <mempool_token_ticker> -emission_value <val>} -net <net_name> [-chain_emission <chain_name>] [-chain_base_tx <chain_name> -addr <addr>] -certs <cert list>\n"); + "token_emit { sign | -token <mempool_token_ticker> -emission_value <value> " + "-addr <addr> [-chain_emission <chain_name>] " + "[-chain_base_tx <chain_name> | use flag '-no_base_tx' if you need create emission has no base transaction] } " + "-net <net_name> -certs <cert list>\n"); dap_cli_server_cmd_add ("mempool_list", com_mempool_list, "List mempool entries for selected chain network", "mempool_list -net <net_name>\n"); + dap_cli_server_cmd_add ("mempool_check", com_mempool_check, "Check mempool entrie for presence in selected chain network", + "mempool_check -net <net_name> -datum <datum hash>\n"); + dap_cli_server_cmd_add ("mempool_proc", com_mempool_proc, "Proc mempool entrie with specified hash for selected chain network", "mempool_proc -net <net_name> -datum <datum hash>\n"); @@ -293,21 +298,22 @@ int dap_chain_node_cli_init(dap_config_t * g_config) dap_cli_server_cmd_add("stats", com_stats, "Print statistics", "stats cpu"); - - - // Exit - dap_cli_server_cmd_add ("exit", com_exit, "Stop application and exit", - "exit\n" ); - - // Export GDB to JSON - dap_cli_server_cmd_add("gdb_export", cmd_gdb_export, "Export gdb to JSON", + // Export GDB to JSON + dap_cli_server_cmd_add("gdb_export", cmd_gdb_export, "Export gdb to JSON", "gdb_export filename <filename without extension> [-groups <group names list>]"); - //Import GDB from JSON - dap_cli_server_cmd_add("gdb_import", cmd_gdb_import, "Import gdb from JSON", + //Import GDB from JSON + dap_cli_server_cmd_add("gdb_import", cmd_gdb_import, "Import gdb from JSON", "gdb_import filename <filename without extension>"); + dap_cli_server_cmd_add ("remove", cmd_remove, "Delete chain files or global database", + "remove -gdb\n" + "remove -chains [-net <net_name> | -all]\n" + "Be careful, the '-all' option for '-chains' will delete all chains and won't ask you for permission!"); + // Exit - always last! + dap_cli_server_cmd_add ("exit", com_exit, "Stop application and exit", + "exit\n" ); return 0; } diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c index c27479e480663795ae568f625c3e04ec42b469da..4904bd70ee8ac22611400ea7e87ff6b65ea01e98 100644 --- a/modules/net/dap_chain_node_cli_cmd.c +++ b/modules/net/dap_chain_node_cli_cmd.c @@ -52,13 +52,10 @@ #include <signal.h> #endif #include <pthread.h> - -#include "iputils/iputils.h" +#include <iputils/iputils.h> #include "uthash.h" #include "utlist.h" - - #include "dap_string.h" #include "dap_hash.h" #include "dap_chain_common.h" @@ -73,11 +70,11 @@ #include "dap_chain_node.h" #include "dap_global_db.h" #include "dap_chain_node_client.h" -#include "dap_chain_node_remote.h" #include "dap_chain_node_cli_cmd.h" #include "dap_chain_node_cli_cmd_tx.h" #include "dap_chain_node_ping.h" #include "dap_chain_net_srv.h" +#include "dap_chain_net_tx.h" #ifndef _WIN32 #include "dap_chain_net_news.h" @@ -1170,7 +1167,7 @@ int com_node(int a_argc, char ** a_argv, char **a_str_reply) l_node_addr.uint64 = l_remote_node_addr->uint64; // clean client struct - dap_chain_node_client_close(l_node_client); + dap_chain_node_client_close(l_node_client->uuid); DAP_DELETE(l_remote_node_info); //return -1; continue; @@ -1192,7 +1189,7 @@ int com_node(int a_argc, char ** a_argv, char **a_str_reply) dap_cli_server_cmd_set_reply_text(a_str_reply, "no response from remote node(s)"); log_it(L_WARNING, "No response from remote node(s): err code %d", res); // clean client struct - dap_chain_node_client_close(l_node_client); + dap_chain_node_client_close(l_node_client->uuid); //DAP_DELETE(l_remote_node_info); return -1; } @@ -1221,7 +1218,7 @@ int com_node(int a_argc, char ** a_argv, char **a_str_reply) NULL, 0); if(res == 0) { log_it(L_WARNING, "Can't send DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_NODE_ADDR_REQUEST packet"); - dap_chain_node_client_close(l_node_client); + dap_chain_node_client_close(l_node_client->uuid); DAP_DELETE(l_remote_node_info); return -1; } @@ -1250,22 +1247,6 @@ int com_node(int a_argc, char ** a_argv, char **a_str_reply) DAP_DELETE(l_remote_node_info); return -1;*/ } - /* if(0 == dap_stream_ch_chain_pkt_write_unsafe(l_ch_chain, DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_NODE_ADDR_REQUEST, - l_net->pub.id, l_chain_id_null, l_chain_cell_id_null, &l_sync_request, - sizeof(l_sync_request))) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Error: Cant send sync chains request"); - // clean client struct - dap_chain_node_client_close(l_node_client); - DAP_DELETE(l_remote_node_info); - return -1; - } - dap_stream_ch_set_ready_to_write(l_ch_chain, true); - // wait for finishing of request - timeout_ms = 120000; // 20 min = 1200 sec = 1 200 000 ms - // TODO add progress info to console - res = dap_chain_node_client_wait(l_node_client, NODE_CLIENT_STATE_SYNCED, timeout_ms); - */ - } log_it(L_NOTICE, "Now lets sync all"); @@ -1287,7 +1268,7 @@ int com_node(int a_argc, char ** a_argv, char **a_str_reply) sizeof(l_sync_request))) { dap_cli_server_cmd_set_reply_text(a_str_reply, "Error: Can't send sync chains request"); // clean client struct - dap_chain_node_client_close(l_node_client); + dap_chain_node_client_close(l_node_client->uuid); DAP_DELETE(l_remote_node_info); return -1; } @@ -1299,7 +1280,7 @@ int com_node(int a_argc, char ** a_argv, char **a_str_reply) if(res < 0) { dap_cli_server_cmd_set_reply_text(a_str_reply, "Error: can't sync with node "NODE_ADDR_FP_STR, NODE_ADDR_FP_ARGS_S(l_node_client->remote_node_addr)); - dap_chain_node_client_close(l_node_client); + dap_chain_node_client_close(l_node_client->uuid); DAP_DELETE(l_remote_node_info); log_it(L_WARNING, "Gdb synced err -2"); return -2; @@ -1327,7 +1308,7 @@ int com_node(int a_argc, char ** a_argv, char **a_str_reply) sizeof(l_sync_request))) { dap_cli_server_cmd_set_reply_text(a_str_reply, "Error: Can't send sync chains request"); // clean client struct - dap_chain_node_client_close(l_node_client); + dap_chain_node_client_close(l_node_client->uuid); DAP_DELETE(l_remote_node_info); log_it(L_INFO, "Chain '%s' synced error: Can't send sync chains request", l_chain->name); return -3; @@ -1347,7 +1328,7 @@ int com_node(int a_argc, char ** a_argv, char **a_str_reply) DAP_DELETE(l_remote_node_info); //dap_client_disconnect(l_node_client->client); //l_node_client->client = NULL; - dap_chain_node_client_close(l_node_client); + dap_chain_node_client_close(l_node_client->uuid); dap_cli_server_cmd_set_reply_text(a_str_reply, "Node sync completed: Chains and gdb are synced"); return 0; @@ -1387,25 +1368,11 @@ int com_node(int a_argc, char ** a_argv, char **a_str_reply) if (res) { dap_cli_server_cmd_set_reply_text(a_str_reply, "No response from node"); // clean client struct - dap_chain_node_client_close(client); + dap_chain_node_client_close(client->uuid); DAP_DELETE(node_info); return -8; } DAP_DELETE(node_info); - - //Add new established connection in the list - int ret = dap_chain_node_client_list_add(&l_node_addr, client); - switch (ret) - { - case -1: - dap_chain_node_client_close(client); - dap_cli_server_cmd_set_reply_text(a_str_reply, "Connection established, but not saved"); - return -9; - case -2: - dap_chain_node_client_close(client); - dap_cli_server_cmd_set_reply_text(a_str_reply, "Connection already present"); - return -10; - } dap_cli_server_cmd_set_reply_text(a_str_reply, "Connection established"); } break; @@ -2308,7 +2275,7 @@ void s_com_mempool_list_print_for_chain(dap_chain_net_t * a_net, dap_chain_t * a } char buf[50] = {[0]='\0'}; dap_hash_fast_t l_data_hash; - char l_data_hash_str[70] = {[0]='\0'}; + char l_data_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE] = {[0]='\0'}; dap_hash_fast(l_datum->data,l_datum->header.data_size,&l_data_hash); dap_hash_fast_to_str(&l_data_hash,l_data_hash_str,DAP_CHAIN_HASH_FAST_STR_SIZE); const char *l_type = NULL; @@ -2333,9 +2300,8 @@ void s_com_mempool_list_print_for_chain(dap_chain_net_t * a_net, dap_chain_t * a dap_chain_datum_dump(a_str_tmp, l_datum, a_hash_out_type); } dap_global_db_objs_delete(l_objs, l_objs_size); + DAP_DELETE(l_gdb_group_mempool); } - - DAP_DELETE(l_gdb_group_mempool); } /** @@ -2364,24 +2330,12 @@ int com_mempool_list(int argc, char ** argv, char ** a_str_reply) } } - if(l_net) { - dap_string_t * l_str_tmp = dap_string_new(NULL); - - if(l_chain) - s_com_mempool_list_print_for_chain(l_net, l_chain, l_str_tmp, l_hash_out_type); - else - DL_FOREACH(l_net->pub.chains, l_chain) - s_com_mempool_list_print_for_chain(l_net, l_chain, l_str_tmp, l_hash_out_type); - - dap_cli_server_cmd_set_reply_text(a_str_reply, l_str_tmp->str); - dap_string_free(l_str_tmp, false); - - return 0; - } else { - dap_cli_server_cmd_set_reply_text(a_str_reply, - "Error! Need both -net <network name> and -chain <chain name> params\n"); - return -2; - } + dap_string_t * l_str_tmp = dap_string_new(NULL); + DL_FOREACH(l_net->pub.chains, l_chain) + s_com_mempool_list_print_for_chain(l_net, l_chain, l_str_tmp, l_hash_out_type); + dap_cli_server_cmd_set_reply_text(a_str_reply, l_str_tmp->str); + dap_string_free(l_str_tmp, true); + return 0; } /** @@ -2398,62 +2352,76 @@ int com_mempool_delete(int argc, char ** argv, char ** a_str_reply) dap_chain_t * l_chain = NULL; dap_chain_net_t * l_net = NULL; - const char * l_hash_out_type = NULL; - dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-H", &l_hash_out_type); - if(!l_hash_out_type) - l_hash_out_type = "hex"; - if(dap_strcmp(l_hash_out_type,"hex") && dap_strcmp(l_hash_out_type,"base58")) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "invalid parameter -H, valid values: -H <hex | base58>"); + if(dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index, argc, argv, a_str_reply, &l_chain, &l_net) != 0) { return -1; } + const char * l_datum_hash_str = NULL; + dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-datum", &l_datum_hash_str); + if (l_datum_hash_str) { + char *l_datum_hash_hex_str = NULL; + // datum hash may be in hex or base58 format + if(dap_strncmp(l_datum_hash_str, "0x", 2) && dap_strncmp(l_datum_hash_str, "0X", 2)) + l_datum_hash_hex_str = dap_enc_base58_to_hex_str_from_str(l_datum_hash_str); - if(dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index, argc, argv, a_str_reply, &l_chain, &l_net) != 0) { - //dap_cli_server_cmd_set_reply_text(a_str_reply, "Error! Need both -net <network name> and -chain <chain name> params\n"); - return -1; + char * l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool_new(l_chain); + uint8_t *l_data_tmp = dap_global_db_get_sync(l_gdb_group_mempool, l_datum_hash_hex_str ? l_datum_hash_hex_str : l_datum_hash_str, + NULL, NULL, NULL); + if(l_data_tmp && dap_global_db_del_sync(l_gdb_group_mempool, l_datum_hash_hex_str) == 0) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Datum %s deleted", l_datum_hash_str); + return 0; + } else { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Error! Can't find datum %s", l_datum_hash_str); + return -4; + } + DAP_DELETE(l_gdb_group_mempool); + DAP_DELETE(l_data_tmp); + DAP_DEL_Z(l_datum_hash_hex_str); + } else { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Error! %s requires -datum <datum hash> option", argv[0]); + return -3; } +} - if(l_chain && l_net) { // UNUSED(l_net) - const char * l_datum_hash_str = NULL; - dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-datum", &l_datum_hash_str); - if(l_datum_hash_str) { - char *l_datum_hash_hex_str; - char *l_datum_hash_base58_str; - // datum hash may be in hex or base58 format - if(!dap_strncmp(l_datum_hash_str, "0x", 2) || !dap_strncmp(l_datum_hash_str, "0X", 2)) { - l_datum_hash_hex_str = dap_strdup(l_datum_hash_str); - l_datum_hash_base58_str = dap_enc_base58_from_hex_str_to_str(l_datum_hash_str); - } - else { - l_datum_hash_hex_str = dap_enc_base58_to_hex_str_from_str(l_datum_hash_str); - l_datum_hash_base58_str = dap_strdup(l_datum_hash_str); - } - char * l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool_new(l_chain); - uint8_t *l_data_tmp = l_datum_hash_hex_str ? dap_global_db_get_sync(l_gdb_group_mempool, l_datum_hash_hex_str, NULL, NULL, NULL ) : NULL; - if(l_data_tmp && dap_global_db_del_sync(l_gdb_group_mempool, l_datum_hash_hex_str) == 0) { - if(!dap_strcmp(l_hash_out_type,"hex")) - dap_cli_server_cmd_set_reply_text(a_str_reply, "Datum %s deleted", l_datum_hash_hex_str); - else - dap_cli_server_cmd_set_reply_text(a_str_reply, "Datum %s deleted", l_datum_hash_base58_str); - return 0; - } else { - if(!dap_strcmp(l_hash_out_type,"hex")) - dap_cli_server_cmd_set_reply_text(a_str_reply, "Error! Can't find datum %s", l_datum_hash_hex_str); - else - dap_cli_server_cmd_set_reply_text(a_str_reply, "Error! Can't find datum %s", l_datum_hash_base58_str); - return -4; - } - DAP_DELETE(l_gdb_group_mempool); - DAP_DELETE(l_data_tmp); - DAP_DELETE(l_datum_hash_hex_str); - DAP_DELETE(l_datum_hash_base58_str); +/** + * @brief com_mempool_check + * @param argc + * @param argv + * @param arg_func + * @param a_str_reply + * @return + */ +int com_mempool_check(int argc, char ** argv, char ** a_str_reply) +{ + int arg_index = 1; + dap_chain_t * l_chain = NULL; + dap_chain_net_t * l_net = NULL; + + if (dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index, argc, argv, a_str_reply, &l_chain, &l_net)) + return -1; + + const char * l_datum_hash_str = NULL; + dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-datum", &l_datum_hash_str); + if(l_datum_hash_str) { + char *l_datum_hash_hex_str = NULL; + // datum hash may be in hex or base58 format + if(dap_strncmp(l_datum_hash_str, "0x", 2) && dap_strncmp(l_datum_hash_str, "0X", 2)) + l_datum_hash_hex_str = dap_enc_base58_to_hex_str_from_str(l_datum_hash_str); + char * l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool_new(l_chain); + uint8_t *l_data_tmp = dap_global_db_get_sync(l_gdb_group_mempool, l_datum_hash_hex_str ? l_datum_hash_hex_str : l_datum_hash_str, + NULL, NULL, NULL); + if (l_data_tmp) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Datum %s is present in mempool", l_datum_hash_str); + return 0; } else { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Error! %s requires -datum <datum hash> option", argv[0]); - return -3; + dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't find datum %s", l_datum_hash_str); + return -4; } + DAP_DELETE(l_gdb_group_mempool); + DAP_DELETE(l_data_tmp); + DAP_DEL_Z(l_datum_hash_hex_str); } else { - dap_cli_server_cmd_set_reply_text(a_str_reply, - "Error! Need both -net <network name> and -chain <chain name> params\n"); - return -2; + dap_cli_server_cmd_set_reply_text(a_str_reply, "Error! %s requires -datum <datum hash> option", argv[0]); + return -3; } } @@ -2580,328 +2548,6 @@ int com_mempool_proc(int argc, char ** argv, char ** a_str_reply) return ret; } - -/** - * @brief com_token_decl_update - * @param argc - * @param argv - * @param arg_func - * @param str_reply - * @return - * @details token_update -net <net_name> -chain <chain_name> -token <token_ticker> [-type private] -flags [<Flag 1>][,<Flag 2>]...[,<Flag N>]... [-<Param name 1> <Param Value 1>] [-Param name 2> <Param Value 2>] ...[-<Param Name N> <Param Value N>]\n" - * \t Update token for <netname>:<chain name> with ticker <token ticker>, flags <Flag 1>,<Flag2>...<Flag N>" - * \t and custom parameters list <Param 1>, <Param 2>...<Param N>." - * \n" - * ==Flags==" - * \t ALL_BLOCKED:\t Blocked all permissions, usefull add it first and then add allows what you want to allow\n" - * \t ALL_ALLOWED:\t Allowed all permissions if not blocked them. Be careful with this mode\n" - * \t ALL_FROZEN:\t All permissions are temprorary frozen\n" - * \t ALL_UNFROZEN:\t Unfrozen permissions\n" - * \t STATIC_ALL:\t No token manipulations after declarations at all. Token declares staticly and can't variabed after\n" - * \t STATIC_FLAGS:\t No token manipulations after declarations with flags\n" - * \t STATIC_PERMISSIONS_ALL:\t No all permissions lists manipulations after declarations\n" - * \t STATIC_PERMISSIONS_DATUM_TYPE:\t No datum type permissions lists manipulations after declarations\n" - * \t STATIC_PERMISSIONS_TX_SENDER:\t No tx sender permissions lists manipulations after declarations\n" - * \t STATIC_PERMISSIONS_TX_RECEIVER:\t No tx receiver permissions lists manipulations after declarations\n" - "\n" - "==Params==\n" - "General:\n" - "\t -flags_set <value>:\t Set list of flags from <value> to token declaration\n" - "\t -flags_unset <value>:\t Unset list of flags from <value> from token declaration\n" - "\t -total_supply <value>:\t Set total supply - emission's maximum - to the <value>\n" - "\t -total_signs_valid <value>:\t Set valid signatures count's minimum\n" - "\t -total_signs_add <value>:\t Add signature's pkey fingerprint to the list of owners\n" - "\t -total_signs_remove <value>:\t Remove signature's pkey fingerprint from the owners\n" - "\nDatum type allowed/blocked updates:\n" - "\t -datum_type_allowed_add <value>:\t Add allowed datum type(s)\n" - "\t -datum_type_allowed_remove <value>:\t Remove datum type(s) from allowed\n" - "\t -datum_type_blocked_add <value>:\t Add blocked datum type(s)\n" - "\t -datum_type_blocked_remove <value>:\t Remove datum type(s) from blocked\n" - "\nTx receiver addresses allowed/blocked updates:\n" - "\t -tx_receiver_allowed_add <value>:\t Add allowed tx receiver(s)\n" - "\t -tx_receiver_allowed_remove <value>:\t Remove tx receiver(s) from allowed\n" - "\t -tx_receiver_blocked_add <value>:\t Add blocked tx receiver(s)\n" - "\t -tx_receiver_blocked_remove <value>:\t Remove tx receiver(s) from blocked\n" - "\n Tx sender addresses allowed/blocked updates:\n" - "\t -tx_sender_allowed_add <value>:\t Add allowed tx sender(s)\n" - "\t -tx_sender_allowed_remove <value>:\t Remove tx sender(s) from allowed\n" - "\t -tx_sender_blocked_add <value>:\t Add allowed tx sender(s)\n" - "\t -tx_sender_blocked_remove <value>:\t Remove tx sender(s) from blocked\n" - "\n" - */ -int com_token_update(int a_argc, char ** a_argv, char ** a_str_reply) -{ - int l_arg_index = 1; - - const char * l_type_str = NULL; - uint16_t l_type = DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_UPDATE; - - const char * l_ticker = NULL; - - uint16_t l_signs_total = 0; - - dap_cert_t ** l_certs = NULL; - size_t l_certs_count = 0; - - dap_chain_t * l_chain = NULL; - dap_chain_net_t * l_net = NULL; - - const char * l_hash_out_type = NULL; - dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-H", &l_hash_out_type); - if(!l_hash_out_type) - l_hash_out_type = "hex"; - if(dap_strcmp(l_hash_out_type, "hex") && dap_strcmp(l_hash_out_type, "base58")) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "invalid parameter -H, valid values: -H <hex | base58>"); - return -1; - } - - if (dap_chain_node_cli_cmd_values_parse_net_chain(&l_arg_index, a_argc, a_argv, a_str_reply, &l_chain, &l_net)) - return -1; - // Token ticker - l_arg_index=dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-token", &l_ticker); - // Check for ticker - if(!l_ticker) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "token_update requires parameter 'token'"); - return -2; - } - - // Token type - l_arg_index=dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-type", &l_type_str); - - if (l_type_str && strcmp(l_type_str, "private")) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "token_update can't accept type \"%s\"", l_type_str); - return -22; - } - - dap_chain_datum_token_t * l_datum_token_update = NULL; - size_t l_datum_data_offset = 0; - uint32_t l_sign_counter = 0; - - switch(l_type){ - case DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_UPDATE: // 256 - case DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_UPDATE: { - dap_list_t *l_tsd_list = dap_list_alloc(); - size_t l_tsd_total_size = 0; - l_arg_index++; - while (l_arg_index<a_argc-1){ - char * l_arg_param= a_argv[l_arg_index+1]; - if ( strcmp( a_argv[l_arg_index],"-flags_set" )==0){ // Flags - char ** l_str_flags = NULL; - l_str_flags = dap_strsplit( l_arg_param,",",0xffff ); - uint16_t l_flags = 0; - while (l_str_flags && *l_str_flags){ - uint16_t l_flag = dap_chain_datum_token_flag_from_str(*l_str_flags); - if ( l_flag == DAP_CHAIN_DATUM_TOKEN_FLAG_UNDEFINED ){ - dap_cli_server_cmd_set_reply_text(a_str_reply, "Flag can't be \"%s\"",*l_str_flags); - return -20; - } - l_flags |= (1<<l_flag); - l_str_flags++; - } - // Add flags as set_flags TDS section - dap_tsd_t * l_tsd = dap_tsd_create_scalar( - DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_SET_FLAGS, l_flags); - dap_list_append( l_tsd_list, l_tsd); - l_tsd_total_size+= dap_tsd_size( l_tsd); - - }else if ( strcmp( a_argv[l_arg_index],"-flags_unset" )==0){ // Flags - char ** l_str_flags = NULL; - l_str_flags = dap_strsplit( l_arg_param,",",0xffff ); - uint16_t l_flags = 0; - while (l_str_flags && *l_str_flags ){ - uint16_t l_flag = dap_chain_datum_token_flag_from_str(*l_str_flags); - if ( l_flag == DAP_CHAIN_DATUM_TOKEN_FLAG_UNDEFINED ){ - dap_cli_server_cmd_set_reply_text(a_str_reply, "Flag can't be \"%s\"",*l_str_flags); - return -20; - } - l_flags |= l_flag; - l_str_flags++; - } - // Add flags as unset_flags TDS section - dap_tsd_t * l_tsd = dap_tsd_create_scalar( - DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_UNSET_FLAGS, l_flags); - dap_list_append( l_tsd_list, l_tsd); - l_tsd_total_size+= dap_tsd_size( l_tsd); - - }else if ( strcmp( a_argv[l_arg_index],"-signs" )==0){ - dap_cert_parse_str_list(l_arg_param, &l_certs, &l_certs_count); - if(!l_certs_count) { - dap_cli_server_cmd_set_reply_text(a_str_reply, - "token_update command requres at least one valid certificate to sign the basic transaction of emission"); - return -10; - } - } else if ( strcmp( a_argv[l_arg_index],"-total_supply" )==0){ // Total supply - dap_tsd_t * l_tsd; - uint256_t l_param_value = dap_chain_balance_scan(l_arg_param); - l_tsd = dap_tsd_create_scalar( - DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SUPPLY, l_param_value); - dap_list_append( l_tsd_list, l_tsd); - l_tsd_total_size+= dap_tsd_size( l_tsd); - }else if ( strcmp( a_argv[l_arg_index],"-total_signs_valid" )==0){ // Signs valid - uint16_t l_param_value = (uint16_t)atoi(l_arg_param); - l_signs_total = l_param_value; - dap_tsd_t * l_tsd = dap_tsd_create_scalar( - DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_VALID, l_param_value); - dap_list_append( l_tsd_list, l_tsd); - l_tsd_total_size+= dap_tsd_size( l_tsd); - }else if ( strcmp( a_argv[l_arg_index],"-datum_type_allowed_add" )==0){ // Datum type allowed add - dap_tsd_t * l_tsd = dap_tsd_create_string( - DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_ALLOWED_ADD, l_arg_param); - dap_list_append( l_tsd_list, l_tsd); - l_tsd_total_size+= dap_tsd_size( l_tsd); - }else if ( strcmp( a_argv[l_arg_index],"-datum_type_allowed_remove" )==0){ // Datum type allowed remove - dap_tsd_t * l_tsd = dap_tsd_create_string( - DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_ALLOWED_REMOVE, l_arg_param); - dap_list_append( l_tsd_list, l_tsd); - l_tsd_total_size+= dap_tsd_size( l_tsd); - }else if ( strcmp( a_argv[l_arg_index],"-datum_type_blocked_add" )==0){ // Datum type blocked add - dap_tsd_t * l_tsd = dap_tsd_create_string( - DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_BLOCKED_ADD, l_arg_param); - dap_list_append( l_tsd_list, l_tsd); - l_tsd_total_size+= dap_tsd_size( l_tsd); - }else if ( strcmp( a_argv[l_arg_index],"-datum_type_blocked_remove" )==0){ // Datum type blocked remove - dap_tsd_t * l_tsd = dap_tsd_create_string( - DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_BLOCKED_REMOVE, l_arg_param); - dap_list_append( l_tsd_list, l_tsd); - l_tsd_total_size+= dap_tsd_size( l_tsd); - }else if ( strcmp( a_argv[l_arg_index],"-tx_receiver_allowed_add" )==0){ // TX Receiver add - dap_tsd_t * l_tsd = dap_tsd_create_string( - DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_ADD, l_arg_param); - dap_list_append( l_tsd_list, l_tsd); - l_tsd_total_size+= dap_tsd_size( l_tsd); - }else if ( strcmp( a_argv[l_arg_index],"-tx_receiver_allowed_remove" )==0){ // TX Receiver remove - dap_tsd_t * l_tsd = dap_tsd_create_string( - DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_REMOVE, l_arg_param); - dap_list_append( l_tsd_list, l_tsd); - l_tsd_total_size+= dap_tsd_size( l_tsd); - }else if ( strcmp( a_argv[l_arg_index],"-tx_receiver_blocked_add" )==0){ // TX Receiver blocked add - dap_tsd_t * l_tsd = dap_tsd_create_string( - DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_ADD, l_arg_param); - dap_list_append( l_tsd_list, l_tsd); - l_tsd_total_size+= dap_tsd_size( l_tsd); - }else if ( strcmp( a_argv[l_arg_index],"-tx_receiver_blocked_remove" )==0){ // TX Receiver blocked remove - dap_tsd_t * l_tsd = dap_tsd_create_string( - DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_REMOVE, l_arg_param); - dap_list_append( l_tsd_list, l_tsd); - l_tsd_total_size+= dap_tsd_size( l_tsd); - }else if ( strcmp( a_argv[l_arg_index],"-tx_sender_allowed_add" )==0){ // TX Sender allowed add - dap_tsd_t * l_tsd = dap_tsd_create_string( - DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_ADD, l_arg_param); - dap_list_append( l_tsd_list, l_tsd); - l_tsd_total_size+= dap_tsd_size( l_tsd); - }else if ( strcmp( a_argv[l_arg_index],"-tx_sender_allowed_remove" )==0){ // TX Sender allowed remove - dap_tsd_t * l_tsd = dap_tsd_create_string( - DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_REMOVE, l_arg_param); - dap_list_append( l_tsd_list, l_tsd); - l_tsd_total_size+= dap_tsd_size( l_tsd); - }else if ( strcmp( a_argv[l_arg_index],"-tx_sender_blocked_add" )==0){ // TX Sender blocked add - dap_tsd_t * l_tsd = dap_tsd_create_string( - DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_ADD, l_arg_param); - dap_list_append( l_tsd_list, l_tsd); - l_tsd_total_size+= dap_tsd_size( l_tsd); - }else if ( strcmp( a_argv[l_arg_index],"-tx_sender_blocked_remove" )==0){ // TX Sender blocked remove - dap_tsd_t * l_tsd = dap_tsd_create_string( - DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_REMOVE, l_arg_param); - dap_list_append( l_tsd_list, l_tsd); - l_tsd_total_size+= dap_tsd_size( l_tsd); - } else if (strcmp( a_argv[l_arg_index], "-chain") && strcmp( a_argv[l_arg_index], "-net") && - strcmp( a_argv[l_arg_index], "-token") && !strcmp( a_argv[l_arg_index], "-type")) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Unknown param \"%s\"",a_argv[l_arg_index]); - return -20; - } - l_arg_index+=2; - } - - if (!l_tsd_total_size) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "No valid params to update"); - return -21; - } - - // If we have more certs than we need signs - use only first part of the list - if(l_certs_count > l_signs_total) - l_certs_count = l_signs_total; - - // Create new datum token - l_datum_token_update = DAP_NEW_Z_SIZE(dap_chain_datum_token_t, sizeof(dap_chain_datum_token_t)+l_tsd_total_size ) ; - l_datum_token_update->type = DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_UPDATE; // 256 - dap_snprintf(l_datum_token_update->ticker, sizeof(l_datum_token_update->ticker), "%s", l_ticker); - l_datum_token_update->header_private_update.tsd_total_size = l_tsd_total_size; - - // Sign header with all certificates in the list and add signs to the end of token update - uint16_t l_sign_counter = 0; - l_datum_token_update = s_sign_cert_in_cycle(l_certs, l_datum_token_update, l_certs_count, &l_tsd_total_size, - &l_sign_counter); - l_datum_token_update->signs_total = l_sign_counter; - - // Add TSD sections in the end - for ( dap_list_t* l_iter=dap_list_first(l_tsd_list); l_iter; l_iter=l_iter->next){ - dap_tsd_t * l_tsd = (dap_tsd_t *) l_iter->data; - size_t l_tsd_size = dap_tsd_size( l_tsd); - memcpy(l_datum_token_update->data_n_tsd + l_datum_data_offset, l_tsd, l_tsd_size); - l_datum_data_offset += l_tsd_size; - } - - - }break; - - default: - dap_cli_server_cmd_set_reply_text(a_str_reply, - "Unknown token type"); - return -8; - } - - if (l_sign_counter == 0) - { - dap_cli_server_cmd_set_reply_text(a_str_reply, - "Token declaration failed. Successful count of certificate signing is 0"); - return -9; - } - - dap_chain_datum_t * l_datum = dap_chain_datum_create(DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_UPDATE, l_datum_token_update, - sizeof(l_datum_token_update->header_simple) + l_datum_data_offset); - size_t l_datum_size = dap_chain_datum_size(l_datum); - - // Calc datum's hash - dap_chain_hash_fast_t l_key_hash; - dap_hash_fast(l_datum, l_datum_size, &l_key_hash); - char * l_key_str = dap_chain_hash_fast_to_str_new(&l_key_hash); - char * l_key_str_base58 = dap_enc_base58_encode_hash_to_str(&l_key_hash); - - // Add datum to mempool with datum_token_update hash as a key - char * l_gdb_group_mempool; - if(l_chain) { - l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool_new(l_chain); - } - else { - l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool_by_chain_type(l_net, CHAIN_TYPE_TOKEN); - - } - if(dap_global_db_set_sync(l_gdb_group_mempool, l_key_str, l_datum, l_datum_size, true) == 0) { - if(!dap_strcmp(l_hash_out_type,"hex")) - dap_cli_server_cmd_set_reply_text(a_str_reply, "datum %s with token update %s is placed in datum pool ", l_key_str, l_ticker); - else - dap_cli_server_cmd_set_reply_text(a_str_reply, "datum %s with token update %s is placed in datum pool ", l_key_str_base58, l_ticker); - DAP_DELETE(l_datum); - DAP_DELETE(l_datum_token_update); - DAP_DELETE(l_gdb_group_mempool); - DAP_DELETE(l_key_str); - DAP_DELETE(l_key_str_base58); - return 0; - } - else { - if(!dap_strcmp(l_hash_out_type,"hex")) - dap_cli_server_cmd_set_reply_text(a_str_reply, "datum tx %s is not placed in datum pool ", l_key_str); - else - dap_cli_server_cmd_set_reply_text(a_str_reply, "datum tx %s is not placed in datum pool ", l_key_str_base58); - DAP_DELETE(l_datum); - DAP_DELETE(l_datum_token_update); - DAP_DELETE(l_gdb_group_mempool); - DAP_DELETE(l_key_str); - DAP_DELETE(l_key_str_base58); - return -2; - } -} - /** * @brief * @@ -2952,41 +2598,43 @@ typedef struct _dap_cli_token_additional_params { const char* tx_receiver_blocked; const char* tx_sender_allowed; const char* tx_sender_blocked; + uint16_t parsed_flags; + size_t tsd_total_size; + byte_t *parsed_tsd; } dap_cli_token_additional_params; typedef struct _dap_sdk_cli_params { - const char* l_hash_out_type; - dap_chain_t * l_chain; - dap_chain_net_t * l_net; - const char* l_chain_str; - const char* l_net_str; - const char* l_ticker; - const char* l_type_str; - uint16_t l_type; - const char* l_certs_str; - uint16_t l_signs_total; - uint16_t l_signs_emission; - uint256_t l_total_supply; - const char* l_decimals_str; + const char *hash_out_type; + const char *chain_str; + const char *net_str; + const char *ticker; + const char *type_str; + const char *certs_str; + dap_chain_t *chain; + dap_chain_net_t *net; + uint16_t type; + uint16_t signs_total; + uint16_t signs_emission; + uint256_t total_supply; + const char* decimals_str; dap_cli_token_additional_params ext; } dap_sdk_cli_params, *pdap_sdk_cli_params; - -int s_parse_common_token_decl_arg(int a_argc, char ** a_argv, char ** a_str_reply, dap_sdk_cli_params* l_params) +static int s_parse_common_token_decl_arg(int a_argc, char ** a_argv, char ** a_str_reply, dap_sdk_cli_params* a_params, bool a_update_token) { - l_params->l_type = DAP_CHAIN_DATUM_TOKEN_TYPE_SIMPLE; - dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-H", &l_params->l_hash_out_type); - if(!l_params->l_hash_out_type) - l_params->l_hash_out_type = "hex"; - if(dap_strcmp(l_params->l_hash_out_type,"hex") && dap_strcmp(l_params->l_hash_out_type,"base58")) { + a_params->type = DAP_CHAIN_DATUM_TOKEN_TYPE_SIMPLE; + dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-H", &a_params->hash_out_type); + if(!a_params->hash_out_type) + a_params->hash_out_type = "hex"; + if(dap_strcmp(a_params->hash_out_type,"hex") && dap_strcmp(a_params->hash_out_type,"base58")) { dap_cli_server_cmd_set_reply_text(a_str_reply, "invalid parameter -H, valid values: -H <hex | base58>"); return -1; } int l_arg_index = 0; - int l_res = dap_chain_node_cli_cmd_values_parse_net_chain(&l_arg_index, a_argc, a_argv, a_str_reply, &l_params->l_chain, &l_params->l_net); + int l_res = dap_chain_node_cli_cmd_values_parse_net_chain(&l_arg_index, a_argc, a_argv, a_str_reply, &a_params->chain, &a_params->net); - if(!l_params->l_net || !l_params->l_chain) + if(!a_params->net || !a_params->chain) return l_res; else { if(*a_str_reply) { @@ -2995,44 +2643,56 @@ int s_parse_common_token_decl_arg(int a_argc, char ** a_argv, char ** a_str_repl } } //net name - dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-net", &l_params->l_net_str); + dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-net", &a_params->net_str); //chainname - dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-chain", &l_params->l_chain_str); + dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-chain", &a_params->chain_str); //token_ticker - dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-token", &l_params->l_ticker); + dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-token", &a_params->ticker); // Token type - dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-type", &l_params->l_type_str); - - if (l_params->l_type_str) { - if (strcmp(l_params->l_type_str, "private") == 0){ - l_params->l_type = DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL; // 256 - }else if (strcmp(l_params->l_type_str, "private_simple") == 0){ - l_params->l_type = DAP_CHAIN_DATUM_TOKEN_TYPE_SIMPLE; // 256 - }else if (strcmp(l_params->l_type_str, "public_simple") == 0){ - l_params->l_type = DAP_CHAIN_DATUM_TOKEN_TYPE_PUBLIC; // 256 - }else if (strcmp(l_params->l_type_str, "CF20") == 0){ - l_params->l_type = DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL; // 256 - }else{ + dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-type", &a_params->type_str); + + if (a_params->type_str) { + if (strcmp(a_params->type_str, "private") == 0) { + a_params->type = a_update_token ? DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_UPDATE : DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL; // 256 + } else if (strcmp(a_params->type_str, "CF20") == 0) { + a_params->type = a_update_token ? DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_UPDATE : DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL; // 256 + } else if (strcmp(a_params->type_str, "private_simple") == 0 && !a_update_token) { + a_params->type = DAP_CHAIN_DATUM_TOKEN_TYPE_SIMPLE; // 256 + } else if (strcmp(a_params->type_str, "public_simple") == 0 && !a_update_token) { + a_params->type = DAP_CHAIN_DATUM_TOKEN_TYPE_PUBLIC; // 256 + } else if (strcmp(a_params->type_str, "CF20") == 0) { + a_params->type = DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL; // 256 + } else if (!a_update_token) { dap_cli_server_cmd_set_reply_text(a_str_reply, "Unknown token type %s was specified. Supported types:\n" " private_simple\n" " private\n" " CF20\n" - "Default token type is private_simple.\n", l_params->l_type_str); + "Default token type is private_simple.\n", a_params->type_str); return -1; - } + } else { + dap_cli_server_cmd_set_reply_text(a_str_reply, + "Unknown token type %s was specified. Supported types:\n" + " private\n" + " CF20\n", a_params->type_str); + return -1; + } + } else if (a_update_token) { + dap_cli_server_cmd_set_reply_text(a_str_reply,"update_token command required parameter:\n-type <CF20 or private>"); + return -1; } + // Certificates thats will be used to sign currend datum token - dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-certs", &l_params->l_certs_str); + dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-certs", &a_params->certs_str); // Signs number thats own emissioncan't find const char* l_signs_total_str = NULL; dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-signs_total", &l_signs_total_str); // Signs total char* l_tmp = NULL; if(l_signs_total_str){ - if((l_params->l_signs_total = (uint16_t) strtol(l_signs_total_str, &l_tmp, 10)) == 0){ + if((a_params->signs_total = (uint16_t) strtol(l_signs_total_str, &l_tmp, 10)) == 0){ dap_cli_server_cmd_set_reply_text(a_str_reply, "'signs_total' parameter must be unsigned integer value that fits in 2 bytes"); return -8; @@ -3043,9 +2703,9 @@ int s_parse_common_token_decl_arg(int a_argc, char ** a_argv, char ** a_str_repl l_tmp = NULL; dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-signs_emission", &l_signs_emission_str); if (l_signs_emission_str){ - if((l_params->l_signs_emission = (uint16_t) strtol(l_signs_emission_str, &l_tmp, 10)) == 0){ + if((a_params->signs_emission = (uint16_t) strtol(l_signs_emission_str, &l_tmp, 10)) == 0){ dap_cli_server_cmd_set_reply_text(a_str_reply, - "token_decl requires parameter 'signs_emission' to be unsigned integer value that fits in 2 bytes"); + "%s requires parameter 'signs_emission' to be unsigned integer value that fits in 2 bytes", a_update_token ? "token_update" : "token_decl"); return -6; } } @@ -3053,95 +2713,204 @@ int s_parse_common_token_decl_arg(int a_argc, char ** a_argv, char ** a_str_repl const char* l_total_supply_str = NULL; dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-total_supply", &l_total_supply_str); if (l_total_supply_str){ - l_params->l_total_supply = dap_chain_balance_scan(l_total_supply_str); - if (IS_ZERO_256(l_params->l_total_supply)){ - dap_cli_server_cmd_set_reply_text(a_str_reply, "'-total_supply' must be unsigned integer value that fits in 8 bytes"); - return -4; - } + a_params->total_supply = dap_chain_balance_scan(l_total_supply_str); + } else if (!a_update_token) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "'-total_supply' must be unsigned integer value that fits in 32 bytes\n" + "If your token is type native (CF20) you can use value 0 for infinite total_supply."); + return -4; + } else { + dap_cli_server_cmd_set_reply_text(a_str_reply, "'-total_supply' must be unsigned integer value that fits in 32 bytes\n" + "You are update a token, be careful!\n" + "You can reset total_supply and make it infinite for native (CF20) tokens only, if set 0" + "for private tokens, you must specify the same or more total_supply."); + return -4; } - // Total supply value - dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-decimals", &l_params->l_decimals_str); + dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-decimals", &a_params->decimals_str); return 0; } -int s_parse_additional_token_decl_arg(int a_argc, char ** a_argv, char ** a_str_reply, dap_sdk_cli_params* l_params) +static int s_parse_additional_token_decl_arg(int a_argc, char ** a_argv, char ** a_str_reply, dap_sdk_cli_params* a_params) { - dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-flags", &l_params->ext.flags); - dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-total_signs_valid", &l_params->ext.total_signs_valid); - dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-delegated_token_from", &l_params->ext.delegated_token_from); - dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-datum_type_allowed", &l_params->ext.datum_type_allowed); - dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-datum_type_blocked", &l_params->ext.datum_type_blocked); - dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-tx_receiver_allowed", &l_params->ext.tx_receiver_allowed); - dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-tx_receiver_blocked", &l_params->ext.tx_receiver_blocked); - dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-tx_sender_allowed", &l_params->ext.tx_sender_allowed); - dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-tx_receiver_allowed", &l_params->ext.tx_receiver_allowed); - dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-tx_sender_blocked", &l_params->ext.tx_sender_blocked); + dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-flags", &a_params->ext.flags); + dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-total_signs_valid", &a_params->ext.total_signs_valid); + dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-delegated_token_from", &a_params->ext.delegated_token_from); + dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-datum_type_allowed", &a_params->ext.datum_type_allowed); + dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-datum_type_blocked", &a_params->ext.datum_type_blocked); + dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-tx_receiver_allowed", &a_params->ext.tx_receiver_allowed); + dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-tx_receiver_blocked", &a_params->ext.tx_receiver_blocked); + dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-tx_sender_allowed", &a_params->ext.tx_sender_allowed); + dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-tx_receiver_allowed", &a_params->ext.tx_receiver_allowed); + dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-tx_sender_blocked", &a_params->ext.tx_sender_blocked); + + if (a_params->type == DAP_CHAIN_DATUM_TOKEN_TYPE_SIMPLE) + return 0; + + dap_list_t *l_tsd_list = NULL; + size_t l_tsd_total_size = 0; + uint16_t l_flags = 0; + char ** l_str_flags = NULL; + + if (a_params->ext.flags){ // Flags + l_str_flags = dap_strsplit(a_params->ext.flags,",",0xffff ); + while (l_str_flags && *l_str_flags){ + uint16_t l_flag = dap_chain_datum_token_flag_from_str(*l_str_flags); + if (l_flag == DAP_CHAIN_DATUM_TOKEN_FLAG_UNDEFINED ){ + dap_cli_server_cmd_set_reply_text(a_str_reply, "Flag can't be \"%s\"",*l_str_flags); + return -20; + } + l_flags |= l_flag; // if we have multiple flags + l_str_flags++; + } + } + a_params->ext.parsed_flags = l_flags; + if (a_params->ext.delegated_token_from) { + dap_chain_datum_token_t* l_delegated_token_from; + if (NULL == (l_delegated_token_from = dap_chain_ledger_token_ticker_check(a_params->net->pub.ledger, a_params->ext.delegated_token_from))) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "To create a delegated token %s, can't find token by ticker %s", a_params->ticker, a_params->ext.delegated_token_from); + return -91; + } + dap_chain_datum_token_tsd_delegate_from_stake_lock_t l_tsd_section; + strcpy(l_tsd_section.ticker_token_from, a_params->ext.delegated_token_from); + l_tsd_section.emission_rate = dap_chain_coins_to_balance("0.001"); + dap_tsd_t* l_tsd = dap_tsd_create_scalar( + DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DELEGATE_EMISSION_FROM_STAKE_LOCK, l_tsd_section); + l_tsd_list = dap_list_append(l_tsd_list, l_tsd); + l_tsd_total_size += dap_tsd_size(l_tsd); + } + if (a_params->ext.total_signs_valid){ // Signs valid + uint16_t l_param_value = (uint16_t)atoi(a_params->ext.total_signs_valid); + a_params->signs_emission = l_param_value; + dap_tsd_t * l_tsd = dap_tsd_create_scalar( + DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_VALID, l_param_value); + l_tsd_list = dap_list_append(l_tsd_list, l_tsd); + l_tsd_total_size+= dap_tsd_size(l_tsd); + } + if (a_params->ext.datum_type_allowed){ + dap_tsd_t * l_tsd = dap_tsd_create_string( + DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_ALLOWED_ADD, a_params->ext.datum_type_allowed); + l_tsd_list = dap_list_append(l_tsd_list, l_tsd); + l_tsd_total_size+= dap_tsd_size(l_tsd); + } + if (a_params->ext.datum_type_blocked){ + dap_tsd_t * l_tsd = dap_tsd_create_string( + DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_BLOCKED_ADD, a_params->ext.datum_type_blocked); + l_tsd_list = dap_list_append(l_tsd_list, l_tsd); + l_tsd_total_size+= dap_tsd_size(l_tsd); + } + if (a_params->ext.tx_receiver_allowed) + l_tsd_list = s_parse_wallet_addresses(a_params->ext.tx_receiver_allowed, l_tsd_list, &l_tsd_total_size, DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_ADD); + + if (a_params->ext.tx_receiver_blocked) + l_tsd_list = s_parse_wallet_addresses(a_params->ext.tx_receiver_blocked, l_tsd_list, &l_tsd_total_size, DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_ADD); + + if (a_params->ext.tx_sender_allowed) + l_tsd_list = s_parse_wallet_addresses(a_params->ext.tx_sender_allowed, l_tsd_list, &l_tsd_total_size, DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_ADD); + + if (a_params->ext.tx_sender_blocked) + l_tsd_list = s_parse_wallet_addresses(a_params->ext.tx_sender_blocked, l_tsd_list, &l_tsd_total_size, DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_ADD); + + if (!l_tsd_total_size) + return 0; + + size_t l_tsd_offset = 0; + a_params->ext.parsed_tsd = DAP_NEW_SIZE(byte_t, l_tsd_total_size); + for (dap_list_t *l_iter = dap_list_first(l_tsd_list); l_iter; l_iter = l_iter->next) { + dap_tsd_t * l_tsd = (dap_tsd_t *) l_iter->data; + if (l_tsd == NULL){ + log_it(L_ERROR, "NULL tsd in list!"); + continue; + } + switch (l_tsd->type){ + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_VALID: + log_it(L_DEBUG,"== TOTAL_SIGNS_VALID: %u", + dap_tsd_get_scalar(l_tsd,uint16_t) ); + break; + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_ALLOWED_ADD: + log_it(L_DEBUG,"== DATUM_TYPE_ALLOWED_ADD: %s", + dap_tsd_get_string_const(l_tsd) ); + break; + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_ADD: + log_it(L_DEBUG,"== TX_SENDER_ALLOWED_ADD: binary data"); + break; + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_ADD: + log_it(L_DEBUG,"== TYPE_TX_SENDER_BLOCKED: binary data"); + break; + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_ADD: + log_it(L_DEBUG,"== TX_RECEIVER_ALLOWED_ADD: binary data"); + break; + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_ADD: + log_it(L_DEBUG,"== TX_RECEIVER_BLOCKED_ADD: binary data"); + break; + default: log_it(L_DEBUG, "== 0x%04X: binary data %u size ",l_tsd->type, l_tsd->size ); + } + size_t l_tsd_size = dap_tsd_size(l_tsd); + memcpy(a_params->ext.parsed_tsd + l_tsd_offset, l_tsd, l_tsd_size); + l_tsd_offset += l_tsd_size; + } + a_params->ext.tsd_total_size = l_tsd_total_size; + return 0; } -int s_token_decl_check_params(int a_argc, char ** a_argv, char ** a_str_reply, dap_sdk_cli_params* l_params) +static int s_token_decl_check_params(int a_argc, char **a_argv, char **a_str_reply, dap_sdk_cli_params *a_params, bool a_update_token) { - int l_parse_params = s_parse_common_token_decl_arg(a_argc,a_argv,a_str_reply,l_params); + int l_parse_params = s_parse_common_token_decl_arg(a_argc,a_argv,a_str_reply,a_params, a_update_token); if (l_parse_params) return l_parse_params; - l_parse_params = s_parse_additional_token_decl_arg(a_argc,a_argv,a_str_reply,l_params); + l_parse_params = s_parse_additional_token_decl_arg(a_argc,a_argv,a_str_reply,a_params); if (l_parse_params) return l_parse_params; - - dap_chain_datum_token_t * l_datum_token = NULL; - size_t l_datum_data_offset = 0; - //DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL uses decimals parameter - if (l_params->l_type == DAP_CHAIN_DATUM_TOKEN_TYPE_SIMPLE || l_params->l_type == DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL){ - if(!l_params->l_decimals_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "token_decl requires parameter '-decimals'"); + if (a_params->type == DAP_CHAIN_DATUM_TOKEN_TYPE_SIMPLE + || a_params->type == DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL + || a_params->type == DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_UPDATE) { + if(!a_params->decimals_str) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "%s requires parameter '-decimals'", a_update_token ? "token_update" : "token_decl"); return -3; - } else if (dap_strcmp(l_params->l_decimals_str, "18")) { + } else if (dap_strcmp(a_params->decimals_str, "18")) { dap_cli_server_cmd_set_reply_text(a_str_reply, - "token_decl support '-decimals' to be 18 only"); + "%s support '-decimals' to be 18 only", a_update_token ? "token_update" : "token_decl"); return -4; } - if(IS_ZERO_256(l_params->l_total_supply)) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "token_decl requires parameter '-total_supply'"); + if(IS_ZERO_256(a_params->total_supply)) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "%s requires parameter '-total_supply'", a_update_token ? "token_update" : "token_decl"); return -3; } - } else if (l_params->l_type == DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL){ //// check l_decimals in CF20 token TODO: At the moment the checks are the same. - if(!l_params->l_decimals_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "token_decl requires parameter '-decimals'"); + } else if ( a_params->type == DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL + || a_params->type == DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_UPDATE){ + //// check l_decimals in CF20 token TODO: At the moment the checks are the same. + if(!a_params->decimals_str) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "%s requires parameter '-decimals'", a_update_token ? "token_update" : "token_decl"); return -3; - } else if (dap_strcmp(l_params->l_decimals_str, "18")) { + } else if (dap_strcmp(a_params->decimals_str, "18")) { dap_cli_server_cmd_set_reply_text(a_str_reply, - "token_decl support '-decimals' to be 18 only"); + "%s support '-decimals' to be 18 only", a_update_token ? "token_update" : "token_decl"); return -4; } - if(IS_ZERO_256(l_params->l_total_supply)) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "token_decl requires parameter '-total_supply'"); - return -3; - } } - if (!l_params->l_signs_emission){ - dap_cli_server_cmd_set_reply_text(a_str_reply, "token_decl requires parameter '-signs_emission'"); + if (!a_params->signs_emission){ + dap_cli_server_cmd_set_reply_text(a_str_reply, "%s requires parameter '-signs_emission'", a_update_token ? "token_update" : "token_decl"); return -5; } - if (!l_params->l_signs_total){ - dap_cli_server_cmd_set_reply_text(a_str_reply, "token_decl requires parameter 'signs_total'"); + if (!a_params->signs_total){ + dap_cli_server_cmd_set_reply_text(a_str_reply, "%s requires parameter '-signs_total'", a_update_token ? "token_update" : "token_decl"); return -7; } - if(!l_params->l_ticker){ - dap_cli_server_cmd_set_reply_text(a_str_reply, "token_decl requires parameter '-token'"); + if(!a_params->ticker){ + dap_cli_server_cmd_set_reply_text(a_str_reply, "%s requires parameter '-token'", a_update_token ? "token_update" : "token_decl"); return -2; } // Check certs list - if(!l_params->l_certs_str){ - dap_cli_server_cmd_set_reply_text(a_str_reply, "token_decl requires parameter 'certs'"); + if(!a_params->certs_str){ + dap_cli_server_cmd_set_reply_text(a_str_reply, "%s requires parameter 'certs'", a_update_token ? "token_update" : "token_decl"); return -9; } return 0; @@ -3209,9 +2978,9 @@ int com_token_decl(int a_argc, char ** a_argv, char ** a_str_reply) if (!l_params) return -1; - l_params->l_type = DAP_CHAIN_DATUM_TOKEN_TYPE_SIMPLE; + l_params->type = DAP_CHAIN_DATUM_TOKEN_TYPE_SIMPLE; - int l_parse_params = s_token_decl_check_params(a_argc,a_argv,a_str_reply,l_params); + int l_parse_params = s_token_decl_check_params(a_argc,a_argv,a_str_reply,l_params, false); if (l_parse_params) return l_parse_params; @@ -3219,146 +2988,52 @@ int com_token_decl(int a_argc, char ** a_argv, char ** a_str_reply) size_t l_datum_data_offset = 0; // Load certs lists - dap_cert_parse_str_list(l_params->l_certs_str, &l_certs, &l_certs_count); + dap_cert_parse_str_list(l_params->certs_str, &l_certs, &l_certs_count); if(!l_certs_count){ dap_cli_server_cmd_set_reply_text(a_str_reply, "token_decl command requres at least one valid certificate to sign token"); return -10; } - l_signs_emission = l_params->l_signs_emission; - l_signs_total = l_params->l_signs_total; - l_total_supply = l_params->l_total_supply; - l_chain = l_params->l_chain; - l_net = l_params->l_net; - l_ticker = l_params->l_ticker; - l_hash_out_type = l_params->l_hash_out_type; + l_signs_emission = l_params->signs_emission; + l_signs_total = l_params->signs_total; + l_total_supply = l_params->total_supply; + l_chain = l_params->chain; + l_net = l_params->net; + l_ticker = l_params->ticker; + l_hash_out_type = l_params->hash_out_type; - switch(l_params->l_type) + switch(l_params->type) { case DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL: case DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL: { // 256 - dap_list_t *l_tsd_list = NULL; - size_t l_tsd_total_size = 0; - uint16_t l_flags = 0; - char ** l_str_flags = NULL; - - if (l_params->ext.flags){ // Flags - l_str_flags = dap_strsplit(l_params->ext.flags,",",0xffff ); - while (l_str_flags && *l_str_flags){ - uint16_t l_flag = dap_chain_datum_token_flag_from_str(*l_str_flags); - if (l_flag == DAP_CHAIN_DATUM_TOKEN_FLAG_UNDEFINED ){ - dap_cli_server_cmd_set_reply_text(a_str_reply, "Flag can't be \"%s\"",*l_str_flags); - return -20; - } - l_flags |= l_flag; // if we have multiple flags - l_str_flags++; - } - } - if (l_params->ext.delegated_token_from) { - dap_chain_datum_token_t* l_delegated_token_from; - if (NULL == (l_delegated_token_from = dap_chain_ledger_token_ticker_check(l_net->pub.ledger, l_params->ext.delegated_token_from))) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "To create a delegated token %s, can't find token by ticket %s", l_ticker, l_params->ext.delegated_token_from); - return -91; - } - dap_chain_datum_token_tsd_delegate_from_stake_lock_t l_tsd_section; - strcpy(l_tsd_section.ticker_token_from, l_params->ext.delegated_token_from); - // l_tsd_section.token_from = dap_hash_fast(); - l_tsd_section.emission_rate = dap_chain_coins_to_balance("1.0");//TODO: ??? - dap_tsd_t* l_tsd = dap_tsd_create_scalar( - DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DELEGATE_EMISSION_FROM_STAKE_LOCK, l_tsd_section); - l_tsd_list = dap_list_append(l_tsd_list, l_tsd); - l_tsd_total_size += dap_tsd_size(l_tsd); - } - if (l_params->ext.total_signs_valid){ // Signs valid - uint16_t l_param_value = (uint16_t)atoi(l_params->ext.total_signs_valid); - l_signs_total = l_param_value; - dap_tsd_t * l_tsd = dap_tsd_create_scalar( - DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_VALID, l_param_value); - l_tsd_list = dap_list_append(l_tsd_list, l_tsd); - l_tsd_total_size+= dap_tsd_size(l_tsd); - } - if (l_params->ext.datum_type_allowed){ - dap_tsd_t * l_tsd = dap_tsd_create_string( - DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_ALLOWED_ADD, l_params->ext.datum_type_allowed); - l_tsd_list = dap_list_append(l_tsd_list, l_tsd); - l_tsd_total_size+= dap_tsd_size(l_tsd); - } - if (l_params->ext.datum_type_blocked){ - dap_tsd_t * l_tsd = dap_tsd_create_string( - DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_BLOCKED_ADD, l_params->ext.datum_type_blocked); - l_tsd_list = dap_list_append(l_tsd_list, l_tsd); - l_tsd_total_size+= dap_tsd_size(l_tsd); - } - if (l_params->ext.tx_receiver_allowed) - l_tsd_list = s_parse_wallet_addresses(l_params->ext.tx_receiver_allowed, l_tsd_list, &l_tsd_total_size, DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_ADD); - - if (l_params->ext.tx_receiver_blocked) - l_tsd_list = s_parse_wallet_addresses(l_params->ext.tx_receiver_blocked, l_tsd_list, &l_tsd_total_size, DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_ADD); - - if (l_params->ext.tx_sender_allowed) - l_tsd_list = s_parse_wallet_addresses(l_params->ext.tx_sender_allowed, l_tsd_list, &l_tsd_total_size, DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_ADD); - - if (l_params->ext.tx_sender_blocked) - l_tsd_list = s_parse_wallet_addresses(l_params->ext.tx_sender_blocked, l_tsd_list, &l_tsd_total_size, DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_ADD); - - // Create new datum token - l_datum_token = DAP_NEW_Z_SIZE(dap_chain_datum_token_t, sizeof(dap_chain_datum_token_t) + l_tsd_total_size) ; - l_datum_token->type = l_params->l_type; - if (l_params->l_type == DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL) { - log_it(L_DEBUG,"Prepared TSD sections for private token on %zd total size", l_tsd_total_size); + l_datum_token = DAP_NEW_Z_SIZE(dap_chain_datum_token_t, sizeof(dap_chain_datum_token_t) + l_params->ext.tsd_total_size) ; + l_datum_token->type = l_params->type; + if (l_params->type == DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL) { + log_it(L_DEBUG,"Prepared TSD sections for private token on %zd total size", l_params->ext.tsd_total_size); dap_snprintf(l_datum_token->ticker, sizeof(l_datum_token->ticker), "%s", l_ticker); - l_datum_token->header_private_decl.flags = l_flags; + l_datum_token->header_private_decl.flags = l_params->ext.parsed_flags; l_datum_token->total_supply = l_total_supply; l_datum_token->signs_valid = l_signs_emission; - l_datum_token->header_private_decl.tsd_total_size = l_tsd_total_size; - l_datum_token->header_native_decl.decimals = atoi(l_params->l_decimals_str); + l_datum_token->header_private_decl.tsd_total_size = l_params->ext.tsd_total_size; + l_datum_token->header_private_decl.decimals = atoi(l_params->decimals_str); } else { //DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL - log_it(L_DEBUG,"Prepared TSD sections for CF20 token on %zd total size", l_tsd_total_size); + log_it(L_DEBUG,"Prepared TSD sections for CF20 token on %zd total size", l_params->ext.tsd_total_size); dap_snprintf(l_datum_token->ticker, sizeof(l_datum_token->ticker), "%s", l_ticker); - l_datum_token->header_native_decl.flags = l_flags; + l_datum_token->header_native_decl.flags = l_params->ext.parsed_flags; l_datum_token->total_supply = l_total_supply; l_datum_token->signs_valid = l_signs_emission; - l_datum_token->header_native_decl.tsd_total_size = l_tsd_total_size; - l_datum_token->header_native_decl.decimals = atoi(l_params->l_decimals_str); + l_datum_token->header_native_decl.tsd_total_size = l_params->ext.tsd_total_size; + l_datum_token->header_native_decl.decimals = atoi(l_params->decimals_str); } // Add TSD sections in the end - for ( dap_list_t* l_iter=dap_list_first(l_tsd_list); l_iter; l_iter=l_iter->next){ - dap_tsd_t * l_tsd = (dap_tsd_t *) l_iter->data; - if (l_tsd == NULL){ - log_it(L_ERROR, "NULL tsd in list!"); - continue; - } - switch (l_tsd->type){ - case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_VALID: - log_it(L_DEBUG,"== TOTAL_SIGNS_VALID: %u", - dap_tsd_get_scalar(l_tsd,uint16_t) ); - break; - case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_ALLOWED_ADD: - log_it(L_DEBUG,"== DATUM_TYPE_ALLOWED_ADD: %s", - dap_tsd_get_string_const(l_tsd) ); - break; - case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_ADD: - log_it(L_DEBUG,"== TX_SENDER_ALLOWED_ADD: binary data"); - break; - case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_ADD: - log_it(L_DEBUG,"== TYPE_TX_SENDER_BLOCKED: binary data"); - break; - case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_ADD: - log_it(L_DEBUG,"== TX_RECEIVER_ALLOWED_ADD: binary data"); - break; - case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_ADD: - log_it(L_DEBUG,"== TX_RECEIVER_BLOCKED_ADD: binary data"); - break; - default: log_it(L_DEBUG, "== 0x%04X: binary data %u size ",l_tsd->type, l_tsd->size ); - } - size_t l_tsd_size = dap_tsd_size(l_tsd); - memcpy(l_datum_token->data_n_tsd + l_datum_data_offset, l_tsd, l_tsd_size); - l_datum_data_offset += l_tsd_size; + if (l_params->ext.tsd_total_size) { + memcpy(l_datum_token->data_n_tsd, l_params->ext.parsed_tsd, l_params->ext.tsd_total_size); + DAP_DELETE(l_params->ext.parsed_tsd); } - log_it(L_DEBUG, "%s token declaration '%s' initialized", l_params->l_type == DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL ? + log_it(L_DEBUG, "%s token declaration '%s' initialized", l_params->type == DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL ? "Private" : "CF20", l_datum_token->ticker); }break;//end case DAP_CHAIN_DATUM_TOKEN_TYPE_SIMPLE: { // 256 @@ -3367,7 +3042,7 @@ int com_token_decl(int a_argc, char ** a_argv, char ** a_str_reply) dap_snprintf(l_datum_token->ticker, sizeof(l_datum_token->ticker), "%s", l_ticker); l_datum_token->total_supply = l_total_supply; l_datum_token->signs_valid = l_signs_emission; - l_datum_token->header_native_decl.decimals = atoi(l_params->l_decimals_str); + l_datum_token->header_simple.decimals = atoi(l_params->decimals_str); }break; default: dap_cli_server_cmd_set_reply_text(a_str_reply, @@ -3431,7 +3106,201 @@ int com_token_decl(int a_argc, char ** a_argv, char ** a_str_reply) return l_ret; } +/** + * @brief com_token_decl_update + * @param argc + * @param argv + * @param arg_func + * @param str_reply + * @return + * @details token_update -net <net name> -chain <chain_name> -token <token ticker> [-type private] -flags [<Flag 1>][,<Flag 2>]...[,<Flag N>]... [-<Param name 1> <Param Value 1>] [-Param name 2> <Param Value 2>] ...[-<Param Name N> <Param Value N>]\n" + * \t Update token for <netname>:<chain name> with ticker <token ticker>, flags <Flag 1>,<Flag2>...<Flag N>" + * \t and custom parameters list <Param 1>, <Param 2>...<Param N>." + * \n" + * ==Flags==" + * \t ALL_BLOCKED:\t Blocked all permissions, usefull add it first and then add allows what you want to allow\n" + * \t ALL_ALLOWED:\t Allowed all permissions if not blocked them. Be careful with this mode\n" + * \t ALL_FROZEN:\t All permissions are temprorary frozen\n" + * \t ALL_UNFROZEN:\t Unfrozen permissions\n" + * \t STATIC_ALL:\t No token manipulations after declarations at all. Token declares staticly and can't variabed after\n" + * \t STATIC_FLAGS:\t No token manipulations after declarations with flags\n" + * \t STATIC_PERMISSIONS_ALL:\t No all permissions lists manipulations after declarations\n" + * \t STATIC_PERMISSIONS_DATUM_TYPE:\t No datum type permissions lists manipulations after declarations\n" + * \t STATIC_PERMISSIONS_TX_SENDER:\t No tx sender permissions lists manipulations after declarations\n" + * \t STATIC_PERMISSIONS_TX_RECEIVER:\t No tx receiver permissions lists manipulations after declarations\n" + "\n" + "==Params==\n" + "General:\n" + "\t -flags_set <value>:\t Set list of flags from <value> to token declaration\n" + "\t -flags_unset <value>:\t Unset list of flags from <value> from token declaration\n" + "\t -total_supply <value>:\t Set total supply - emission's maximum - to the <value>\n" + "\t -total_signs_valid <value>:\t Set valid signatures count's minimum\n" + "\t -total_signs_add <value>:\t Add signature's pkey fingerprint to the list of owners\n" + "\t -total_signs_remove <value>:\t Remove signature's pkey fingerprint from the owners\n" + "\nDatum type allowed/blocked updates:\n" + "\t -datum_type_allowed_add <value>:\t Add allowed datum type(s)\n" + "\t -datum_type_allowed_remove <value>:\t Remove datum type(s) from allowed\n" + "\t -datum_type_blocked_add <value>:\t Add blocked datum type(s)\n" + "\t -datum_type_blocked_remove <value>:\t Remove datum type(s) from blocked\n" + "\nTx receiver addresses allowed/blocked updates:\n" + "\t -tx_receiver_allowed_add <value>:\t Add allowed tx receiver(s)\n" + "\t -tx_receiver_allowed_remove <value>:\t Remove tx receiver(s) from allowed\n" + "\t -tx_receiver_blocked_add <value>:\t Add blocked tx receiver(s)\n" + "\t -tx_receiver_blocked_remove <value>:\t Remove tx receiver(s) from blocked\n" + "\n Tx sender addresses allowed/blocked updates:\n" + "\t -tx_sender_allowed_add <value>:\t Add allowed tx sender(s)\n" + "\t -tx_sender_allowed_remove <value>:\t Remove tx sender(s) from allowed\n" + "\t -tx_sender_blocked_add <value>:\t Add allowed tx sender(s)\n" + "\t -tx_sender_blocked_remove <value>:\t Remove tx sender(s) from blocked\n" + "\n" + */ +int com_token_update(int a_argc, char ** a_argv, char ** a_str_reply) +{ + const char * l_ticker = NULL; + uint256_t l_total_supply = {}; // 256 + uint16_t l_signs_emission = 0; + uint16_t l_signs_total = 0; + dap_cert_t ** l_certs = NULL; + size_t l_certs_count = 0; + + dap_chain_t * l_chain = NULL; + dap_chain_net_t * l_net = NULL; + const char * l_hash_out_type = NULL; + + dap_sdk_cli_params* l_params = DAP_NEW_Z(dap_sdk_cli_params); + + if (!l_params) + return -1; + + l_params->type = DAP_CHAIN_DATUM_TOKEN_TYPE_SIMPLE; + int l_parse_params = s_token_decl_check_params(a_argc,a_argv,a_str_reply,l_params, true); + if (l_parse_params) + return l_parse_params; + + dap_chain_datum_token_t * l_datum_token = NULL; + size_t l_datum_data_offset = 0; + + // Load certs lists + dap_cert_parse_str_list(l_params->certs_str, &l_certs, &l_certs_count); + if(!l_certs_count){ + dap_cli_server_cmd_set_reply_text(a_str_reply, + "com_token_update command requres at least one valid certificate to sign token"); + return -10; + } + + l_signs_emission = l_params->signs_emission; + l_signs_total = l_params->signs_total; + l_total_supply = l_params->total_supply; + l_chain = l_params->chain; + l_net = l_params->net; + l_ticker = l_params->ticker; + l_hash_out_type = l_params->hash_out_type; + + switch(l_params->type) + { + case DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_UPDATE: + case DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_UPDATE: + { // 256 + // Create new datum token + l_datum_token = DAP_NEW_Z_SIZE(dap_chain_datum_token_t, sizeof(dap_chain_datum_token_t) + l_params->ext.tsd_total_size) ; + l_datum_token->type = l_params->type; + if (l_params->type == DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_UPDATE) { + log_it(L_DEBUG,"Prepared TSD sections for CF20 token on %zd total size", l_params->ext.tsd_total_size); + dap_snprintf(l_datum_token->ticker, sizeof(l_datum_token->ticker), "%s", l_ticker); + l_datum_token->header_native_update.flags = l_params->ext.parsed_flags; + l_datum_token->total_supply = l_total_supply; + l_datum_token->signs_valid = l_signs_emission; + l_datum_token->header_native_update.tsd_total_size = l_params->ext.tsd_total_size; + l_datum_token->header_native_update.decimals = atoi(l_params->decimals_str); + } else { // if (l_params->type == DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_UPDATE) { + log_it(L_DEBUG,"Prepared TSD sections for private token on %zd total size", l_params->ext.tsd_total_size); + dap_snprintf(l_datum_token->ticker, sizeof(l_datum_token->ticker), "%s", l_ticker); + l_datum_token->header_private_update.flags = l_params->ext.parsed_flags; + l_datum_token->total_supply = l_total_supply; + l_datum_token->signs_valid = l_signs_emission; + l_datum_token->header_private_update.tsd_total_size = l_params->ext.tsd_total_size; + l_datum_token->header_private_update.decimals = atoi(l_params->decimals_str); + } + // Add TSD sections in the end + // Add TSD sections in the end + if (l_params->ext.tsd_total_size) { + memcpy(l_datum_token->data_n_tsd, l_params->ext.parsed_tsd, l_params->ext.tsd_total_size); + DAP_DELETE(l_params->ext.parsed_tsd); + } + log_it(L_DEBUG, "%s token declaration update '%s' initialized", ( l_params->type == DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL + || l_params->type == DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_UPDATE) ? + "Private" : "CF20", l_datum_token->ticker); + }break;//end + case DAP_CHAIN_DATUM_TOKEN_TYPE_SIMPLE: { // 256 + l_datum_token = DAP_NEW_Z_SIZE(dap_chain_datum_token_t, sizeof(dap_chain_datum_token_t)); + l_datum_token->type = DAP_CHAIN_DATUM_TOKEN_TYPE_SIMPLE; // 256 + dap_snprintf(l_datum_token->ticker, sizeof(l_datum_token->ticker), "%s", l_ticker); + l_datum_token->total_supply = l_total_supply; + l_datum_token->signs_valid = l_signs_emission; + if (l_params->decimals_str) + l_datum_token->header_simple.decimals = atoi(l_params->decimals_str); + }break; + default: + dap_cli_server_cmd_set_reply_text(a_str_reply, + "Unknown token type"); + return -8; + } + // If we have more certs than we need signs - use only first part of the list + if(l_certs_count > l_signs_total) + l_certs_count = l_signs_total; + // Sign header with all certificates in the list and add signs to the end of TSD cetions + uint16_t l_sign_counter = 0; + l_datum_token = s_sign_cert_in_cycle(l_certs, l_datum_token, l_certs_count, &l_datum_data_offset, &l_sign_counter); + l_datum_token->signs_total = l_sign_counter; + + // We skip datum creation opeartion, if count of signed certificates in s_sign_cert_in_cycle is 0. + // Usually it happen, when certificate in token_decl or token_update command doesn't contain private data or broken + if (!l_datum_token || l_datum_token->signs_total == 0){ + dap_cli_server_cmd_set_reply_text(a_str_reply, + "Token declaration update failed. Successful count of certificate signing is 0"); + return -9; + } + + dap_chain_datum_t * l_datum = dap_chain_datum_create(DAP_CHAIN_DATUM_TOKEN_DECL, + l_datum_token, + sizeof(*l_datum_token) + l_datum_data_offset); + DAP_DELETE(l_datum_token); + size_t l_datum_size = dap_chain_datum_size(l_datum); + + // Calc datum's hash + dap_chain_hash_fast_t l_key_hash; + dap_hash_fast(l_datum, l_datum_size, &l_key_hash); + char * l_key_str = dap_chain_hash_fast_to_str_new(&l_key_hash); + char * l_key_str_out = dap_strcmp(l_hash_out_type, "hex") ? + dap_enc_base58_encode_hash_to_str(&l_key_hash) : l_key_str; + + // Add datum to mempool with datum_token hash as a key + char * l_gdb_group_mempool; + if (!l_chain) + dap_chain_net_get_default_chain_by_chain_type(l_net, CHAIN_TYPE_TOKEN); + l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool_new(l_chain); + if (!l_gdb_group_mempool) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "No suitable chain for placing token datum found"); + DAP_DELETE(l_datum); + return -10; + } + int l_ret = 0; + bool l_placed = dap_global_db_set_sync(l_gdb_group_mempool, l_key_str, (uint8_t *)l_datum, l_datum_size, false); + dap_cli_server_cmd_set_reply_text(a_str_reply, "Datum %s with 256bit token %s is%s placed in datum pool", + l_key_str_out, l_ticker, l_placed ? "" : " not"); + //additional checking for incorrect key format + if (l_key_str_out != l_key_str) + DAP_DELETE(l_key_str); + else + DAP_DELETE(l_key_str); + DAP_DELETE(l_datum); + DAP_DELETE(l_params); + if (!l_placed) { + l_ret = -2; + } + return l_ret; +} /** * @brief com_token_emit @@ -3546,8 +3415,8 @@ int com_token_emit(int a_argc, char ** a_argv, char ** a_str_reply) if(l_chain_emission_str) { if((l_chain_emission = dap_chain_net_get_chain_by_name(l_net, l_chain_emission_str)) == NULL) { // Can't find such chain dap_cli_server_cmd_set_reply_text(a_str_reply, - "token_create requires parameter '-chain_emission' to be valid chain name in chain net %s or set default datum type in chain configuration file", - l_net->pub.name); + "token_emit requires parameter '-chain_base_tx' to be valid chain name in chain net %s or set default datum type in chain configuration file " + "but, if you need create emission has no base transaction, use flag '-no_base_tx'", l_net->pub.name); return -45; } } @@ -3580,21 +3449,21 @@ int com_token_emit(int a_argc, char ** a_argv, char ** a_str_reply) DAP_DEL_Z(l_addr); return -47; } - goto CheckTicker; // --->> } else if (no_base_tx < 0) { if((l_chain_base_tx = dap_chain_net_get_default_chain_by_chain_type(l_net, CHAIN_TYPE_TX)) == NULL) { // Can't find such chain dap_cli_server_cmd_set_reply_text(a_str_reply, - "token_create requires parameter '-chain_base_tx' to be valid chain name in chain net %s or set default datum type in chain configuration file", l_net->pub.name); + "token_emit requires parameter '-chain_base_tx' to be valid chain name in chain net %s or set default datum type in chain configuration file " + "but, if you need create emission has no base transaction, use flag '-no_base_tx'", l_net->pub.name); + DAP_DEL_Z(l_addr); return -47; } - CheckTicker: // <<--- - if(!l_ticker) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "token_emit requires parameter '-token'"); - DAP_DEL_Z(l_addr); - return -3; - } - } + } + if(!l_ticker) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "token_emit requires parameter '-token'"); + DAP_DEL_Z(l_addr); + return -3; + } if (!l_add_sign) { if (!l_chain_emission) { @@ -4593,15 +4462,23 @@ int com_tx_create(int argc, char ** argv, char **str_reply) if(l_tx_num_str) l_tx_num = strtoul(l_tx_num_str, NULL, 10); - if(dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-fee", &str_tmp)) { - l_value_fee = dap_chain_balance_scan(str_tmp); - } else { - l_value_fee = dap_chain_coins_to_balance("0.1"); - } - if(dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-value", &str_tmp)) { + if(dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-value", &str_tmp)) l_value = dap_chain_balance_scan(str_tmp); + if(IS_ZERO_256(l_value)) { + dap_cli_server_cmd_set_reply_text(str_reply, "tx_create requires parameter '-value' to be valid uint256 value"); + return -4; } + + // Validator's fee + if(dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-fee", &str_tmp)) + l_value_fee = dap_chain_balance_scan(str_tmp); + if (IS_ZERO_256(l_value_fee)) { + dap_cli_server_cmd_set_reply_text(str_reply, + "tx_create requires parameter '-fee' to be valid uint256"); + return -5; + } + if(!l_from_wallet_name && !l_emission_hash_str) { dap_cli_server_cmd_set_reply_text(str_reply, "tx_create requires one of parameters '-from_wallet' or '-from_emission'"); return -1; @@ -4655,15 +4532,6 @@ int com_tx_create(int argc, char ** argv, char **str_reply) return -5; } } - if(IS_ZERO_256(l_value)) { - dap_cli_server_cmd_set_reply_text(str_reply, "tx_create requires parameter '-value' to be valid uint256 value"); - return -4; - } - if (IS_ZERO_256(l_value_fee)) { - dap_cli_server_cmd_set_reply_text(str_reply, - "tx_create requires parameter '-value_fee' to be valid uint256"); - return -5; - } dap_chain_t *l_chain = NULL; if (l_chain_name) { @@ -5236,6 +5104,141 @@ int cmd_gdb_import(int argc, char ** argv, char ** a_str_reply) return 0; } +dap_list_t *s_go_all_nets_offline() +{ + dap_list_t *l_net_returns = NULL; + uint16_t l_net_count; + dap_chain_net_t **l_net_list = dap_chain_net_list(&l_net_count); + for (uint16_t i = 0; i < l_net_count; i++) { // Shutdown all networks + if (dap_chain_net_stop(l_net_list[i])) + l_net_returns = dap_list_append(l_net_returns, l_net_list[i]); + } + sleep(2); // waiting for networks to go offline + return l_net_returns; +} + +int cmd_remove(int argc, char ** argv, char ** a_str_reply) +{ + //default init + const char *return_message = NULL; + const char *l_gdb_path = NULL; + const char *l_chains_path = NULL; + const char *l_net_str = NULL; + dap_chain_net_t *l_net = NULL; + int all = 0; + + //for enum + uint8_t error = 0; + uint8_t successful = 0; + + //enum for errors + enum { + GDB_FAIL_PATH = 0x00000001, + CHAINS_FAIL_PATH = 0x00000002, + COMMAND_NOT_CORRECT = 0x00000004, + NET_NOT_VALID = 0x00000008 + }; + + //enum for successful + enum { + REMOVED_GDB = 0x00000001, + REMOVED_CHAINS = 0x00000002 + }; + + //check path's from config file + if (dap_cli_server_cmd_check_option(argv, 1, argc, "-gdb") >= 0 + && (NULL == (l_gdb_path = dap_config_get_item_str(g_config, "resources", "dap_global_db_path")))){ + error |= GDB_FAIL_PATH; + } + if (dap_cli_server_cmd_check_option(argv, 1, argc, "-chains") >= 0 + && (NULL == (l_chains_path = dap_config_get_item_str(g_config, "resources", "dap_chains_path")))) { + error |= CHAINS_FAIL_PATH; + } + + dap_list_t *l_net_returns = NULL; + //perform deletion according to the specified parameters, if the path is specified + if (l_gdb_path) { + l_net_returns = s_go_all_nets_offline(); + char *l_gdb_rm_path = dap_strdup_printf("%s/gdb-%s", l_gdb_path, + dap_config_get_item_str_default(g_config, "resources", "global_db_driver", "mdbx")); + dap_rm_rf(l_gdb_rm_path); + DAP_DELETE(l_gdb_rm_path); + if (!error) + successful |= REMOVED_GDB; + } + + if (l_chains_path) { + dap_cli_server_cmd_find_option_val(argv, 1, argc, "-net", &l_net_str); + all = dap_cli_server_cmd_check_option(argv, 1, argc, "-all"); + + if (NULL == l_net_str && all >= 0) { + if (NULL == l_gdb_path) + l_net_returns = s_go_all_nets_offline(); + uint16_t l_net_count; + dap_chain_net_t **l_net_list = dap_chain_net_list(&l_net_count); + for (uint16_t i = 0; i < l_net_count; i++) { + char *l_chains_rm_path = dap_strdup_printf("%s/%s", l_chains_path, + l_net_list[i]->pub.gdb_groups_prefix); + dap_rm_rf(l_chains_rm_path); + DAP_DELETE(l_chains_rm_path); + } + if (!error) + successful |= REMOVED_CHAINS; + + } else if (NULL != l_net_str && all < 0) { + if (NULL != (l_net = dap_chain_net_by_name(l_net_str))) { + if (NULL == l_gdb_path && dap_chain_net_stop(l_net)) + l_net_returns = dap_list_append(l_net_returns, l_net); + } else { + error |= NET_NOT_VALID; + } + sleep(1); + char *l_chains_rm_path = dap_strdup_printf("%s/%s", l_chains_path, l_net->pub.gdb_groups_prefix); + dap_rm_rf(l_chains_rm_path); + DAP_DELETE(l_chains_rm_path); + if (!error) + successful |= REMOVED_CHAINS; + + } else { + error |= COMMAND_NOT_CORRECT; + } + } + + //handling errors + if (error & GDB_FAIL_PATH + || error & CHAINS_FAIL_PATH) { + return_message = "The node configuration file does not specify the path to the database and/or chains.\n" + "Please check the cellframe-node.cfg file in the [resources] item for subitems:\n" + "dap_global_db_path=<PATH>\n" + "dap_chains_path=<PATH>"; + } else if (error & COMMAND_NOT_CORRECT) { + return_message = "You need to make a decision whether to remove all chains or a chain from a specific network.\n" + "You cannot use two keys '-net' and '-all' at the same time.\n" + "Be careful, the '-all' option will delete ALL CHAINS and won't ask you for permission!"; + } else if (error & NET_NOT_VALID) { + return_message = "The specified network was not found.\n" + "The list of available networks can be viewed using the command:" + "'net list'"; + } + + if (error) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Error when deleting, because:\n%s", return_message); + } + else if (successful) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Successful removal: %s %s", successful & REMOVED_GDB ? "gdb" : "-", successful & REMOVED_CHAINS ? "chains" : "-"); + } else { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Nothing to delete. Check if the command is correct.\nUse flags: -gdb or/and -chains [-net <net_name> | -all]\n" + "Be careful, the '-all' option will delete ALL CHAINS and won't ask you for permission!"); + } + + for (dap_list_t *it = l_net_returns; it; it = it->next) + dap_chain_net_start((dap_chain_net_t *)it->data); + dap_list_free(l_net_returns); + + return error; +} + + /* * block code signer */ @@ -5256,8 +5259,6 @@ static int s_sign_file(const char *a_filename, dap_sign_signer_file_t a_flags, c dap_sign_t **a_signed, dap_chain_hash_fast_t *a_hash); static int s_signer_cmd(int a_arg_index, int a_argc, char **a_argv, char **a_str_reply); static int s_check_cmd(int a_arg_index, int a_argc, char **a_argv, char **a_str_reply); -static uint8_t *s_byte_to_hex(const char *a_line, size_t *a_size); -static uint8_t s_get_num(uint8_t a_byte, int a_pp); struct opts { char *name; uint32_t cmd; @@ -5351,7 +5352,6 @@ static int s_check_cmd(int a_arg_index, int a_argc, char **a_argv, char **a_str_ dap_sign_t *l_sign = NULL; dap_chain_datum_t *l_datum = NULL; - dap_global_db_obj_t *l_objs = NULL; char *l_gdb_group = NULL; l_gdb_group = dap_chain_net_get_gdb_group_mempool_new(l_chain); @@ -5385,12 +5385,9 @@ static int s_check_cmd(int a_arg_index, int a_argc, char **a_argv, char **a_str_ dap_hash_fast(l_datum->data, l_datum->header.data_size, &l_hash_tmp); } - - dap_chain_cell_id_t l_cell_id = {0}; dap_chain_atom_iter_t *l_iter = NULL; dap_chain_cell_t *l_cell_tmp = NULL; dap_chain_cell_t *l_cell = NULL; - dap_chain_datum_t *l_datum_tmp = NULL; size_t l_size = 0; HASH_ITER(hh, l_chain->cells, l_cell, l_cell_tmp) { @@ -5511,7 +5508,6 @@ static int s_signer_cmd(int a_arg_index, int a_argc, char **a_argv, char **a_str int l_ret = 0; dap_sign_t *l_sign = NULL; dap_chain_datum_t *l_datum = NULL; - dap_global_db_obj_t *l_objs = NULL; l_ret = s_get_key_from_file(l_opts_sign[OPT_FILE], l_opts_sign[OPT_MIME], l_opts_sign[OPT_CERT], &l_sign); if (!l_ret) { @@ -5529,9 +5525,6 @@ static int s_signer_cmd(int a_arg_index, int a_argc, char **a_argv, char **a_str goto end; } - - dap_chain_cell_id_t l_cell_id = {0}; - dap_chain_cell_create_fill(l_chain, l_cell_id); l_ret = l_chain->callback_add_datums(l_chain, &l_datum, 1); dap_hash_fast_t l_hash; diff --git a/modules/net/dap_chain_node_cli_cmd_tx.c b/modules/net/dap_chain_node_cli_cmd_tx.c index b266e418d6cb6f1c0256465617813cb289c0094e..0beb7fc6e02b570bdd0d5e348a68e9e0d480224d 100644 --- a/modules/net/dap_chain_node_cli_cmd_tx.c +++ b/modules/net/dap_chain_node_cli_cmd_tx.c @@ -40,6 +40,7 @@ #include "dap_chain_datum_tx_items.h" #include "dap_chain_node_cli.h" #include "dap_chain_node_cli_cmd_tx.h" +#include "dap_chain_net_tx.h" #define LOG_TAG "chain_node_cli_cmd_tx" @@ -61,17 +62,15 @@ typedef struct dap_chain_tx_hash_processed_ht{ }dap_chain_tx_hash_processed_ht_t; /** - * @brief _dap_chain_tx_hash_processed_ht_free + * @brief s_chain_tx_hash_processed_ht_free * free l_current_hash->hash, l_current_hash, l_hash_processed * @param l_hash_processed dap_chain_tx_hash_processed_ht_t */ -void _dap_chain_tx_hash_processed_ht_free(dap_chain_tx_hash_processed_ht_t *l_hash_processed){ - dap_chain_tx_hash_processed_ht_t *l_tmp; - dap_chain_tx_hash_processed_ht_t *l_current_hash; - HASH_ITER(hh, l_hash_processed, l_current_hash, l_tmp){ +static void s_dap_chain_tx_hash_processed_ht_free(dap_chain_tx_hash_processed_ht_t *l_hash_processed) +{ + dap_chain_tx_hash_processed_ht_t *l_tmp, *l_current_hash; + HASH_ITER(hh, l_hash_processed, l_current_hash, l_tmp) DAP_FREE(l_current_hash); - } - DAP_FREE(l_hash_processed); } /** @@ -382,6 +381,44 @@ char* dap_db_history_tx(dap_chain_hash_fast_t* a_tx_hash, dap_chain_t * a_chain, return l_ret_str; } +static void s_tx_header_print(dap_string_t *a_str_out, dap_chain_tx_hash_processed_ht_t *a_tx_data_ht, + dap_chain_datum_tx_t *a_tx, dap_chain_atom_iter_t *a_atom_iter, + const char *a_hash_out_type, dap_ledger_t *a_ledger, + dap_chain_hash_fast_t *a_tx_hash) +{ + bool l_declined = false; + // transaction time + char l_time_str[32] = "unknown"; /* Prefill string */ + if (a_tx->header.ts_created) { + uint64_t l_ts = a_tx->header.ts_created; + dap_ctime_r(&l_ts, l_time_str); /* Convert ts to Sat May 17 01:17:08 2014 */ + } + dap_hash_fast(a_tx, dap_chain_datum_tx_get_size(a_tx), a_tx_hash); + dap_chain_tx_hash_processed_ht_t *l_tx_data = NULL; + HASH_FIND(hh, a_tx_data_ht, a_tx_hash, sizeof(*a_tx_hash), l_tx_data); + if (l_tx_data) // this tx already present in ledger (double) + l_declined = true; + else { + l_tx_data = DAP_NEW_Z(dap_chain_tx_hash_processed_ht_t); + l_tx_data->hash = *a_tx_hash; + HASH_ADD(hh, a_tx_data_ht, hash, sizeof(*a_tx_hash), l_tx_data); + const char *l_token_ticker = dap_chain_ledger_tx_get_token_ticker_by_hash(a_ledger, a_tx_hash); + if (!l_token_ticker) + l_declined = true; + } + char *l_tx_hash_str, *l_atom_hash_str; + if (!dap_strcmp(a_hash_out_type, "hex")) { + l_tx_hash_str = dap_chain_hash_fast_to_str_new(a_tx_hash); + l_atom_hash_str = dap_chain_hash_fast_to_str_new(a_atom_iter->cur_hash); + } else { + l_tx_hash_str = dap_enc_base58_encode_hash_to_str(a_tx_hash); + l_atom_hash_str = dap_enc_base58_encode_hash_to_str(a_atom_iter->cur_hash); + } + dap_string_append_printf(a_str_out, "%s TX hash %s (atom %s) \n\t%s", l_declined ? "DECLINED" : "ACCEPTED", + l_tx_hash_str, l_atom_hash_str, l_time_str); + DAP_DELETE(l_tx_hash_str); + DAP_DELETE(l_atom_hash_str); +} /** * @brief dap_db_history_addr @@ -393,12 +430,10 @@ char* dap_db_history_tx(dap_chain_hash_fast_t* a_tx_hash, dap_chain_t * a_chain, * @param a_hash_out_type * @return char* */ -char* dap_db_history_addr(dap_chain_addr_t * a_addr, dap_chain_t * a_chain, const char *a_hash_out_type) +char* dap_db_history_addr(dap_chain_addr_t *a_addr, dap_chain_t *a_chain, const char *a_hash_out_type) { - char l_time_str[32] = {0}; dap_string_t *l_str_out = dap_string_new(NULL); - - dap_tx_data_t *l_tx_data_hash = NULL; + dap_chain_tx_hash_processed_ht_t *l_tx_data_ht = NULL; // load transactions dap_chain_atom_iter_t *l_atom_iter = a_chain->callback_atom_iter_create(a_chain, a_chain->cells->id, 0); size_t l_atom_size=0; @@ -406,129 +441,144 @@ char* dap_db_history_addr(dap_chain_addr_t * a_addr, dap_chain_t * a_chain, cons if (!l_atom) { return NULL; } + if (!a_chain->callback_atom_get_datums) { + log_it(L_WARNING, "Not defined callback_atom_get_datums for chain \"%s\"", a_chain->name); + return NULL; + } + dap_ledger_t *l_ledger = dap_chain_net_by_id(a_chain->net_id)->pub.ledger; while (l_atom && l_atom_size) { size_t l_datums_count = 0; - dap_chain_datum_t **l_datums = a_chain->callback_atom_get_datums ? a_chain->callback_atom_get_datums(l_atom, l_atom_size, &l_datums_count) : - NULL; - if (!l_datums) { - log_it(L_WARNING, "Not defined callback_atom_get_datums for chain \"%s\"", a_chain->name); - break; - } - + dap_chain_datum_t **l_datums = a_chain->callback_atom_get_datums(l_atom, l_atom_size, &l_datums_count); for (size_t d = 0; d < l_datums_count; d++) { - dap_chain_datum_t *l_datum = l_datums && l_datums_count ? l_datums[d] : NULL; + dap_chain_datum_t *l_datum = l_datums ? l_datums[d] : NULL; if (!l_datum || l_datum->header.type_id != DAP_CHAIN_DATUM_TX) { - // go to next transaction + // go to next datum continue; } - dap_tx_data_t *l_tx_data = DAP_NEW_Z(dap_tx_data_t); - // transaction + // it's a transaction + dap_hash_fast_t l_tx_hash; dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t *)l_datum->data; - - // find Token items - present in base transaction - dap_list_t *l_list_tx_token = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_TOKEN, NULL); - // save token name - if (l_list_tx_token) { - strcpy(l_tx_data->token_ticker, - ((dap_chain_tx_token_t *)l_list_tx_token->data)->header.ticker); - dap_list_free(l_list_tx_token); - } - - dap_list_t *l_list_in_items = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_IN, NULL); - if (!l_list_in_items) { // a bad tx - DAP_DELETE(l_tx_data); + dap_list_t *l_list_in_items = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_IN_ALL, NULL); + if (!l_list_in_items) { // a bad tx continue; } // all in items should be from the same address - dap_chain_tx_in_t *l_tx_in = (dap_chain_tx_in_t *)l_list_in_items->data; - dap_chain_hash_fast_t *l_tx_prev_hash = &l_tx_in->header.tx_prev_hash; dap_chain_addr_t *l_src_addr = NULL; - char *l_src_addr_str = NULL; - if (!dap_hash_fast_is_blank(l_tx_prev_hash)) { - dap_tx_data_t *l_tx_data_prev = NULL; - HASH_FIND(hh, l_tx_data_hash, l_tx_prev_hash, sizeof(dap_chain_hash_fast_t), l_tx_data_prev); - if (!l_tx_data_prev) { // prev tx not found - no info for history - dap_list_free(l_list_in_items); - DAP_DELETE(l_tx_data); - continue; + bool l_base_tx = false; + const char *l_src_token = NULL; + int l_src_subtype = DAP_CHAIN_TX_OUT_COND_SUBTYPE_UNDEFINED; + for (dap_list_t *it = l_list_in_items; it; it = it->next) { + dap_chain_hash_fast_t *l_tx_prev_hash; + int l_tx_prev_out_idx; + dap_chain_datum_tx_t *l_tx_prev = NULL; + if (*(byte_t *)l_list_in_items->data == TX_ITEM_TYPE_IN) { + dap_chain_tx_in_t *l_tx_in = (dap_chain_tx_in_t *)l_list_in_items->data; + l_tx_prev_hash = &l_tx_in->header.tx_prev_hash; + l_tx_prev_out_idx = l_tx_in->header.tx_out_prev_idx; + } else { // TX_ITEM_TYPE_IN_COND + dap_chain_tx_in_cond_t *l_tx_in_cond = (dap_chain_tx_in_cond_t *)l_list_in_items->data; + l_tx_prev_hash = &l_tx_in_cond->header.tx_prev_hash; + l_tx_prev_out_idx = l_tx_in_cond->header.tx_out_prev_idx; } - - strncpy(l_tx_data->token_ticker, l_tx_data_prev->token_ticker, DAP_CHAIN_TICKER_SIZE_MAX); - - dap_chain_datum_tx_t *l_tx_prev; - dap_list_t *l_list_prev_out_items = NULL, *l_list_out_prev_item; - - if ( (l_tx_prev = (dap_chain_datum_tx_t *)l_tx_data_prev->datum->data) ) - if ( (l_list_prev_out_items = dap_chain_datum_tx_items_get(l_tx_prev, TX_ITEM_TYPE_OUT, NULL)) ) - if ( (l_list_out_prev_item = dap_list_nth(l_list_prev_out_items, l_tx_in->header.tx_out_prev_idx)) ) - { - l_src_addr = &((dap_chain_tx_out_t *)l_list_out_prev_item->data)->addr; - l_src_addr_str = dap_chain_addr_to_str(l_src_addr); - } - - dap_list_free(l_list_prev_out_items); + if (dap_hash_fast_is_blank(l_tx_prev_hash)) { + l_base_tx = true; + dap_chain_tx_token_t *l_token = (dap_chain_tx_token_t *)dap_chain_datum_tx_item_get( + l_tx, NULL, TX_ITEM_TYPE_TOKEN, NULL); + if (l_token) + l_src_token = l_token->header.ticker; + break; + } + l_tx_prev = a_chain->callback_tx_find_by_hash(a_chain, l_tx_prev_hash); + if (l_tx_prev) { + uint8_t *l_prev_out_union = dap_chain_datum_tx_item_get_nth(l_tx_prev, TX_ITEM_TYPE_OUT_ALL, l_tx_prev_out_idx); + if (!l_prev_out_union) + continue; + switch (*l_prev_out_union) { + case TX_ITEM_TYPE_OUT: + l_src_addr = &((dap_chain_tx_out_t *)l_prev_out_union)->addr; + break; + case TX_ITEM_TYPE_OUT_EXT: + l_src_addr = &((dap_chain_tx_out_ext_t *)l_prev_out_union)->addr; + l_src_token = (const char *)(((dap_chain_tx_out_ext_t *)l_prev_out_union)->token); + break; + case TX_ITEM_TYPE_OUT_COND: + l_src_subtype = ((dap_chain_tx_out_cond_t *)l_prev_out_union)->header.subtype; + default: + break; + } + } + if (!l_src_token) + l_src_token = dap_chain_ledger_tx_get_token_ticker_by_hash(l_ledger, l_tx_prev_hash); + if (l_src_addr && memcmp(l_src_addr, a_addr, sizeof(dap_chain_addr_t))) + break; //it's not our addr } dap_list_free(l_list_in_items); - dap_hash_fast(l_tx, dap_chain_datum_tx_get_size(l_tx), &l_tx_data->tx_hash); - - // transaction time - l_time_str[0] = ' ', l_time_str[1] = '\0'; /* Prefill string with the space */ - - if ( l_tx->header.ts_created) { - uint64_t l_ts = l_tx->header.ts_created; - dap_ctime_r(&l_ts, l_time_str); /* Convert ts to Sat May 17 01:17:08 2014 */ - } - - char *l_tx_hash_str; - if (!dap_strcmp(a_hash_out_type, "hex")) - l_tx_hash_str = dap_hash_fast_to_str_new(&l_tx_data->tx_hash); - else - l_tx_hash_str = dap_enc_base58_encode_to_str(&l_tx_data->tx_hash_str, sizeof(dap_chain_hash_fast_t)); - // find OUT items bool l_header_printed = false; - dap_list_t *l_list_out_items = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_OUT, NULL); + dap_list_t *l_list_out_items = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_OUT_ALL, NULL); for (dap_list_t *l_list_out = l_list_out_items; l_list_out; l_list_out = dap_list_next(l_list_out)) { - dap_chain_tx_out_t *l_tx_out = (dap_chain_tx_out_t *)l_list_out->data; - if (l_src_addr && !memcmp(&l_tx_out->addr, l_src_addr, sizeof(dap_chain_addr_t))) + dap_chain_addr_t *l_dst_addr = NULL; + uint8_t l_type = *(uint8_t *)l_list_out->data; + uint256_t l_value; + switch (l_type) { + case TX_ITEM_TYPE_OUT: + l_dst_addr = &((dap_chain_tx_out_t *)l_list_out->data)->addr; + l_value = ((dap_chain_tx_out_t *)l_list_out->data)->header.value; + break; + case TX_ITEM_TYPE_OUT_EXT: + l_dst_addr = &((dap_chain_tx_out_ext_t *)l_list_out->data)->addr; + l_value = ((dap_chain_tx_out_ext_t *)l_list_out->data)->header.value; + break; + case TX_ITEM_TYPE_OUT_COND: + l_value = ((dap_chain_tx_out_cond_t *)l_list_out->data)->header.value; + default: + break; + } + if (l_src_addr && l_dst_addr && !memcmp(l_dst_addr, l_src_addr, sizeof(dap_chain_addr_t))) continue; // send to self if (l_src_addr && !memcmp(l_src_addr, a_addr, sizeof(dap_chain_addr_t))) { if (!l_header_printed) { - dap_string_append_printf(l_str_out, "TX hash %s\n\t%s", l_tx_hash_str, l_time_str); + s_tx_header_print(l_str_out, l_tx_data_ht, l_tx, l_atom_iter, a_hash_out_type, l_ledger, &l_tx_hash); l_header_printed = true; } - char *l_dst_addr_str = dap_chain_addr_to_str(&l_tx_out->addr); - char *l_value_str = dap_chain_balance_print(l_tx_out->header.value); + //const char *l_token_ticker = dap_chain_ledger_tx_get_token_ticker_by_hash(l_ledger, &l_tx_hash); + const char *l_dst_addr_str = l_dst_addr ? dap_chain_addr_to_str(l_dst_addr) + : dap_chain_tx_out_cond_subtype_to_str( + ((dap_chain_tx_out_cond_t *)l_list_out->data)->header.subtype); + char *l_value_str = dap_chain_balance_print(l_value); dap_string_append_printf(l_str_out, "\tsend %s %s to %s\n", l_value_str, - l_tx_data->token_ticker, + l_src_token ? l_src_token : "UNKNOWN", l_dst_addr_str); - DAP_DELETE(l_dst_addr_str); + if (l_dst_addr) + DAP_DELETE(l_dst_addr_str); DAP_DELETE(l_value_str); } - if (!memcmp(&l_tx_out->addr, a_addr, sizeof(dap_chain_addr_t))) { + if (l_dst_addr && !memcmp(l_dst_addr, a_addr, sizeof(dap_chain_addr_t))) { if (!l_header_printed) { - dap_string_append_printf(l_str_out, "TX hash %s\n\t%s", l_tx_hash_str, l_time_str); + s_tx_header_print(l_str_out, l_tx_data_ht, l_tx, l_atom_iter, a_hash_out_type, l_ledger, &l_tx_hash); l_header_printed = true; } - char *l_value_str = dap_chain_balance_print(l_tx_out->header.value); + const char *l_dst_token = (l_type == TX_ITEM_TYPE_OUT_EXT) ? + (const char *)(((dap_chain_tx_out_ext_t *)l_list_out->data)->token) : NULL; + const char *l_src_addr_str = l_base_tx ? "emission" + : (l_src_addr ? dap_chain_addr_to_str(l_src_addr) + : dap_chain_tx_out_cond_subtype_to_str( + l_src_subtype)); + char *l_value_str = dap_chain_balance_print(l_value); dap_string_append_printf(l_str_out, "\trecv %s %s from %s\n", l_value_str, - l_tx_data->token_ticker, - l_src_addr ? l_src_addr_str : "emission"); + l_dst_token ? l_dst_token : + (l_src_token ? l_src_token : "UNKNOWN"), + l_src_addr_str); + if (l_src_addr) + DAP_DELETE(l_src_addr_str); DAP_DELETE(l_value_str); } } dap_list_free(l_list_out_items); - DAP_DELETE(l_src_addr_str); - DAP_DELETE(l_tx_hash_str); - - size_t l_datum_size = dap_chain_datum_tx_get_size(l_tx) + sizeof(dap_chain_datum_t); - l_tx_data->datum = DAP_NEW_SIZE(dap_chain_datum_t, l_datum_size); - memcpy(l_tx_data->datum, l_datum, l_datum_size); // for GDB chains with data replace with each itreation - HASH_ADD(hh, l_tx_data_hash, tx_hash, sizeof(dap_chain_hash_fast_t), l_tx_data); } DAP_DELETE(l_datums); // go to next atom (event or block) @@ -536,13 +586,7 @@ char* dap_db_history_addr(dap_chain_addr_t * a_addr, dap_chain_t * a_chain, cons } // delete hashes - dap_tx_data_t *l_iter_current, *l_item_tmp; - HASH_ITER(hh, l_tx_data_hash , l_iter_current, l_item_tmp) { - HASH_DEL(l_tx_data_hash, l_iter_current); - // delete struct - DAP_DELETE(l_iter_current->datum); - DAP_DELETE(l_iter_current); - } + s_dap_chain_tx_hash_processed_ht_free(l_tx_data_ht); // if no history if(!l_str_out->len) dap_string_append(l_str_out, "\tempty"); @@ -561,6 +605,10 @@ char* dap_db_history_addr(dap_chain_addr_t * a_addr, dap_chain_t * a_chain, cons */ static char* dap_db_history_token_list(dap_chain_t * a_chain, const char *a_token_name, const char *a_hash_out_type, size_t *a_token_num) { + if (!a_chain->callback_atom_get_datums) { + log_it(L_WARNING, "Not defined callback_atom_get_datums for chain \"%s\"", a_chain->name); + return NULL; + } dap_string_t *l_str_out = dap_string_new(NULL); *a_token_num = 0; size_t l_atom_size = 0; @@ -572,7 +620,7 @@ static char* dap_db_history_token_list(dap_chain_t * a_chain, const char *a_toke return NULL ; } for (dap_chain_atom_ptr_t l_atom = a_chain->callback_atom_iter_get_first(l_atom_iter, &l_atom_size); - l_atom && l_atom_size; l_atom = a_chain->callback_atom_iter_get_next(l_atom_iter, &l_atom_size)) { + l_atom && l_atom_size; l_atom = a_chain->callback_atom_iter_get_next(l_atom_iter, &l_atom_size)) { size_t l_datums_count = 0; dap_chain_datum_t **l_datums = a_chain->callback_atom_get_datums(l_atom, l_atom_size, &l_datums_count); for(size_t l_datum_n = 0; l_datum_n < l_datums_count; l_datum_n++) { @@ -612,6 +660,10 @@ static char* dap_db_history_token_list(dap_chain_t * a_chain, const char *a_toke */ static char* dap_db_history_filter(dap_chain_t * a_chain, dap_ledger_t *a_ledger, const char *a_filter_token_name, const char *a_filtr_addr_base58, const char *a_hash_out_type, long a_datum_start, long a_datum_end, long *a_total_datums, dap_chain_tx_hash_processed_ht_t *a_tx_hash_processed) { + if (!a_chain->callback_atom_get_datums) { + log_it(L_WARNING, "Not defined callback_atom_get_datums for chain \"%s\"", a_chain->name); + return NULL; + } dap_string_t *l_str_out = dap_string_new(NULL); // list all transactions dap_tx_data_t *l_tx_data_hash = NULL; @@ -620,36 +672,28 @@ static char* dap_db_history_filter(dap_chain_t * a_chain, dap_ledger_t *a_ledger // load transactions size_t l_atom_size = 0; dap_chain_atom_iter_t *l_atom_iter = a_chain->callback_atom_iter_create(a_chain, l_cell->id, 0); - dap_chain_atom_ptr_t l_atom = a_chain->callback_atom_iter_get_first(l_atom_iter, &l_atom_size); size_t l_datum_num = 0, l_token_num = 0, l_emission_num = 0, l_tx_num = 0; size_t l_datum_num_global = a_total_datums ? *a_total_datums : 0; - while(l_atom && l_atom_size) { + for (dap_chain_atom_ptr_t l_atom = a_chain->callback_atom_iter_get_first(l_atom_iter, &l_atom_size); + l_atom && l_atom_size; l_atom = a_chain->callback_atom_iter_get_next(l_atom_iter, &l_atom_size)) { size_t l_datums_count = 0; - dap_chain_datum_t **l_datums = - (a_chain->callback_atom_get_datums && l_atom && l_atom_size) ? - a_chain->callback_atom_get_datums(l_atom, l_atom_size, &l_datums_count) : NULL; - if(!l_datums) { - log_it(L_WARNING, "Not defined callback_atom_get_datums for chain \"%s\"", a_chain->name); - return NULL ; - } + dap_chain_datum_t **l_datums = a_chain->callback_atom_get_datums(l_atom, l_atom_size, &l_datums_count); + if (!l_datums || !l_datums_count) + continue; for(size_t l_datum_n = 0; l_datum_n < l_datums_count; l_datum_n++) { dap_chain_datum_t *l_datum = l_datums[l_datum_n]; - if(!l_datum) { // || l_datum->header.type_id != DAP_CHAIN_DATUM_TX) { + if(!l_datum) continue; - } - char l_time_str[70]; - // get time of create datum - if(dap_time_to_str_rfc822(l_time_str, 71, l_datum->header.ts_create) < 1) - l_time_str[0] = '\0'; - switch (l_datum->header.type_id) { - + char l_time_str[70]; + // get time of create datum + if(dap_time_to_str_rfc822(l_time_str, 71, l_datum->header.ts_create) < 1) + l_time_str[0] = '\0'; + switch (l_datum->header.type_id) { // token case DAP_CHAIN_DATUM_TOKEN_DECL: { // no token necessary for addr - if(a_filtr_addr_base58) { - break; - } - + if(a_filtr_addr_base58) + break; dap_chain_datum_token_t *l_token = (dap_chain_datum_token_t*) l_datum->data; //if(a_datum_start < 0 || (l_datum_num >= a_datum_start && l_datum_num < a_datum_end)) // datum out of page @@ -708,16 +752,14 @@ static char* dap_db_history_filter(dap_chain_t * a_chain, dap_ledger_t *a_ledger l_tx_num++; } break; - default: - dap_string_append_printf(l_str_out, "unknown datum type=%d\n", l_datum->header.type_id); - break; + default: { + const char *l_type_str; + DAP_DATUM_TYPE_STR(l_datum->header.type_id, l_type_str); + dap_string_append_printf(l_str_out, "datum type %s\n", l_type_str); + } break; } l_datum_num++; } - // go to next transaction - l_atom = a_chain->callback_atom_iter_get_next(l_atom_iter, &l_atom_size); - //l_atom = a_chain->callback_atom_iter_get_next(l_atom_iter); - //l_atom_size = a_chain->callback_atom_get_size(l_atom); } a_chain->callback_atom_iter_delete(l_atom_iter); //total @@ -866,15 +908,14 @@ int com_ledger(int a_argc, char ** a_argv, char **a_str_reply) } dap_string_t *l_str_ret = dap_string_new(NULL); //char *l_str_ret = NULL; dap_chain_t *l_chain_cur; - void *l_chain_tmp = (void*)0x1; int l_num = 0; // only one chain - if(l_chain) + if (l_chain) l_chain_cur = l_chain; // all chain else - l_chain_cur = dap_chain_enum(&l_chain_tmp); - while(l_chain_cur) { + l_chain_cur = l_net->pub.chains; + while (l_chain_cur) { // only selected net if(l_net->pub.id.uint64 == l_chain_cur->net_id.uint64) { // separator between chains @@ -910,11 +951,10 @@ int com_ledger(int a_argc, char ** a_argv, char **a_str_reply) // only one chain use if(l_chain) break; - dap_chain_enum_unlock(); - l_chain_cur = dap_chain_enum(&l_chain_tmp); + l_chain_cur = l_chain_cur->next; } DAP_DELETE(l_addr); - _dap_chain_tx_hash_processed_ht_free(l_list_tx_hash_processd); + s_dap_chain_tx_hash_processed_ht_free(l_list_tx_hash_processd); // all chain if(!l_chain) dap_chain_enum_unlock(); @@ -1218,7 +1258,7 @@ int com_token(int a_argc, char ** a_argv, char **a_str_reply) l_chain_cur = dap_chain_enum(&l_chain_tmp); } dap_chain_enum_unlock(); - _dap_chain_tx_hash_processed_ht_free(l_list_tx_hash_processd); + s_dap_chain_tx_hash_processed_ht_free(l_list_tx_hash_processd); dap_cli_server_cmd_set_reply_text(a_str_reply, l_str_out->str); dap_string_free(l_str_out, true); return 0; diff --git a/modules/net/dap_chain_node_client.c b/modules/net/dap_chain_node_client.c index 056da9cba38412bfe56a29478016856fe4a7e92d..74acc571aa544b61af1353f8141034d468bd56a4 100644 --- a/modules/net/dap_chain_node_client.c +++ b/modules/net/dap_chain_node_client.c @@ -136,6 +136,31 @@ static void s_stage_status_callback(dap_client_t *a_client, void *a_arg) //printf("* stage_status_callback client=%x data=%x\n", a_client, a_arg); } +static bool s_timer_node_reconnect(void *a_arg) +{ + dap_events_socket_uuid_t *l_uuid = (dap_events_socket_uuid_t *)a_arg; + assert(l_uuid); + dap_chain_node_client_handle_t *l_client_found = NULL; + HASH_FIND(hh, s_clients, l_uuid, sizeof(*l_uuid), l_client_found); + if(l_client_found) { + dap_chain_node_client_t *l_me = l_client_found->client; + if (l_me->keep_connection && l_me->state == NODE_CLIENT_STATE_DISCONNECTED) { + if (dap_client_pvt_find(l_me->client->pvt_uuid)) { + if (dap_client_get_stage(l_me->client) == STAGE_BEGIN) { + log_it(L_INFO, "Reconnecting node client with peer "NODE_ADDR_FP_STR, NODE_ADDR_FP_ARGS_S(l_me->remote_node_addr)); + l_me->state = NODE_CLIENT_STATE_CONNECTING ; + dap_client_go_stage(l_me->client, STAGE_STREAM_STREAMING, s_stage_connected_callback); + } else { + dap_chain_node_client_close(*l_uuid); + } + } else + dap_chain_node_client_close(*l_uuid); + } + } + DAP_DELETE(l_uuid); + return false; +} + /** * @brief s_stage_status_error_callback * @param a_client @@ -167,20 +192,13 @@ static void s_stage_status_error_callback(dap_client_t *a_client, void *a_arg) l_node_client->callbacks.disconnected(l_node_client, l_node_client->callbacks_arg); } if (l_node_client->keep_connection) { - dap_events_socket_uuid_t *l_uuid = DAP_DUP(&l_node_client->uuid); - if(l_node_client->stream_worker){ - l_node_client->sync_timer = dap_timerfd_start_on_worker( l_node_client->stream_worker->worker - , s_timer_update_states * 1000, - s_timer_update_states_callback, - l_uuid); - }else{ - log_it(L_ERROR,"After NODE_CLIENT_STATE_DISCONNECTED: Node client has no worker, too dangerous to run update states in alien context"); - } - } - return; - } - // TODO make different error codes - if(l_node_client->callbacks.error) + if (dap_client_get_stage(l_node_client->client) != STAGE_BEGIN) + dap_client_go_stage(l_node_client->client, STAGE_BEGIN, NULL); + dap_timerfd_start(45 * 1000, s_timer_node_reconnect, DAP_DUP(&l_node_client->uuid)); + } else + dap_chain_node_client_close(l_node_client->uuid); + + } else if(l_node_client->callbacks.error) // TODO make different error codes l_node_client->callbacks.error(l_node_client, EINVAL, l_node_client->callbacks_arg); } @@ -284,19 +302,18 @@ static bool s_timer_update_states_callback(void *a_arg) dap_client_go_stage(l_me->client, STAGE_BEGIN, NULL); return true; } - if (l_me->callbacks.disconnected) { + if (l_me->is_connected && l_me->callbacks.disconnected) l_me->callbacks.disconnected(l_me, l_me->callbacks_arg); - } if (l_me->keep_connection) { log_it(L_INFO, "Reconnecting node client with peer "NODE_ADDR_FP_STR, NODE_ADDR_FP_ARGS_S(l_me->remote_node_addr)); l_me->state = NODE_CLIENT_STATE_CONNECTING ; dap_client_go_stage(l_me->client, STAGE_STREAM_STREAMING, s_stage_connected_callback); return true; } else { - dap_chain_node_client_close(l_me); + dap_chain_node_client_close(*l_uuid); } } else - dap_chain_node_client_close(l_me); + dap_chain_node_client_close(*l_uuid); } } DAP_DELETE(l_uuid); @@ -582,7 +599,7 @@ static void s_ch_chain_callback_notify_packet_out(dap_stream_ch_chain_t* a_ch_ch } } break; case DAP_STREAM_CH_CHAIN_PKT_TYPE_DELETE: { - dap_chain_node_client_close(l_node_client); + dap_chain_node_client_close(l_node_client->uuid); } break; default: { } @@ -813,7 +830,7 @@ static bool dap_chain_node_client_connect_internal(dap_chain_node_client_t *a_no } // address not defined if(!strcmp(host, "::")) { - dap_chain_node_client_close(a_node_client); + dap_chain_node_client_close(a_node_client->uuid); return false; } dap_client_set_uplink_unsafe(a_node_client->client, host, a_node_client->info->hdr.ext_port); @@ -848,62 +865,64 @@ void dap_chain_node_client_reset(dap_chain_node_client_t *a_client) } } +dap_chain_node_client_t *dap_chain_node_client_find(dap_events_socket_uuid_t a_uuid) +{ + dap_chain_node_client_handle_t * l_client_found = NULL; + HASH_FIND(hh,s_clients, &a_uuid, sizeof(a_uuid), l_client_found); + return l_client_found ? l_client_found->client : NULL; +} /** * @brief dap_chain_node_client_close * Close connection to server, delete chain_node_client_t *client * @param a_client dap_chain_node_client_t */ -void dap_chain_node_client_close(dap_chain_node_client_t *a_client) +void dap_chain_node_client_close(dap_events_socket_uuid_t a_uuid) { - if (!a_client) - return; dap_chain_node_client_handle_t * l_client_found = NULL; - HASH_FIND(hh,s_clients,&a_client->uuid,sizeof(a_client->uuid),l_client_found); + HASH_FIND(hh, s_clients, &a_uuid, sizeof(a_uuid), l_client_found); if (l_client_found) { - - if (l_client_found->client->sync_timer) { - // Free memory callback_arg=uuid - DAP_DELETE(l_client_found->client->sync_timer->callback_arg); - dap_timerfd_delete(l_client_found->client->sync_timer); + dap_chain_node_client_t *l_client = l_client_found->client; + if (l_client->sync_timer) { + DAP_DELETE(l_client->sync_timer->callback_arg); + dap_timerfd_delete(l_client->sync_timer); } - HASH_DEL(s_clients,l_client_found); DAP_DELETE(l_client_found); - if (a_client->callbacks.delete) - a_client->callbacks.delete(a_client, a_client->net); + if (l_client->callbacks.delete) + l_client->callbacks.delete(l_client, l_client->net); char l_node_addr_str[INET_ADDRSTRLEN] = {}; - inet_ntop(AF_INET, &a_client->info->hdr.ext_addr_v4, l_node_addr_str, INET_ADDRSTRLEN); - log_it(L_INFO, "Closing node client to uplink %s:%d", l_node_addr_str, a_client->info->hdr.ext_port); - if (a_client->stream_worker) { - dap_stream_ch_t *l_ch = dap_stream_ch_find_by_uuid_unsafe(a_client->stream_worker, a_client->ch_chain_uuid); + inet_ntop(AF_INET, &l_client->info->hdr.ext_addr_v4, l_node_addr_str, INET_ADDRSTRLEN); + log_it(L_INFO, "Closing node client to uplink %s:%d", l_node_addr_str, l_client->info->hdr.ext_port); + if (l_client->stream_worker) { + dap_stream_ch_t *l_ch = dap_stream_ch_find_by_uuid_unsafe(l_client->stream_worker, l_client->ch_chain_uuid); if (l_ch) { dap_stream_ch_chain_t *l_ch_chain = DAP_STREAM_CH_CHAIN(l_ch); l_ch_chain->callback_notify_packet_in = NULL; l_ch_chain->callback_notify_packet_out = NULL; } - l_ch = dap_stream_ch_find_by_uuid_unsafe(a_client->stream_worker, a_client->ch_chain_net_uuid); + l_ch = dap_stream_ch_find_by_uuid_unsafe(l_client->stream_worker, l_client->ch_chain_net_uuid); if (l_ch) { dap_stream_ch_chain_net_t *l_ch_chain_net = DAP_STREAM_CH_CHAIN_NET(l_ch); l_ch_chain_net->notify_callback = NULL; } } // clean client - dap_client_pvt_t *l_client_pvt = dap_client_pvt_find(a_client->client->pvt_uuid); + dap_client_pvt_t *l_client_pvt = dap_client_pvt_find(l_client->client->pvt_uuid); if (l_client_pvt) { - dap_client_delete_mt(a_client->client); - a_client->client->_inheritor = NULL; + dap_client_delete_mt(l_client->client); + l_client->client->_inheritor = NULL; } #ifndef _WIN32 - pthread_cond_destroy(&a_client->wait_cond); + pthread_cond_destroy(&l_client->wait_cond); #else - CloseHandle( a_client->wait_cond ); + CloseHandle( l_client->wait_cond ); #endif - pthread_mutex_destroy(&a_client->wait_mutex); - a_client->client = NULL; - if (a_client->info) - DAP_DELETE(a_client->info); - DAP_DELETE(a_client); + pthread_mutex_destroy(&l_client->wait_mutex); + l_client->client = NULL; + if (l_client->info) + DAP_DELETE(l_client->info); + DAP_DELETE(l_client); } else { log_it(L_WARNING, "Chain node client was removed from hash table before for some reasons"); } diff --git a/modules/net/dap_chain_node_remote.c b/modules/net/dap_chain_node_remote.c deleted file mode 100644 index cabf4dd34e4b5e07bcf67b93169b5a38f6a54636..0000000000000000000000000000000000000000 --- a/modules/net/dap_chain_node_remote.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Authors: - * Dmitriy A. Gearasimov <naeper@demlabs.net> - * DeM Labs Inc. https://demlabs.net - - 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 <stdio.h> -#include <time.h> -#include <stdlib.h> -#include <stddef.h> -#include <stdint.h> -#include <pthread.h> - -#ifdef WIN32 -#include <winsock2.h> -#include <windows.h> -#include <mswsock.h> -#include <ws2tcpip.h> -#include <io.h> -#endif - -#include "uthash.h" -#include "dap_common.h" -#include "dap_chain_node_remote.h" - -typedef struct dap_chain_node_link_item { - dap_chain_node_addr_t address; - dap_chain_node_client_t *client; - UT_hash_handle hh; -} dap_chain_node_link_item_t; - -// List of connections -static dap_chain_node_link_item_t *conn_list = NULL; - -// for separate access to connect_list -static pthread_mutex_t connect_list_mutex = PTHREAD_MUTEX_INITIALIZER; - - -/** - * Add new established connection to the list - * - * return 0 OK, -1 error, -2 already present - */ -int dap_chain_node_client_list_add(dap_chain_node_addr_t *a_address, dap_chain_node_client_t *a_client) -{ - int l_ret = 0; - if(!a_address || !a_client) - return -1; - dap_chain_node_link_item_t *item_tmp = NULL; - pthread_mutex_lock(&connect_list_mutex); - HASH_FIND(hh, conn_list, a_address, sizeof(dap_chain_node_addr_t), item_tmp); // address already in the hash? - if(item_tmp == NULL) { - item_tmp = DAP_NEW(dap_chain_node_link_item_t); - item_tmp->address.uint64 = a_address->uint64; - item_tmp->client = a_client; - HASH_ADD(hh, conn_list, address, sizeof(dap_chain_node_addr_t), item_tmp); // address: name of key field - l_ret = 0; - } - // connection already present - else - l_ret = -2; - //connect_list = g_list_append(connect_list, client); - pthread_mutex_unlock(&connect_list_mutex); - return l_ret; -} - -/** - * Delete established connection from the list - * - * return 0 OK, -1 error, -2 address not found - */ -int chain_node_client_list_del(dap_chain_node_addr_t *address) -{ - int ret = -1; - if(!address) - return -1; - dap_chain_node_link_item_t *item_tmp; - pthread_mutex_lock(&connect_list_mutex); - HASH_FIND(hh, conn_list, address, sizeof(dap_chain_node_addr_t), item_tmp); - if(item_tmp != NULL) { - HASH_DEL(conn_list, item_tmp); - ret = 0; - } - else - // address not found in the hash - ret = -2; - pthread_mutex_unlock(&connect_list_mutex); - if(!ret) { - // close connection - dap_chain_node_client_close(item_tmp->client); - // del struct for hash - DAP_DELETE(item_tmp); - } - return ret; -} - -/** - * Delete all established connection from the list - */ -void chain_node_client_list_del_all(void) -{ - int ret = -1; - dap_chain_node_link_item_t *iter_current, *item_tmp; - pthread_mutex_lock(&connect_list_mutex); - HASH_ITER(hh, conn_list , iter_current, item_tmp) { - // close connection - dap_chain_node_client_close(iter_current->client); - // del struct for hash - HASH_DEL(conn_list, iter_current); - } - pthread_mutex_unlock(&connect_list_mutex); -} - -/** - * Get present established connection by address - * - * return client, or NULL if the connection not found in the list - */ -const dap_chain_node_client_t* chain_node_client_find(dap_chain_node_addr_t *address) -{ - int ret = 0; - if(!address) - return NULL; - dap_chain_node_client_t *client_ret = NULL; - dap_chain_node_link_item_t *item_tmp; - pthread_mutex_lock(&connect_list_mutex); - HASH_FIND(hh, conn_list, address, sizeof(dap_chain_node_addr_t), item_tmp); // address already in the hash? - if(item_tmp != NULL) { - client_ret = item_tmp->client; - } - pthread_mutex_unlock(&connect_list_mutex); - return client_ret; -} diff --git a/modules/net/include/dap_chain_net.h b/modules/net/include/dap_chain_net.h index 5dee1800032bb6a3f0c21ba8b11df3e2316b63cd..a1fd95757fcc9999c582f5de3964fdeb9074352b 100644 --- a/modules/net/include/dap_chain_net.h +++ b/modules/net/include/dap_chain_net.h @@ -81,12 +81,14 @@ typedef struct dap_chain_net{ bool mempool_autoproc; dap_chain_t * chains; // double-linked list of chains - dap_chain_t * default_chain; + const char *native_ticker; dap_ledger_t *ledger; } pub; uint8_t pvt[]; } dap_chain_net_t; +typedef bool (dap_chain_datum_filter_func_t)(dap_chain_datum_t *a_datum, dap_chain_t * a_chain, void *a_filter_func_param); + int dap_chain_net_init(void); void dap_chain_net_deinit(void); @@ -94,15 +96,24 @@ void dap_chain_net_load_all(); int dap_chain_net_state_go_to(dap_chain_net_t * a_net, dap_chain_net_state_t a_new_state); dap_chain_net_state_t dap_chain_net_get_target_state(dap_chain_net_t *a_net); +void dap_chain_net_set_state ( dap_chain_net_t * l_net, dap_chain_net_state_t a_state); +dap_chain_net_state_t dap_chain_net_get_state ( dap_chain_net_t * l_net); inline static int dap_chain_net_start(dap_chain_net_t * a_net){ return dap_chain_net_state_go_to(a_net,NET_STATE_ONLINE); } -inline static int dap_chain_net_stop(dap_chain_net_t * a_net) { return dap_chain_net_state_go_to(a_net,NET_STATE_OFFLINE); } +inline static int dap_chain_net_stop(dap_chain_net_t *a_net) +{ + if (dap_chain_net_get_target_state(a_net) == NET_STATE_ONLINE) { + dap_chain_net_state_go_to(a_net, NET_STATE_OFFLINE); + return true; + } + if (dap_chain_net_get_state(a_net) != NET_STATE_OFFLINE) + dap_chain_net_state_go_to(a_net, NET_STATE_OFFLINE); + return false; +} inline static int dap_chain_net_links_establish(dap_chain_net_t * a_net) { return dap_chain_net_state_go_to(a_net,NET_STATE_LINKS_ESTABLISHED); } inline static int dap_chain_net_sync_gdb(dap_chain_net_t * a_net) { return dap_chain_net_state_go_to(a_net,NET_STATE_SYNC_GDB); } inline static int dap_chain_net_sync_chains(dap_chain_net_t * a_net) { return dap_chain_net_state_go_to(a_net,NET_STATE_SYNC_CHAINS); } inline static int dap_chain_net_sync_all(dap_chain_net_t * a_net) { return dap_chain_net_state_go_to(a_net,NET_STATE_SYNC_CHAINS); } -void dap_chain_net_set_state ( dap_chain_net_t * l_net, dap_chain_net_state_t a_state); -dap_chain_net_state_t dap_chain_net_get_state ( dap_chain_net_t * l_net); /** * @brief dap_chain_net_state_to_str @@ -127,7 +138,7 @@ bool dap_chain_net_sync_trylock_nolock(dap_chain_net_t* a_net, dap_chain_node_cl dap_chain_net_t * dap_chain_net_by_name( const char * a_name); dap_chain_net_t * dap_chain_net_by_id( dap_chain_net_id_t a_id); -uint16_t dap_chain_net_acl_idx_by_id(dap_chain_net_id_t a_id); +uint16_t dap_chain_net_get_acl_idx(dap_chain_net_t *a_net); dap_chain_net_id_t dap_chain_net_id_by_name( const char * a_name); dap_ledger_t * dap_chain_ledger_by_net_name( const char * a_net_name); dap_string_t* dap_cli_list_net(); @@ -141,55 +152,6 @@ const char* dap_chain_net_get_type(dap_chain_t *l_chain); dap_list_t* dap_chain_net_get_link_node_list(dap_chain_net_t * l_net, bool a_is_only_cur_cell); dap_list_t* dap_chain_net_get_node_list(dap_chain_net_t * l_net); - -typedef enum dap_chain_net_tx_search_type { - /// Search local, in memory, possible load data from drive to memory - TX_SEARCH_TYPE_LOCAL, - /// Do the request to the network if its not full node, search inside shard - TX_SEARCH_TYPE_CELL, - /// Do the request for unspent txs in cell - TX_SEARCH_TYPE_CELL_UNSPENT, - /// Do the search in whole network and request tx from others cells if need - TX_SEARCH_TYPE_NET, - /// Do the search in whole network but search only unspent - TX_SEARCH_TYPE_NET_UNSPENT, - /// Do the request for spent txs in cell - TX_SEARCH_TYPE_CELL_SPENT, - /// Do the search in whole - TX_SEARCH_TYPE_NET_SPENT -}dap_chain_net_tx_search_type_t; - -dap_chain_datum_tx_t * dap_chain_net_get_tx_by_hash(dap_chain_net_t * a_net, dap_chain_hash_fast_t * a_tx_hash, - dap_chain_net_tx_search_type_t a_search_type); - -uint256_t dap_chain_net_get_tx_total_value(dap_chain_net_t * a_net, dap_chain_datum_tx_t * a_tx); - -dap_list_t * dap_chain_net_get_tx_cond_all_by_srv_uid(dap_chain_net_t * a_net, const dap_chain_net_srv_uid_t a_srv_uid, - const dap_time_t a_time_from, const dap_time_t a_time_to, - const dap_chain_net_tx_search_type_t a_search_type); - -typedef struct dap_chain_datum_tx_spends_item { - dap_chain_datum_tx_t* tx; - dap_hash_fast_t tx_hash; - - dap_chain_tx_out_cond_t* out_cond; - dap_chain_tx_in_cond_t* in_cond; - - dap_chain_datum_tx_t* tx_next; - UT_hash_handle hh; -}dap_chain_datum_tx_spends_item_t; - -typedef struct dap_chain_datum_tx_spends_items { - dap_chain_datum_tx_spends_item_t* tx_outs; - dap_chain_datum_tx_spends_item_t* tx_ins; -} dap_chain_datum_tx_spends_items_t; - -dap_chain_datum_tx_spends_items_t* dap_chain_net_get_tx_cond_all_with_spends_by_srv_uid(dap_chain_net_t* a_net, const dap_chain_net_srv_uid_t a_srv_uid, - const dap_time_t a_time_from, const dap_time_t a_time_to, - const dap_chain_net_tx_search_type_t a_search_type); -void dap_chain_datum_tx_spends_item_free(dap_chain_datum_tx_spends_item_t* a_items); -void dap_chain_datum_tx_spends_items_free(dap_chain_datum_tx_spends_items_t* a_items); - dap_chain_node_role_t dap_chain_net_get_role(dap_chain_net_t * a_net); /** @@ -197,34 +159,30 @@ dap_chain_node_role_t dap_chain_net_get_role(dap_chain_net_t * a_net); * @param l_chain * @return */ -DAP_STATIC_INLINE char * dap_chain_net_get_gdb_group_mempool_new(dap_chain_t * l_chain) +DAP_STATIC_INLINE char *dap_chain_net_get_gdb_group_mempool_new(dap_chain_t *a_chain) { - dap_chain_net_t * l_net = l_chain ? dap_chain_net_by_id(l_chain->net_id) : NULL; - if ( l_net ) { - const char c_mempool_group_str[]="mempool"; - return dap_strdup_printf("%s.chain-%s.%s",l_net->pub.gdb_groups_prefix,l_chain->name,c_mempool_group_str); - } + dap_chain_net_t *l_net = a_chain ? dap_chain_net_by_id(a_chain->net_id) : NULL; + if ( l_net ) + return dap_strdup_printf("%s.chain-%s.mempool", l_net->pub.gdb_groups_prefix,a_chain->name); return NULL; } -DAP_STATIC_INLINE char * dap_chain_net_get_gdb_group_from_chain_new(dap_chain_t * l_chain) +DAP_STATIC_INLINE char *dap_chain_net_get_gdb_group_from_chain_new(dap_chain_t *a_chain) { - dap_chain_net_t * l_net = l_chain ? dap_chain_net_by_id(l_chain->net_id) : NULL; + dap_chain_net_t *l_net = a_chain ? dap_chain_net_by_id(a_chain->net_id) : NULL; if ( l_net ) - return dap_strdup_printf( "chain-gdb.%s.chain-%016llX",l_net->pub.name, l_chain->id.uint64); - + return dap_strdup_printf("chain-gdb.%s.chain-%016llX",l_net->pub.name, a_chain->id.uint64); return NULL; } -dap_chain_t * dap_chain_net_get_chain_by_chain_type(dap_chain_net_t * l_net, dap_chain_type_t a_datum_type); -dap_chain_t * dap_chain_net_get_default_chain_by_chain_type(dap_chain_net_t * l_net, dap_chain_type_t a_datum_type); -char * dap_chain_net_get_gdb_group_mempool_by_chain_type(dap_chain_net_t * l_net, dap_chain_type_t a_datum_type); +dap_chain_t *dap_chain_net_get_chain_by_chain_type(dap_chain_net_t *a_net, dap_chain_type_t a_datum_type); +dap_chain_t *dap_chain_net_get_default_chain_by_chain_type(dap_chain_net_t *a_net, dap_chain_type_t a_datum_type); +char *dap_chain_net_get_gdb_group_mempool_by_chain_type(dap_chain_net_t *a_net, dap_chain_type_t a_datum_type); dap_chain_net_t **dap_chain_net_list(uint16_t *a_size); bool dap_chain_net_get_extra_gdb_group(dap_chain_net_t *a_net, dap_chain_node_addr_t a_node_addr); int dap_chain_net_verify_datum_for_add(dap_chain_net_t *a_net, dap_chain_datum_t * a_datum ); -void dap_chain_net_dump_datum(dap_string_t *a_str_out, dap_chain_datum_t *a_datum, const char *a_hash_out_type); -int dap_chain_net_add_downlink(dap_chain_net_t *a_net, dap_stream_worker_t *a_worker, dap_stream_ch_uuid_t a_ch_uuid); +int dap_chain_net_add_downlink(dap_chain_net_t *a_net, dap_stream_worker_t *a_worker, dap_stream_ch_uuid_t a_ch_uuid, dap_events_socket_uuid_t a_esocket_uuid); void dap_chain_net_add_gdb_notify_callback(dap_chain_net_t *a_net, dap_global_db_obj_callback_notify_t a_callback, void *a_cb_arg); void dap_chain_net_sync_gdb_broadcast(void *a_arg, const char a_op_code, const char *a_group, const char *a_key, const void *a_value, const size_t a_value_len); @@ -233,7 +191,6 @@ struct dap_chain_node_client * dap_chain_net_client_create_n_connect( dap_chain_ struct dap_chain_node_client * dap_chain_net_client_create_n_connect_channels( dap_chain_net_t * a_net,struct dap_chain_node_info *a_link_info, const char * a_channels); -typedef bool (datum_filter_func_t)(dap_chain_datum_t *a_datum, dap_chain_t * a_chain, void *a_filter_func_param); /** * @brief dap_chain_datum_list * Get datum list by filter @@ -242,6 +199,6 @@ typedef bool (datum_filter_func_t)(dap_chain_datum_t *a_datum, dap_chain_t * a_c * @param a_filter_func * @param a_filter_func_param */ -dap_list_t* dap_chain_datum_list(dap_chain_net_t *a_net, dap_chain_t *a_chain, datum_filter_func_t *a_filter_func, void *a_filter_func_param); +dap_list_t *dap_chain_datum_list(dap_chain_net_t *a_net, dap_chain_t *a_chain, dap_chain_datum_filter_func_t *a_filter_func, void *a_filter_func_param); -int dap_chain_datum_add(dap_chain_t* a_chain, dap_chain_datum_t* a_datum, size_t a_datum_size); +int dap_chain_datum_add(dap_chain_t * a_chain, dap_chain_datum_t *a_datum, size_t a_datum_size, dap_hash_fast_t *a_tx_hash); diff --git a/modules/net/include/dap_chain_net_tx.h b/modules/net/include/dap_chain_net_tx.h new file mode 100644 index 0000000000000000000000000000000000000000..2c59bf7165ba7f4289221b2891d9cf12d43cbfd9 --- /dev/null +++ b/modules/net/include/dap_chain_net_tx.h @@ -0,0 +1,90 @@ +/* + * Authors: + * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net> + * DeM Labs Inc. https://demlabs.net + * Cellframe Network https://cellframe.net + * Copyright (c) 2022 + * 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_net.h" + +typedef enum dap_chain_net_tx_search_type { + /// Search local, in memory, possible load data from drive to memory + TX_SEARCH_TYPE_LOCAL, + /// Do the request to the network if its not full node, search inside shard + TX_SEARCH_TYPE_CELL, + /// Do the request for unspent txs in cell + TX_SEARCH_TYPE_CELL_UNSPENT, + /// Do the search in whole network and request tx from others cells if need + TX_SEARCH_TYPE_NET, + /// Do the search in whole network but search only unspent + TX_SEARCH_TYPE_NET_UNSPENT, + /// Do the request for spent txs in cell + TX_SEARCH_TYPE_CELL_SPENT, + /// Do the search in whole + TX_SEARCH_TYPE_NET_SPENT +}dap_chain_net_tx_search_type_t; + +typedef struct dap_chain_datum_tx_spends_item{ + dap_chain_datum_tx_t * tx; + dap_hash_fast_t tx_hash; + + dap_chain_tx_out_cond_t *out_cond; + dap_chain_tx_in_cond_t *in_cond; + + dap_chain_datum_tx_t * tx_next; + UT_hash_handle hh; +}dap_chain_datum_tx_spends_item_t; + +typedef struct dap_chain_datum_tx_spends_items{ + dap_chain_datum_tx_spends_item_t * tx_outs; + dap_chain_datum_tx_spends_item_t * tx_ins; +} dap_chain_datum_tx_spends_items_t; +typedef void (dap_chain_net_tx_hash_callback_t)(dap_chain_net_t* a_net, dap_chain_datum_tx_t *a_tx, void *a_arg); + + +// TX functions +dap_chain_datum_tx_t * dap_chain_net_get_tx_by_hash(dap_chain_net_t * a_net, dap_chain_hash_fast_t * a_tx_hash, + dap_chain_net_tx_search_type_t a_search_type); + +dap_list_t * dap_chain_net_get_tx_cond_chain(dap_chain_net_t * a_net, dap_hash_fast_t * a_tx_hash, dap_chain_net_srv_uid_t a_srv_uid); + +uint256_t dap_chain_net_get_tx_total_value(dap_chain_net_t * a_net, dap_chain_datum_tx_t * a_tx ); + +void dap_chain_net_get_tx_all(dap_chain_net_t * a_net, dap_chain_net_tx_search_type_t a_search_type ,dap_chain_net_tx_hash_callback_t a_tx_callback, void * a_arg); + + +dap_list_t * dap_chain_net_get_tx_cond_all_by_srv_uid(dap_chain_net_t * a_net, const dap_chain_net_srv_uid_t a_srv_uid, + const dap_time_t a_time_from, const dap_time_t a_time_to, + const dap_chain_net_tx_search_type_t a_search_type); +dap_list_t * dap_chain_net_get_tx_cond_all_for_addr(dap_chain_net_t * a_net, dap_chain_addr_t * a_addr, dap_chain_net_srv_uid_t a_srv_uid); + +dap_list_t * dap_chain_net_get_tx_all_from_tx(dap_chain_net_t * a_net, dap_hash_fast_t * l_tx_hash); + + + + +dap_chain_datum_tx_spends_items_t * dap_chain_net_get_tx_cond_all_with_spends_by_srv_uid(dap_chain_net_t * a_net, const dap_chain_net_srv_uid_t a_srv_uid, + const dap_time_t a_time_from, const dap_time_t a_time_to, + const dap_chain_net_tx_search_type_t a_search_type); +void dap_chain_datum_tx_spends_item_free(dap_chain_datum_tx_spends_item_t * a_items); +void dap_chain_datum_tx_spends_items_free(dap_chain_datum_tx_spends_items_t * a_items); + +bool dap_chain_net_tx_get_fee(dap_chain_net_id_t a_net_id, uint256_t *a_value, dap_chain_addr_t *a_addr); diff --git a/modules/net/include/dap_chain_node.h b/modules/net/include/dap_chain_node.h index ea796943cd098277b8e1d2d9ba555d4baf9640b1..99327817e476d3f6506d0ee3a338388b9c1f8366 100644 --- a/modules/net/include/dap_chain_node.h +++ b/modules/net/include/dap_chain_node.h @@ -164,7 +164,9 @@ inline static char* dap_chain_node_addr_to_hash_str(dap_chain_node_addr_t *addre return a_key; } -int dap_chain_node_mempool_process(dap_chain_t *a_chain, dap_chain_datum_t *a_datum); +bool dap_chain_node_mempool_need_process(dap_chain_t *a_chain, dap_chain_datum_t *a_datum); +bool dap_chain_node_mempool_process(dap_chain_t *a_chain, dap_chain_datum_t *a_datum); +void dap_chain_node_mempool_process_all(dap_chain_t *a_chain); bool dap_chain_node_mempool_autoproc_init(); void dap_chain_node_mempool_autoproc_deinit(); diff --git a/modules/net/include/dap_chain_node_cli_cmd.h b/modules/net/include/dap_chain_node_cli_cmd.h index 36b75456e6410b1813eb64b89054924c75081896..bf07fa891ccdc2ff08650e7882ac0f30cc5c4cd8 100644 --- a/modules/net/include/dap_chain_node_cli_cmd.h +++ b/modules/net/include/dap_chain_node_cli_cmd.h @@ -141,6 +141,7 @@ int cmd_gdb_export(int argc, char ** argv, char ** a_str_reply); int com_mempool_delete(int argc, char ** argv, char ** a_str_reply); int com_mempool_list(int argc, char ** argv, char ** a_str_reply); int com_mempool_proc(int argc, char ** argv, char ** a_str_reply); +int com_mempool_check(int argc, char ** argv, char ** a_str_reply); /** * Place public CA into the mempool */ @@ -148,3 +149,5 @@ int com_mempool_add_ca( int a_argc, char ** a_argv, char ** a_str_reply); int com_chain_ca_pub( int a_argc, char ** a_argv, char ** a_str_reply); int com_chain_ca_copy( int a_argc, char ** a_argv, char ** a_str_reply); int com_signer(int a_argc, char **a_argv, char **a_str_reply); +//remove func +int cmd_remove(int argc, char ** argv, char ** a_str_reply); diff --git a/modules/net/include/dap_chain_node_client.h b/modules/net/include/dap_chain_node_client.h index 14a0cbb542e9a22cb80339bc559be024060b0c1e..6dc818ca336d84bc805b9416e3fe125c3e282835 100644 --- a/modules/net/include/dap_chain_node_client.h +++ b/modules/net/include/dap_chain_node_client.h @@ -145,7 +145,6 @@ int dap_chain_node_client_init(void); void dap_chain_node_client_deinit(void); - dap_chain_node_client_t* dap_chain_node_client_create_n_connect(dap_chain_net_t * a_net, dap_chain_node_info_t *a_node_info, const char *a_active_channels,dap_chain_node_client_callbacks_t *a_callbacks, void * a_callback_arg ); @@ -159,15 +158,16 @@ dap_chain_node_client_t* dap_chain_node_client_connect_channels(dap_chain_net_t */ dap_chain_node_client_t* dap_chain_node_client_connect(dap_chain_net_t * a_net, dap_chain_node_info_t *node_info); +dap_chain_node_client_t *dap_chain_node_client_find(dap_events_socket_uuid_t a_uuid); /** * Reset client state to connected state if it is connected */ void dap_chain_node_client_reset(dap_chain_node_client_t *a_client); /** - * Close connection to server, delete chain_node_client_t *client + * Close connection to server, delete chain_node_client_t with specified UUID */ -void dap_chain_node_client_close(dap_chain_node_client_t *client); +void dap_chain_node_client_close(dap_events_socket_uuid_t a_uuid); /** * Send stream request to server diff --git a/modules/net/include/dap_chain_node_remote.h b/modules/net/include/dap_chain_node_remote.h deleted file mode 100644 index ce8aedc93262ac6e2a2bf67cb27529d78726d50c..0000000000000000000000000000000000000000 --- a/modules/net/include/dap_chain_node_remote.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Authors: - * Dmitriy A. Gearasimov <naeper@demlabs.net> - * DeM Labs Inc. https://demlabs.net - - 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 <stdbool.h> - -#include "dap_chain_node.h" -#include "dap_chain_node_client.h" - -/** - * Add new established connection to the list - * - * return 0 OK, -1 error, -2 already present - */ -int dap_chain_node_client_list_add(dap_chain_node_addr_t *address, dap_chain_node_client_t *client); - -/** - * Delete established connection from the list - * - * return 0 OK, -1 error, -2 address not found - */ -int chain_node_client_list_del(dap_chain_node_addr_t *address); - -/** - * Delete all established connection from the list - */ -void chain_node_client_list_del_all(void); - -/** - * Get present established connection by address - * - * return client, or NULL if the connection not found in the list - */ -const dap_chain_node_client_t* chain_node_client_find(dap_chain_node_addr_t *address); diff --git a/modules/net/srv/CMakeLists.txt b/modules/net/srv/CMakeLists.txt index aaa29abbe4d1fd6080ef7ac917095b819e1f9c9c..87b8572e9f7b3cb16bcfe73fe0e870f6bdd2e7d6 100644 --- a/modules/net/srv/CMakeLists.txt +++ b/modules/net/srv/CMakeLists.txt @@ -1,19 +1,18 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.13) project (dap_chain_net_srv) -file(GLOB DAP_CHAIN_NET_SRV_SRCS *.c libmaxminddb/*.c) - -file(GLOB DAP_CHAIN_NET_SRV_HEADERS include/*.h libmaxminddb/*.h) - +file(GLOB DAP_CHAIN_NET_SRV_SRCS *.c) +file(GLOB DAP_CHAIN_NET_SRV_HEADERS *.h) add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_NET_SRV_SRCS} ${DAP_CHAIN_NET_SRV_HEADERS}) -set(NET_SRV_LIBS dap_chain_net_srv dap_core dap_crypto dap_chain dap_chain_net dap_chain_wallet) +add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../../../3rdparty/libmaxminddb ${CMAKE_CURRENT_BINARY_DIR}/../../../3rdparty/libmaxminddb) +set(NET_SRV_LIBS maxminddb dap_core dap_crypto dap_chain dap_chain_net dap_chain_wallet) if (CELLFRAME_MODULES MATCHES "modules-dynamic") set(NET_SRV_LIBS ${NET_SRV_LIBS} dap_modules_dynamic_cdb) endif() +target_link_libraries(${PROJECT_NAME} ${NET_SRV_LIBS}) -target_link_libraries(${NET_SRV_LIBS}) target_include_directories(${PROJECT_NAME} INTERFACE .) target_include_directories(${PROJECT_NAME} PUBLIC include) target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../3rdparty/uthash/src) diff --git a/modules/net/srv/dap_chain_net_srv.c b/modules/net/srv/dap_chain_net_srv.c index 321120b7cf724a979f329d660cf4a7d9281693db..b1d852de4630718ea17d88301707ef6e14c101f9 100644 --- a/modules/net/srv/dap_chain_net_srv.c +++ b/modules/net/srv/dap_chain_net_srv.c @@ -29,34 +29,25 @@ #include <stddef.h> #include <stdint.h> -#ifdef WIN32 -#include <winsock2.h> -#include <windows.h> -#include <mswsock.h> -#include <ws2tcpip.h> -#include <io.h> -#endif - #ifdef DAP_OS_LINUX #include <dlfcn.h> #endif #include <json-c/json.h> #include <json-c/json_object.h> - #include <pthread.h> #include <dirent.h> - #include "uthash.h" #include "utlist.h" + +#include "dap_chain_net.h" +#include "dap_hash.h" #include "dap_common.h" #include "dap_enc_base58.h" #include "dap_list.h" #include "dap_string.h" #include "dap_file_utils.h" - #include "dap_chain.h" #include "dap_chain_common.h" -#include "dap_chain_net.h" #include "dap_chain_net_srv.h" #include "dap_chain_net_srv_order.h" #include "dap_chain_net_srv_stream_session.h" @@ -88,12 +79,19 @@ static int s_cli_net_srv(int argc, char **argv, char **a_str_reply); static void s_load(const char * a_path); static void s_load_all(void); +static bool s_pay_verificator_callback(dap_ledger_t * a_ledger,dap_hash_fast_t *a_tx_out_hash, dap_chain_tx_out_cond_t *a_cond, + dap_chain_datum_tx_t *a_tx_in, bool a_owner); +static bool s_fee_verificator_callback(dap_ledger_t * a_ledger, dap_hash_fast_t *a_tx_out_hash,dap_chain_tx_out_cond_t *a_cond, + dap_chain_datum_tx_t *a_tx_in, bool a_owner); + /** * @brief dap_chain_net_srv_init * @return */ int dap_chain_net_srv_init() -{ +{ + dap_chain_ledger_verificator_add(DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY, s_pay_verificator_callback, NULL); + dap_chain_ledger_verificator_add(DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE, s_fee_verificator_callback, NULL); dap_stream_ch_chain_net_srv_init(); m_uid = NULL; m_uid_count = 0; @@ -597,13 +595,39 @@ static int s_cli_net_srv( int argc, char **argv, char **a_str_reply) return ret; } -bool dap_chain_net_srv_pay_verificator(dap_ledger_t* a_ledger, dap_chain_tx_out_cond_t *a_cond, dap_chain_datum_tx_t *a_tx, bool a_owner) +/** + * @brief s_fee_verificator_callback + * @param a_ledger + * @param a_tx_out_hash + * @param a_cond + * @param a_tx_in + * @param a_owner + * @return + */ +static bool s_fee_verificator_callback(dap_ledger_t * a_ledger, dap_hash_fast_t *a_tx_out_hash,dap_chain_tx_out_cond_t *a_cond, + dap_chain_datum_tx_t *a_tx_in, bool a_owner) +{ + return false; +} + +/** + * @brief s_pay_verificator_callback + * @param a_ledger + * @param a_tx_out + * @param a_cond + * @param a_tx_in + * @param a_owner + * @return + */ +static bool s_pay_verificator_callback(dap_ledger_t * a_ledger,dap_hash_fast_t *a_tx_out_hash, dap_chain_tx_out_cond_t *a_cond, + dap_chain_datum_tx_t *a_tx_in, bool a_owner) { UNUSED(a_ledger); + UNUSED(a_tx_out_hash); if (!a_owner) return false; dap_chain_datum_tx_receipt_t *l_receipt = (dap_chain_datum_tx_receipt_t *) - dap_chain_datum_tx_item_get(a_tx, NULL, TX_ITEM_TYPE_RECEIPT, NULL); + dap_chain_datum_tx_item_get(a_tx_in, NULL, TX_ITEM_TYPE_RECEIPT, NULL); if (!l_receipt) return false; dap_sign_t *l_sign = dap_chain_datum_tx_receipt_sign_get(l_receipt, l_receipt->size, 1); diff --git a/modules/net/srv/dap_chain_net_srv_geoip.c b/modules/net/srv/dap_chain_net_srv_geoip.c index 90ec027e29d2ec278dd004426f9937a76edd2bbc..ab1f044b7276dce7e8501a6499fecb15137fe7b5 100644 --- a/modules/net/srv/dap_chain_net_srv_geoip.c +++ b/modules/net/srv/dap_chain_net_srv_geoip.c @@ -32,7 +32,7 @@ #include "dap_enc_key.h" #include "dap_enc_base64.h" #include "dap_chain_net_srv_geoip.h" -#include "libmaxminddb/maxminddb.h" +#include "maxminddb.h" #define LOG_TAG "chain_net_srv_geoip" #define LOCALE_DEFAULT "en" diff --git a/modules/net/srv/dap_chain_net_srv_order.c b/modules/net/srv/dap_chain_net_srv_order.c index 8619797b6a0175093e82d93ad1029c3c6c651942..23bec9c32f4b37b6f0fc23c22726dde8ea9ded58 100644 --- a/modules/net/srv/dap_chain_net_srv_order.c +++ b/modules/net/srv/dap_chain_net_srv_order.c @@ -589,10 +589,8 @@ void dap_chain_net_srv_order_dump_to_string(dap_chain_net_srv_order_t *a_order,d static void s_srv_order_callback_notify(void *a_arg, const char a_op_code, const char *a_group, const char *a_key, const void *a_value, const size_t a_value_len) { - UNUSED(a_value_len); - if (!a_arg || !a_key) { + if (!a_arg || !a_key) return; - } dap_chain_net_t *l_net = (dap_chain_net_t *)a_arg; dap_global_db_context_t * l_gdb_context = dap_global_db_context_current(); assert(l_net); @@ -616,9 +614,10 @@ static void s_srv_order_callback_notify(void *a_arg, const char a_op_code, const dap_global_db_del_unsafe(l_gdb_context, a_group, a_key); } else { dap_sign_t *l_sign = (dap_sign_t *)(l_order->ext_n_sign + l_order->ext_size); - if (!dap_sign_verify_size(l_sign, a_value_len) || - dap_sign_verify(l_sign, l_order, - sizeof(dap_chain_net_srv_order_t) + l_order->ext_size) != 1) { + size_t l_max_size = a_value_len - sizeof(dap_chain_net_srv_order_t) - l_order->ext_size; + int l_verify = dap_sign_verify_all(l_sign, l_max_size, l_order, sizeof(dap_chain_net_srv_order_t) + l_order->ext_size); + if (l_verify) { + log_it(L_ERROR, "Order unverified, err %d", l_verify); dap_global_db_del_unsafe(l_gdb_context, a_group, a_key); } /*dap_chain_hash_fast_t l_pkey_hash; diff --git a/modules/net/srv/include/dap_chain_net_srv.h b/modules/net/srv/include/dap_chain_net_srv.h index b747dc4e6a696969aa2e602faaae9d4b544d03ae..c621b8df2b0f19f6a9297406353dc4ea0c06ebc3 100755 --- a/modules/net/srv/include/dap_chain_net_srv.h +++ b/modules/net/srv/include/dap_chain_net_srv.h @@ -257,9 +257,32 @@ typedef struct dap_chain_net_srv void *_internal; } dap_chain_net_srv_t; +// Fees section +typedef enum dap_chain_net_srv_fee_tsd_type { + TSD_FEE = 0x0001, + TSD_FEE_TYPE, + TSD_FEE_ADDR +} dap_chain_net_srv_fee_tsd_type_t; + +typedef enum dap_chain_net_srv_fee_type { + SERVICE_FEE_OWN_FIXED = 0x1, + SERVICE_FEE_OWN_PERCENT, + SERVICE_FEE_NATIVE_FIXED, + SERIVCE_FEE_NATIVE_PERCENT +} dap_chain_net_srv_fee_type_t; + +typedef struct dap_chain_net_srv_fee_item { + dap_chain_net_id_t net_id; + // Sevice fee + uint16_t fee_type; + uint256_t fee; + dap_chain_addr_t fee_addr; // Addr collector + + UT_hash_handle hh; +} dap_chain_net_srv_fee_item_t; + int dap_chain_net_srv_init(); void dap_chain_net_srv_deinit(void); -bool dap_chain_net_srv_pay_verificator(dap_ledger_t* a_ledger, dap_chain_tx_out_cond_t *a_cond, dap_chain_datum_tx_t *a_tx, bool a_owner); dap_chain_net_srv_t* dap_chain_net_srv_add(dap_chain_net_srv_uid_t a_uid, const char *a_config_section, dap_chain_net_srv_callbacks_t* a_callbacks); diff --git a/modules/service/stake_lock/dap_chain_net_srv_stake_lock.c b/modules/service/stake_lock/dap_chain_net_srv_stake_lock.c index 9e5d0bb98834c138babab5e01c166255eb9403d3..1a16a57dd5be146346330a3b25634fa9235a4868 100644 --- a/modules/service/stake_lock/dap_chain_net_srv_stake_lock.c +++ b/modules/service/stake_lock/dap_chain_net_srv_stake_lock.c @@ -28,6 +28,7 @@ #include "dap_chain_node_cli.h" #include "dap_chain_mempool.h" #include "dap_chain_wallet.h" +#include "dap_chain_ledger.h" #include "dap_common.h" #include "dap_hash.h" #include "dap_time.h" @@ -35,60 +36,48 @@ static bool s_debug_more = false; enum error_code { - STAKE_NO_ERROR = 0, - NET_ARG_ERROR = 1, - NET_ERROR = 2, - TOKEN_ARG_ERROR = 3, - TOKEN_ERROR = 4, - COINS_ARG_ERROR = 5, - COINS_FORMAT_ERROR = 6, - ADDR_ARG_ERROR = 7, - ADDR_FORMAT_ERROR = 8, - CERT_ARG_ERROR = 9, - CERT_LOAD_ERROR = 10, - CHAIN_ERROR = 11, - CHAIN_EMISSION_ERROR = 12, - TIME_ERROR = 13, - NO_MONEY_ERROR = 14, - WALLET_ARG_ERROR = 15, - WALLET_OPEN_ERROR = 16, - CERT_KEY_ERROR = 17, - WALLET_ADDR_ERROR = 18, - STAKE_ERROR = 19, - TX_ARG_ERROR = 20, - HASH_IS_BLANK_ERROR = 21, - NO_TX_ERROR = 22, - CREATE_LOCK_TX_ERROR = 23, - TX_TICKER_ERROR = 24, - NO_DELEGATE_TOKEN_ERROR = 25, - NO_VALID_SUBTYPE_ERROR = 26, - IS_USED_OUT_ERROR = 27, - OWNER_KEY_ERROR = 28, - CREATE_TX_ERROR = 29, - CREATE_BURNING_TX_ERROR = 31, - CREATE_RECEIPT_ERROR = 32, - SIGN_ERROR = 33, - CREATE_DATUM_ERROR = 34, - ADD_DATUM_BURNING_TX_ERROR = 35, - ADD_DATUM_TX_TAKE_ERROR = 36, - BASE_TX_CREATE_ERROR = 37, - WRONG_PARAM_SIZE = 38, - NOT_ENOUGH_TIME = 39, - REINVEST_ARG_ERROR = 40 + STAKE_NO_ERROR = 0, + NET_ARG_ERROR = 1, + NET_ERROR = 2, + TOKEN_ARG_ERROR = 3, + TOKEN_ERROR = 4, + COINS_ARG_ERROR = 5, + COINS_FORMAT_ERROR = 6, + ADDR_ARG_ERROR = 7, + ADDR_FORMAT_ERROR = 8, + CERT_ARG_ERROR = 9, + CERT_LOAD_ERROR = 10, + CHAIN_ERROR = 11, + CHAIN_EMISSION_ERROR = 12, + TIME_ERROR = 13, + NO_MONEY_ERROR = 14, + WALLET_ARG_ERROR = 15, + WALLET_OPEN_ERROR = 16, + CERT_KEY_ERROR = 17, + WALLET_ADDR_ERROR = 18, + STAKE_ERROR = 19, + TX_ARG_ERROR = 20, + HASH_IS_BLANK_ERROR = 21, + NO_TX_ERROR = 22, + CREATE_LOCK_TX_ERROR = 23, + TX_TICKER_ERROR = 24, + NO_DELEGATE_TOKEN_ERROR = 25, + NO_VALID_SUBTYPE_ERROR = 26, + IS_USED_OUT_ERROR = 27, + OWNER_KEY_ERROR = 28, + CREATE_TX_ERROR = 29, + CREATE_BURNING_TX_ERROR = 31, + CREATE_RECEIPT_ERROR = 32, + SIGN_ERROR = 33, + CREATE_DATUM_ERROR = 34, + ADD_DATUM_BURNING_TX_ERROR = 35, + ADD_DATUM_TX_TAKE_ERROR = 36, + BASE_TX_CREATE_ERROR = 37, + WRONG_PARAM_SIZE = 38, + NOT_ENOUGH_TIME = 39, + REINVEST_ARG_ERROR = 40 }; -/** - * @brief The cond_params struct thats placed in tx_cond->params[] section - */ -typedef struct cond_params { - dap_time_t time_unlock; - uint32_t flags; - uint8_t reinvest; - uint8_t padding[7]; - dap_hash_fast_t token_delegated; // Delegate token - dap_hash_fast_t pkey_delegated; // Delegate public key -} DAP_ALIGN_PACKED cond_params_t; - typedef struct dap_chain_ledger_token_emission_for_stake_lock_item { dap_chain_hash_fast_t datum_token_emission_for_stake_lock_hash; dap_chain_hash_fast_t tx_used_out; @@ -100,31 +89,47 @@ typedef struct dap_chain_ledger_token_emission_for_stake_lock_item { #define MONTH_INDEX 8 #define YEAR_INDEX 12 -static int s_cli_stake_lock(int a_argc, char** a_argv, char** a_str_reply); -// Verificator callbacks -static void s_callback_decree(dap_chain_net_srv_t* a_srv, dap_chain_net_t* a_net, dap_chain_t* a_chain, dap_chain_datum_decree_t* a_decree, size_t a_decree_size); -dap_chain_ledger_token_emission_for_stake_lock_item_t *s_emission_for_stake_lock_item_add(dap_ledger_t *a_ledger, const dap_chain_hash_fast_t *a_token_emission_hash); - +static int s_cli_stake_lock(int a_argc, char **a_argv, char **a_str_reply); +static dap_chain_hash_fast_t *dap_chain_mempool_base_tx_for_stake_lock_create(dap_chain_t *a_chain, dap_chain_hash_fast_t *a_emission_hash, + dap_chain_id_t a_emission_chain_id, uint256_t a_emission_value, const char *a_ticker, + dap_chain_addr_t *a_addr_to, dap_enc_key_t *a_key_from); +// Callbacks +static void s_callback_decree (dap_chain_net_srv_t * a_srv, dap_chain_net_t *a_net, dap_chain_t * a_chain, + dap_chain_datum_decree_t * a_decree, size_t a_decree_size); +static bool s_stake_lock_callback_verificator_added(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_tx_out_cond_t *a_tx_item); +static bool s_stake_lock_callback_verificator(dap_ledger_t *a_ledger, dap_hash_fast_t *a_tx_out_hash, dap_chain_tx_out_cond_t *a_cond, + dap_chain_datum_tx_t *a_tx_in, bool a_owner); /** * @brief dap_chain_net_srv_external_stake_init * @return */ int dap_chain_net_srv_stake_lock_init() { + dap_chain_ledger_verificator_add(DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK, s_stake_lock_callback_verificator, s_stake_lock_callback_verificator_added); dap_cli_server_cmd_add("stake_lock", s_cli_stake_lock, "Stake lock service commands", - "stake_lock hold -net <net_name> -wallet <wallet_name> -time_staking <in YYMMDD>\n" - "\t-token <token_ticker> -coins <value> -reinvest <percentage from 1 to 100 (not necessary)>\n" - "\t-cert <priv_cert_name> -chain <chain (not necessary)> -chain_emission <chain (not necessary)>\n" - "stake_lock take -net <net_name> -tx <transaction_hash> -wallet <wallet_name>\n" - "\t-chain <chain (not necessary)>\n" + "Command:" + "stake_lock hold\n" + "Required parameters:\n" + "-net <net name> -wallet <wallet name> -time_staking <in YYMMDD>\n" + "-token <ticker> -coins <value>\n" + "Optional parameters:\n" + "-cert <name> -chain <chain> -reinvest <percentage from 1 to 100>\n" + "-no_base_tx(flag to create a transaction without base transaction)\n" + "Command:" + "stake_lock take\n" + "Required parameters:\n" + "-net <net name> -wallet <wallet name> -tx <transaction hash>\n" + "Optional parameters:\n" + "-chain <chain>\n" ); + s_debug_more = dap_config_get_item_bool_default(g_config,"ledger","debug_more",false); dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_STAKE_LOCK_ID }; dap_chain_net_srv_callbacks_t l_srv_callbacks = {}; l_srv_callbacks.decree = s_callback_decree; - dap_chain_net_srv_t* l_srv = dap_chain_net_srv_add(l_uid, "stake_lock", &l_srv_callbacks); + dap_chain_net_srv_t *l_srv = dap_chain_net_srv_add(l_uid, "stake_lock", &l_srv_callbacks); return 0; } @@ -144,7 +149,7 @@ void dap_chain_net_srv_stake_lock_deinit() * @param a_decree * @param a_decree_size */ -static void s_callback_decree(dap_chain_net_srv_t* a_srv, dap_chain_net_t* a_net, dap_chain_t* a_chain, dap_chain_datum_decree_t* a_decree, size_t a_decree_size) +static void s_callback_decree (dap_chain_net_srv_t * a_srv, dap_chain_net_t *a_net, dap_chain_t * a_chain, dap_chain_datum_decree_t * a_decree, size_t a_decree_size) { } @@ -156,18 +161,18 @@ static void s_callback_decree(dap_chain_net_srv_t* a_srv, dap_chain_net_t* a_net * @param datoshi_burned * @return */ -static dap_chain_datum_tx_receipt_t* s_receipt_create(dap_hash_fast_t* hash_burning_transaction, const char* token, uint256_t datoshi_burned) +static dap_chain_datum_tx_receipt_t *s_receipt_create(dap_hash_fast_t *hash_burning_transaction, const char *token, uint256_t datoshi_burned) { - uint32_t l_ext_size = sizeof(dap_hash_fast_t) + dap_strlen(token) + 1; - uint8_t* l_ext = DAP_NEW_STACK_SIZE(uint8_t, l_ext_size); + uint32_t l_ext_size = sizeof(dap_hash_fast_t) + dap_strlen(token) + 1; + uint8_t *l_ext = DAP_NEW_STACK_SIZE(uint8_t, l_ext_size); memcpy(l_ext, hash_burning_transaction, sizeof(dap_hash_fast_t)); - strcpy((char*)&l_ext[sizeof(dap_hash_fast_t)], token); + strcpy((char *)&l_ext[sizeof(dap_hash_fast_t)], token); - dap_chain_net_srv_price_unit_uid_t l_unit = { .uint32 = SERV_UNIT_UNDEFINED }; - dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_STAKE_LOCK_ID }; - dap_chain_datum_tx_receipt_t* l_receipt = dap_chain_datum_tx_receipt_create(l_uid, l_unit, 0, datoshi_burned, - l_ext, l_ext_size); + dap_chain_net_srv_price_unit_uid_t l_unit = { .uint32 = SERV_UNIT_UNDEFINED}; + dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_STAKE_LOCK_ID }; + dap_chain_datum_tx_receipt_t *l_receipt = dap_chain_datum_tx_receipt_create(l_uid, l_unit, 0, datoshi_burned, + l_ext, l_ext_size); return l_receipt; } @@ -179,29 +184,30 @@ static dap_chain_datum_tx_receipt_t* s_receipt_create(dap_hash_fast_t* hash_burn * @param output_line * @return */ -static enum error_code s_cli_hold(int a_argc, char** a_argv, int a_arg_index, dap_string_t* output_line) +static enum error_code s_cli_hold(int a_argc, char **a_argv, int a_arg_index, dap_string_t *output_line) { - const char *l_net_str, *l_ticker_str, *l_coins_str, *l_wallet_str, *l_cert_str, *l_chain_str, *l_chain_emission_str, *l_time_staking_str, *l_reinvest_percent_str; - l_net_str = l_ticker_str = l_coins_str = l_wallet_str = l_cert_str = l_chain_str = l_chain_emission_str = l_time_staking_str = l_reinvest_percent_str = NULL; + const char *l_net_str, *l_ticker_str, *l_coins_str, *l_wallet_str, *l_cert_str, *l_chain_str, /* *l_chain_emission_str,*/ *l_time_staking_str, *l_reinvest_percent_str; + l_net_str = l_ticker_str = l_coins_str = l_wallet_str = l_cert_str = l_chain_str = /*l_chain_emission_str =*/ l_time_staking_str = l_reinvest_percent_str = NULL; const char *l_wallets_path = dap_chain_wallet_get_path(g_config); char delegate_ticker_str[DAP_CHAIN_TICKER_SIZE_MAX] = {[0] = 'm'}; dap_chain_net_t *l_net = NULL; dap_chain_t *l_chain = NULL; - dap_chain_t *l_chain_emission = NULL; +// dap_chain_t *l_chain_emission = NULL; + dap_cert_t *l_cert = NULL; + dap_pkey_t *l_key_cond = NULL; + dap_hash_fast_t *l_base_tx_hash = NULL; dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_STAKE_LOCK_ID }; dap_time_t l_time_staking = 0; - uint8_t l_reinvest_percent = 0; + uint256_t l_reinvest_percent = {}; uint256_t l_value_delegated = {}; + bool create_base_tx = true; uint256_t l_value; dap_ledger_t *l_ledger; char *l_hash_str; dap_hash_fast_t *l_tx_cond_hash; - dap_hash_fast_t *l_base_tx_hash; dap_enc_key_t *l_key_from; - dap_pkey_t *l_key_cond; dap_chain_wallet_t *l_wallet; dap_chain_addr_t *l_addr_holder; - dap_cert_t *l_cert; dap_chain_datum_token_t *delegate_token; dap_tsd_t *l_tsd; dap_chain_datum_token_tsd_delegate_from_stake_lock_t l_tsd_section; @@ -209,7 +215,7 @@ static enum error_code s_cli_hold(int a_argc, char** a_argv, int a_arg_index, da dap_string_append_printf(output_line, "---> HOLD <---\n"); if (!dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-net", &l_net_str) - || NULL == l_net_str) + || NULL == l_net_str) return NET_ARG_ERROR; if (NULL == (l_net = dap_chain_net_by_name(l_net_str))) { @@ -218,95 +224,109 @@ static enum error_code s_cli_hold(int a_argc, char** a_argv, int a_arg_index, da } if (!dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-token", &l_ticker_str) - || NULL == l_ticker_str - || dap_strlen(l_ticker_str) > 8) // for 'm' delegated + || NULL == l_ticker_str + || dap_strlen(l_ticker_str) > 8) // for 'm' delegated return TOKEN_ARG_ERROR; l_ledger = l_net->pub.ledger; + if (NULL == dap_chain_ledger_token_ticker_check(l_ledger, l_ticker_str)) { dap_string_append_printf(output_line, "'%s'", l_ticker_str); return TOKEN_ERROR; } - strcpy(delegate_ticker_str + 1, l_ticker_str); + if (dap_cli_server_cmd_check_option(a_argv, a_arg_index, a_argc, "-no_base_tx") >= 0) + create_base_tx = false; - if (NULL == (delegate_token = dap_chain_ledger_token_ticker_check(l_ledger, delegate_ticker_str)) - || delegate_token->type != DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL - || !delegate_token->header_native_decl.tsd_total_size - || NULL == (l_tsd = dap_tsd_find(delegate_token->data_n_tsd, delegate_token->header_native_decl.tsd_total_size, DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DELEGATE_EMISSION_FROM_STAKE_LOCK))) { - dap_string_append_printf(output_line, "'%s'", delegate_ticker_str); - return NO_DELEGATE_TOKEN_ERROR; - } + if (create_base_tx) { + strcpy(delegate_ticker_str + 1, l_ticker_str); - l_tsd_section = dap_tsd_get_scalar(l_tsd, dap_chain_datum_token_tsd_delegate_from_stake_lock_t); - if (strcmp(l_ticker_str, l_tsd_section.ticker_token_from)) - return TOKEN_ERROR; + if (NULL == (delegate_token = dap_chain_ledger_token_ticker_check(l_ledger, delegate_ticker_str)) + || (delegate_token->type != DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL && delegate_token->type != DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_UPDATE) + || !delegate_token->header_native_decl.tsd_total_size + || NULL == (l_tsd = dap_tsd_find(delegate_token->data_n_tsd, delegate_token->header_native_decl.tsd_total_size, DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DELEGATE_EMISSION_FROM_STAKE_LOCK))) { + dap_string_append_printf(output_line, "'%s'", delegate_ticker_str); + return NO_DELEGATE_TOKEN_ERROR; + } + + l_tsd_section = dap_tsd_get_scalar(l_tsd, dap_chain_datum_token_tsd_delegate_from_stake_lock_t); + if (strcmp(l_ticker_str, l_tsd_section.ticker_token_from)) + return TOKEN_ERROR; + } if (!dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-coins", &l_coins_str) - || NULL == l_coins_str) + || NULL == l_coins_str) return COINS_ARG_ERROR; - if (IS_ZERO_256((l_value = dap_chain_balance_scan(l_coins_str)))) + if (IS_ZERO_256( (l_value = dap_chain_balance_scan(l_coins_str)) )) return COINS_FORMAT_ERROR; - if (!IS_ZERO_256(l_tsd_section.emission_rate)) { + if (create_base_tx + && !IS_ZERO_256(l_tsd_section.emission_rate)) { MULT_256_COIN(l_value, l_tsd_section.emission_rate, &l_value_delegated); if (IS_ZERO_256(l_value_delegated)) return COINS_FORMAT_ERROR; - } else { + } else l_value_delegated = l_value; - } - if (!dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-cert", &l_cert_str) - || NULL == l_cert_str) - return CERT_ARG_ERROR; + dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-cert", &l_cert_str); - if (NULL == (l_cert = dap_cert_find_by_name(l_cert_str))) { + if (NULL != l_cert_str + && NULL == (l_cert = dap_cert_find_by_name(l_cert_str))) { dap_string_append_printf(output_line, "'%s'", l_cert_str); return CERT_LOAD_ERROR; } if (dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-chain", &l_chain_str) - && l_chain_str) + && l_chain_str) l_chain = dap_chain_net_get_chain_by_name(l_net, l_chain_str); else l_chain = dap_chain_net_get_default_chain_by_chain_type(l_net, CHAIN_TYPE_TX); - if (!l_chain) + if(!l_chain) return CHAIN_ERROR; - if (dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-chain_emission", &l_chain_emission_str) - && l_chain_emission_str) +/* if (dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, "-chain_emission", &l_chain_emission_str) + && l_chain_emission_str) l_chain_emission = dap_chain_net_get_chain_by_name(l_net, l_chain_str); else l_chain_emission = dap_chain_net_get_default_chain_by_chain_type(l_net, CHAIN_TYPE_EMISSION); - if (!l_chain_emission) - return CHAIN_EMISSION_ERROR; + if(!l_chain_emission) + return CHAIN_EMISSION_ERROR;*/ if (!dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-wallet", &l_wallet_str) - || NULL == l_wallet_str) + || NULL == l_wallet_str) return WALLET_ARG_ERROR; // Read time staking if (!dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-time_staking", &l_time_staking_str) - || NULL == l_time_staking_str) + || NULL == l_time_staking_str) return TIME_ERROR; - if (0 == (l_time_staking = dap_time_from_str_simplified(l_time_staking_str)) - || (time_t)(l_time_staking - dap_time_now()) <= 0) + l_time_staking = dap_time_from_str_simplified(l_time_staking_str); + if (0 == l_time_staking) return TIME_ERROR; + dap_time_t l_time_now = dap_time_now(); + if (l_time_staking < l_time_now) + return TIME_ERROR; + l_time_staking -= l_time_now; - l_time_staking -= dap_time_now(); - - if (dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-l_reinvest_percent", &l_reinvest_percent_str) - && NULL != l_reinvest_percent_str) { - if ((l_reinvest_percent = atoi(l_reinvest_percent_str)) > 100 - || l_reinvest_percent <= 0) + if (dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-reinvest", &l_reinvest_percent_str) + && NULL != l_reinvest_percent_str) { + l_reinvest_percent = dap_chain_coins_to_balance(l_reinvest_percent_str); + if (compare256(l_reinvest_percent, dap_chain_coins_to_balance("100.0")) == 1) return REINVEST_ARG_ERROR; + if (IS_ZERO_256(l_reinvest_percent)) { + int l_reinvest_percent_int = atoi(l_reinvest_percent_str); + if (l_reinvest_percent_int <= 0 || l_reinvest_percent_int > 100) + return REINVEST_ARG_ERROR; + l_reinvest_percent = dap_chain_uint256_from(l_reinvest_percent_int); + MULT_256_256(l_reinvest_percent, GET_256_FROM_64(1000000000000000000ULL), &l_reinvest_percent); + } } - /*________________________________________________________________________________________________________________*/ +/*________________________________________________________________________________________________________________*/ - if (NULL == (l_wallet = dap_chain_wallet_open(l_wallet_str, l_wallets_path))) { + if(NULL == (l_wallet = dap_chain_wallet_open(l_wallet_str, l_wallets_path))) { dap_string_append_printf(output_line, "'%s'", l_wallet_str); return WALLET_OPEN_ERROR; } @@ -323,7 +343,9 @@ static enum error_code s_cli_hold(int a_argc, char** a_argv, int a_arg_index, da } l_key_from = dap_chain_wallet_get_key(l_wallet, 0); - if (NULL == (l_key_cond = dap_pkey_from_enc_key(l_cert->enc_key))) { + + if (NULL != l_cert + && NULL == (l_key_cond = dap_pkey_from_enc_key(l_cert->enc_key))) { dap_chain_wallet_close(l_wallet); DAP_DEL_Z(l_addr_holder); dap_string_append_printf(output_line, "'%s'", l_cert_str); @@ -331,10 +353,10 @@ static enum error_code s_cli_hold(int a_argc, char** a_argv, int a_arg_index, da } l_tx_cond_hash = dap_chain_net_srv_stake_lock_mempool_create(l_net, l_key_from, l_key_cond, - l_ticker_str, l_value, l_uid, - l_addr_holder, l_time_staking, l_reinvest_percent); + l_ticker_str,l_value, l_uid, + l_addr_holder, l_chain, l_time_staking, + l_reinvest_percent, create_base_tx); - dap_chain_wallet_close(l_wallet); DAP_DEL_Z(l_key_cond); l_hash_str = (l_tx_cond_hash) ? dap_chain_hash_fast_to_str_new(l_tx_cond_hash) : NULL; @@ -342,25 +364,30 @@ static enum error_code s_cli_hold(int a_argc, char** a_argv, int a_arg_index, da if (l_hash_str) dap_string_append_printf(output_line, "TX STAKE LOCK CREATED\nSuccessfully hash=%s\nSave to take!\n", l_hash_str); else { + dap_chain_wallet_close(l_wallet); DAP_DEL_Z(l_addr_holder); return CREATE_LOCK_TX_ERROR; } DAP_DEL_Z(l_hash_str); - l_base_tx_hash = dap_chain_mempool_base_tx_create(l_chain_emission, l_tx_cond_hash, l_chain_emission->id, - l_value_delegated, delegate_ticker_str, l_addr_holder, - &l_cert, 1); + if (create_base_tx) { + l_base_tx_hash = dap_chain_mempool_base_tx_for_stake_lock_create(l_chain, l_tx_cond_hash, l_chain->id, + l_value_delegated, delegate_ticker_str, l_addr_holder, l_key_from); + } + dap_chain_wallet_close(l_wallet); - l_hash_str = (l_base_tx_hash) ? dap_chain_hash_fast_to_str_new(l_base_tx_hash) : NULL; + if (create_base_tx) { + l_hash_str = (l_base_tx_hash) ? dap_chain_hash_fast_to_str_new(l_base_tx_hash) : NULL; - if (l_hash_str) - dap_string_append_printf(output_line, "BASE_TX_DATUM_HASH=%s\n", l_hash_str); - else { - DAP_DEL_Z(l_addr_holder); - DAP_DEL_Z(l_tx_cond_hash); - return BASE_TX_CREATE_ERROR; + if (l_hash_str) + dap_string_append_printf(output_line, "BASE_TX_DATUM_HASH=%s\n", l_hash_str); + else { + DAP_DEL_Z(l_addr_holder); + DAP_DEL_Z(l_tx_cond_hash); + return BASE_TX_CREATE_ERROR; + } } DAP_DEL_Z(l_addr_holder); @@ -371,31 +398,30 @@ static enum error_code s_cli_hold(int a_argc, char** a_argv, int a_arg_index, da return STAKE_NO_ERROR; } -static enum error_code s_cli_take(int a_argc, char** a_argv, int a_arg_index, dap_string_t* output_line) +static enum error_code s_cli_take(int a_argc, char **a_argv, int a_arg_index, dap_string_t *output_line) { const char *l_net_str, *l_ticker_str, *l_wallet_str, *l_tx_str, *l_tx_burning_str, *l_chain_str; l_net_str = l_ticker_str = l_wallet_str = l_tx_str = l_tx_burning_str = l_chain_str = NULL; - dap_chain_net_t* l_net = NULL; - const char* l_wallets_path = dap_chain_wallet_get_path(g_config); + dap_chain_net_t *l_net = NULL; + dap_chain_datum_t *l_datum_burning_tx = NULL; + const char *l_wallets_path = dap_chain_wallet_get_path(g_config); char delegate_ticker_str[DAP_CHAIN_TICKER_SIZE_MAX] = {[0] = 'm'}; - int l_prev_cond_idx = 0; + int l_prev_cond_idx = 0; uint256_t l_value_delegated = {}; - cond_params_t *l_params; - char *l_datum_hash_str; - dap_ledger_t *l_ledger; - dap_chain_wallet_t *l_wallet; + char *l_datum_hash_str; + dap_ledger_t *l_ledger; + dap_chain_wallet_t *l_wallet; dap_hash_fast_t l_tx_hash; dap_hash_fast_t l_tx_burning_hash; - dap_chain_datum_t *l_datum_burning_tx; - dap_chain_datum_tx_receipt_t *l_receipt; - dap_chain_datum_tx_t *l_tx; - dap_chain_datum_tx_t *l_cond_tx; - dap_chain_tx_out_cond_t *l_tx_out_cond; - dap_chain_addr_t *l_owner_addr; - dap_enc_key_t *l_owner_key; + dap_chain_datum_tx_receipt_t *l_receipt; + dap_chain_datum_tx_t *l_tx; + dap_chain_datum_tx_t *l_cond_tx; + dap_chain_tx_out_cond_t *l_tx_out_cond; + dap_chain_addr_t *l_owner_addr; + dap_enc_key_t *l_owner_key; size_t l_tx_size; - dap_chain_datum_t *l_datum; - dap_chain_t *l_chain; + dap_chain_datum_t *l_datum; + dap_chain_t *l_chain; dap_chain_datum_token_t *delegate_token; dap_tsd_t *l_tsd; dap_chain_datum_token_tsd_delegate_from_stake_lock_t l_tsd_section; @@ -403,7 +429,7 @@ static enum error_code s_cli_take(int a_argc, char** a_argv, int a_arg_index, da dap_string_append_printf(output_line, "---> TAKE <---\n"); if (!dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-net", &l_net_str) - || NULL == l_net_str) + || NULL == l_net_str) return NET_ARG_ERROR; if (NULL == (l_net = dap_chain_net_by_name(l_net_str))) { @@ -412,15 +438,15 @@ static enum error_code s_cli_take(int a_argc, char** a_argv, int a_arg_index, da } if (dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-chain", &l_chain_str) - && l_chain_str) + && l_chain_str) l_chain = dap_chain_net_get_chain_by_name(l_net, l_chain_str); else l_chain = dap_chain_net_get_default_chain_by_chain_type(l_net, CHAIN_TYPE_TX); - if (!l_chain) + if(!l_chain) return CHAIN_ERROR; if (!dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-tx", &l_tx_str) - || NULL == l_tx_str) + || NULL == l_tx_str) return TX_ARG_ERROR; dap_chain_hash_fast_from_hex_str(l_tx_str, &l_tx_hash); @@ -430,28 +456,10 @@ static enum error_code s_cli_take(int a_argc, char** a_argv, int a_arg_index, da l_ledger = l_net->pub.ledger; - if (NULL == (l_ticker_str = dap_chain_ledger_tx_get_token_ticker_by_hash(l_ledger, &l_tx_hash))) - return TX_TICKER_ERROR; - - - strcpy(delegate_ticker_str + 1, l_ticker_str); - - if (NULL == (delegate_token = dap_chain_ledger_token_ticker_check(l_ledger, delegate_ticker_str)) - || delegate_token->type != DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL - || !delegate_token->header_native_decl.tsd_total_size - || NULL == (l_tsd = dap_tsd_find(delegate_token->data_n_tsd, delegate_token->header_native_decl.tsd_total_size, DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DELEGATE_EMISSION_FROM_STAKE_LOCK))) { - dap_string_append_printf(output_line, "'%s'", delegate_ticker_str); - return NO_DELEGATE_TOKEN_ERROR; - } - - l_tsd_section = dap_tsd_get_scalar(l_tsd, dap_chain_datum_token_tsd_delegate_from_stake_lock_t); - if (strcmp(l_ticker_str, l_tsd_section.ticker_token_from)) { - return TOKEN_ERROR; - } - l_cond_tx = dap_chain_ledger_tx_find_by_hash(l_ledger, &l_tx_hash); - if (NULL == (l_tx_out_cond = dap_chain_datum_tx_out_cond_get(l_cond_tx, &l_prev_cond_idx))) + if (NULL == (l_tx_out_cond = dap_chain_datum_tx_out_cond_get(l_cond_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK, + &l_prev_cond_idx))) return NO_TX_ERROR; if (l_tx_out_cond->header.subtype != DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK) @@ -461,34 +469,49 @@ static enum error_code s_cli_take(int a_argc, char** a_argv, int a_arg_index, da return IS_USED_OUT_ERROR; } - if (l_tx_out_cond->params_size != sizeof(*l_params))// Wrong params size - return WRONG_PARAM_SIZE; - l_params = (cond_params_t*)l_tx_out_cond->params; - - if (l_params->flags & DAP_CHAIN_NET_SRV_STAKE_LOCK_FLAG_BY_TIME) { - if (l_params->time_unlock > dap_time_now()) + if (l_tx_out_cond->subtype.srv_stake_lock.flags & DAP_CHAIN_NET_SRV_STAKE_LOCK_FLAG_BY_TIME) { + if (l_tx_out_cond->subtype.srv_stake_lock.time_unlock > dap_time_now()) return NOT_ENOUGH_TIME; } - if (!IS_ZERO_256(l_tsd_section.emission_rate)) { + if (NULL == (l_ticker_str = dap_chain_ledger_tx_get_token_ticker_by_hash(l_ledger, &l_tx_hash))) + return TX_TICKER_ERROR; + + if (l_tx_out_cond->subtype.srv_stake_lock.flags & DAP_CHAIN_NET_SRV_STAKE_LOCK_FLAG_CREATE_BASE_TX) { + strcpy(delegate_ticker_str + 1, l_ticker_str); + + if (NULL == (delegate_token = dap_chain_ledger_token_ticker_check(l_ledger, delegate_ticker_str)) + || (delegate_token->type != DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL && delegate_token->type != DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_UPDATE) + || !delegate_token->header_native_decl.tsd_total_size + || NULL == (l_tsd = dap_tsd_find(delegate_token->data_n_tsd, delegate_token->header_native_decl.tsd_total_size, DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DELEGATE_EMISSION_FROM_STAKE_LOCK))) { + dap_string_append_printf(output_line, "'%s'", delegate_ticker_str); + return NO_DELEGATE_TOKEN_ERROR; + } + + l_tsd_section = dap_tsd_get_scalar(l_tsd, dap_chain_datum_token_tsd_delegate_from_stake_lock_t); + if (strcmp(l_ticker_str, l_tsd_section.ticker_token_from)) + return TOKEN_ERROR; + } + + if ((l_tx_out_cond->subtype.srv_stake_lock.flags & DAP_CHAIN_NET_SRV_STAKE_LOCK_FLAG_CREATE_BASE_TX) + && !IS_ZERO_256(l_tsd_section.emission_rate)) { MULT_256_COIN(l_tx_out_cond->header.value, l_tsd_section.emission_rate, &l_value_delegated); if (IS_ZERO_256(l_value_delegated)) return COINS_FORMAT_ERROR; - } else { + } else l_value_delegated = l_tx_out_cond->header.value; - } if (!dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-wallet", &l_wallet_str) - || NULL == l_wallet_str) + || NULL == l_wallet_str) return WALLET_ARG_ERROR; if (NULL == (l_wallet = dap_chain_wallet_open(l_wallet_str, l_wallets_path))) return WALLET_OPEN_ERROR; - if (NULL == (l_owner_addr = (dap_chain_addr_t*)dap_chain_wallet_get_addr(l_wallet, l_net->pub.id))) { + if (NULL == (l_owner_addr = (dap_chain_addr_t *)dap_chain_wallet_get_addr(l_wallet, l_net->pub.id))) { dap_chain_wallet_close(l_wallet); return WALLET_ADDR_ERROR; - } + } if (NULL == (l_owner_key = dap_chain_wallet_get_key(l_wallet, 0))) { dap_chain_wallet_close(l_wallet); @@ -496,9 +519,9 @@ static enum error_code s_cli_take(int a_argc, char** a_argv, int a_arg_index, da return OWNER_KEY_ERROR; } - /*________________________________________________________________________________________________________________*/ +/*________________________________________________________________________________________________________________*/ - //add tx + //add tx if (NULL == (l_tx = dap_chain_datum_tx_create())) {//malloc dap_chain_wallet_close(l_wallet); DAP_DEL_Z(l_owner_addr); @@ -510,28 +533,30 @@ static enum error_code s_cli_take(int a_argc, char** a_argv, int a_arg_index, da dap_chain_datum_tx_add_out_item(&l_tx, l_owner_addr, l_tx_out_cond->header.value); //add burning tx - if (NULL == (l_datum_burning_tx = dap_chain_burning_tx_create(l_chain, l_owner_key, l_owner_addr, NULL, - delegate_ticker_str, l_value_delegated))) {//malloc - dap_chain_wallet_close(l_wallet); - DAP_DEL_Z(l_owner_addr); - dap_chain_datum_tx_delete(l_tx); - return CREATE_BURNING_TX_ERROR; - } + if (l_tx_out_cond->subtype.srv_stake_lock.flags & DAP_CHAIN_NET_SRV_STAKE_LOCK_FLAG_CREATE_BASE_TX) { + if (NULL == (l_datum_burning_tx = dap_chain_burning_tx_create(l_chain, l_owner_key, l_owner_addr, NULL, + delegate_ticker_str, l_value_delegated))) {//malloc + dap_chain_wallet_close(l_wallet); + DAP_DEL_Z(l_owner_addr); + dap_chain_datum_tx_delete(l_tx); + return CREATE_BURNING_TX_ERROR; + } - //get tx hash - dap_hash_fast(l_datum_burning_tx->data, l_datum_burning_tx->header.data_size, &l_tx_burning_hash); + //get tx hash + dap_hash_fast(l_datum_burning_tx->data, l_datum_burning_tx->header.data_size, &l_tx_burning_hash); - if (NULL == (l_receipt = s_receipt_create(&l_tx_burning_hash, delegate_ticker_str, l_value_delegated))) { - dap_chain_wallet_close(l_wallet); - DAP_DEL_Z(l_owner_addr); - dap_chain_datum_tx_delete(l_tx); - DAP_DEL_Z(l_datum_burning_tx); - return CREATE_RECEIPT_ERROR; - } + if (NULL == (l_receipt = s_receipt_create(&l_tx_burning_hash, delegate_ticker_str, l_value_delegated))) { + dap_chain_wallet_close(l_wallet); + DAP_DEL_Z(l_owner_addr); + dap_chain_datum_tx_delete(l_tx); + DAP_DEL_Z(l_datum_burning_tx); + return CREATE_RECEIPT_ERROR; + } - dap_chain_datum_tx_add_item(&l_tx, (byte_t*)l_receipt); + dap_chain_datum_tx_add_item(&l_tx, (byte_t *)l_receipt); + } - if (dap_chain_datum_tx_add_sign_item(&l_tx, l_owner_key) != 1) { + if(dap_chain_datum_tx_add_sign_item(&l_tx, l_owner_key) != 1) { dap_chain_wallet_close(l_wallet); DAP_DEL_Z(l_owner_addr); dap_chain_datum_tx_delete(l_tx); @@ -553,16 +578,18 @@ static enum error_code s_cli_take(int a_argc, char** a_argv, int a_arg_index, da dap_chain_datum_tx_delete(l_tx); - if (NULL == (l_datum_hash_str = dap_chain_mempool_datum_add(l_datum_burning_tx, l_chain))) { + if (l_tx_out_cond->subtype.srv_stake_lock.flags & DAP_CHAIN_NET_SRV_STAKE_LOCK_FLAG_CREATE_BASE_TX) { + if (NULL == (l_datum_hash_str = dap_chain_mempool_datum_add(l_datum_burning_tx, l_chain))) { + DAP_DEL_Z(l_datum_burning_tx); + DAP_DEL_Z(l_datum); + return ADD_DATUM_BURNING_TX_ERROR; + } + + dap_string_append_printf(output_line, "BURNING_TX_DATUM_HASH=%s\n", l_datum_hash_str); DAP_DEL_Z(l_datum_burning_tx); - DAP_DEL_Z(l_datum); - return ADD_DATUM_BURNING_TX_ERROR; + DAP_DEL_Z(l_datum_hash_str); } - dap_string_append_printf(output_line, "BURNING_TX_DATUM_HASH=%s\n", l_datum_hash_str); - DAP_DEL_Z(l_datum_burning_tx); - DAP_DEL_Z(l_datum_hash_str); - // Processing will be made according to autoprocess policy if (NULL == (l_datum_hash_str = dap_chain_mempool_datum_add(l_datum, l_chain))) { DAP_DEL_Z(l_datum); @@ -582,173 +609,173 @@ static enum error_code s_cli_take(int a_argc, char** a_argv, int a_arg_index, da * @param errorCode * @param output_line */ -static void s_error_handler(enum error_code errorCode, dap_string_t* output_line) +static void s_error_handler(enum error_code errorCode, dap_string_t *output_line) { dap_string_append_printf(output_line, "ERROR!\n"); switch (errorCode) { - case NET_ARG_ERROR: { - dap_string_append_printf(output_line, "stake_lock command required parameter -net"); - } break; - - case NET_ERROR: { - dap_string_append_printf(output_line, "^^^ network not found"); - } break; - - case TOKEN_ARG_ERROR: { - dap_string_append_printf(output_line, "stake_lock command required parameter -token"); - } break; - - case TOKEN_ERROR: { - dap_string_append_printf(output_line, "^^^ token ticker not found"); - } break; - - case COINS_ARG_ERROR: { - dap_string_append_printf(output_line, "stake_lock command required parameter -coins"); - } break; - - case COINS_FORMAT_ERROR: { - dap_string_append_printf(output_line, "Format -coins <256 bit integer>"); - } break; - - case ADDR_ARG_ERROR: { - dap_string_append_printf(output_line, "stake_lock command required parameter -addr_holder"); - } break; - - case ADDR_FORMAT_ERROR: { - dap_string_append_printf(output_line, "wrong address holder format"); - } break; - - case CERT_ARG_ERROR: { - dap_string_append_printf(output_line, "stake_lock command required parameter -cert"); - } break; - - case CERT_LOAD_ERROR: { - dap_string_append_printf(output_line, "^^^ can't load cert"); - } break; - - case CHAIN_ERROR: { - dap_string_append_printf(output_line, "stake_lock command requires parameter '-chain'.\n" - "you can set default datum type in chain configuration file"); - } break; - - case CHAIN_EMISSION_ERROR: { - dap_string_append_printf(output_line, "stake_lock command requires parameter '-chain_emission'.\n" - "you can set default datum type in chain configuration file"); - } break; - - case TIME_ERROR: { - dap_string_append_printf(output_line, "stake_ext command requires parameter '-time_staking' in simplified format YYMMDD\n" - "Example: \"220610\" == \"10 june 2022 00:00\""); - } break; + case NET_ARG_ERROR: { + dap_string_append_printf(output_line, "stake_lock command required parameter -net"); + } break; + + case NET_ERROR: { + dap_string_append_printf(output_line, " ^^^ network not found"); + } break; + + case TOKEN_ARG_ERROR: { + dap_string_append_printf(output_line, "stake_lock command required parameter -token"); + } break; + + case TOKEN_ERROR: { + dap_string_append_printf(output_line, " ^^^ token ticker not found"); + } break; + + case COINS_ARG_ERROR: { + dap_string_append_printf(output_line, "stake_lock command required parameter -coins"); + } break; + + case COINS_FORMAT_ERROR: { + dap_string_append_printf(output_line, "Format -coins <256 bit integer>"); + } break; + + case ADDR_ARG_ERROR: { + dap_string_append_printf(output_line, "stake_lock command required parameter -addr_holder"); + } break; + + case ADDR_FORMAT_ERROR: { + dap_string_append_printf(output_line, "wrong address holder format"); + } break; + + case CERT_ARG_ERROR: { + dap_string_append_printf(output_line, "stake_lock command required parameter -cert"); + } break; + + case CERT_LOAD_ERROR: { + dap_string_append_printf(output_line, " ^^^ can't load cert"); + } break; + + case CHAIN_ERROR: { + dap_string_append_printf(output_line, "stake_lock command requires parameter '-chain'.\n" + "you can set default datum type in chain configuration file"); + } break; + + case CHAIN_EMISSION_ERROR: { + dap_string_append_printf(output_line, "stake_lock command requires parameter '-chain_emission'.\n" + "you can set default datum type in chain configuration file"); + } break; + + case TIME_ERROR: { + dap_string_append_printf(output_line, "stake_lock command requires parameter '-time_staking' in simplified format YYMMDD\n" + "Example: \"220610\" == \"10 june 2022 00:00\""); + } break; - case NO_MONEY_ERROR: { - dap_string_append_printf(output_line, "Not enough money"); - } break; + case NO_MONEY_ERROR: { + dap_string_append_printf(output_line, "Not enough money"); + } break; - case WALLET_ARG_ERROR: { - dap_string_append_printf(output_line, "stake_lock command required parameter -wallet"); - } break; - - case WALLET_OPEN_ERROR: { - dap_string_append_printf(output_line, "^^^ can't open wallet"); - } break; - - case CERT_KEY_ERROR: { - dap_string_append_printf(output_line, "^^^ cert doesn't contain a valid public key"); - } break; - - case WALLET_ADDR_ERROR: { - dap_string_append_printf(output_line, "^^^ failed to get wallet address"); - } break; - - case TX_ARG_ERROR: { - dap_string_append_printf(output_line, "stake_lock command required parameter -tx"); - } break; - - case HASH_IS_BLANK_ERROR: { - dap_string_append_printf(output_line, "tx hash is blank"); - } break; - - case NO_TX_ERROR: { - dap_string_append_printf(output_line, "^^^ could not find transaction"); - } break; - - case STAKE_ERROR: { - dap_string_append_printf(output_line, "STAKE ERROR"); - } break; - - case NOT_ENOUGH_TIME: { - dap_string_append_printf(output_line, "Not enough time has passed"); - } break; - - case TX_TICKER_ERROR: { - dap_string_append_printf(output_line, "ticker not found"); - } break; - - case NO_DELEGATE_TOKEN_ERROR: { - dap_string_append_printf(output_line, " ^^^ delegated token not found"); - } break; - - case NO_VALID_SUBTYPE_ERROR: { - dap_string_append_printf(output_line, "wrong subtype for transaction"); - } break; - - case IS_USED_OUT_ERROR: { - dap_string_append_printf(output_line, "tx hash is used out"); - } break; - - case OWNER_KEY_ERROR: { - dap_string_append_printf(output_line, "key retrieval error"); - } break; - - case CREATE_TX_ERROR: { - dap_string_append_printf(output_line, "memory allocation error when creating a transaction"); - } break; - - case CREATE_BURNING_TX_ERROR: { - dap_string_append_printf(output_line, "failed to create a transaction that burns funds"); - } break; - - case CREATE_RECEIPT_ERROR: { - dap_string_append_printf(output_line, "failed to create receipt"); - } break; - - case SIGN_ERROR: { - dap_string_append_printf(output_line, "failed to sign transaction"); - } break; - - case ADD_DATUM_BURNING_TX_ERROR: { - dap_string_append_printf(output_line, "failed to add datum with burning-transaction to mempool"); - } break; - - case ADD_DATUM_TX_TAKE_ERROR: { - dap_string_append_printf(output_line, "failed to add datum with take-transaction to mempool"); - } break; - - case BASE_TX_CREATE_ERROR: { - dap_string_append_printf(output_line, "failed to create the base transaction for emission"); - } break; - - case WRONG_PARAM_SIZE: { - dap_string_append_printf(output_line, "error while checking conditional transaction parameters"); - } break; - - case CREATE_LOCK_TX_ERROR: { - dap_string_append_printf(output_line, "error creating transaction"); - } break; - - case CREATE_DATUM_ERROR: { - dap_string_append_printf(output_line, "error while creating datum from transaction"); - } break; + case WALLET_ARG_ERROR: { + dap_string_append_printf(output_line, "stake_lock command required parameter -wallet"); + } break; + + case WALLET_OPEN_ERROR: { + dap_string_append_printf(output_line, " ^^^ can't open wallet"); + } break; + + case CERT_KEY_ERROR: { + dap_string_append_printf(output_line, " ^^^ cert doesn't contain a valid public key"); + } break; + + case WALLET_ADDR_ERROR: { + dap_string_append_printf(output_line, " ^^^ failed to get wallet address"); + } break; + + case TX_ARG_ERROR: { + dap_string_append_printf(output_line, "stake_lock command required parameter -tx"); + } break; + + case HASH_IS_BLANK_ERROR: { + dap_string_append_printf(output_line, "tx hash is blank"); + } break; + + case NO_TX_ERROR: { + dap_string_append_printf(output_line, " ^^^ could not find transaction"); + } break; + + case STAKE_ERROR: { + dap_string_append_printf(output_line, "STAKE ERROR"); + } break; + + case NOT_ENOUGH_TIME: { + dap_string_append_printf(output_line, "Not enough time has passed"); + } break; + + case TX_TICKER_ERROR: { + dap_string_append_printf(output_line, "ticker not found"); + } break; + + case NO_DELEGATE_TOKEN_ERROR: { + dap_string_append_printf(output_line, " ^^^ delegated token not found"); + } break; + + case NO_VALID_SUBTYPE_ERROR: { + dap_string_append_printf(output_line, "wrong subtype for transaction"); + } break; + + case IS_USED_OUT_ERROR: { + dap_string_append_printf(output_line, "tx hash is used out"); + } break; + + case OWNER_KEY_ERROR: { + dap_string_append_printf(output_line, "key retrieval error"); + } break; + + case CREATE_TX_ERROR: { + dap_string_append_printf(output_line, "memory allocation error when creating a transaction"); + } break; + + case CREATE_BURNING_TX_ERROR: { + dap_string_append_printf(output_line, "failed to create a transaction that burns funds"); + } break; + + case CREATE_RECEIPT_ERROR: { + dap_string_append_printf(output_line, "failed to create receipt"); + } break; + + case SIGN_ERROR: { + dap_string_append_printf(output_line, "failed to sign transaction"); + } break; + + case ADD_DATUM_BURNING_TX_ERROR: { + dap_string_append_printf(output_line, "failed to add datum with burning-transaction to mempool"); + } break; + + case ADD_DATUM_TX_TAKE_ERROR: { + dap_string_append_printf(output_line, "failed to add datum with take-transaction to mempool"); + } break; + + case BASE_TX_CREATE_ERROR: { + dap_string_append_printf(output_line, "failed to create the base transaction for emission"); + } break; + + case WRONG_PARAM_SIZE: { + dap_string_append_printf(output_line, "error while checking conditional transaction parameters"); + } break; + + case CREATE_LOCK_TX_ERROR: { + dap_string_append_printf(output_line, "error creating transaction"); + } break; + + case CREATE_DATUM_ERROR: { + dap_string_append_printf(output_line, "error while creating datum from transaction"); + } break; - case REINVEST_ARG_ERROR: { - dap_string_append_printf(output_line, "reinvestment is set as a percentage from 1 to 100"); - } break; + case REINVEST_ARG_ERROR: { + dap_string_append_printf(output_line, "reinvestment is set as a percentage from 1 to 100"); + } break; - default: { - dap_string_append_printf(output_line, "STAKE_LOCK: Unrecognized error"); - } break; + default: { + dap_string_append_printf(output_line, "STAKE_LOCK: Unrecognized error"); + } break; } } @@ -759,16 +786,16 @@ static void s_error_handler(enum error_code errorCode, dap_string_t* output_line * @param a_str_reply * @return */ -static int s_cli_stake_lock(int a_argc, char** a_argv, char** a_str_reply) +static int s_cli_stake_lock(int a_argc, char **a_argv, char **a_str_reply) { - enum { + enum{ CMD_NONE, CMD_HOLD, CMD_TAKE }; enum error_code errorCode; - int l_arg_index = 1; - int l_cmd_num = CMD_NONE; - dap_string_t* output_line = dap_string_new(NULL); + int l_arg_index = 1; + int l_cmd_num = CMD_NONE; + dap_string_t *output_line = dap_string_new(NULL); if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, min(a_argc, l_arg_index + 1), "hold", NULL)) l_cmd_num = CMD_HOLD; @@ -777,18 +804,18 @@ static int s_cli_stake_lock(int a_argc, char** a_argv, char** a_str_reply) switch (l_cmd_num) { - case CMD_HOLD: { - errorCode = s_cli_hold(a_argc, a_argv, l_arg_index + 1, output_line); - } break; + case CMD_HOLD: { + errorCode = s_cli_hold(a_argc, a_argv, l_arg_index + 1, output_line); + } break; - case CMD_TAKE: { - errorCode = s_cli_take(a_argc, a_argv, l_arg_index + 1, output_line); - } break; + case CMD_TAKE: { + errorCode = s_cli_take(a_argc, a_argv, l_arg_index + 1, output_line); + } break; - default: { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command %s not recognized", a_argv[l_arg_index]); - dap_string_free(output_line, false); - } return 1; + default: { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Command %s not recognized", a_argv[l_arg_index]); + dap_string_free(output_line, false); + } return 1; } if (STAKE_NO_ERROR != errorCode) @@ -807,51 +834,51 @@ static int s_cli_stake_lock(int a_argc, char** a_argv, char** a_str_reply) * @param month_count * @return */ -static const char* s_give_month_str_from_month_count(uint8_t month_count) +static const char *s_give_month_str_from_month_count(uint8_t month_count) { switch (month_count) { - case 1: { - return "Jan"; - } - case 2: { - return "Feb"; - } - case 3: { - return "Mar"; - } - case 4: { - return "Apr"; - } - case 5: { - return "May"; - } - case 6: { - return "Jun"; - } - case 7: { - return "Jul"; - } - case 8: { - return "Aug"; - } - case 9: { - return "Sep"; - } - case 10: { - return "Oct"; - } - case 11: { - return "Nov"; - } - case 12: { - return "Dec"; - } + case 1: { + return "Jan"; + } + case 2: { + return "Feb"; + } + case 3: { + return "Mar"; + } + case 4: { + return "Apr"; + } + case 5: { + return "May"; + } + case 6: { + return "Jun"; + } + case 7: { + return "Jul"; + } + case 8: { + return "Aug"; + } + case 9: { + return "Sep"; + } + case 10: { + return "Oct"; + } + case 11: { + return "Nov"; + } + case 12: { + return "Dec"; + } - default: { - return ""; - } + default: { + return ""; + } } } @@ -860,7 +887,7 @@ static const char* s_give_month_str_from_month_count(uint8_t month_count) * @param time * @return */ -static uint8_t s_give_month_count_from_time_str(char* time) +static uint8_t s_give_month_count_from_time_str(char *time) { const uint8_t len_month = 3; @@ -898,20 +925,20 @@ static uint8_t s_give_month_count_from_time_str(char* time) * @param month_count * @return */ -static char* s_update_date_by_using_month_count(char* time, uint8_t month_count) +static char *s_update_date_by_using_month_count(char *time, uint8_t month_count) { uint8_t current_month; int current_year; - const char* month_str; - const char* year_str; + const char *month_str; + const char *year_str; if (!time || !month_count) return NULL; - if ((current_month = s_give_month_count_from_time_str(time)) == 0) + if ( (current_month = s_give_month_count_from_time_str(time)) == 0 ) return NULL; - if ((current_year = atoi(&time[YEAR_INDEX])) <= 0 - || current_year < 22 - || current_year > 99) + if ( (current_year = atoi(&time[YEAR_INDEX])) <= 0 + || current_year < 22 + || current_year > 99 ) return NULL; @@ -925,16 +952,15 @@ static char* s_update_date_by_using_month_count(char* time, uint8_t month_count) current_month++; } - month_str = s_give_month_str_from_month_count(current_month); - year_str = dap_itoa(current_year); + month_str = s_give_month_str_from_month_count(current_month); + year_str = dap_itoa(current_year); if (*month_str - && *year_str - && dap_strlen(year_str) == 2) { - memcpy(&time[MONTH_INDEX], month_str, 3); // 3 == len month in time RFC822 format - memcpy(&time[YEAR_INDEX], year_str, 2); // 2 == len year in time RFC822 format - } - else + && *year_str + && dap_strlen(year_str) == 2) { + memcpy(&time[MONTH_INDEX], month_str, 3); // 3 == len month in time RFC822 format + memcpy(&time[YEAR_INDEX], year_str, 2); // 2 == len year in time RFC822 format + } else return NULL; return time; @@ -942,62 +968,62 @@ static char* s_update_date_by_using_month_count(char* time, uint8_t month_count) /** * @brief s_callback_verificator + * @param a_ledger + * @param a_tx_out_hash * @param a_cond - * @param a_tx + * @param a_tx_in * @param a_owner * @return */ -bool s_callback_verificator(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_t *a_cond, dap_chain_datum_tx_t *a_tx, bool a_owner) +static bool s_stake_lock_callback_verificator(dap_ledger_t *a_ledger, dap_hash_fast_t *a_tx_out_hash, dap_chain_tx_out_cond_t *a_cond, + dap_chain_datum_tx_t *a_tx_in, bool a_owner) { + UNUSED(a_tx_out_hash); dap_chain_datum_tx_t *burning_tx = NULL; dap_chain_tx_out_t *burning_transaction_out = NULL; + dap_chain_datum_tx_receipt_t *l_receipt = NULL; uint256_t l_value_delegated = {}; dap_hash_fast_t hash_burning_transaction; dap_chain_datum_token_tsd_delegate_from_stake_lock_t l_tsd_section; dap_tsd_t *l_tsd; - cond_params_t *l_params; - dap_chain_datum_tx_receipt_t *l_receipt; dap_chain_tx_out_t *l_tx_out; dap_chain_tx_in_cond_t *l_tx_in_cond; const char *l_tx_ticker; dap_chain_datum_token_t *delegate_token; + char delegated_ticker[DAP_CHAIN_TICKER_SIZE_MAX]; /*if (!a_owner) TODO: ??? return false;*/ - if (a_cond->params_size != sizeof(*l_params))// Wrong params size - return false; - l_params = (cond_params_t*)a_cond->params; - - if (l_params->flags & DAP_CHAIN_NET_SRV_STAKE_LOCK_FLAG_BY_TIME) { - if (l_params->time_unlock > dap_time_now()) + if (a_cond->subtype.srv_stake_lock.flags & DAP_CHAIN_NET_SRV_STAKE_LOCK_FLAG_BY_TIME) { + if (a_cond->subtype.srv_stake_lock.time_unlock > dap_time_now()) return false; } - l_receipt = (dap_chain_datum_tx_receipt_t *)dap_chain_datum_tx_item_get(a_tx, 0, TX_ITEM_TYPE_RECEIPT, 0); - if (!l_receipt) - return false; + if (a_cond->subtype.srv_stake_lock.flags & DAP_CHAIN_NET_SRV_STAKE_LOCK_FLAG_CREATE_BASE_TX) { + l_receipt = (dap_chain_datum_tx_receipt_t *)dap_chain_datum_tx_item_get(a_tx_in, 0, TX_ITEM_TYPE_RECEIPT, 0); + if (!l_receipt) + return false; #if DAP_CHAIN_NET_SRV_UID_SIZE == 8 - if (l_receipt->receipt_info.srv_uid.uint64 != DAP_CHAIN_NET_SRV_STAKE_LOCK_ID) - return false; + if (l_receipt->receipt_info.srv_uid.uint64 != DAP_CHAIN_NET_SRV_STAKE_LOCK_ID) + return false; #elif DAP_CHAIN_NET_SRV_UID_SIZE == 16 - if (l_receipt->receipt_info.srv_uid.uint128 != DAP_CHAIN_NET_SRV_EXTERNAL_STAKE_ID) - return false; + if (l_receipt->receipt_info.srv_uid.uint128 != DAP_CHAIN_NET_SRV_EXTERNAL_STAKE_ID) + return false; #endif - char delegated_ticker[DAP_CHAIN_TICKER_SIZE_MAX]; - if (l_receipt->exts_size) { - hash_burning_transaction = *(dap_hash_fast_t*)l_receipt->exts_n_signs; - strcpy(delegated_ticker, (char *)&l_receipt->exts_n_signs[sizeof(dap_hash_fast_t)]); - } else { - return false; - } + if (l_receipt->exts_size) { + hash_burning_transaction = *(dap_hash_fast_t*)l_receipt->exts_n_signs; + strcpy(delegated_ticker, (char *)&l_receipt->exts_n_signs[sizeof(dap_hash_fast_t)]); + } else + return false; - if (dap_hash_fast_is_blank(&hash_burning_transaction)) - return false; + if (dap_hash_fast_is_blank(&hash_burning_transaction)) + return false; + } - l_tx_out = (dap_chain_tx_out_t *)dap_chain_datum_tx_item_get(a_tx, 0, TX_ITEM_TYPE_OUT,0); + l_tx_out = (dap_chain_tx_out_t *)dap_chain_datum_tx_item_get(a_tx_in, 0, TX_ITEM_TYPE_OUT, 0); if (!l_tx_out) return false; @@ -1005,66 +1031,67 @@ bool s_callback_verificator(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_t *a_c if (!EQUAL_256(a_cond->header.value, l_tx_out->header.value)) return false; - if (NULL == (delegate_token = dap_chain_ledger_token_ticker_check(a_ledger, delegated_ticker)) - || delegate_token->type != DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL - || !delegate_token->header_native_decl.tsd_total_size - || NULL == (l_tsd = dap_tsd_find(delegate_token->data_n_tsd, delegate_token->header_native_decl.tsd_total_size, DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DELEGATE_EMISSION_FROM_STAKE_LOCK))) { - return false; - } + if (a_cond->subtype.srv_stake_lock.flags & DAP_CHAIN_NET_SRV_STAKE_LOCK_FLAG_CREATE_BASE_TX) { + if (NULL == (delegate_token = dap_chain_ledger_token_ticker_check(a_ledger, delegated_ticker)) + || (delegate_token->type != DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL && delegate_token->type != DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_UPDATE) + || !delegate_token->header_native_decl.tsd_total_size + || NULL == (l_tsd = dap_tsd_find(delegate_token->data_n_tsd, delegate_token->header_native_decl.tsd_total_size, DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DELEGATE_EMISSION_FROM_STAKE_LOCK))) { + return false; + } - l_tsd_section = dap_tsd_get_scalar(l_tsd, dap_chain_datum_token_tsd_delegate_from_stake_lock_t); + l_tsd_section = dap_tsd_get_scalar(l_tsd, dap_chain_datum_token_tsd_delegate_from_stake_lock_t); - if (NULL == (l_tx_in_cond = (dap_chain_tx_in_cond_t *)dap_chain_datum_tx_item_get(a_tx, 0, TX_ITEM_TYPE_IN_COND, 0))) - return false; - if (dap_hash_fast_is_blank(&l_tx_in_cond->header.tx_prev_hash)) - return false; - if (NULL == (l_tx_ticker = dap_chain_ledger_tx_get_token_ticker_by_hash(a_ledger, &l_tx_in_cond->header.tx_prev_hash))) - return false; - if (strcmp(l_tx_ticker, l_tsd_section.ticker_token_from)) - return false; - if (NULL == (l_tx_ticker = dap_chain_ledger_tx_get_token_ticker_by_hash(a_ledger, &hash_burning_transaction))) - return false; - if (strcmp(l_tx_ticker, delegated_ticker)) { - return false; - } + if (NULL == (l_tx_in_cond = (dap_chain_tx_in_cond_t *)dap_chain_datum_tx_item_get(a_tx_in, 0, TX_ITEM_TYPE_IN_COND, 0))) + return false; + if (dap_hash_fast_is_blank(&l_tx_in_cond->header.tx_prev_hash)) + return false; + if (NULL == (l_tx_ticker = dap_chain_ledger_tx_get_token_ticker_by_hash(a_ledger, &l_tx_in_cond->header.tx_prev_hash))) + return false; + if (strcmp(l_tx_ticker, l_tsd_section.ticker_token_from)) + return false; + if (NULL == (l_tx_ticker = dap_chain_ledger_tx_get_token_ticker_by_hash(a_ledger, &hash_burning_transaction))) + return false; + if (strcmp(l_tx_ticker, delegated_ticker)) + return false; - burning_tx = dap_chain_ledger_tx_find_by_hash(a_ledger, &hash_burning_transaction); - burning_transaction_out = (dap_chain_tx_out_t*)dap_chain_datum_tx_item_get(burning_tx, 0, TX_ITEM_TYPE_OUT, 0); + burning_tx = dap_chain_ledger_tx_find_by_hash(a_ledger, &hash_burning_transaction); + burning_transaction_out = (dap_chain_tx_out_t *)dap_chain_datum_tx_item_get(burning_tx, 0, TX_ITEM_TYPE_OUT,0); - if (!burning_transaction_out) - return false; + if (!burning_transaction_out) + return false; + + if (!dap_hash_fast_is_blank(&burning_transaction_out->addr.data.hash_fast)) { + if (s_debug_more) { + const char *addr_srt = dap_chain_hash_fast_to_str_new(&burning_transaction_out->addr.data.hash_fast); + log_it(L_ERROR, "ADDR from burning NOT BLANK: %s", addr_srt); + DAP_DEL_Z(addr_srt); + } + return false; + } + + if (!IS_ZERO_256(l_tsd_section.emission_rate)) { + MULT_256_COIN(l_tx_out->header.value, l_tsd_section.emission_rate, &l_value_delegated); + if (IS_ZERO_256(l_value_delegated)) + return COINS_FORMAT_ERROR; + } else + l_value_delegated = l_tx_out->header.value; - if (!dap_hash_fast_is_blank(&burning_transaction_out->addr.data.hash_fast)) { if (s_debug_more) { - const char *addr_srt = dap_chain_hash_fast_to_str_new(&burning_transaction_out->addr.data.hash_fast); - log_it(L_ERROR, "ADDR from burning NOT BLANK: %s", addr_srt); - DAP_DEL_Z(addr_srt); + char *str1 = dap_chain_balance_print(burning_transaction_out->header.value); + char *str2 = dap_chain_balance_print(l_tx_out->header.value); + char *str3 = dap_chain_balance_print(l_value_delegated); + log_it(L_INFO, "burning_value: |%s|", str1); + log_it(L_INFO, "hold/take_value: |%s|", str2); + log_it(L_INFO, "delegated_value |%s|", str3); + DAP_DEL_Z(str1); + DAP_DEL_Z(str2); + DAP_DEL_Z(str3); } - return false; - } - if (!IS_ZERO_256(l_tsd_section.emission_rate)) { - MULT_256_COIN(l_tx_out->header.value, l_tsd_section.emission_rate, &l_value_delegated); - if (IS_ZERO_256(l_value_delegated)) - return COINS_FORMAT_ERROR; - } else - l_value_delegated = l_tx_out->header.value; - - if (s_debug_more) { - char *str1 = dap_chain_balance_print(burning_transaction_out->header.value); - char *str2 = dap_chain_balance_print(l_tx_out->header.value); - char *str3 = dap_chain_balance_print(l_value_delegated); - log_it(L_INFO, "burning_value: |%s|", str1); - log_it(L_INFO, "hold/take_value: |%s|", str2); - log_it(L_INFO, "delegated_value |%s|", str3); - DAP_DEL_Z(str1); - DAP_DEL_Z(str2); - DAP_DEL_Z(str3); + if (!EQUAL_256(burning_transaction_out->header.value, l_value_delegated)) + return false; } - if (!EQUAL_256(burning_transaction_out->header.value, l_value_delegated))//MULT - return false; - return true; } @@ -1075,22 +1102,19 @@ bool s_callback_verificator(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_t *a_c * @param a_tx_item_idx * @return */ -bool s_callback_verificator_added(dap_ledger_t * a_ledger,dap_chain_datum_tx_t* a_tx, dap_chain_tx_out_cond_t *a_tx_item) +static bool s_stake_lock_callback_verificator_added(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_tx_out_cond_t *a_tx_item) { - dap_chain_hash_fast_t* l_key_hash = DAP_NEW_Z(dap_chain_hash_fast_t); - if (!l_key_hash) - return false; - size_t l_tx_size = dap_chain_datum_tx_get_size(a_tx); - dap_hash_fast(a_tx, l_tx_size, l_key_hash); - if (dap_hash_fast_is_blank(l_key_hash)) { - DAP_DEL_Z(l_key_hash); - return false; + if (a_tx_item) // this is IN_COND tx + return true; + int l_out_num = 0; + dap_chain_tx_out_cond_t *l_cond = dap_chain_datum_tx_out_cond_get(a_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK, &l_out_num); + if (l_cond->subtype.srv_stake_lock.flags & DAP_CHAIN_NET_SRV_STAKE_LOCK_FLAG_CREATE_BASE_TX) { + dap_chain_hash_fast_t l_key_hash; + dap_hash_fast( a_tx, dap_chain_datum_tx_get_size(a_tx), &l_key_hash); + if (dap_hash_fast_is_blank(&l_key_hash)) + return false; + dap_chain_ledger_emission_for_stake_lock_item_add(a_ledger, &l_key_hash); } - - s_emission_for_stake_lock_item_add(a_ledger, l_key_hash); - - DAP_DEL_Z(l_key_hash); - return true; } @@ -1106,15 +1130,16 @@ bool s_callback_verificator_added(dap_ledger_t * a_ledger,dap_chain_datum_tx_t* * @param a_count_months * @return */ -static dap_chain_datum_t* s_mempool_create(dap_chain_net_t* a_net, - dap_enc_key_t* a_key_from, dap_pkey_t* a_key_cond, - const char a_token_ticker[DAP_CHAIN_TICKER_SIZE_MAX], - uint256_t a_value, dap_chain_net_srv_uid_t a_srv_uid, - dap_chain_addr_t* a_addr_holder, dap_time_t a_time_staking, uint8_t reinvest) +static dap_chain_datum_t* s_mempool_create(dap_chain_net_t *a_net, + dap_enc_key_t *a_key_from, dap_pkey_t *a_key_cond, + const char a_token_ticker[DAP_CHAIN_TICKER_SIZE_MAX], + uint256_t a_value, dap_chain_net_srv_uid_t a_srv_uid, + dap_chain_addr_t *a_addr_holder, dap_time_t a_time_staking, + uint256_t a_reinvest_percent, bool create_base_tx) { - dap_ledger_t* l_ledger = a_net ? dap_chain_ledger_by_net_name(a_net->pub.name) : NULL; + dap_ledger_t * l_ledger = a_net ? dap_chain_ledger_by_net_name( a_net->pub.name ) : NULL; // check valid param - if (!a_net || !l_ledger || !a_key_from || !a_key_cond || + if (!a_net || !l_ledger || !a_key_from || !a_key_from->priv_key_data || !a_key_from->priv_key_data_size || IS_ZERO_256(a_value)) return NULL; @@ -1126,15 +1151,15 @@ static dap_chain_datum_t* s_mempool_create(dap_chain_net_t* a_net, dap_chain_addr_t l_addr_from; dap_chain_addr_fill_from_key(&l_addr_from, a_key_from, a_net->pub.id); // list of transaction with 'out' items - dap_list_t* l_list_used_out = dap_chain_ledger_get_list_tx_outs_with_val(l_ledger, a_token_ticker, - &l_addr_from, a_value, &l_value_transfer); - if (!l_list_used_out) { - log_it(L_ERROR, "Nothing to tranfer (not enough funds)"); + dap_list_t *l_list_used_out = dap_chain_ledger_get_list_tx_outs_with_val(l_ledger, a_token_ticker, + &l_addr_from, a_value, &l_value_transfer); + if(!l_list_used_out) { + log_it( L_ERROR, "Nothing to tranfer (not enough funds)"); return NULL; } // create empty transaction - dap_chain_datum_tx_t* l_tx = dap_chain_datum_tx_create(); + dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create(); // add 'in' items { uint256_t l_value_to_items = dap_chain_datum_tx_add_in_item_list(&l_tx, l_list_used_out); @@ -1144,37 +1169,37 @@ static dap_chain_datum_t* s_mempool_create(dap_chain_net_t* a_net, // add 'out_cond' and 'out' items { uint256_t l_value_pack = {}; // how much coin add to 'out' items - dap_chain_tx_out_cond_t* l_tx_out_cond = dap_chain_net_srv_stake_lock_create_cond_out(a_key_cond, a_srv_uid, a_value, a_time_staking, reinvest); - if (l_tx_out_cond) { + dap_chain_tx_out_cond_t* l_tx_out_cond = dap_chain_net_srv_stake_lock_create_cond_out(a_key_cond, a_srv_uid, a_value, a_time_staking, a_reinvest_percent, create_base_tx); + if(l_tx_out_cond) { SUM_256_256(l_value_pack, a_value, &l_value_pack); - dap_chain_datum_tx_add_item(&l_tx, (const uint8_t*)l_tx_out_cond); - // DAP_DEL_Z(l_tx_out_cond); - // transaction fee - // if (!IS_ZERO_256(a_value_fee)) { - // TODO add condition with fee for mempool-as-service - // } + dap_chain_datum_tx_add_item(&l_tx, (const uint8_t *)l_tx_out_cond); +// DAP_DEL_Z(l_tx_out_cond); + // transaction fee +// if (!IS_ZERO_256(a_value_fee)) { + // TODO add condition with fee for mempool-as-service +// } }//TODO: else return false; // coin back uint256_t l_value_back = {}; SUBTRACT_256_256(l_value_transfer, l_value_pack, &l_value_back); if (!IS_ZERO_256(l_value_back)) { - if (dap_chain_datum_tx_add_out_item(&l_tx, &l_addr_from, l_value_back) != 1) { + if(dap_chain_datum_tx_add_out_item(&l_tx, &l_addr_from, l_value_back) != 1) { dap_chain_datum_tx_delete(l_tx); - log_it(L_ERROR, "Cant add coin back output"); + log_it( L_ERROR, "Cant add coin back output"); return NULL; } } } // add 'sign' items - if (dap_chain_datum_tx_add_sign_item(&l_tx, a_key_from) != 1) { + if(dap_chain_datum_tx_add_sign_item(&l_tx, a_key_from) != 1) { dap_chain_datum_tx_delete(l_tx); - log_it(L_ERROR, "Can't add sign output"); + log_it( L_ERROR, "Can't add sign output"); return NULL; } - size_t l_tx_size = dap_chain_datum_tx_get_size(l_tx); - dap_chain_datum_t* l_datum = dap_chain_datum_create(DAP_CHAIN_DATUM_TX, l_tx, l_tx_size); + size_t l_tx_size = dap_chain_datum_tx_get_size( l_tx ); + dap_chain_datum_t *l_datum = dap_chain_datum_create( DAP_CHAIN_DATUM_TX, l_tx, l_tx_size ); return l_datum; } @@ -1188,25 +1213,27 @@ static dap_chain_datum_t* s_mempool_create(dap_chain_net_t* a_net, * @param token * @return */ -dap_chain_tx_out_cond_t* dap_chain_net_srv_stake_lock_create_cond_out(dap_pkey_t* a_key, dap_chain_net_srv_uid_t a_srv_uid, uint256_t a_value, - uint64_t a_time_staking, uint8_t reinvest) +dap_chain_tx_out_cond_t *dap_chain_net_srv_stake_lock_create_cond_out(dap_pkey_t *a_key, dap_chain_net_srv_uid_t a_srv_uid, + uint256_t a_value, uint64_t a_time_staking, + uint256_t a_reinvest_percent, bool create_base_tx) { if (IS_ZERO_256(a_value)) return NULL; - dap_chain_tx_out_cond_t* l_item = DAP_NEW_Z_SIZE(dap_chain_tx_out_cond_t, sizeof(dap_chain_tx_out_cond_t) + sizeof(cond_params_t)); + dap_chain_tx_out_cond_t *l_item = DAP_NEW_Z(dap_chain_tx_out_cond_t); l_item->header.item_type = TX_ITEM_TYPE_OUT_COND; l_item->header.value = a_value; l_item->header.subtype = DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK; l_item->header.srv_uid = a_srv_uid; - l_item->params_size = sizeof(cond_params_t); - cond_params_t* l_params = (cond_params_t*)l_item->params; - l_params->reinvest = reinvest; + l_item->subtype.srv_stake_lock.reinvest_percent = a_reinvest_percent; if (a_time_staking) { - l_params->time_unlock = dap_time_now() + a_time_staking; - l_params->flags |= DAP_CHAIN_NET_SRV_STAKE_LOCK_FLAG_BY_TIME; +// l_item->header.ts_expires = dap_time_now() + a_time_staking; + l_item->subtype.srv_stake_lock.time_unlock = dap_time_now() + a_time_staking; + l_item->subtype.srv_stake_lock.flags |= DAP_CHAIN_NET_SRV_STAKE_LOCK_FLAG_BY_TIME; } + if (create_base_tx) + l_item->subtype.srv_stake_lock.flags |= DAP_CHAIN_NET_SRV_STAKE_LOCK_FLAG_CREATE_BASE_TX; if (a_key) - dap_hash_fast(a_key->pkey, a_key->header.size, &l_params->pkey_delegated); + dap_hash_fast(a_key->pkey, a_key->header.size, &l_item->subtype.srv_stake_lock.pkey_delegated); return l_item; } @@ -1224,31 +1251,33 @@ dap_chain_tx_out_cond_t* dap_chain_net_srv_stake_lock_create_cond_out(dap_pkey_t * @param a_time_staking * @return */ -dap_chain_hash_fast_t* dap_chain_net_srv_stake_lock_mempool_create(dap_chain_net_t* a_net, - dap_enc_key_t* a_key_from, dap_pkey_t* a_key_cond, - const char a_token_ticker[DAP_CHAIN_TICKER_SIZE_MAX], - uint256_t a_value, dap_chain_net_srv_uid_t a_srv_uid, - dap_chain_addr_t* a_addr_holder, uint64_t a_time_staking, uint8_t reinvest) +dap_chain_hash_fast_t* dap_chain_net_srv_stake_lock_mempool_create(dap_chain_net_t *a_net, + dap_enc_key_t *a_key_from, dap_pkey_t *a_key_cond, + const char a_token_ticker[DAP_CHAIN_TICKER_SIZE_MAX], + uint256_t a_value, dap_chain_net_srv_uid_t a_srv_uid, + dap_chain_addr_t *a_addr_holder, dap_chain_t *a_chain, + uint64_t a_time_staking, uint256_t a_reinvest_percent, + bool create_base_tx) { // Make transfer transaction - dap_chain_datum_t* l_datum = s_mempool_create(a_net, a_key_from, a_key_cond, a_token_ticker, a_value, a_srv_uid, - a_addr_holder, a_time_staking, reinvest); + dap_chain_datum_t *l_datum = s_mempool_create(a_net, a_key_from, a_key_cond, a_token_ticker, a_value, a_srv_uid, + a_addr_holder, a_time_staking, a_reinvest_percent, create_base_tx); - if (!l_datum) + if(!l_datum) return NULL; - dap_chain_datum_tx_t* l_tx = (dap_chain_datum_tx_t*)&(l_datum->data); + dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t*)&(l_datum->data); size_t l_tx_size = l_datum->header.data_size; - dap_chain_hash_fast_t* l_key_hash = DAP_NEW_Z(dap_chain_hash_fast_t); - dap_hash_fast(l_tx, l_tx_size, l_key_hash); + dap_chain_hash_fast_t *l_key_hash = DAP_NEW_Z( dap_chain_hash_fast_t ); + dap_hash_fast( l_tx, l_tx_size, l_key_hash); - char* l_key_str = dap_chain_hash_fast_to_str_new(l_key_hash); - char* l_gdb_group = dap_chain_net_get_gdb_group_mempool_by_chain_type(a_net, CHAIN_TYPE_TX); + char * l_key_str = dap_chain_hash_fast_to_str_new( l_key_hash ); + char * l_gdb_group = dap_chain_net_get_gdb_group_mempool_new(a_chain); - if (dap_global_db_set(l_gdb_group, l_key_str, l_datum, dap_chain_datum_size(l_datum), false, NULL, NULL) == true) { + if (dap_global_db_set_sync(l_gdb_group, l_key_str, l_datum, dap_chain_datum_size(l_datum), false) == + DAP_GLOBAL_DB_RC_SUCCESS) log_it(L_NOTICE, "Transaction %s placed in mempool group %s", l_key_str, l_gdb_group); - } DAP_DELETE(l_gdb_group); DAP_DELETE(l_key_str); @@ -1256,26 +1285,26 @@ dap_chain_hash_fast_t* dap_chain_net_srv_stake_lock_mempool_create(dap_chain_net return l_key_hash; } -dap_chain_datum_t* dap_chain_burning_tx_create(dap_chain_t* a_chain, dap_enc_key_t* a_key_from, - const dap_chain_addr_t* a_addr_from, const dap_chain_addr_t* a_addr_to, - const char a_token_ticker[DAP_CHAIN_TICKER_SIZE_MAX], - uint256_t a_value) +dap_chain_datum_t *dap_chain_burning_tx_create(dap_chain_t *a_chain, dap_enc_key_t *a_key_from, + const dap_chain_addr_t* a_addr_from, const dap_chain_addr_t* a_addr_to, + const char a_token_ticker[DAP_CHAIN_TICKER_SIZE_MAX], + uint256_t a_value) { // check valid param - if (!a_chain | !a_key_from || !a_addr_from || !a_key_from->priv_key_data || !a_key_from->priv_key_data_size || - !dap_chain_addr_check_sum(a_addr_from) || (a_addr_to && !dap_chain_addr_check_sum(a_addr_to)) || IS_ZERO_256(a_value)) + if(!a_chain | !a_key_from || ! a_addr_from || !a_key_from->priv_key_data || !a_key_from->priv_key_data_size || + !dap_chain_addr_check_sum(a_addr_from) || (a_addr_to && !dap_chain_addr_check_sum(a_addr_to)) || IS_ZERO_256(a_value)) return NULL; // find the transactions from which to take away coins uint256_t l_value_transfer = {}; // how many coins to transfer - dap_list_t* l_list_used_out = dap_chain_ledger_get_list_tx_outs_with_val(a_chain->ledger, a_token_ticker, - a_addr_from, a_value, &l_value_transfer); + dap_list_t *l_list_used_out = dap_chain_ledger_get_list_tx_outs_with_val(a_chain->ledger, a_token_ticker, + a_addr_from, a_value, &l_value_transfer); if (!l_list_used_out) { - log_it(L_WARNING, "Not enough funds to transfer"); + log_it(L_WARNING,"Not enough funds to transfer"); return NULL; } // create empty transaction - dap_chain_datum_tx_t* l_tx = dap_chain_datum_tx_create(); + dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create(); // add 'in' items { uint256_t l_value_to_items = dap_chain_datum_tx_add_in_item_list(&l_tx, l_list_used_out); @@ -1285,14 +1314,14 @@ dap_chain_datum_t* dap_chain_burning_tx_create(dap_chain_t* a_chain, dap_enc_key // add 'out' items { uint256_t l_value_pack = {}; // how much datoshi add to 'out' items - if (dap_chain_datum_tx_add_out_item(&l_tx, a_addr_to, a_value) == 1) { + if(dap_chain_datum_tx_add_out_item(&l_tx, a_addr_to, a_value) == 1) { SUM_256_256(l_value_pack, a_value, &l_value_pack); } // coin back uint256_t l_value_back; SUBTRACT_256_256(l_value_transfer, l_value_pack, &l_value_back); - if (!IS_ZERO_256(l_value_back)) { - if (dap_chain_datum_tx_add_out_item(&l_tx, a_addr_from, l_value_back) != 1) { + if(!IS_ZERO_256(l_value_back)) { + if(dap_chain_datum_tx_add_out_item(&l_tx, a_addr_from, l_value_back) != 1) { dap_chain_datum_tx_delete(l_tx); return NULL; } @@ -1300,30 +1329,84 @@ dap_chain_datum_t* dap_chain_burning_tx_create(dap_chain_t* a_chain, dap_enc_key } // add 'sign' items - if (dap_chain_datum_tx_add_sign_item(&l_tx, a_key_from) != 1) { + if(dap_chain_datum_tx_add_sign_item(&l_tx, a_key_from) != 1) { dap_chain_datum_tx_delete(l_tx); return NULL; } size_t l_tx_size = dap_chain_datum_tx_get_size(l_tx); - dap_chain_datum_t* l_datum = dap_chain_datum_create(DAP_CHAIN_DATUM_TX, l_tx, l_tx_size); + dap_chain_datum_t *l_datum = dap_chain_datum_create(DAP_CHAIN_DATUM_TX, l_tx, l_tx_size); DAP_DELETE(l_tx); return l_datum; - // dap_hash_fast_t * l_ret = DAP_NEW_Z(dap_hash_fast_t); - // dap_hash_fast(l_tx, l_tx_size, l_ret); - // DAP_DELETE(l_tx); - // char *l_hash_str = dap_chain_mempool_datum_add(l_datum, a_chain); - - // DAP_DELETE( l_datum ); - // - // if (l_hash_str) { - // DAP_DELETE(l_hash_str); - // return l_ret; - // }else{ - // DAP_DELETE(l_ret); - // return NULL; - // } +// dap_hash_fast_t * l_ret = DAP_NEW_Z(dap_hash_fast_t); +// dap_hash_fast(l_tx, l_tx_size, l_ret); +// DAP_DELETE(l_tx); +// char *l_hash_str = dap_chain_mempool_datum_add(l_datum, a_chain); + +// DAP_DELETE( l_datum ); +// +// if (l_hash_str) { +// DAP_DELETE(l_hash_str); +// return l_ret; +// }else{ +// DAP_DELETE(l_ret); +// return NULL; +// } +} + +static dap_chain_hash_fast_t *dap_chain_mempool_base_tx_for_stake_lock_create(dap_chain_t *a_chain, dap_chain_hash_fast_t *a_emission_hash, + dap_chain_id_t a_emission_chain_id, uint256_t a_emission_value, const char *a_ticker, + dap_chain_addr_t *a_addr_to, dap_enc_key_t *a_key_from) +{ + char *l_gdb_group_mempool_base_tx = dap_chain_net_get_gdb_group_mempool_new(a_chain); + // create first transaction (with tx_token) + dap_chain_datum_tx_t *l_tx = DAP_NEW_Z_SIZE(dap_chain_datum_tx_t, sizeof(dap_chain_datum_tx_t)); + l_tx->header.ts_created = time(NULL); + dap_chain_hash_fast_t l_tx_prev_hash = { 0 }; + // create items + + dap_chain_tx_token_t *l_tx_token = dap_chain_datum_tx_item_token_create(a_emission_chain_id, a_emission_hash, a_ticker); + dap_chain_tx_in_t *l_in = dap_chain_datum_tx_item_in_create(&l_tx_prev_hash, 0); + dap_chain_tx_out_t *l_out = dap_chain_datum_tx_item_out_create(a_addr_to, a_emission_value); + + // pack items to transaction + dap_chain_datum_tx_add_item(&l_tx, (const uint8_t*) l_tx_token); + dap_chain_datum_tx_add_item(&l_tx, (const uint8_t*) l_in); + dap_chain_datum_tx_add_item(&l_tx, (const uint8_t*) l_out); + + if (a_key_from) { + if(dap_chain_datum_tx_add_sign_item(&l_tx, a_key_from) < 0) { + log_it(L_WARNING, "Private key not valid"); + return NULL; + } + } else { + log_it(L_WARNING, "No private key for base TX!"); + return NULL; + } + + DAP_DEL_Z(l_tx_token); + DAP_DEL_Z(l_in); + DAP_DEL_Z(l_out); + + size_t l_tx_size = dap_chain_datum_tx_get_size(l_tx); + + // Pack transaction into the datum + dap_chain_datum_t * l_datum_tx = dap_chain_datum_create(DAP_CHAIN_DATUM_TX, l_tx, l_tx_size); + size_t l_datum_tx_size = dap_chain_datum_size(l_datum_tx); + DAP_DEL_Z(l_tx); + // calc datum hash + dap_chain_hash_fast_t *l_datum_tx_hash = DAP_NEW(dap_hash_fast_t); + dap_hash_fast(l_datum_tx, l_datum_tx_size, l_datum_tx_hash); + char *l_tx_hash_str = dap_chain_hash_fast_to_str_new(l_datum_tx_hash); + // Add to mempool tx token + bool l_placed = dap_global_db_set_sync(l_gdb_group_mempool_base_tx, l_tx_hash_str, l_datum_tx, + l_datum_tx_size, false) == DAP_GLOBAL_DB_RC_SUCCESS; + DAP_DEL_Z(l_tx_hash_str); + DAP_DELETE(l_datum_tx); + if (!l_placed) + return NULL; + return l_datum_tx_hash; } diff --git a/modules/service/stake_lock/include/dap_chain_net_srv_stake_lock.h b/modules/service/stake_lock/include/dap_chain_net_srv_stake_lock.h index 6018736c6dea95a89ea3b9f8d836a27a5cc7cb74..b7fbb5d2523fcf7089943d260a6a03a93829e986 100644 --- a/modules/service/stake_lock/include/dap_chain_net_srv_stake_lock.h +++ b/modules/service/stake_lock/include/dap_chain_net_srv_stake_lock.h @@ -39,27 +39,31 @@ #define DAP_CHAIN_NET_SRV_STAKE_LOCK_FLAG_DELEGATE_PKEY 0x00000004 // Lock by time #define DAP_CHAIN_NET_SRV_STAKE_LOCK_FLAG_BY_TIME 0x00000008 +// Create base tx for delegated token +#define DAP_CHAIN_NET_SRV_STAKE_LOCK_FLAG_CREATE_BASE_TX 0x00000010 + +/** + * @brief The cond_params struct thats placed in tx_cond->params[] section + */ int dap_chain_net_srv_stake_lock_init(void); void dap_chain_net_srv_stake_lock_deinit(void); -bool s_callback_verificator(dap_ledger_t *a_ledger,dap_chain_tx_out_cond_t *a_cond, dap_chain_datum_tx_t *a_tx, bool a_owner); -bool s_callback_verificator_added(dap_ledger_t *a_ledger,dap_chain_datum_tx_t * a_tx, dap_chain_tx_out_cond_t *a_tx_item); - // Create cond out -dap_chain_tx_out_cond_t *dap_chain_net_srv_stake_lock_create_cond_out(dap_pkey_t *a_key, dap_chain_net_srv_uid_t a_srv_uid, uint256_t a_value, - uint64_t a_time_staking, uint8_t reinvest); - +dap_chain_tx_out_cond_t *dap_chain_net_srv_stake_lock_create_cond_out(dap_pkey_t *a_key, dap_chain_net_srv_uid_t a_srv_uid, + uint256_t a_value, uint64_t a_time_staking, + uint256_t a_reinvest_percent, bool create_base_tx); // Create mempool dap_chain_hash_fast_t *dap_chain_net_srv_stake_lock_mempool_create(dap_chain_net_t *a_net, - dap_enc_key_t* a_key_from, dap_pkey_t* a_key_cond, - const char a_token_ticker[DAP_CHAIN_TICKER_SIZE_MAX], - uint256_t a_value, dap_chain_net_srv_uid_t a_srv_uid, - dap_chain_addr_t* a_addr_holder, uint64_t a_time_staking, uint8_t reinvest); - + dap_enc_key_t* a_key_from, dap_pkey_t* a_key_cond, + const char a_token_ticker[DAP_CHAIN_TICKER_SIZE_MAX], + uint256_t a_value, dap_chain_net_srv_uid_t a_srv_uid, + dap_chain_addr_t *a_addr_holder, dap_chain_t *a_chain, + uint64_t a_time_staking, uint256_t a_reinvest_percent, + bool create_base_tx); // Burning_tx_create dap_chain_datum_t* dap_chain_burning_tx_create(dap_chain_t* a_chain, dap_enc_key_t* a_key_from, - const dap_chain_addr_t* a_addr_from, const dap_chain_addr_t* a_addr_to, - const char a_token_ticker[DAP_CHAIN_TICKER_SIZE_MAX], - uint256_t a_value); + const dap_chain_addr_t* a_addr_from, const dap_chain_addr_t* a_addr_to, + const char a_token_ticker[DAP_CHAIN_TICKER_SIZE_MAX], + uint256_t a_value); diff --git a/modules/service/stake_pos_delegate/dap_chain_net_srv_stake_pos_delegate.c b/modules/service/stake_pos_delegate/dap_chain_net_srv_stake_pos_delegate.c index 3eb577a03dc3a3c5c9ebe7b20fe37a8070a252f5..18ff05af79b5d2433869212417d365d58ebc8dcb 100644 --- a/modules/service/stake_pos_delegate/dap_chain_net_srv_stake_pos_delegate.c +++ b/modules/service/stake_pos_delegate/dap_chain_net_srv_stake_pos_delegate.c @@ -41,6 +41,9 @@ static int s_callback_requested(dap_chain_net_srv_t *a_srv, uint32_t a_usage_id, static int s_callback_response_success(dap_chain_net_srv_t *a_srv, uint32_t a_usage_id, dap_chain_net_srv_client_remote_t *a_srv_client, const void *a_data, size_t a_data_size); static int s_callback_response_error(dap_chain_net_srv_t *a_srv, uint32_t a_usage_id, dap_chain_net_srv_client_remote_t *a_srv_client, const void *a_data, size_t a_data_size); static int s_callback_receipt_next_success(dap_chain_net_srv_t *a_srv, uint32_t a_usage_id, dap_chain_net_srv_client_remote_t *a_srv_client, const void *a_data, size_t a_data_size); +static bool s_verificator_stake_callback(dap_ledger_t * a_ledger,dap_hash_fast_t *a_tx_out_hash, dap_chain_tx_out_cond_t *a_cond, + dap_chain_datum_tx_t *a_tx_in, bool a_owner); +static bool s_verificator_stake_updater_callback(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_tx_out_cond_t *a_cond); static dap_chain_net_srv_stake_t *s_srv_stake = NULL; @@ -52,6 +55,7 @@ static dap_chain_net_srv_stake_t *s_srv_stake = NULL; */ int dap_chain_net_srv_stake_pos_delegate_init() { + dap_chain_ledger_verificator_add(DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE, s_verificator_stake_callback, s_verificator_stake_updater_callback); dap_cli_server_cmd_add("srv_stake", s_cli_srv_stake, "Delegated stake service commands", "srv_stake order create -net <net_name> -addr_hldr <addr> -token <token_ticker> -coins <value> -cert <priv_cert_name> -fee_percent <value>\n" "\tCreate a new order with specified amount of datoshi to delegate specified cert from the specified address.\n" @@ -105,7 +109,8 @@ int dap_chain_net_srv_stake_pos_delegate_init() } // Find all stake transactions do { - l_tx_tmp = dap_chain_ledger_tx_cache_find_out_cond(l_ledger, &l_tx_cur_hash, &l_out_cond, &l_out_cond_idx, l_token); + l_tx_tmp = dap_chain_ledger_tx_cache_find_out_cond(l_ledger, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE, + &l_tx_cur_hash, &l_out_cond, &l_out_cond_idx, l_token); if (!l_tx_tmp) { break; } @@ -215,8 +220,9 @@ static bool s_stake_conditions_calc(dap_chain_tx_out_cond_t *a_cond, dap_chain_d { dap_chain_tx_out_cond_t *l_out_cond = NULL; if (!a_cond) { + int l_out_num = 0; // New stake tx - l_out_cond = (dap_chain_tx_out_cond_t *)dap_chain_datum_tx_item_get(a_tx, NULL, TX_ITEM_TYPE_OUT_COND, NULL); + l_out_cond = dap_chain_datum_tx_out_cond_get(a_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK, &l_out_num); } else l_out_cond = a_cond; dap_chain_net_id_t l_cur_net_id = l_out_cond->subtype.srv_stake.hldr_addr.net_id; @@ -254,22 +260,6 @@ static bool s_stake_conditions_calc(dap_chain_tx_out_cond_t *a_cond, dap_chain_d return false; } -bool dap_chain_net_srv_stake_pos_delegate_verificator(dap_ledger_t* a_ledger, dap_chain_tx_out_cond_t *a_cond, dap_chain_datum_tx_t *a_tx, bool a_owner) -{ - if (!s_srv_stake) { - return false; - } - return s_stake_conditions_calc(a_cond, a_tx, a_owner, false); -} - -bool dap_chain_net_srv_stake_updater(dap_ledger_t* a_ledger, dap_chain_tx_out_cond_t *a_cond, dap_chain_datum_tx_t *a_tx, bool a_owner) -{ - if (!s_srv_stake) { - return false; - } - return s_stake_conditions_calc(a_cond, a_tx, a_owner, true); -} - bool dap_chain_net_srv_stake_key_delegated(dap_chain_addr_t *a_addr) { if (!s_srv_stake) { @@ -358,11 +348,11 @@ bool dap_chain_net_srv_stake_validator(dap_chain_addr_t *a_addr, dap_chain_datum } dap_list_free(l_list_out_items); uint256_t l_fee = uint256_0; // TODO replace with fractional mult MULT_256_FRAC_FRAC(l_outs_sum, l_stake->fee_value / 100.0); +++ - DIV_256(l_stake->fee_value, dap_chain_coins_to_balance("100.0"), &l_fee); - if (MULT_256_COIN(l_outs_sum, l_fee, &l_fee)) { - log_it(L_WARNING, "DANGER: MULT_256_COIN overflow! in dap_chain_net_srv_stake_validator()"); - l_fee = uint256_0; - } + DIV_256(l_stake->fee_value, dap_chain_coins_to_balance("100.0"), &l_fee); + if (MULT_256_COIN(l_outs_sum, l_fee, &l_fee)) { + log_it(L_WARNING, "DANGER: MULT_256_COIN overflow! in dap_chain_net_srv_stake_validator()"); + l_fee = uint256_0; + } if (compare256(l_fee_sum, l_fee) == -1) { return false; } @@ -487,7 +477,8 @@ static dap_chain_datum_tx_t *s_stake_tx_approve(dap_chain_net_srv_stake_item_t * return NULL; } int l_prev_cond_idx = 0; - dap_chain_tx_out_cond_t *l_tx_out_cond = dap_chain_datum_tx_out_cond_get(l_cond_tx, &l_prev_cond_idx); + dap_chain_tx_out_cond_t *l_tx_out_cond = dap_chain_datum_tx_out_cond_get(l_cond_tx, + DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE, &l_prev_cond_idx); if (dap_chain_ledger_tx_hash_is_used_out_item(l_ledger, &a_stake->tx_hash, l_prev_cond_idx)) { log_it(L_WARNING, "Requested conditional transaction is already used out"); return NULL; @@ -540,9 +531,10 @@ static bool s_stake_tx_invalidate(dap_chain_net_srv_stake_item_t *a_stake, dap_c if (!l_cond_tx) { log_it(L_WARNING, "Requested conditional transaction not found"); return false; - } + } int l_prev_cond_idx = 0; - dap_chain_tx_out_cond_t *l_tx_out_cond = dap_chain_datum_tx_out_cond_get(l_cond_tx, &l_prev_cond_idx); + dap_chain_tx_out_cond_t *l_tx_out_cond = dap_chain_datum_tx_out_cond_get(l_cond_tx, + DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE, &l_prev_cond_idx); if (dap_chain_ledger_tx_hash_is_used_out_item(l_ledger, &a_stake->tx_hash, l_prev_cond_idx)) { log_it(L_WARNING, "Requested conditional transaction is already used out"); return false; @@ -600,11 +592,10 @@ dap_chain_net_srv_stake_item_t *s_stake_item_from_order(dap_chain_net_t *a_net, } dap_srv_stake_order_ext_t *l_ext = (dap_srv_stake_order_ext_t *)a_order->ext_n_sign; dap_sign_t *l_sign = (dap_sign_t *)(a_order->ext_n_sign + a_order->ext_size); - if (!dap_sign_verify_size(l_sign, dap_chain_net_srv_order_get_size(a_order)) || - dap_sign_verify(l_sign, a_order, sizeof(dap_chain_net_srv_order_t) + a_order->ext_size) != 1) { + if (dap_sign_verify(l_sign, a_order, sizeof(dap_chain_net_srv_order_t) + a_order->ext_size) != 1) { log_it(L_WARNING, "Order sign is invalid"); return NULL; - } + } /* no need to check size here */ dap_hash_fast_t l_pkey_hash; dap_sign_get_pkey_hash(l_sign, &l_pkey_hash); dap_chain_addr_t l_cert_addr; @@ -629,15 +620,6 @@ dap_chain_net_srv_stake_item_t *s_stake_item_from_order(dap_chain_net_t *a_net, return l_item; } -// Ledger verificator for DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE_STAKE -bool dap_chain_net_srv_fee_stake_verificator(dap_chain_tx_out_cond_t *a_cond, dap_chain_datum_tx_t *a_tx, bool a_owner) -{ - if (!s_srv_stake) { - return false; - } - return false; -} - static bool s_stake_block_commit(dap_chain_net_t *a_net, dap_list_t *a_tx_hash_list) { size_t l_all_tx = 0, l_process_tx = 0; @@ -674,16 +656,11 @@ static bool s_stake_block_commit(dap_chain_net_t *a_net, dap_list_t *a_tx_hash_l a_tx_hash_list = dap_list_next(a_tx_hash_list); continue; } - // Get cond out with type=DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE_STAKE within tx + // Get cond out with type=DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE_STAKE within tx ??? dap_chain_tx_out_cond_t *l_tx_out_cond = NULL; int l_prev_cond_idx = 0; - do { - l_tx_out_cond = dap_chain_datum_tx_out_cond_get(l_tx_with_cond, &l_prev_cond_idx); - if(l_tx_out_cond && l_tx_out_cond->header.subtype==DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE_STAKE) { - break; - } - } - while(l_tx_out_cond); + l_tx_out_cond = dap_chain_datum_tx_out_cond_get(l_tx_with_cond, + DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE, &l_prev_cond_idx); if(!l_tx_out_cond) { // go to the next tx @@ -1281,7 +1258,7 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, char **a_str_reply) dap_chain_datum_tx_t *l_tx = s_stake_tx_create(l_stake, l_wallet); dap_chain_wallet_close(l_wallet); if (l_tx && s_stake_tx_put(l_tx, l_net)) { - dap_hash_fast(l_tx, dap_chain_datum_tx_get_size(l_tx), &l_stake->tx_hash); + dap_hash_fast(l_tx, dap_chain_datum_tx_get_size(l_tx), &l_stake->tx_hash); // TODO send a notification to order owner to delete it dap_chain_net_srv_order_delete_by_hash_str_sync(l_net, l_order_hash_str); } @@ -1494,22 +1471,31 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, char **a_str_reply) return 0; } -static int s_callback_requested(dap_chain_net_srv_t *a_srv, uint32_t a_usage_id, dap_chain_net_srv_client_remote_t *a_srv_client, const void *a_data, size_t a_data_size) -{ - return 0; -} - -static int s_callback_response_success(dap_chain_net_srv_t *a_srv, uint32_t a_usage_id, dap_chain_net_srv_client_remote_t *a_srv_client, const void *a_data, size_t a_data_size) -{ - return 0; -} - -static int s_callback_response_error(dap_chain_net_srv_t *a_srv, uint32_t a_usage_id, dap_chain_net_srv_client_remote_t *a_srv_client, const void *a_data, size_t a_data_size) +static bool s_verificator_stake_callback(dap_ledger_t * a_ledger, dap_hash_fast_t *a_tx_out_hash, dap_chain_tx_out_cond_t *a_cond, + dap_chain_datum_tx_t *a_tx_in, bool a_owner) { - return 0; + UNUSED(a_ledger); + UNUSED(a_tx_out_hash); + if (!s_srv_stake) { + return false; + } + return s_stake_conditions_calc(a_cond, a_tx_in, a_owner, false); } -static int s_callback_receipt_next_success(dap_chain_net_srv_t *a_srv, uint32_t a_usage_id, dap_chain_net_srv_client_remote_t *a_srv_client, const void *a_data, size_t a_data_size) +/** + * @brief s_verificator_stake_updater_callback + * @param a_ledger + * @param a_tx_out + * @param a_cond + * @param a_tx_in + * @param a_owner + * @return + */ +static bool s_verificator_stake_updater_callback(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_tx_out_cond_t *a_cond) { - return 0; + UNUSED(a_ledger); + if (!s_srv_stake) { + return false; + } + return s_stake_conditions_calc(a_cond, a_tx, true, true); } diff --git a/modules/service/stake_pos_delegate/include/dap_chain_net_srv_stake_pos_delegate.h b/modules/service/stake_pos_delegate/include/dap_chain_net_srv_stake_pos_delegate.h index 69ecdce4f2980ef04e6c5230d9641e7c5a4ba040..5c1ebf6a8f9b33484e0c9b47a6218529ca05455c 100644 --- a/modules/service/stake_pos_delegate/include/dap_chain_net_srv_stake_pos_delegate.h +++ b/modules/service/stake_pos_delegate/include/dap_chain_net_srv_stake_pos_delegate.h @@ -57,11 +57,6 @@ typedef struct dap_chain_net_srv_stake { int dap_chain_net_srv_stake_pos_delegate_init(); void dap_chain_net_srv_stake_pos_delegate_deinit(); -bool dap_chain_net_srv_stake_pos_delegate_verificator(dap_ledger_t* a_ledger, dap_chain_tx_out_cond_t *a_cond, dap_chain_datum_tx_t *a_tx, bool a_owner); -bool dap_chain_net_srv_stake_updater(dap_ledger_t* a_ledger, dap_chain_tx_out_cond_t *a_cond, dap_chain_datum_tx_t *a_tx, bool a_owner); bool dap_chain_net_srv_stake_validator(dap_chain_addr_t *a_addr, dap_chain_datum_t *a_datum); bool dap_chain_net_srv_stake_key_delegated(dap_chain_addr_t *a_addr); dap_list_t *dap_chain_net_srv_stake_get_validators(); - -// Ledger verificator for DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE_STAKE -bool dap_chain_net_srv_fee_stake_verificator(dap_chain_tx_out_cond_t *a_cond, dap_chain_datum_tx_t *a_tx, bool a_owner); diff --git a/modules/service/vpn/dap_chain_net_vpn_client.c b/modules/service/vpn/dap_chain_net_vpn_client.c index acc3710bb286e01d0637c45c97753086c8163abd..a6a3a14fb60101f8d6a95e4e41e20b8955a32435 100644 --- a/modules/service/vpn/dap_chain_net_vpn_client.c +++ b/modules/service/vpn/dap_chain_net_vpn_client.c @@ -58,6 +58,7 @@ #include "dap_chain_common.h" #include "dap_chain_mempool.h" +#include "dap_chain_net_tx.h" #include "dap_chain_node_cli.h" #include "dap_chain_node_client.h" #include "dap_chain_net_srv_order.h" @@ -528,7 +529,7 @@ int dap_chain_net_vpn_client_check(dap_chain_net_t *a_net, const char *a_ipv4_st if(l_res) { log_it(L_ERROR, "No response from VPN server=%s:%d", a_ipv4_str, a_port); // clean client struct - dap_chain_node_client_close(s_vpn_client); + dap_chain_node_client_close(s_vpn_client->uuid); DAP_DELETE(s_node_info); s_node_info = NULL; return -3; @@ -574,7 +575,7 @@ int dap_chain_net_vpn_client_check(dap_chain_net_t *a_net, const char *a_ipv4_st log_it(L_NOTICE, "Got response from VPN server=%s:%d", a_ipv4_str, a_port); } // clean client struct - dap_chain_node_client_close(s_vpn_client); + dap_chain_node_client_close(s_vpn_client->uuid); DAP_DELETE(s_node_info); s_node_info = NULL; if(l_res) @@ -607,7 +608,7 @@ int dap_chain_net_vpn_client_start(dap_chain_net_t *a_net, const char *a_ipv4_st if(!s_vpn_client) { log_it(L_ERROR, "Can't connect to VPN server=%s:%d", a_ipv4_str, a_port); // clean client struct - dap_chain_node_client_close(s_vpn_client); + dap_chain_node_client_close(s_vpn_client->uuid); DAP_DELETE(s_node_info); s_node_info = NULL; return -2; @@ -618,7 +619,7 @@ int dap_chain_net_vpn_client_start(dap_chain_net_t *a_net, const char *a_ipv4_st if(res) { log_it(L_ERROR, "No response from VPN server=%s:%d", a_ipv4_str, a_port); // clean client struct - dap_chain_node_client_close(s_vpn_client); + dap_chain_node_client_close(s_vpn_client->uuid); DAP_DELETE(s_node_info); s_node_info = NULL; return -3; @@ -657,7 +658,7 @@ int dap_chain_net_vpn_client_stop(void) { // delete connection with VPN server if(s_vpn_client) { - dap_chain_node_client_close(s_vpn_client); + dap_chain_node_client_close(s_vpn_client->uuid); s_vpn_client = NULL; } DAP_DELETE(s_node_info); diff --git a/modules/service/xchange/dap_chain_net_srv_xchange.c b/modules/service/xchange/dap_chain_net_srv_xchange.c index e42b695dc2f4c5970049f73b2c415a8122a19746..52377773602666bf435c71b10b6090f236106dba 100644 --- a/modules/service/xchange/dap_chain_net_srv_xchange.c +++ b/modules/service/xchange/dap_chain_net_srv_xchange.c @@ -24,8 +24,13 @@ #include <math.h> #include <pthread.h> +#include <stdbool.h> #include "dap_chain_net.h" #include "dap_chain_datum_tx.h" +#include "dap_chain_datum_tx_out_cond.h" +#include "dap_chain_datum_tx_sig.h" +#include "dap_list.h" +#include "dap_sign.h" #include "dap_time.h" #include "dap_chain_net_srv.h" #include "dap_chain_ledger.h" @@ -38,35 +43,19 @@ #include "dap_chain_mempool.h" #include "dap_chain_datum_decree.h" #include "dap_tsd.h" +#include "dap_chain_net_tx.h" #include "dap_chain_net_srv.h" #include "dap_chain_net_srv_xchange.h" #include "uthash.h" #define LOG_TAG "dap_chain_net_srv_xchange" -// -enum tsd_type{ - TSD_FEE_PERCENT = 0x0001, - TSD_FEE_FIXED = 0x0002, - TSD_FEE_ADDR = 0x0003, -}; - -struct net_fee -{ - dap_chain_net_id_t net_id; - - // Network fee - uint256_t fee_percents; - uint256_t fee_fixed; - dap_chain_addr_t fee_addr; // Addr collector - - UT_hash_handle hh; -} *s_net_fees = NULL; // Governance statements for networks -pthread_rwlock_t s_net_fees_rwlock = PTHREAD_RWLOCK_INITIALIZER; +static dap_chain_net_srv_fee_item_t *s_service_fees = NULL; // Governance statements for networks +static pthread_rwlock_t s_service_fees_rwlock = PTHREAD_RWLOCK_INITIALIZER; static void s_callback_decree (dap_chain_net_srv_t * a_srv, dap_chain_net_t *a_net, dap_chain_t * a_chain, dap_chain_datum_decree_t * a_decree, size_t a_decree_size); - - +static bool s_xchange_verificator_callback(dap_ledger_t * a_ledger,dap_hash_fast_t *a_tx_out_hash, dap_chain_tx_out_cond_t *a_cond, + dap_chain_datum_tx_t *a_tx_in, bool a_owner); const dap_chain_net_srv_uid_t c_dap_chain_net_srv_xchange_uid = {.uint64= DAP_CHAIN_NET_SRV_XCHANGE_ID}; @@ -75,14 +64,13 @@ static int s_callback_requested(dap_chain_net_srv_t *a_srv, uint32_t a_usage_id, static int s_callback_response_success(dap_chain_net_srv_t *a_srv, uint32_t a_usage_id, dap_chain_net_srv_client_remote_t *a_srv_client, const void *a_data, size_t a_data_size); static int s_callback_response_error(dap_chain_net_srv_t *a_srv, uint32_t a_usage_id, dap_chain_net_srv_client_remote_t *a_srv_client, const void *a_data, size_t a_data_size); static int s_callback_receipt_next_success(dap_chain_net_srv_t *a_srv, uint32_t a_usage_id, dap_chain_net_srv_client_remote_t *a_srv_client, const void *a_data, size_t a_data_size); -static dap_chain_net_srv_xchange_price_t *s_xchange_db_load(char *a_key, uint8_t *a_item); static int s_tx_check_for_open_close(dap_chain_net_t * a_net, dap_chain_datum_tx_t * a_tx); -static void s_string_append_tx_info( dap_string_t * a_reply_str, dap_chain_net_t * a_net, dap_chain_datum_tx_t * a_tx ); - +static void s_string_append_tx_cond_info( dap_string_t * a_reply_str, dap_chain_net_t * a_net, dap_chain_datum_tx_t * a_tx ); +static bool s_srv_xchange_get_fee(dap_chain_net_id_t a_net_id, uint256_t *a_fee, dap_chain_addr_t *a_addr, uint16_t *a_type); static dap_chain_net_srv_xchange_t *s_srv_xchange; - +static bool s_debug_more = true; /** * @brief dap_stream_ch_vpn_init Init actions for VPN stream channel @@ -92,17 +80,24 @@ static dap_chain_net_srv_xchange_t *s_srv_xchange; */ int dap_chain_net_srv_xchange_init() { + dap_chain_ledger_verificator_add(DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE, s_xchange_verificator_callback, NULL); dap_cli_server_cmd_add("srv_xchange", s_cli_srv_xchange, "eXchange service commands", - "srv_xchange order create -net <net_name> -token_sell <token_ticker> -token_buy <token_ticker> -wallet <wallet_name> -coins <value> -rate <value>\n" + "srv_xchange order create -net <net_name> -token_sell <token_ticker> -token_buy <token_ticker> -wallet <wallet_name>" + " -coins <value> -rate <value> -fee <value>\n" "\tCreate a new order and tx with specified amount of datoshi to exchange with specified rate (buy / sell)\n" "srv_xchange order remove -net <net_name> -order <order_hash> -wallet <wallet_name>\n" "\tRemove order with specified order hash in specified net name\n" "srv_xchange order update -net <net_name> -order <order_hash> -wallet <wallet_name> [-token_sell <token_ticker>] " "[-net_buy <net_name>] [-token_buy <token_ticker>] [-coins <value>] [-rate <value>]\n" "\tUpdate order with specified order hash in specified net name\n" + "srv_xchange order history -net <net_name> {-order <order_hash> | -addr <wallet_addr>}" + "\tShows transaction history for the selected order\n" + "srv_xchange order status -net <net_name> -order <order_hash>" + "\tShows current amount of unselled coins from the selected order and percentage of its completion\n" "srv_xchange orders -net <net_name>\n" "\tGet the exchange orders list within specified net name\n" + "srv_xchange purchase -order <order hash> -net <net_name> -wallet <wallet_name> -coins <value>\n" "\tExchange tokens with specified order within specified net name. Specify how many datoshies to sell with rate specified by order\n" @@ -112,14 +107,10 @@ int dap_chain_net_srv_xchange_init() "srv_xchange token_pair -net <net_name> list all\n" "\tList of all token pairs\n" - "srv_xchange token_pair -net <net_name> price average -token_from <token_ticker> -token_to <token_ticker> [-time_from <From time>] [-time_to <To time>] \n" "\tGet average rate for token pair <token from>:<token to> from <From time> to <To time> \n" "\tAll times are in RFC822\n" - "srv_xchange token_pair -net <net_name> price last -token_from <token_ticker> -token_to <token_ticker> [-time_from <From time>] [-time_to <To time>] \n" - "\tGet average rate for token pair <token from>:<token to> from <From time> to <To time> \n" - "\tAll times are in RFC822\n" - "srv_xchange token_pair -net <net_name> price history -token_from <token_ticker> -token2 <token_ticker> [-time_from <From time>] [-time_to <To time>] \n" + "srv_xchange token_pair -net <net_name> price history -token_from <token_ticker> -token_to <token_ticker> [-time_from <From time>] [-time_to <To time>] \n" "\tPrint rate history for token pair <token from>:<token to> from <From time> to <To time>\n" "\tAll times are in RFC822\n" @@ -142,6 +133,7 @@ int dap_chain_net_srv_xchange_init() l_srv->_internal = s_srv_xchange; s_srv_xchange->parent = l_srv; s_srv_xchange->enabled = false; + s_debug_more = dap_config_get_item_bool_default(g_config, "srv_xchange", "debug_more", s_debug_more); return 0; } @@ -154,61 +146,104 @@ void dap_chain_net_srv_xchange_deinit() DAP_DELETE(s_srv_xchange); } -bool dap_chain_net_srv_xchange_verificator(dap_ledger_t * a_ledger, dap_chain_tx_out_cond_t *a_cond, dap_chain_datum_tx_t *a_tx, bool a_owner) +/** + * @brief s_verificator_callback + * @param a_ledger + * @param a_tx_out_hash + * @param a_cond + * @param a_tx_in + * @param a_owner + * @return + */ +static bool s_xchange_verificator_callback(dap_ledger_t * a_ledger,dap_hash_fast_t *a_tx_out_hash, dap_chain_tx_out_cond_t *a_tx_out_cond, + dap_chain_datum_tx_t *a_tx_in, bool a_owner) { + return true;//for tests if (a_owner) return true; + if(!a_tx_out_hash || !a_tx_in || !a_tx_out_cond) + return false; - pthread_rwlock_rdlock(&s_net_fees_rwlock); - struct net_fee * l_fee = NULL; - dap_chain_net_t * l_net = dap_chain_ledger_get_net(a_ledger); - HASH_FIND(hh,s_net_fees, &l_net->pub.id, sizeof(l_net->pub.id),l_fee); - if(l_fee == NULL) - pthread_rwlock_unlock(&s_net_fees_rwlock); + const char *l_sell_ticker = dap_chain_ledger_tx_get_token_ticker_by_hash(a_ledger,a_tx_out_hash); + if (!l_sell_ticker) + return false; + const char *l_buy_ticker = a_tx_out_cond->subtype.srv_xchange.buy_token; + + uint256_t l_buy_val = {}, l_fee_val = {}, + l_sell_again_val = {}, l_service_fee_val = {}; + int l_item_idx_start = 0; + byte_t * l_tx_item; + + dap_chain_addr_t l_service_fee_addr, *l_seller_addr = &a_tx_out_cond->subtype.srv_xchange.seller_addr; + uint16_t l_service_fee_type; + dap_chain_net_t *l_net = dap_chain_net_by_name(a_ledger->net_name); + bool l_service_fee_used = s_srv_xchange_get_fee(l_net->pub.id, &l_service_fee_val, &l_service_fee_addr, &l_service_fee_type); + const char *l_native_ticker = l_net->pub.native_ticker; + const char *l_service_ticker = (l_service_fee_type == SERVICE_FEE_OWN_FIXED || l_service_fee_type == SERVICE_FEE_OWN_PERCENT) ? + l_buy_ticker : l_native_ticker; + while ((l_tx_item = dap_chain_datum_tx_item_get(a_tx_in, &l_item_idx_start, TX_ITEM_TYPE_OUT_ALL, NULL)) != NULL) + { + dap_chain_tx_item_type_t l_tx_out_type = dap_chain_datum_tx_item_get_type(l_tx_item); + switch(l_tx_out_type){ + case TX_ITEM_TYPE_OUT_EXT: { + dap_chain_tx_out_ext_t *l_tx_in_output = (dap_chain_tx_out_ext_t *)l_tx_item; + const char * l_out_token = l_tx_in_output->token; + const uint256_t *l_out_value = &l_tx_in_output->header.value; + dap_chain_addr_t * l_out_addr = &l_tx_in_output->addr; + // Out is with token to buy + if (!strcmp(l_out_token, l_buy_ticker) && + !memcmp(l_out_addr, l_seller_addr, sizeof(*l_out_addr))) + SUM_256_256(l_buy_val, *l_out_value, &l_buy_val); + // Out is with token to fee + if (l_service_fee_used && !strcmp(l_out_token, l_service_ticker) && + !memcmp(l_out_addr, &l_service_fee_addr, sizeof(*l_out_addr))) + SUM_256_256(l_fee_val, *l_out_value, &l_fee_val); + } break; + case TX_ITEM_TYPE_OUT_COND: { + dap_chain_tx_out_cond_t *l_tx_in_output = (dap_chain_tx_out_cond_t *)l_tx_item; + if (l_tx_in_output->header.subtype == a_tx_out_cond->header.subtype && // Same subtype + l_tx_in_output->header.srv_uid.uint64 == a_tx_out_cond->header.srv_uid.uint64 && // Same service uid + l_tx_in_output->header.ts_expires == a_tx_out_cond->header.ts_expires && // Same expires time + l_tx_in_output->tsd_size == a_tx_out_cond->tsd_size && // Same params size + memcmp(l_tx_in_output->tsd, a_tx_out_cond->tsd, l_tx_in_output->tsd_size) == 0 && // Same params itself + memcmp(&l_tx_in_output->subtype.srv_xchange, &a_tx_out_cond->subtype.srv_xchange, // Same subtype header + sizeof(a_tx_out_cond->subtype.srv_xchange)) == 0) { + l_sell_again_val = l_tx_in_output->header.value; // It is back to cond owner value + } + }break; + default: break; + } + l_item_idx_start++; + } - /* Check the condition for verification success + /* Check the condition for rate verification success + * seller rate >= buyer_rate + * OR * a_cond.srv_xchange.rate (a_cond->header.value / a_cond->subtype.srv_xchange.buy_value) >= - * a_tx.out.rate ((a_cond->header.value - l_back_val) / l_out_val) + * a_tx.out.rate ((a_cond->header.value - new_cond->header.value) / out_ext.seller_addr(buy_ticker).value) + * OR + * a_cond->header.value * out_ext.seller_addr(buy_ticker).value >= + * a_cond->subtype.srv_xchange.buy_value * (a_cond->header.value - new_cond->header.value) */ - dap_list_t *l_list_out = dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_OUT_EXT, NULL); - uint256_t l_out_val = {}, l_back_val = {}, l_fee_val = {}; - char *l_ticker_ctrl = NULL; - for (dap_list_t *l_list_tmp = l_list_out; l_list_tmp; l_list_tmp = l_list_tmp->next) { - dap_chain_tx_out_ext_t *l_tx_out = (dap_chain_tx_out_ext_t *)l_list_tmp->data; - if (memcmp(&l_tx_out->addr, &l_fee->fee_addr, sizeof(l_fee->fee_addr) == 0 ) ){ - SUM_256_256(l_fee_val, l_tx_out->header.value, &l_fee_val); - } - - // If its returning back to owner - if (memcmp(&l_tx_out->addr, &a_cond->params, sizeof(dap_chain_addr_t))) { - continue; - } - // Chek if its buy token or not - if (strcmp(l_tx_out->token, a_cond->subtype.srv_xchange.buy_token)) { + uint256_t l_sell_val, l_buyer_mul, l_seller_mul; + if (compare256(l_sell_again_val, a_tx_out_cond->header.value) >= 0) + return false; + SUBTRACT_256_256(a_tx_out_cond->header.value, l_sell_again_val, &l_sell_val); + MULT_256_256(a_tx_out_cond->header.value, l_buy_val, &l_seller_mul); + MULT_256_256(a_tx_out_cond->subtype.srv_xchange.buy_value, l_sell_val, &l_buyer_mul); + if (compare256(l_seller_mul, l_buyer_mul) < 0) + return false; - // If we alredy have buy token out - if (l_ticker_ctrl && strcmp(l_ticker_ctrl, l_tx_out->token)) { - if(l_fee) pthread_rwlock_unlock(&s_net_fees_rwlock); - return false; // too many tokens - } - l_ticker_ctrl = l_tx_out->token; - SUM_256_256(l_back_val, l_tx_out->header.value, &l_back_val); - } else { // buying token - SUM_256_256(l_out_val, l_tx_out->header.value, &l_out_val); - } - } - //long double l_buyer_rate = (a_cond->header.value - l_back_val) / (long double)l_out_val; - //long double l_seller_rate = - uint256_t l_buyer_val = {}, l_buyer_mul = {}, l_seller_mul = {}; - SUBTRACT_256_256(a_cond->header.value, l_back_val, &l_buyer_val); - MULT_256_256(l_buyer_val, a_cond->subtype.srv_xchange.buy_value, &l_buyer_mul); - MULT_256_256(l_out_val, a_cond->header.value, &l_seller_mul); - if (compare256(l_seller_mul, l_buyer_mul) == -1) { - if(l_fee) pthread_rwlock_unlock(&s_net_fees_rwlock); - return false; // wrong changing rate + /* Check the condition for fee verification success + * out_ext.fee_addr(fee_ticker).value >= fee_value + */ + if (l_service_fee_used) { + if (l_service_fee_type == SERIVCE_FEE_NATIVE_PERCENT || l_service_fee_type == SERVICE_FEE_OWN_PERCENT) + MULT_256_COIN(l_service_fee_val, l_sell_val, &l_service_fee_val); + if (compare256(l_fee_val, l_service_fee_val) < 0) + return false; } - if(l_fee) pthread_rwlock_unlock(&s_net_fees_rwlock); return true; } @@ -222,45 +257,68 @@ bool dap_chain_net_srv_xchange_verificator(dap_ledger_t * a_ledger, dap_chain_tx */ static void s_callback_decree (dap_chain_net_srv_t * a_srv, dap_chain_net_t *a_net, dap_chain_t * a_chain, dap_chain_datum_decree_t * a_decree, size_t a_decree_size) { - pthread_rwlock_wrlock(&s_net_fees_rwlock); - struct net_fee * l_fee = NULL; + pthread_rwlock_wrlock(&s_service_fees_rwlock); + dap_chain_net_srv_fee_item_t *l_fee = NULL; switch(a_decree->header.action){ case DAP_CHAIN_DATUM_DECREE_ACTION_UPDATE:{ - HASH_FIND(hh,s_net_fees,&a_net->pub.id, sizeof(a_net->pub.id), l_fee); + HASH_FIND(hh,s_service_fees,&a_net->pub.id, sizeof(a_net->pub.id), l_fee); if(l_fee == NULL){ log_it(L_WARNING,"Decree update for net id 0x%016" DAP_UINT64_FORMAT_X" when such id can't find in hash table", a_net->pub.id.uint64); + pthread_rwlock_unlock(&s_service_fees_rwlock); return; } }break; case DAP_CHAIN_DATUM_DECREE_ACTION_CREATE:{ - l_fee = DAP_NEW_Z(struct net_fee); + HASH_FIND(hh,s_service_fees,&a_net->pub.id, sizeof(a_net->pub.id), l_fee); + if (l_fee) { + log_it(L_WARNING, "Decree create for net id 0x%016" DAP_UINT64_FORMAT_X" when such id already in hash table", a_net->pub.id.uint64); + pthread_rwlock_unlock(&s_service_fees_rwlock); + return; + } + l_fee = DAP_NEW_Z(dap_chain_net_srv_fee_item_t); l_fee->net_id = a_net->pub.id; - HASH_ADD(hh, s_net_fees, net_id, sizeof(l_fee->net_id), l_fee); + HASH_ADD(hh, s_service_fees, net_id, sizeof(l_fee->net_id), l_fee); } break; } size_t l_tsd_offset = 0; while(l_tsd_offset < (a_decree_size - sizeof(a_decree->header)) ){ dap_tsd_t *l_tsd = (dap_tsd_t*) (a_decree->tsd_sections + l_tsd_offset); - switch( (enum tsd_type) l_tsd->type){ - case TSD_FEE_ADDR:{ - l_fee->fee_addr = dap_tsd_get_scalar(l_tsd, dap_chain_addr_t); - } break; - case TSD_FEE_PERCENT:{ - l_fee->fee_percents = dap_tsd_get_scalar(l_tsd, uint256_t); - } break; - case TSD_FEE_FIXED:{ - l_fee->fee_fixed = dap_tsd_get_scalar(l_tsd, uint256_t); - } break; + switch((dap_chain_net_srv_fee_tsd_type_t)l_tsd->type) { + case TSD_FEE_TYPE: + l_fee->fee_type = dap_tsd_get_scalar(l_tsd, uint16_t); + break; + case TSD_FEE: + l_fee->fee = dap_tsd_get_scalar(l_tsd, uint256_t); + break; + case TSD_FEE_ADDR: + l_fee->fee_addr = dap_tsd_get_scalar(l_tsd, dap_chain_addr_t); + default: + break; } l_tsd_offset += dap_tsd_size(l_tsd); } - pthread_rwlock_unlock(&s_net_fees_rwlock); + pthread_rwlock_unlock(&s_service_fees_rwlock); } +static bool s_srv_xchange_get_fee(dap_chain_net_id_t a_net_id, uint256_t *a_fee, dap_chain_addr_t *a_addr, uint16_t *a_type) +{ + pthread_rwlock_wrlock(&s_service_fees_rwlock); + dap_chain_net_srv_fee_item_t *l_fee = NULL; + HASH_FIND(hh,s_service_fees, &a_net_id, sizeof(a_net_id), l_fee); + pthread_rwlock_unlock(&s_service_fees_rwlock); + if (!l_fee || IS_ZERO_256(l_fee->fee)) + return false; + if (a_type) + *a_type = l_fee->fee_type; + if (a_addr) + *a_addr = l_fee->fee_addr; + if (a_fee) + *a_fee = l_fee->fee; + return true; +} - -static dap_chain_datum_tx_receipt_t *s_xchage_receipt_create(dap_chain_net_srv_xchange_price_t *a_price, uint256_t a_datoshi_buy) +static dap_chain_datum_tx_receipt_t *s_xchange_receipt_create(dap_chain_net_srv_xchange_price_t *a_price, uint256_t a_datoshi_buy) { uint32_t l_ext_size = sizeof(uint256_t) + DAP_CHAIN_TICKER_SIZE_MAX; uint8_t *l_ext = DAP_NEW_STACK_SIZE(uint8_t, l_ext_size); @@ -269,15 +327,13 @@ static dap_chain_datum_tx_receipt_t *s_xchage_receipt_create(dap_chain_net_srv_x dap_chain_net_srv_price_unit_uid_t l_unit = { .uint32 = SERV_UNIT_UNDEFINED}; dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_XCHANGE_ID }; uint256_t l_datoshi_sell = {}; - if (compare256(a_price->rate, uint256_0)!=0){ + if (!IS_ZERO_256(a_price->rate)){ DIV_256_COIN(a_datoshi_buy, a_price->rate, &l_datoshi_sell); dap_chain_datum_tx_receipt_t *l_receipt = dap_chain_datum_tx_receipt_create(l_uid, l_unit, 0, l_datoshi_sell, l_ext, l_ext_size); return l_receipt; - }else{ - DAP_DELETE(l_ext); - return NULL; } + return NULL; } static dap_chain_datum_tx_t *s_xchange_tx_create_request(dap_chain_net_srv_xchange_price_t *a_price, dap_chain_wallet_t *a_wallet) @@ -285,42 +341,75 @@ static dap_chain_datum_tx_t *s_xchange_tx_create_request(dap_chain_net_srv_xchan if (!a_price || !a_price->net || !*a_price->token_sell || !*a_price->token_buy || !a_wallet) { return NULL; } - - // create empty transaction - dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create(); - - dap_ledger_t *l_ledger = dap_chain_ledger_by_net_name(a_price->net->pub.name); + const char *l_native_ticker = a_price->net->pub.native_ticker; + bool l_single_channel = !dap_strcmp(a_price->token_sell, l_native_ticker); + // find the transactions from which to take away coins + uint256_t l_value_transfer; // how many coins to transfer + uint256_t l_value_need = a_price->datoshi_sell, + l_net_fee, + l_total_fee = a_price->fee, + l_fee_transfer; + dap_chain_addr_t l_addr_net_fee; + dap_list_t *l_list_fee_out = NULL; + bool l_net_fee_used = dap_chain_net_tx_get_fee(a_price->net->pub.id, &l_net_fee, &l_addr_net_fee); + if (l_net_fee_used) + SUM_256_256(l_total_fee, l_net_fee, &l_total_fee); + + dap_ledger_t *l_ledger = a_price->net->pub.ledger; dap_chain_addr_t *l_seller_addr = (dap_chain_addr_t *)dap_chain_wallet_get_addr(a_wallet, a_price->net->pub.id); + if (l_single_channel) + SUM_256_256(l_value_need, l_total_fee, &l_value_need); + else { + l_list_fee_out = dap_chain_ledger_get_list_tx_outs_with_val(l_ledger, l_native_ticker, + l_seller_addr, l_total_fee, &l_fee_transfer); + if (!l_list_fee_out) { + log_it(L_WARNING, "Not enough funds to pay fee"); + return NULL; + } + } dap_enc_key_t *l_seller_key = dap_chain_wallet_get_key(a_wallet, 0); - uint256_t l_value_sell = {}; // how many coins to transfer // list of transaction with 'out' items to sell dap_list_t *l_list_used_out = dap_chain_ledger_get_list_tx_outs_with_val(l_ledger, a_price->token_sell, - l_seller_addr, a_price->datoshi_sell, &l_value_sell); + l_seller_addr, l_value_need, &l_value_transfer); if(!l_list_used_out) { - dap_chain_datum_tx_delete(l_tx); DAP_DELETE(l_seller_addr); log_it(L_WARNING, "Nothing to change (not enough funds)"); return NULL; } + // create empty transaction + dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create(); + // add 'in' items to sell uint256_t l_value_to_items = dap_chain_datum_tx_add_in_item_list(&l_tx, l_list_used_out); - dap_list_free_full(l_list_used_out, free); - if (compare256(l_value_to_items, l_value_sell) != 0) { + dap_list_free_full(l_list_used_out, NULL); + if (!EQUAL_256(l_value_to_items, l_value_transfer) != 0) { dap_chain_datum_tx_delete(l_tx); DAP_DELETE(l_seller_addr); log_it(L_ERROR, "Can't compose the transaction input"); return NULL; } + if (!l_single_channel) { + // add 'in' items to fee + uint256_t l_value_fee_items = dap_chain_datum_tx_add_in_item_list(&l_tx, l_list_fee_out); + dap_list_free_full(l_list_used_out, NULL); + if (!EQUAL_256(l_value_fee_items, l_fee_transfer) != 0) { + dap_chain_datum_tx_delete(l_tx); + DAP_DELETE(l_seller_addr); + log_it(L_ERROR, "Can't compose the transaction input"); + return NULL; + } + } // add 'out_cond' & 'out' items + { uint256_t l_datoshi_buy = uint256_0; MULT_256_COIN(a_price->datoshi_sell, a_price->rate, &l_datoshi_buy); dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_XCHANGE_ID }; dap_chain_tx_out_cond_t *l_tx_out = dap_chain_datum_tx_item_out_cond_create_srv_xchange(l_uid, a_price->net->pub.id, a_price->datoshi_sell, a_price->net->pub.id, a_price->token_buy, l_datoshi_buy, - (void *)l_seller_addr, sizeof(dap_chain_addr_t)); + l_seller_addr, NULL, 0); if (!l_tx_out) { dap_chain_datum_tx_delete(l_tx); DAP_DELETE(l_seller_addr); @@ -329,9 +418,27 @@ static dap_chain_datum_tx_t *s_xchange_tx_create_request(dap_chain_net_srv_xchan } dap_chain_datum_tx_add_item(&l_tx, (const uint8_t *)l_tx_out); DAP_DELETE(l_tx_out); + // Network fee + if (l_net_fee_used) { + if (dap_chain_datum_tx_add_out_item(&l_tx, &l_addr_net_fee, l_net_fee) != 1) { + dap_chain_datum_tx_delete(l_tx); + DAP_DELETE(l_seller_addr); + log_it(L_ERROR, "Cant add network fee output"); + return NULL; + } + } + // Validator's fee + if (!IS_ZERO_256(a_price->fee)) { + if (dap_chain_datum_tx_add_fee_item(&l_tx, a_price->fee) == 1) { + dap_chain_datum_tx_delete(l_tx); + DAP_DELETE(l_seller_addr); + log_it(L_ERROR, "Cant add validator's fee output"); + return NULL; + } + } // coin back uint256_t l_value_back = {}; - SUBTRACT_256_256(l_value_sell, a_price->datoshi_sell, &l_value_back); + SUBTRACT_256_256(l_value_transfer, l_value_need, &l_value_back); if (!IS_ZERO_256(l_value_back)) { if (dap_chain_datum_tx_add_out_item(&l_tx, l_seller_addr, l_value_back) != 1) { dap_chain_datum_tx_delete(l_tx); @@ -340,6 +447,19 @@ static dap_chain_datum_tx_t *s_xchange_tx_create_request(dap_chain_net_srv_xchan return NULL; } } + // Fee coinback + if (!l_single_channel) { + SUBTRACT_256_256(l_fee_transfer, l_total_fee, &l_value_back); + if (!IS_ZERO_256(l_value_back)) { + if (dap_chain_datum_tx_add_out_ext_item(&l_tx, l_seller_addr, l_value_back, + a_price->net->pub.native_ticker) != 1) { + dap_chain_datum_tx_delete(l_tx); + DAP_DELETE(l_seller_addr); + log_it(L_ERROR, "Cant add fee back output"); + return NULL; + } + } + } } DAP_DELETE(l_seller_addr); @@ -359,25 +479,68 @@ static dap_chain_datum_tx_t *s_xchange_tx_create_exchange(dap_chain_net_srv_xcha if (!a_price || !a_price->net || !*a_price->token_sell || !*a_price->token_buy || !a_wallet) { return NULL; } - - // create empty transaction - dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create(); - - dap_ledger_t *l_ledger = dap_chain_ledger_by_net_name(a_price->net->pub.name); + const char *l_native_ticker = a_price->net->pub.native_ticker; + const char *l_service_ticker; + bool l_pay_with_native = !dap_strcmp(a_price->token_buy, l_native_ticker); + // find the transactions from which to take away coins + uint256_t l_value_transfer, // how many coins to transfer + l_value_need = a_price->datoshi_buy, + l_net_fee, + l_service_fee, + l_total_fee = a_price->fee, + l_fee_transfer; + dap_chain_addr_t l_net_fee_addr, l_service_fee_addr; + dap_list_t *l_list_fee_out = NULL; + bool l_net_fee_used = dap_chain_net_tx_get_fee(a_price->net->pub.id, &l_net_fee, &l_net_fee_addr); + if (l_net_fee_used) + SUM_256_256(l_net_fee, a_price->fee, &l_total_fee); + uint16_t l_service_fee_type; + bool l_service_fee_used = s_srv_xchange_get_fee(a_price->net->pub.id, &l_service_fee, &l_service_fee_addr, &l_service_fee_type); + if (l_service_fee_used) { + switch (l_service_fee_type) { + case SERIVCE_FEE_NATIVE_PERCENT: + MULT_256_COIN(l_service_fee, a_price->datoshi_buy, &l_service_fee); + case SERVICE_FEE_NATIVE_FIXED: + SUM_256_256(l_total_fee, l_service_fee, &l_total_fee); + l_service_ticker = l_native_ticker; + break; + case SERVICE_FEE_OWN_PERCENT: + MULT_256_COIN(l_service_fee, a_price->datoshi_buy, &l_service_fee); + case SERVICE_FEE_OWN_FIXED: + SUM_256_256(l_value_need, l_service_fee, &l_value_need); + l_service_ticker = a_price->token_buy; + default: + break; + } + } + dap_ledger_t *l_ledger = a_price->net->pub.ledger; dap_chain_addr_t *l_buyer_addr = (dap_chain_addr_t *)dap_chain_wallet_get_addr(a_wallet, a_price->net->pub.id); - dap_enc_key_t *l_seller_key = dap_chain_wallet_get_key(a_wallet, 0); - uint256_t l_value_buy = {}; // how many coins to transfer + if (l_pay_with_native) + SUM_256_256(l_value_need, l_total_fee, &l_value_need); + else { + l_list_fee_out = dap_chain_ledger_get_list_tx_outs_with_val(l_ledger, l_native_ticker, + l_buyer_addr, l_total_fee, &l_fee_transfer); + if (!l_list_fee_out) { + log_it(L_WARNING, "Not enough funds to pay fee"); + return NULL; + } + } // list of transaction with 'out' items to sell dap_list_t *l_list_used_out = dap_chain_ledger_get_list_tx_outs_with_val(l_ledger, a_price->token_buy, - l_buyer_addr, a_datoshi_buy, &l_value_buy); + l_buyer_addr, l_value_need, &l_value_transfer); if(!l_list_used_out) { - dap_chain_datum_tx_delete(l_tx); + DAP_DELETE(l_buyer_addr); log_it(L_WARNING, "Nothing to change (not enough funds)"); return NULL; } + dap_enc_key_t *l_seller_key = dap_chain_wallet_get_key(a_wallet, 0); + + // create empty transaction + dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create(); + // create and add reciept - dap_chain_datum_tx_receipt_t *l_receipt = s_xchage_receipt_create(a_price, a_datoshi_buy); + dap_chain_datum_tx_receipt_t *l_receipt = s_xchange_receipt_create(a_price, a_datoshi_buy); if( l_receipt == NULL){ DAP_DELETE(l_buyer_addr); log_it(L_ERROR, "Can't compose the receipt"); @@ -388,12 +551,23 @@ static dap_chain_datum_tx_t *s_xchange_tx_create_exchange(dap_chain_net_srv_xcha // add 'in' items to sell uint256_t l_value_to_items = dap_chain_datum_tx_add_in_item_list(&l_tx, l_list_used_out); dap_list_free_full(l_list_used_out, NULL); - if (compare256(l_value_to_items, l_value_buy) != 0) { + if (!EQUAL_256(l_value_to_items, l_value_transfer)) { dap_chain_datum_tx_delete(l_tx); DAP_DELETE(l_buyer_addr); log_it(L_ERROR, "Can't compose the transaction input"); return NULL; } + if (!l_pay_with_native) { + // add 'in' items to fee + uint256_t l_value_fee_items = dap_chain_datum_tx_add_in_item_list(&l_tx, l_list_fee_out); + dap_list_free_full(l_list_used_out, NULL); + if (!EQUAL_256(l_value_fee_items, l_fee_transfer)) { + dap_chain_datum_tx_delete(l_tx); + DAP_DELETE(l_buyer_addr); + log_it(L_ERROR, "Can't compose the transaction input"); + return NULL; + } + } // add 'in' item to buy from conditional transaction dap_chain_datum_tx_t *l_cond_tx = dap_chain_ledger_tx_find_by_hash(l_ledger, &a_price->tx_hash); if (!l_cond_tx) { @@ -401,61 +575,131 @@ static dap_chain_datum_tx_t *s_xchange_tx_create_exchange(dap_chain_net_srv_xcha return NULL; } int l_prev_cond_idx = 0; - dap_chain_tx_out_cond_t *l_tx_out_cond = dap_chain_datum_tx_out_cond_get(l_cond_tx, &l_prev_cond_idx); + dap_chain_tx_out_cond_t *l_tx_out_cond = dap_chain_datum_tx_out_cond_get(l_cond_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE, + &l_prev_cond_idx); + if (!l_tx_out_cond) { + log_it(L_WARNING, "Requested transaction has no conditional output"); + return NULL; + } if (dap_chain_ledger_tx_hash_is_used_out_item(l_ledger, &a_price->tx_hash, l_prev_cond_idx)) { log_it(L_WARNING, "Requested conditional transaction is already used out"); return NULL; } + const dap_chain_addr_t *l_seller_addr = &l_tx_out_cond->subtype.srv_xchange.seller_addr; dap_chain_datum_tx_add_in_cond_item(&l_tx, &a_price->tx_hash, l_prev_cond_idx, 0); + // add 'out' items - { - // transfer buying coins - const dap_chain_addr_t *l_seller_addr = (dap_chain_addr_t *)l_tx_out_cond->params; - if (dap_chain_datum_tx_add_out_ext_item(&l_tx, l_seller_addr, a_datoshi_buy, a_price->token_buy) == -1) { + // transfer selling coins + uint256_t l_datoshi_sell, + l_datoshi_buy, + l_value_back; + if (!IS_ZERO_256(a_price->rate)) { + DIV_256_COIN(a_datoshi_buy, a_price->rate, &l_datoshi_sell); + if (compare256(l_tx_out_cond->header.value, l_datoshi_sell) < 0) { + l_datoshi_sell = l_tx_out_cond->header.value; + MULT_256_COIN(l_datoshi_sell, a_price->rate, &l_datoshi_buy); + } else + l_datoshi_buy = a_datoshi_buy; + debug_if(s_debug_more, L_NOTICE, "l_datoshi_sell = %s", dap_chain_balance_to_coins(l_datoshi_sell)); + if (dap_chain_datum_tx_add_out_ext_item(&l_tx, l_buyer_addr, l_datoshi_sell, a_price->token_sell) == -1) { dap_chain_datum_tx_delete(l_tx); DAP_DELETE(l_buyer_addr); - log_it(L_ERROR, "Can't add buying coins output"); + log_it(L_ERROR, "Can't add selling coins output"); return NULL; } - // coin back - uint256_t l_value_back = {}; - SUBTRACT_256_256(l_value_buy, a_datoshi_buy, &l_value_back); - if (!IS_ZERO_256(l_value_back)) { - if (dap_chain_datum_tx_add_out_ext_item(&l_tx, l_buyer_addr, l_value_back, a_price->token_buy) == -1) { - dap_chain_datum_tx_delete(l_tx); - DAP_DELETE(l_buyer_addr); - log_it(L_ERROR, "Can't add buying coins back output"); - return NULL; - } + }else{ + DAP_DELETE(l_buyer_addr); + log_it(L_ERROR, "Can't add selling coins output because price rate is 0"); + return NULL; + } + DAP_DELETE(l_buyer_addr); + // transfer unselling coins (partial exchange) + debug_if(s_debug_more, L_NOTICE, "l_datoshi_cond = %s", dap_chain_balance_to_coins(l_tx_out_cond->header.value)); + if (compare256(l_tx_out_cond->header.value, l_datoshi_sell) == 1) { + SUBTRACT_256_256(l_tx_out_cond->header.value, l_datoshi_sell, &l_value_back); + debug_if(s_debug_more, L_NOTICE, "l_value_back = %s", dap_chain_balance_to_coins(l_value_back)); + uint256_t l_datoshi_buy_again; + MULT_256_COIN(l_value_back, a_price->rate, &l_datoshi_buy_again); + debug_if(s_debug_more, L_NOTICE, "l_datoshi_buy_again = %s", dap_chain_balance_to_coins(l_datoshi_buy_again)); + dap_chain_tx_out_cond_t *l_tx_out = dap_chain_datum_tx_item_out_cond_create_srv_xchange( + c_dap_chain_net_srv_xchange_uid, a_price->net->pub.id, l_value_back, + a_price->net->pub.id, a_price->token_buy, l_datoshi_buy_again, + l_seller_addr, NULL, 0); + if (!l_tx_out) { + dap_chain_datum_tx_delete(l_tx); + DAP_DELETE(l_seller_addr); + log_it(L_WARNING, "Can't add selling coins back conditioned output (cond cashback)"); + return NULL; } - //transfer selling coins - uint256_t l_datoshi_sell = {}; - if (compare256(a_price->rate, uint256_0)!=0){ - DIV_256_COIN(a_datoshi_buy, a_price->rate, &l_datoshi_sell); + dap_chain_datum_tx_add_item(&l_tx, (const uint8_t *)l_tx_out); + DAP_DELETE(l_tx_out); + } else // mark price order as ready + memset(&a_price->order_hash, 0, sizeof(dap_hash_fast_t)); - if (dap_chain_datum_tx_add_out_ext_item(&l_tx, l_buyer_addr, l_datoshi_sell, a_price->token_sell) == -1) { - dap_chain_datum_tx_delete(l_tx); - DAP_DELETE(l_buyer_addr); - log_it(L_ERROR, "Can't add selling coins output"); - return NULL; - } - }else{ + // transfer buying coins + if (dap_chain_datum_tx_add_out_ext_item(&l_tx, l_seller_addr, l_datoshi_buy, a_price->token_buy) == -1) { + dap_chain_datum_tx_delete(l_tx); + DAP_DELETE(l_buyer_addr); + log_it(L_ERROR, "Can't add buying coins output"); + return NULL; + } + debug_if(s_debug_more, L_NOTICE, "l_datoshi_buy = %s", dap_chain_balance_to_coins(l_datoshi_buy)); + // transfer validator's fee + if (!IS_ZERO_256(a_price->fee)) { + if (dap_chain_datum_tx_add_fee_item(&l_tx, a_price->fee) == -1) { + dap_chain_datum_tx_delete(l_tx); DAP_DELETE(l_buyer_addr); - log_it(L_ERROR, "Can't add selling coins output because price rate is 0"); + log_it(L_ERROR, "Can't add validator fee output"); return NULL; } - DAP_DELETE(l_buyer_addr); - //transfer unselling coins (partial exchange) - SUBTRACT_256_256(l_tx_out_cond->header.value, l_datoshi_sell, &l_value_back); + debug_if(s_debug_more, L_NOTICE, "l_validator_fee = %s", dap_chain_balance_to_coins(a_price->fee)); + } + // transfer net fee + if (l_net_fee_used) { + if (dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_net_fee_addr, l_net_fee, l_native_ticker) == -1) { + dap_chain_datum_tx_delete(l_tx); + DAP_DELETE(l_buyer_addr); + log_it(L_ERROR, "Can't add net fee output"); + return NULL; + } + debug_if(s_debug_more, L_NOTICE, "l_net_fee = %s", dap_chain_balance_to_coins(l_net_fee)); + } + // transfer service fee + if (l_service_fee_used) { + if (dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_service_fee_addr, l_service_fee, l_service_ticker) == -1) { + dap_chain_datum_tx_delete(l_tx); + DAP_DELETE(l_buyer_addr); + log_it(L_ERROR, "Can't add net fee output"); + return NULL; + } + debug_if(s_debug_more, L_NOTICE, "l_service_fee = %s", dap_chain_balance_to_coins(l_net_fee)); + } + // coin back + SUBTRACT_256_256(l_value_transfer, l_value_need, &l_value_back); + if (!IS_ZERO_256(l_value_back)) { + if (dap_chain_datum_tx_add_out_ext_item(&l_tx, l_buyer_addr, l_value_back, a_price->token_buy) == -1) { + dap_chain_datum_tx_delete(l_tx); + DAP_DELETE(l_buyer_addr); + log_it(L_ERROR, "Can't add buying coins back output"); + return NULL; + } + } + debug_if(s_debug_more, L_NOTICE, "l_value_transfer = %s", dap_chain_balance_to_coins(l_value_transfer)); + debug_if(s_debug_more, L_NOTICE, "l_value_back = %s", dap_chain_balance_to_coins(l_value_back)); + // fee back + if (!l_pay_with_native) { + SUBTRACT_256_256(l_fee_transfer, l_total_fee, &l_value_back); if (!IS_ZERO_256(l_value_back)) { - if (dap_chain_datum_tx_add_out_ext_item(&l_tx, l_seller_addr, l_value_back, a_price->token_sell) == -1) { - log_it(L_WARNING, "Can't add selling coins back output (cashback)"); + if (dap_chain_datum_tx_add_out_ext_item(&l_tx, l_buyer_addr, l_value_back, a_price->token_buy) == -1) { dap_chain_datum_tx_delete(l_tx); + DAP_DELETE(l_buyer_addr); + log_it(L_ERROR, "Can't add buying coins back output"); return NULL; } } + debug_if(s_debug_more, L_NOTICE, "l_fee_transfer = %s", dap_chain_balance_to_coins(l_fee_transfer)); + debug_if(s_debug_more, L_NOTICE, "l_value_back = %s", dap_chain_balance_to_coins(l_value_back)); } - // add 'sign' items if(dap_chain_datum_tx_add_sign_item(&l_tx, l_seller_key) != 1) { dap_chain_datum_tx_delete(l_tx); @@ -493,8 +737,9 @@ static bool s_xchange_tx_put(dap_chain_datum_tx_t *a_tx, dap_chain_net_t *a_net) return true; } -static bool s_xchage_tx_invalidate(dap_chain_net_srv_xchange_price_t *a_price, dap_chain_wallet_t *a_wallet) +static bool s_xchange_tx_invalidate(dap_chain_net_srv_xchange_price_t *a_price, dap_chain_wallet_t *a_wallet) { + const char *l_native_ticker = a_price->net->pub.native_ticker; // create empty transaction dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create(); @@ -503,9 +748,10 @@ static bool s_xchage_tx_invalidate(dap_chain_net_srv_xchange_price_t *a_price, d dap_enc_key_t *l_seller_key = dap_chain_wallet_get_key(a_wallet, 0); // create and add reciept - dap_chain_datum_tx_receipt_t *l_receipt = s_xchage_receipt_create(a_price, uint256_0); + dap_chain_datum_tx_receipt_t *l_receipt = s_xchange_receipt_create(a_price, uint256_0); if (!l_receipt) { log_it(L_WARNING, "Can't create receipt"); + dap_chain_datum_tx_delete(l_tx); return false; } dap_chain_datum_tx_add_item(&l_tx, (byte_t *)l_receipt); @@ -515,26 +761,95 @@ static bool s_xchage_tx_invalidate(dap_chain_net_srv_xchange_price_t *a_price, d dap_chain_datum_tx_t *l_cond_tx = dap_chain_ledger_tx_find_by_hash(l_ledger, &a_price->tx_hash); if (!l_cond_tx) { log_it(L_WARNING, "Requested conditional transaction not found"); + dap_chain_datum_tx_delete(l_tx); return false; } + const char *l_tx_ticker = dap_chain_ledger_tx_get_token_ticker_by_hash(l_ledger, &a_price->tx_hash); + bool l_single_channel = !dap_strcmp(l_tx_ticker, l_native_ticker); int l_prev_cond_idx; - dap_chain_tx_out_cond_t *l_tx_out_cond = dap_chain_datum_tx_out_cond_get(l_cond_tx, &l_prev_cond_idx); + dap_chain_tx_out_cond_t *l_tx_out_cond = dap_chain_datum_tx_out_cond_get(l_cond_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE, + &l_prev_cond_idx); if (dap_chain_ledger_tx_hash_is_used_out_item(l_ledger, &a_price->tx_hash, l_prev_cond_idx)) { log_it(L_WARNING, "Requested conditional transaction is already used out"); + dap_chain_datum_tx_delete(l_tx); return false; } dap_chain_datum_tx_add_in_cond_item(&l_tx, &a_price->tx_hash, l_prev_cond_idx, 0); - // add 'out' item - const dap_chain_addr_t *l_buyer_addr = (dap_chain_addr_t *)l_tx_out_cond->params; - if (memcmp(l_seller_addr->data.hash, l_buyer_addr->data.hash, sizeof(dap_chain_hash_fast_t))) { + // check 'out_cond' item + dap_chain_addr_t *l_cond_addr = &l_tx_out_cond->subtype.srv_xchange.seller_addr; + if (dap_hash_fast_compare(&l_seller_addr->data.hash_fast, &l_cond_addr->data.hash_fast)) { log_it(L_WARNING, "Only owner can invalidate exchange transaction"); + dap_chain_datum_tx_delete(l_tx); return false; } - if (dap_chain_datum_tx_add_out_item(&l_tx, l_seller_addr, l_tx_out_cond->header.value) == -1) { + uint256_t l_net_fee = {}, l_transfer_fee; + dap_chain_addr_t l_addr_fee = {}; + bool l_net_fee_used = dap_chain_net_tx_get_fee(a_price->net->pub.id, &l_net_fee, &l_addr_fee); + uint256_t l_total_fee = {}; + SUM_256_256(a_price->fee, l_net_fee, &l_total_fee); + // list of transaction with 'out' items to get net fee + dap_list_t *l_list_used_out = dap_chain_ledger_get_list_tx_outs_with_val(l_ledger, l_native_ticker, + l_seller_addr, l_total_fee, &l_transfer_fee); + if(!l_list_used_out) { + dap_chain_datum_tx_delete(l_tx); + log_it(L_WARNING, "Nothing to pay for network fee (not enough funds)"); + return false; + } + // add 'in' items to net fee + uint256_t l_value_to_items = dap_chain_datum_tx_add_in_item_list(&l_tx, l_list_used_out); + dap_list_free_full(l_list_used_out, NULL); + if (!EQUAL_256(l_value_to_items, l_transfer_fee)) { + dap_chain_datum_tx_delete(l_tx); + log_it(L_ERROR, "Can't compose the transaction input"); + return NULL; + } + + // return coins to owner + if (l_single_channel) { + if (dap_chain_datum_tx_add_out_item(&l_tx, l_seller_addr, l_tx_out_cond->header.value) == -1) { + dap_chain_datum_tx_delete(l_tx); + DAP_DELETE(l_seller_addr); + log_it(L_ERROR, "Cant add returning coins output"); + return false; + } + } else { + if (dap_chain_datum_tx_add_out_ext_item(&l_tx, l_seller_addr, l_tx_out_cond->header.value, + l_tx_ticker) == -1) { + dap_chain_datum_tx_delete(l_tx); + DAP_DELETE(l_seller_addr); + log_it(L_ERROR, "Cant add returning coins output"); + return false; + } + } + + // Network fee + if (l_net_fee_used) { + if (dap_chain_datum_tx_add_out_item(&l_tx, &l_addr_fee, l_net_fee) != 1) { + dap_chain_datum_tx_delete(l_tx); + DAP_DELETE(l_seller_addr); + log_it(L_ERROR, "Cant add network fee output"); + return NULL; + } + } + // Validator's fee + if (!IS_ZERO_256(a_price->fee)) { + if (dap_chain_datum_tx_add_fee_item(&l_tx, a_price->fee) == 1) { + dap_chain_datum_tx_delete(l_tx); + DAP_DELETE(l_seller_addr); + log_it(L_ERROR, "Cant add validator's fee output"); + return NULL; + } + } + + // put the net fee cashback + uint256_t l_fee_back = {}; + SUBTRACT_256_256(l_transfer_fee, l_total_fee, &l_fee_back); + if (!IS_ZERO_256(l_fee_back) && + dap_chain_datum_tx_add_out_item(&l_tx, l_seller_addr, l_tx_out_cond->header.value) == -1) { dap_chain_datum_tx_delete(l_tx); DAP_DELETE(l_seller_addr); - log_it(L_ERROR, "Cant add returning coins output"); + log_it(L_ERROR, "Cant add fee cachback output"); return false; } DAP_DELETE(l_seller_addr); @@ -562,18 +877,17 @@ char *s_xchange_order_create(dap_chain_net_srv_xchange_price_t *a_price, dap_cha dap_chain_hash_fast_t l_tx_hash = {}; dap_hash_fast(a_tx, dap_chain_datum_tx_get_size(a_tx), &l_tx_hash); a_price->tx_hash = l_tx_hash; - dap_srv_xchange_order_ext_t l_ext={0}; - l_ext.datoshi_sell = a_price->datoshi_sell; - strncpy(l_ext.token_sell, a_price->token_sell, DAP_CHAIN_TICKER_SIZE_MAX); - uint32_t l_ext_size = sizeof(dap_srv_xchange_order_ext_t); dap_chain_node_addr_t *l_node_addr = dap_chain_net_get_cur_addr(a_price->net); dap_chain_net_srv_price_unit_uid_t l_unit = { .uint32 = SERV_UNIT_UNDEFINED}; dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_XCHANGE_ID }; uint256_t l_datoshi_buy = uint256_0; MULT_256_COIN(a_price->datoshi_sell, a_price->rate, &l_datoshi_buy); - - char *l_order_hash_str = dap_chain_net_srv_order_create(a_price->net, SERV_DIR_BUY, l_uid, *l_node_addr, - l_tx_hash, &l_datoshi_buy, l_unit, a_price->token_buy, 0, + dap_srv_xchange_order_ext_t l_ext={0}; + l_ext.datoshi_buy = l_datoshi_buy; + strncpy(l_ext.token_buy, a_price->token_buy, DAP_CHAIN_TICKER_SIZE_MAX); + uint32_t l_ext_size = sizeof(dap_srv_xchange_order_ext_t); + char *l_order_hash_str = dap_chain_net_srv_order_create(a_price->net, SERV_DIR_SELL, l_uid, *l_node_addr, + l_tx_hash, &a_price->datoshi_sell, l_unit, a_price->token_sell, 0, (uint8_t *)&l_ext, l_ext_size, NULL, 0, a_price->wallet_key); return l_order_hash_str; } @@ -588,18 +902,24 @@ dap_chain_net_srv_xchange_price_t *s_xchange_price_from_order(dap_chain_net_t *a { dap_chain_net_srv_xchange_price_t *l_price = DAP_NEW_Z(dap_chain_net_srv_xchange_price_t); dap_srv_xchange_order_ext_t *l_ext = (dap_srv_xchange_order_ext_t *)a_order->ext_n_sign; - l_price->datoshi_sell = l_ext->datoshi_sell; - strcpy(l_price->token_sell, l_ext->token_sell); + strcpy(l_price->token_buy, l_ext->token_buy); + l_price->datoshi_buy = l_ext->datoshi_buy; + strcpy(l_price->token_sell, a_order->price_ticker); + l_price->datoshi_sell = a_order->price; l_price->net = a_net; - strcpy(l_price->token_buy, a_order->price_ticker); - if( compare256(l_price->datoshi_sell, uint256_0) !=0 ){ - DIV_256_COIN(a_order->price, l_price->datoshi_sell, &l_price->rate); - l_price->tx_hash = a_order->tx_cond_hash; - return l_price; - }else{ - DAP_DELETE(l_price); - return NULL; - } + if (!IS_ZERO_256(l_price->datoshi_buy)) { + DIV_256_COIN(l_price->datoshi_buy, l_price->datoshi_sell, &l_price->rate); + dap_hash_fast_t *l_final_hash = dap_chain_ledger_get_final_chain_tx_hash(a_net->pub.ledger, + DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE, &a_order->tx_cond_hash); + if (l_final_hash) { + l_price->tx_hash = *l_final_hash; + return l_price; + } else + log_it(L_WARNING, "This order have no active conditional transaction"); + } else + log_it(L_WARNING, "Can't calculate price rate, because amount od datoshi sell is zero"); + DAP_DELETE(l_price); + return NULL; } /** @@ -613,7 +933,7 @@ dap_chain_net_srv_xchange_price_t *s_xchange_price_from_order(dap_chain_net_t *a static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, char **a_str_reply) { enum { - CMD_NONE, CMD_CREATE, CMD_REMOVE, CMD_UPDATE, CMD_HISTORY + CMD_NONE, CMD_CREATE, CMD_REMOVE, CMD_UPDATE, CMD_HISTORY, CMD_STATUS }; int l_cmd_num = CMD_NONE; if(dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, min(a_argc, a_arg_index + 1), "create", NULL)) { @@ -628,6 +948,9 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, c else if(dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, min(a_argc, a_arg_index + 1), "history", NULL)) { l_cmd_num = CMD_HISTORY; } + else if(dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, min(a_argc, a_arg_index + 1), "status", NULL)) { + l_cmd_num = CMD_STATUS; + } int l_arg_index = a_arg_index + 1; const char *l_net_str = NULL; const char *l_token_sell_str = NULL, *l_token_buy_str = NULL; @@ -671,7 +994,7 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, c } uint256_t l_datoshi_sell = dap_chain_balance_scan(l_val_sell_str); if (IS_ZERO_256(l_datoshi_sell)) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Format -coins <unsigned long long>"); + dap_cli_server_cmd_set_reply_text(a_str_reply, "Format -coins <unsigned integer 256>"); return -9; } dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-rate", &l_val_rate_str); @@ -680,10 +1003,21 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, c return -8; } uint256_t l_rate = dap_chain_coins_to_balance(l_val_rate_str); - if (!compare256(l_rate, uint256_0)) { // if (l_rate == 0) + if (!IS_ZERO_256(l_rate)) { dap_cli_server_cmd_set_reply_text(a_str_reply, "Format -rate n.n = buy / sell (eg: 1.0, 1.135)"); return -9; } + const char *l_fee_str = NULL; + dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-fee", &l_fee_str); + if (!l_fee_str) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'price create' required parameter -fee"); + return -20; + } + uint256_t l_fee = dap_chain_coins_to_balance(l_fee_str); + if (!IS_ZERO_256(l_fee)) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Format -fee <unsigned integer 256>"); + return -21; + } dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-wallet", &l_wallet_str); if (!l_wallet_str) { dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'price create' required parameter -wallet"); @@ -695,7 +1029,22 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, c return -11; } uint256_t l_value = dap_chain_wallet_get_balance(l_wallet, l_net->pub.id, l_token_sell_str); - if (compare256(l_value, l_datoshi_sell) == -1) { + uint256_t l_value_sell = l_datoshi_sell; + if (!dap_strcmp(l_net->pub.native_ticker, l_token_sell_str)) { + if (SUM_256_256(l_value_sell, l_fee, &l_value_sell)) { + dap_chain_wallet_close(l_wallet); + log_it(L_ERROR, "Integer overflow with sum of value and fee"); + return -22; + } + } else { // sell non-native ticker + uint256_t l_fee_value = dap_chain_wallet_get_balance(l_wallet, l_net->pub.id, l_net->pub.native_ticker); + if (compare256(l_fee_value, l_fee) == -1) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Not enough cash for fee in specified wallet"); + dap_chain_wallet_close(l_wallet); + return -23; + } + } + if (compare256(l_value, l_value_sell) == -1) { dap_cli_server_cmd_set_reply_text(a_str_reply, "Not enough cash in specified wallet"); dap_chain_wallet_close(l_wallet); return -12; @@ -708,6 +1057,7 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, c dap_stpcpy(l_price->token_buy, l_token_buy_str); l_price->datoshi_sell = l_datoshi_sell; l_price->rate = l_rate; + l_price->fee = l_fee; // Create conditional transaction dap_chain_datum_tx_t *l_tx = s_xchange_tx_create_request(l_price, l_wallet); if (!l_tx) { @@ -740,10 +1090,11 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, c return -18; } } break; + case CMD_HISTORY:{ dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-net", &l_net_str); if (!l_net_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'order create' required parameter -net"); + dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'order history' required parameter -net"); return -2; } l_net = dap_chain_net_by_name(l_net_str); @@ -752,44 +1103,70 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, c return -3; } - } break; - const char * l_order_hash_str = NULL; + const char * l_addr_hash_str = NULL; + dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-order", &l_order_hash_str); - if (!l_order_hash_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'price %s' required parameter -order", - l_cmd_num == CMD_REMOVE ? "remove" : "update"); + dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-addr", &l_addr_hash_str); + + if (!l_order_hash_str && ! l_addr_hash_str) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'order history' required parameter -order or -addr" ); return -12; } - dap_chain_net_srv_order_t *l_order = dap_chain_net_srv_order_find_by_hash_str(l_net, l_order_hash_str); - if (!l_order) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified order not found"); - return -13; + if(l_addr_hash_str){ + dap_chain_addr_t *l_addr = dap_chain_addr_from_str(l_addr_hash_str); + if (!l_addr) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Incorrect chain address"); + return -14; + } + if (dap_chain_addr_check_sum(l_addr) != 1 ) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Incorrect chain address"); + return -15; + } + dap_list_t *l_tx_list = dap_chain_net_get_tx_cond_all_for_addr(l_net,l_addr, c_dap_chain_net_srv_xchange_uid ); + dap_string_t * l_str_reply = dap_string_new(""); + while(l_tx_list ){ + dap_chain_datum_tx_t * l_tx_cur = (dap_chain_datum_tx_t*) l_tx_list->data; + s_string_append_tx_cond_info(l_str_reply, l_net, l_tx_cur ); + } + dap_list_free(l_tx_list); + *a_str_reply = dap_string_free(l_str_reply, false); + DAP_DELETE(l_addr); } + if(l_order_hash_str){ + dap_chain_net_srv_order_t *l_order = dap_chain_net_srv_order_find_by_hash_str(l_net, l_order_hash_str); + if (!l_order) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified order not found"); + return -13; + } - dap_chain_datum_tx_t * l_tx = dap_chain_net_get_tx_by_hash(l_net,&l_order->tx_cond_hash, TX_SEARCH_TYPE_NET); - if( l_tx){ - int l_rc = s_tx_check_for_open_close(l_net,l_tx); - char *l_tx_hash = dap_chain_hash_fast_to_str_new(&l_order->tx_cond_hash); - if(l_rc == 0){ - dap_cli_server_cmd_set_reply_text(a_str_reply, "WRONG TX %s", l_tx_hash); - }else if(l_rc == 1){ - dap_string_t * l_str_reply = dap_string_new(""); - s_string_append_tx_info(l_str_reply, l_net, l_tx); - *a_str_reply = dap_string_free(l_str_reply, false); - }else if(l_rc == 2){ - dap_string_t * l_str_reply = dap_string_new(""); - while(l_tx){ - s_string_append_tx_info(l_str_reply, l_net, l_tx); - + dap_chain_datum_tx_t * l_tx = dap_chain_net_get_tx_by_hash(l_net,&l_order->tx_cond_hash, TX_SEARCH_TYPE_NET); + if( l_tx){ + int l_rc = s_tx_check_for_open_close(l_net,l_tx); + char *l_tx_hash = dap_chain_hash_fast_to_str_new(&l_order->tx_cond_hash); + if(l_rc == 0){ + dap_cli_server_cmd_set_reply_text(a_str_reply, "WRONG TX %s", l_tx_hash); + }else if(l_rc == 1){ + dap_string_t * l_str_reply = dap_string_new(""); + s_string_append_tx_cond_info(l_str_reply, l_net, l_tx); + *a_str_reply = dap_string_free(l_str_reply, false); + }else if(l_rc == 2){ + dap_string_t * l_str_reply = dap_string_new(""); + dap_list_t *l_tx_list = dap_chain_net_get_tx_cond_chain(l_net,&l_order->tx_cond_hash, c_dap_chain_net_srv_xchange_uid ); + while(l_tx_list ){ + dap_chain_datum_tx_t * l_tx_cur = (dap_chain_datum_tx_t*) l_tx_list->data; + s_string_append_tx_cond_info(l_str_reply, l_net, l_tx_cur ); + } + dap_list_free(l_tx_list); + *a_str_reply = dap_string_free(l_str_reply, false); + }else{ + dap_cli_server_cmd_set_reply_text(a_str_reply, "Internal error!"); } - *a_str_reply = dap_string_free(l_str_reply, false); }else{ - dap_cli_server_cmd_set_reply_text(a_str_reply, "Internal error!"); + dap_cli_server_cmd_set_reply_text(a_str_reply, "No history"); } - }else{ - dap_cli_server_cmd_set_reply_text(a_str_reply, "No history"); } + } break; case CMD_REMOVE: case CMD_UPDATE: { @@ -835,14 +1212,13 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, c if (l_cmd_num == CMD_REMOVE) { dap_string_t *l_str_reply = dap_string_new(""); - bool l_ret = s_xchage_tx_invalidate(l_price, l_wallet); + bool l_ret = s_xchange_tx_invalidate(l_price, l_wallet); dap_chain_wallet_close(l_wallet); if (!l_ret) { char *l_tx_hash_str = dap_chain_hash_fast_to_str_new(&l_price->tx_hash); dap_string_append_printf(l_str_reply, "Can't invalidate transaction %s\n", l_tx_hash_str); DAP_DELETE(l_tx_hash_str); } - char *l_order_hash_str = dap_chain_hash_fast_to_str_new(&l_price->order_hash); if (dap_chain_net_srv_order_delete_by_hash_str_sync(l_price->net, l_order_hash_str)) { dap_string_append_printf(l_str_reply, "Can't remove order %s\n", l_order_hash_str); } @@ -868,7 +1244,7 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, c dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-rate", &l_val_rate_str); if (l_val_rate_str) { l_rate = dap_chain_coins_to_balance(l_val_rate_str); - if (!compare256(l_rate, uint256_0)) { // if (l_rate == 0) + if (IS_ZERO_256(l_rate)) { dap_cli_server_cmd_set_reply_text(a_str_reply, "Format -rate <long double> = sell / buy"); return -9; } @@ -908,7 +1284,7 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, c dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't compose the conditional transaction"); return -14; } - bool l_ret = s_xchage_tx_invalidate(l_price, l_wallet); // may be changed to old price later + bool l_ret = s_xchange_tx_invalidate(l_price, l_wallet); // may be changed to old price later dap_chain_wallet_close(l_wallet); if (!l_ret) { char *l_tx_hash_str = dap_chain_hash_fast_to_str_new(&l_price->tx_hash); @@ -917,7 +1293,6 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, c return -17; } // Update the order - char *l_order_hash_str = dap_chain_hash_fast_to_str_new(&l_price->order_hash); dap_chain_net_srv_order_delete_by_hash_str_sync(l_price->net, l_order_hash_str); DAP_DELETE(l_order_hash_str); l_order_hash_str = s_xchange_order_create(l_price, l_tx); @@ -939,6 +1314,70 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, c } } } break; + + case CMD_STATUS: { + dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-net", &l_net_str); + if (!l_net_str) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'order status' required parameter -net"); + return -2; + } + l_net = dap_chain_net_by_name(l_net_str); + if (!l_net) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Network %s not found", l_net_str); + return -3; + } + const char * l_order_hash_str = NULL; + dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-order", &l_order_hash_str); + if (!l_order_hash_str) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'order history' required parameter -order or -addr" ); + return -12; + } + dap_chain_net_srv_order_t *l_order = dap_chain_net_srv_order_find_by_hash_str(l_net, l_order_hash_str); + if (!l_order) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified order not found"); + return -13; + } + dap_hash_fast_t *l_final_hash = dap_chain_ledger_get_final_chain_tx_hash(l_net->pub.ledger, + DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE, &l_order->tx_cond_hash); + if (!l_final_hash) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified order have no active tx (copmleted)"); + DAP_DELETE(l_order); + return -18; + } + dap_chain_datum_tx_t *l_tx = dap_chain_ledger_tx_find_by_hash(l_net->pub.ledger, l_final_hash); + if (!l_tx) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Internal error"); + DAP_DELETE(l_order); + return -19; + } + dap_chain_tx_out_cond_t *l_out_cond = dap_chain_datum_tx_out_cond_get(l_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE, + NULL); + if (!l_out_cond) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified order have no active conditional tx (copmleted)"); + DAP_DELETE(l_order); + return -20; + } + uint256_t l_filled, l_filled_percent, l_rate; + dap_srv_xchange_order_ext_t *l_ext = (dap_srv_xchange_order_ext_t *)l_order->ext_n_sign; + char *l_amount_str = dap_chain_balance_to_coins(l_order->price); + char *l_current_str = dap_chain_balance_to_coins(l_out_cond->header.value); + SUBTRACT_256_256(l_order->price, l_out_cond->header.value, &l_filled); + DIV_256_COIN(l_filled, l_out_cond->header.value, &l_filled_percent); + MULT_256_256(l_filled_percent, dap_chain_uint256_from(100), &l_filled_percent); + char *l_filled_str = dap_chain_balance_to_coins(l_filled_percent); + DIV_256_COIN(l_ext->datoshi_buy, l_order->price, &l_rate); + char *l_rate_str = dap_chain_balance_to_coins(l_rate); + dap_cli_server_cmd_set_reply_text(a_str_reply, "tokenSell: %s, tokenBuy: %s, amount: %s, current %s, filled: %s%% rate(buy/sell): %s\n", + l_order->price_ticker, l_ext->token_buy, + l_amount_str, l_current_str, + l_filled_str, l_rate_str); + DAP_DEL_Z(l_amount_str); + DAP_DEL_Z(l_current_str); + DAP_DEL_Z(l_filled_str); + DAP_DEL_Z(l_rate_str); + DAP_DELETE(l_order); + } break; + default: { dap_cli_server_cmd_set_reply_text(a_str_reply, "Subcommand %s not recognized", a_argv[a_arg_index]); return -4; @@ -995,14 +1434,13 @@ static int s_tx_check_for_open_close(dap_chain_net_t * a_net, dap_chain_datum_tx dap_hash_fast_t l_tx_hash = {0}; size_t l_tx_size = dap_chain_datum_tx_get_size(a_tx); dap_hash_fast(a_tx, l_tx_size, &l_tx_hash); - dap_chain_tx_out_cond_t *l_out_cond_item = dap_chain_datum_tx_out_cond_get(a_tx, &l_cond_idx); - if ( l_out_cond_item && (l_out_cond_item->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE) ) - { + dap_chain_tx_out_cond_t *l_out_cond_item = dap_chain_datum_tx_out_cond_get(a_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE, + &l_cond_idx); + if (l_out_cond_item) { if(dap_chain_ledger_tx_hash_is_used_out_item(a_net->pub.ledger, &l_tx_hash, l_cond_idx)) return 1; // If its SRV_XCHANGE and spent its closed else return 2; // If its SRV_XCHANGE and not spent its open - } return 0; } @@ -1013,7 +1451,7 @@ static int s_tx_check_for_open_close(dap_chain_net_t * a_net, dap_chain_datum_tx * @param a_net * @param a_tx */ -static void s_string_append_tx_info( dap_string_t * a_reply_str, dap_chain_net_t * a_net, dap_chain_datum_tx_t * a_tx ) +static void s_string_append_tx_cond_info( dap_string_t * a_reply_str, dap_chain_net_t * a_net, dap_chain_datum_tx_t * a_tx ) { size_t l_tx_size = dap_chain_datum_tx_get_size(a_tx); @@ -1028,9 +1466,14 @@ static void s_string_append_tx_info( dap_string_t * a_reply_str, dap_chain_net_t const char * l_tx_input_ticker = dap_chain_ledger_tx_get_token_ticker_by_hash( a_net->pub.ledger, &l_tx_hash); + + + // Find SRV_XCHANGE out_cond item int l_cond_idx = 0; - dap_chain_tx_out_cond_t *l_out_cond_item = dap_chain_datum_tx_out_cond_get(a_tx, &l_cond_idx); + dap_chain_tx_out_cond_t *l_out_cond_item = dap_chain_datum_tx_out_cond_get(a_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE, + &l_cond_idx); + bool l_is_cond_out = false; if ( l_out_cond_item && (l_out_cond_item->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE) ) { bool l_is_closed = dap_chain_ledger_tx_hash_is_used_out_item(a_net->pub.ledger, &l_tx_hash, l_cond_idx); @@ -1040,14 +1483,29 @@ static void s_string_append_tx_info( dap_string_t * a_reply_str, dap_chain_net_t char *l_value_to_str = dap_chain_balance_to_coins(l_value_to); char *l_value_from_str = dap_chain_balance_to_coins(l_value_from); - dap_string_append_printf(a_reply_str, "Hash: %s,", l_tx_hash_str); - dap_string_append_printf(a_reply_str, " Status: %s,", l_is_closed ? "closed" : "open"); - dap_string_append_printf(a_reply_str, " From: %s %s,", l_value_from_str, l_tx_input_ticker); - dap_string_append_printf(a_reply_str, " To: %s %s\n", l_value_to_str, l_out_cond_item->subtype.srv_xchange.buy_token); + dap_string_append_printf(a_reply_str, "Hash: %s", l_tx_hash_str); + dap_string_append_printf(a_reply_str, " Status: %s", l_is_closed ? "closed" : "open"); + dap_string_append_printf(a_reply_str, " From: %s %s", l_value_from_str, l_tx_input_ticker); + dap_string_append_printf(a_reply_str, " To: %s %s", l_value_to_str, l_out_cond_item->subtype.srv_xchange.buy_token); DAP_DELETE(l_value_from_str); DAP_DELETE(l_value_to_str); + l_is_cond_out = true; } + if(l_is_cond_out){ + // Get IN_COND items from transaction + int l_item_idx = 0; + byte_t *l_tx_item; + while ((l_tx_item = dap_chain_datum_tx_item_get(a_tx, &l_item_idx, TX_ITEM_TYPE_IN_COND , NULL)) != NULL){ + dap_chain_tx_in_cond_t * l_in_cond = (dap_chain_tx_in_cond_t *) l_tx_item; + char l_tx_prev_cond_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE]; + dap_hash_fast_to_str(&l_in_cond->header.tx_prev_hash,l_tx_prev_cond_hash_str, sizeof(l_tx_prev_cond_hash_str)); + dap_string_append_printf(a_reply_str, " Prev cond: %s", l_tx_prev_cond_hash_str); + l_item_idx++; + } + dap_string_append_printf(a_reply_str, "\n"); + } + } @@ -1279,7 +1737,7 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, char **a_str_reply) } uint256_t l_datoshi_buy = dap_chain_balance_scan(l_val_buy_str); if (IS_ZERO_256(l_datoshi_buy)) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Format -coins <unsigned long long>"); + dap_cli_server_cmd_set_reply_text(a_str_reply, "Format -coins <unsigned int256>"); return -9; } dap_chain_net_srv_order_t *l_order = dap_chain_net_srv_order_find_by_hash_str(l_net, l_order_hash_str); @@ -1290,11 +1748,11 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, char **a_str_reply) return -13; } // Create conditional transaction + dap_chain_hash_fast_from_str(l_order_hash_str, &l_price->order_hash); dap_chain_datum_tx_t *l_tx = s_xchange_tx_create_exchange(l_price, l_wallet, l_datoshi_buy); - if (l_tx && s_xchange_tx_put(l_tx, l_net)) { - // TODO send request to seller to update / delete order & price + if (l_tx && s_xchange_tx_put(l_tx, l_net) && + dap_hash_fast_is_blank(&l_price->order_hash)) dap_chain_net_srv_order_delete_by_hash_str_sync(l_price->net, l_order_hash_str); - } DAP_DELETE(l_price); DAP_DELETE(l_order); dap_cli_server_cmd_set_reply_text(a_str_reply, l_tx ? "Exchange transaction has done" : @@ -1421,9 +1879,9 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, char **a_str_reply) // Find SRV_XCHANGE out_cond item int l_prev_cond_idx = 0; - dap_chain_tx_out_cond_t *l_out_cond_item = dap_chain_datum_tx_out_cond_get(l_datum_tx, &l_prev_cond_idx); - if ( l_out_cond_item && (l_out_cond_item->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE) ) - { + dap_chain_tx_out_cond_t *l_out_cond_item = dap_chain_datum_tx_out_cond_get(l_datum_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE, + &l_prev_cond_idx); + if (l_out_cond_item) { uint256_t l_value_from = l_out_cond_item->header.value; uint256_t l_value_to = l_out_cond_item->subtype.srv_xchange.buy_value; char *l_value_to_str = dap_chain_balance_to_coins(l_value_to); @@ -1550,13 +2008,14 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, char **a_str_reply) continue; } int l_cond_idx = 0; - dap_chain_tx_out_cond_t *l_out_cond_item = dap_chain_datum_tx_out_cond_get(l_tx, &l_cond_idx); - if(l_out_cond_item && l_out_cond_item->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE && + dap_chain_tx_out_cond_t *l_out_cond_item = dap_chain_datum_tx_out_cond_get(l_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE, + &l_cond_idx); + if (l_out_cond_item && dap_chain_ledger_tx_hash_is_used_out_item(l_net->pub.ledger, l_tx_hash, l_cond_idx)) { uint256_t l_value_sell = l_out_cond_item->header.value; uint256_t l_value_buy = l_out_cond_item->subtype.srv_xchange.buy_value; if( l_direction == 1){ - if(compare256(l_value_sell,uint256_0) !=0 ){ + if (!IS_ZERO_256(l_value_sell)) { DIV_256_COIN(l_value_buy, l_value_sell, &l_rate); if(SUM_256_256(l_rate, l_total_rates, &l_total_rates )!= 0) log_it(L_ERROR, "Overflow on avarage price calculation (summing)"); @@ -1565,7 +2024,7 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, char **a_str_reply) log_it(L_ERROR, "Sell value is 0 in avarage price calculation (summing)"); } }else if (l_direction == -1){ - if(compare256(l_value_buy,uint256_0) !=0 ){ + if (!IS_ZERO_256(l_value_buy)) { DIV_256_COIN(l_value_sell, l_value_buy, &l_rate); if(SUM_256_256(l_rate, l_total_rates, &l_total_rates )!= 0) log_it(L_ERROR, "Overflow on avarage price calculation (summing)"); @@ -1583,10 +2042,10 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, char **a_str_reply) } dap_list_free_full(l_tx_cond_list, NULL); uint256_t l_rate_average = {0}; - if( compare256(l_total_rates_count, uint256_0) != 0 ) + if (!IS_ZERO_256(l_total_rates_count)) DIV_256(l_total_rates,l_total_rates_count,&l_rate_average); - if( compare256(l_total_rates_count, uint256_0) != 0 ) + if (!IS_ZERO_256(l_total_rates_count)) DIV_256(l_total_rates,l_total_rates_count,&l_rate_average); char *l_rate_average_str = dap_chain_balance_to_coins(l_rate_average); @@ -1625,7 +2084,6 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, char **a_str_reply) } // Check if output is spent - int l_cond_idx = 0; dap_chain_tx_out_cond_t *l_out_cond_item = l_cur->out_cond; if(l_out_cond_item && l_cur->tx_next) { @@ -1691,7 +2149,11 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, char **a_str_reply) *a_str_reply = dap_string_free(l_reply_str, false); break; - }break; + } else { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Unrecognized subcommand '%s'", + l_price_subcommand); + return -38; + } } const char * l_list_subcommand = NULL; @@ -1701,7 +2163,7 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, char **a_str_reply) dap_string_t *l_reply_str = dap_string_new(""); char ** l_tickers = NULL; size_t l_tickers_count = 0; - dap_chain_ledger_addr_get_token_ticker_all(l_net->pub.ledger,NULL,&l_tickers,&l_tickers_count); + dap_chain_ledger_addr_get_token_ticker_all( l_net->pub.ledger,NULL,&l_tickers,&l_tickers_count); size_t l_pairs_count = 0; if(l_tickers){ diff --git a/modules/service/xchange/include/dap_chain_net_srv_xchange.h b/modules/service/xchange/include/dap_chain_net_srv_xchange.h index 06b7b15e348f3ea75e660312457ed25955f8232b..cbc65a355f1660c140d2546c1bd5b08797693885 100644 --- a/modules/service/xchange/include/dap_chain_net_srv_xchange.h +++ b/modules/service/xchange/include/dap_chain_net_srv_xchange.h @@ -36,7 +36,9 @@ typedef struct dap_chain_net_srv_xchange_price { uint256_t datoshi_sell; dap_chain_net_t *net; char token_buy[DAP_CHAIN_TICKER_SIZE_MAX]; + uint256_t datoshi_buy; uint256_t rate; + uint256_t fee; dap_chain_hash_fast_t tx_hash; dap_chain_hash_fast_t order_hash; dap_enc_key_t *wallet_key; @@ -44,9 +46,9 @@ typedef struct dap_chain_net_srv_xchange_price { typedef struct dap_srv_xchange_order_ext { uint64_t padding; - uint256_t datoshi_sell; - char token_sell[DAP_CHAIN_TICKER_SIZE_MAX]; -} dap_srv_xchange_order_ext_t; + uint256_t datoshi_buy; + char token_buy[DAP_CHAIN_TICKER_SIZE_MAX]; +} DAP_ALIGN_PACKED dap_srv_xchange_order_ext_t; typedef struct dap_chain_net_srv_xchange { dap_chain_net_srv_t *parent; @@ -57,4 +59,3 @@ extern const dap_chain_net_srv_uid_t c_dap_chain_net_srv_xchange_uid; int dap_chain_net_srv_xchange_init(); void dap_chain_net_srv_xchange_deinit(); -bool dap_chain_net_srv_xchange_verificator(dap_ledger_t * a_ledger, dap_chain_tx_out_cond_t *a_cond, dap_chain_datum_tx_t *a_tx, bool a_owner); diff --git a/modules/type/blocks/dap_chain_cs_blocks.c b/modules/type/blocks/dap_chain_cs_blocks.c index c762017a3767df85780cb37c9b0bdbf0debdd440..9fc5f3c5554ee1c339b741252d49db5a68c4ca47 100644 --- a/modules/type/blocks/dap_chain_cs_blocks.c +++ b/modules/type/blocks/dap_chain_cs_blocks.c @@ -131,7 +131,7 @@ static size_t s_callback_add_datums(dap_chain_t * a_chain, dap_chain_datum_t ** static void s_callback_cs_blocks_purge(dap_chain_t *a_chain); -static void s_new_block_delete(dap_chain_cs_blocks_t *a_blocks); +static dap_chain_block_t *s_new_block_move(dap_chain_cs_blocks_t *a_blocks, size_t *a_new_block_size); //Work with atoms static size_t s_callback_count_atom(dap_chain_t *a_chain); @@ -226,13 +226,7 @@ int dap_chain_cs_blocks_new(dap_chain_t * a_chain, dap_config_t * a_chain_config a_chain->callback_count_atom = s_callback_count_atom; a_chain->callback_get_atoms = s_callback_get_atoms; - - //dap_strdup_printf("%s.chain-%s.%s",l_net->pub.gdb_groups_prefix,l_chain->name,c_mempool_group_str); - //l_cs_blocks->gdb_group_datums_queue = "local.datums-queue."; - dap_chain_net_t *l_net = dap_chain_net_by_id(a_chain->net_id); - l_cs_blocks->gdb_group_datums_queue = dap_strdup_printf("local.datums-queue.chain-%s.%s", - l_net->pub.gdb_groups_prefix, a_chain->name); - l_cs_blocks->callback_new_block_del = s_new_block_delete; + l_cs_blocks->callback_new_block_move = s_new_block_move; 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; @@ -446,33 +440,26 @@ static int s_cli_blocks(int a_argc, char ** a_argv, char **a_str_reply) dap_chain_datum_t * l_datum = (dap_chain_datum_t*) dap_global_db_get_sync(l_gdb_group_mempool, l_subcmd_str_arg , &l_datum_size, NULL, NULL); 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_global_db_del_sync( l_gdb_group_mempool, l_datums_datum_hash_str) == 0 ){ - dap_cli_server_cmd_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_cli_server_cmd_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; - } + 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); + bool l_err = dap_chain_node_mempool_process(l_chain, l_datums[i]); + if (l_err) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Error! Datum %s doesn't pass verifications, examine node log files", + l_datums_datum_hash_str); + ret = -9; + } else { + log_it(L_INFO, "Pass datum %s from mempool to block in the new forming round ", + l_datums_datum_hash_str); + ret = 0; } - }else { - dap_cli_server_cmd_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_datums_datum_hash_str); + if (l_err) + break; } - - DAP_DELETE(l_gdb_group_mempool); - }break; + dap_cli_server_cmd_set_reply_text(a_str_reply, "All datums processed"); + } break; case SUBCMD_NEW_COMPLETE:{ dap_chain_net_sync_all(l_net); @@ -495,7 +482,7 @@ static int s_cli_blocks(int a_argc, char ** a_argv, char **a_str_reply) 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%04hX\n",l_block->hdr.version); + dap_string_append_printf(l_str_tmp, "\t\t\tversion: 0x%04X\n", l_block->hdr.version); dap_string_append_printf(l_str_tmp,"\t\t\tcell_id: 0x%016"DAP_UINT64_FORMAT_X"\n",l_block->hdr.cell_id.uint64); dap_string_append_printf(l_str_tmp,"\t\t\tchain_id: 0x%016"DAP_UINT64_FORMAT_X"\n",l_block->hdr.chain_id.uint64); ctime_r(&l_ts_reated, buf); @@ -674,38 +661,31 @@ static int s_add_atom_to_ledger(dap_chain_cs_blocks_t * a_blocks, dap_ledger_t * a_block_cache->block_hash_str, l_block_offset,l_datum_size ); break; } - int l_res = dap_chain_datum_add(a_blocks->chain, l_datum,l_datum_size ); - if(l_res == 0 ){ - 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; - // Check tx correcntess - size_t l_tx_size = dap_chain_datum_tx_get_size(l_tx); - - // Save tx hash -> block_hash link in hash table - dap_chain_tx_block_index_t * l_tx_block= DAP_NEW_Z(dap_chain_tx_block_index_t); - l_tx_block->ts_added = time(NULL); - l_tx_block->block_hash = a_block_cache->block_hash; - dap_hash_fast(l_tx, l_tx_size, &l_tx_block->tx_hash); - pthread_rwlock_wrlock( &PVT(a_blocks)->rwlock ); - HASH_ADD(hh, PVT(a_blocks)->tx_block_index, tx_hash, sizeof(l_tx_block->tx_hash), l_tx_block); - pthread_rwlock_unlock( &PVT(a_blocks)->rwlock ); - } break; - } + dap_hash_fast_t l_tx_hash; + int l_res = dap_chain_datum_add(a_blocks->chain, l_datum, l_datum_size, &l_tx_hash); + if (!l_res) { l_ret++; + if (l_datum->header.type_id == DAP_CHAIN_DATUM_TX) { + // Save tx hash -> block_hash link in hash table + dap_chain_tx_block_index_t * l_tx_block= DAP_NEW_Z(dap_chain_tx_block_index_t); + l_tx_block->ts_added = time(NULL); + l_tx_block->block_hash = a_block_cache->block_hash; + l_tx_block->tx_hash = l_tx_hash; + pthread_rwlock_wrlock( &PVT(a_blocks)->rwlock ); + HASH_ADD(hh, PVT(a_blocks)->tx_block_index, tx_hash, sizeof(l_tx_block->tx_hash), l_tx_block); + pthread_rwlock_unlock( &PVT(a_blocks)->rwlock ); + } } else { - char l_time_str[256]; - l_time_str[0] = '\0'; - dap_time_to_str_rfc822(l_time_str, sizeof(l_time_str)-1, l_datum->header.ts_create ); - log_it(L_WARNING, "Can't load datum #%zu %s with hash %s from block %s to ledger: code %d", i, - dap_chain_datum_type_id_to_str(l_datum->header.type_id ), l_time_str, - a_block_cache->block_hash_str, l_res); - break; + /* @RRL: disabled due spaming ... + debug_if(s_debug_more, L_ERROR, "Can't load datum #%zu (%s) from block %s to ledger: code %d", i, + dap_chain_datum_type_id_to_str(l_datum->header.type_id), a_block_cache->block_hash_str, l_res); + */ } } return l_ret; } + /** * @brief s_add_atom_to_blocks * @param a_blocks @@ -724,7 +704,8 @@ static int s_add_atom_to_blocks(dap_chain_cs_blocks_t * a_blocks, dap_ledger_t * pthread_rwlock_unlock( &PVT(a_blocks)->rwlock ); res = s_add_atom_to_ledger(a_blocks, a_ledger, a_block_cache); debug_if(s_debug_more, L_DEBUG, "Block %s checked, %s", a_block_cache->block_hash_str, - res ? "but ledger declined" : "all correct"); + res == (int)a_block_cache->datum_count ? + "all correct" : "but ledger declined"); //All correct, no matter for result pthread_rwlock_wrlock( &PVT(a_blocks)->rwlock ); HASH_ADD(hh, PVT(a_blocks)->blocks,block_hash,sizeof (a_block_cache->block_hash), a_block_cache); @@ -860,14 +841,15 @@ static dap_chain_atom_verify_res_t s_callback_atom_add(dap_chain_t * a_chain, da log_it(L_DEBUG, "... error adding (code %d)", l_consensus_check); ret = ATOM_REJECT; } + // !TODO make chunks add to blocks }else if(ret == ATOM_MOVE_TO_THRESHOLD){ dap_chain_block_chunks_add( PVT(l_blocks)->chunks,l_block_cache); - dap_chain_block_chunks_sort(PVT(l_blocks)->chunks); + //dap_chain_block_chunks_sort(PVT(l_blocks)->chunks); }else if (ret == ATOM_REJECT ){ DAP_DELETE(l_block_cache); } - s_bft_consensus_setup(l_blocks); + //s_bft_consensus_setup(l_blocks); return ret; } @@ -1096,12 +1078,12 @@ static dap_chain_atom_ptr_t s_callback_atom_iter_get_next( dap_chain_atom_iter_t *a_atom_size = l_cur_cache->block_size; return l_cur_cache->block; } - else { - a_atom_iter->cur = NULL; - a_atom_iter->cur_size = 0; - a_atom_iter->cur_hash = NULL; - return NULL; - } + a_atom_iter->cur = NULL; + a_atom_iter->cur_size = 0; + a_atom_iter->cur_hash = NULL; + if (a_atom_size) + *a_atom_size = 0; + return NULL; } /** @@ -1172,38 +1154,22 @@ static void s_callback_atom_iter_delete(dap_chain_atom_iter_t * a_atom_iter ) DAP_DELETE(a_atom_iter); } -static void s_new_block_delete(dap_chain_cs_blocks_t *a_blocks) { +static dap_chain_block_t *s_new_block_move(dap_chain_cs_blocks_t *a_blocks, size_t *a_new_block_size) +{ + size_t l_ret_size = 0; + dap_chain_block_t *l_ret = NULL; dap_chain_cs_blocks_pvt_t *l_blocks_pvt = PVT(a_blocks); pthread_rwlock_wrlock(&l_blocks_pvt->datums_lock); if ( a_blocks->block_new ) { - DAP_DEL_Z(a_blocks->block_new); + l_ret = a_blocks->block_new; + l_ret_size = a_blocks->block_new_size; + a_blocks->block_new = NULL; a_blocks->block_new_size = 0; } pthread_rwlock_unlock(&l_blocks_pvt->datums_lock); -} - -static int s_new_block_complete(dap_chain_cs_blocks_t *a_blocks) -{ - dap_hash_fast_t l_merkle_root = {}; // TODO compute the merkle root of block's datums - a_blocks->block_new_size = dap_chain_block_meta_add(&a_blocks->block_new, a_blocks->block_new_size, - DAP_CHAIN_BLOCK_META_MERKLE, &l_merkle_root, sizeof(l_merkle_root)); - size_t l_signed_size = a_blocks->callback_block_sign(a_blocks, &a_blocks->block_new, a_blocks->block_new_size); - if (l_signed_size) - a_blocks->block_new_size = l_signed_size; - else { - log_it(L_WARNING, "Block signing failed"); - return -1; - } - dap_chain_atom_verify_res_t l_res = s_callback_atom_add(a_blocks->chain, a_blocks->block_new, a_blocks->block_new_size); - DAP_DEL_Z(a_blocks->block_new); - if (l_res == ATOM_ACCEPT) { - if (dap_chain_atom_save(a_blocks->chain, (uint8_t *)a_blocks->block_new, a_blocks->block_new_size, a_blocks->chain->cells->id) < 0) { - log_it(L_ERROR, "Can't add new event to the file"); - } - /* TODO add all atoms from treshold */ - return 0; - } - return -2; + if (a_new_block_size) + *a_new_block_size = l_ret_size; + return l_ret; } /** @@ -1216,151 +1182,34 @@ static int s_new_block_complete(dap_chain_cs_blocks_t *a_blocks) static size_t s_callback_add_datums(dap_chain_t *a_chain, dap_chain_datum_t **a_datums, size_t a_datums_count) { dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(a_chain); - char *l_gdb_group = l_blocks->gdb_group_datums_queue; + dap_chain_cs_blocks_pvt_t *l_blocks_pvt = PVT(l_blocks); size_t l_datum_processed = 0; - for (size_t i = 0; i < a_datums_count; i++) { - size_t l_datum_size = dap_chain_datum_size(a_datums[i]); - dap_chain_datum_t *l_datum = (dap_chain_datum_t *)a_datums[i]; - if (!l_datum_size || !l_datum) - continue; - - // Verify for correctness - dap_chain_net_t *l_net = dap_chain_net_by_id(a_chain->net_id); - int l_verify_datum = dap_chain_net_verify_datum_for_add(l_net, l_datum); - if (l_verify_datum != 0 && - l_verify_datum != DAP_CHAIN_CS_VERIFY_CODE_TX_NO_PREVIOUS && - l_verify_datum != DAP_CHAIN_CS_VERIFY_CODE_TX_NO_EMISSION && - l_verify_datum != DAP_CHAIN_CS_VERIFY_CODE_TX_NO_TOKEN) { - log_it(L_WARNING, "Datum doesn't pass verifications (code %d)", - l_verify_datum); + pthread_rwlock_wrlock(&l_blocks_pvt->datums_lock); + for (size_t i = 0; i < a_datums_count; ++i) { + dap_chain_datum_t *l_datum = a_datums[i]; + size_t l_datum_size = dap_chain_datum_size(l_datum); + if (!l_datum_size) { + log_it(L_WARNING, "Empty datum"); /* How might it be? */ continue; } - - //Check minimum commission - bool tx_commission_valid = true; - if (l_datum->header.type_id == DAP_CHAIN_DATUM_TX) { - dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t *)l_datum->data; - uint32_t l_tx_items_count = 0; - uint32_t l_tx_items_size = l_tx->header.tx_items_size; - size_t l_item_tx_size = 0; - uint8_t *item = NULL; - while (l_tx_items_count < l_tx_items_size) - { - item = l_tx->tx_items + l_tx_items_count; - l_item_tx_size = dap_chain_datum_item_tx_get_size(item); - if( dap_chain_datum_tx_item_get_type(item) == TX_ITEM_TYPE_OUT_COND - && ((dap_chain_tx_out_cond_t*)item)->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE) { - if (compare256(((dap_chain_tx_out_cond_t*)item)->header.value, a_chain->minimum_commission) == -1) - tx_commission_valid = false; - } - - l_tx_items_count += l_item_tx_size; - if(!l_item_tx_size) - break; - } - } - if (!tx_commission_valid) - continue; - - dap_chain_hash_fast_t l_key_hash; - dap_hash_fast(l_datum, l_datum_size, &l_key_hash); - char *l_key_str = dap_chain_hash_fast_to_str_new(&l_key_hash); - - if (dap_global_db_set(l_gdb_group, l_key_str, l_datum, l_datum_size,true, NULL, NULL ) ==0 ) { - l_datum_processed++; + if (l_blocks->block_new_size + l_datum_size > l_blocks_pvt->block_size_maximum) { + log_it(L_DEBUG, "Maximum size exeeded, %zu > %zu", l_blocks->block_new_size + l_datum_size, l_blocks_pvt->block_size_maximum); + break; } - } - return l_datum_processed; -} - -/** - * @brief blocks async operations arguments - * @param blocks Consensus blocks object - */ -struct op_results_args{ - dap_chain_cs_blocks_t * blocks; - dap_chain_cs_blocks_callback_op_results_t callback_op_results; - void * callback_arg; -}; - - -static bool s_callback_new_block_add_datums (dap_global_db_context_t * a_global_db_context,int a_rc, const char * a_group, const char * a_key, const size_t a_values_total, const size_t a_values_shift, - const size_t a_values_count, dap_global_db_obj_t * a_values, void * a_arg) -{ - struct op_results_args *l_args = (struct op_results_args *) a_arg; - dap_chain_cs_blocks_t *l_blocks = l_args->blocks; - dap_chain_t * l_chain = l_blocks->chain; - dap_chain_cs_blocks_pvt_t *l_blocks_pvt = PVT(l_blocks); - - pthread_rwlock_wrlock(&l_blocks_pvt->datums_lock); - - if (a_values_count) { - for (size_t i = 0; i < a_values_count; i++) { - dap_chain_datum_t *l_datum = (dap_chain_datum_t *)a_values[i].value; - size_t l_datum_size = dap_chain_datum_size(l_datum); - if (l_blocks->block_new_size + l_datum_size > l_blocks_pvt->block_size_maximum) - break; - dap_global_db_del_unsafe(a_global_db_context, a_values[i].key, a_group); // delete from datums queue - if (!a_values[i].key || !a_values[i].value || !a_values[i].value_len) { - log_it(L_WARNING, "DB object field in block new queue comes NULL"); - continue; - } - if (!l_datum_size) { - log_it(L_WARNING, "Datum size in block new queue comes NULL"); - continue; - } - // Verify for correctness - dap_chain_net_t *l_net = dap_chain_net_by_id(l_chain->net_id); - int l_verify_datum = dap_chain_net_verify_datum_for_add(l_net, l_datum); - if (l_verify_datum != 0 && - l_verify_datum != DAP_CHAIN_CS_VERIFY_CODE_TX_NO_PREVIOUS && - l_verify_datum != DAP_CHAIN_CS_VERIFY_CODE_TX_NO_EMISSION && - l_verify_datum != DAP_CHAIN_CS_VERIFY_CODE_TX_NO_TOKEN) { - log_it(L_WARNING, "Datum doesn't pass verifications (code %d)", - l_verify_datum); - continue; - } - - if (!l_blocks->block_new) { - l_blocks->block_new = dap_chain_block_new(&l_blocks_pvt->block_cache_last->block_hash, &l_blocks->block_new_size); - l_blocks->block_new->hdr.cell_id.uint64 = l_chain->cells->id.uint64; - l_blocks->block_new->hdr.chain_id.uint64 = l_blocks->chain->id.uint64; - } - - l_blocks->block_new_size = dap_chain_block_datum_add(&l_blocks->block_new, l_blocks->block_new_size, - l_datum, l_datum_size); + if (!l_blocks->block_new) { + l_blocks->block_new = dap_chain_block_new(&l_blocks_pvt->block_cache_last->block_hash, &l_blocks->block_new_size); + l_blocks->block_new->hdr.cell_id.uint64 = a_chain->cells->id.uint64; + l_blocks->block_new->hdr.chain_id.uint64 = l_blocks->chain->id.uint64; } - } - pthread_rwlock_unlock(&l_blocks_pvt->datums_lock); - l_args->callback_op_results( l_args->blocks,0, l_args->callback_arg); - DAP_DELETE(l_args); - return true; -} - -/** - * @brief Create new block and add datums from block's queue - * @param a_chain Chain object - * @param a_callback_op_results Executes after request completed - * @param a_arg Custom argument - */ -void dap_chain_cs_new_block_add_datums(dap_chain_t *a_chain, dap_chain_cs_blocks_callback_op_results_t a_callback_op_results, void * a_arg ) -{ - dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(a_chain); - - struct op_results_args * l_args = DAP_NEW_Z(struct op_results_args); - l_args->blocks = l_blocks; - l_args->callback_op_results = a_callback_op_results; - l_args->callback_arg = a_arg; - if( dap_global_db_get_all(l_blocks->gdb_group_datums_queue,0,s_callback_new_block_add_datums, l_args ) != 0 ){ - log_it(L_ERROR, "Can't execute get_all gdb request for dap_chain_cs_new_block_add_datums() function"); - DAP_DELETE(l_args); + l_blocks->block_new_size = dap_chain_block_datum_add(&l_blocks->block_new, l_blocks->block_new_size, l_datum, l_datum_size); + l_datum_processed++; } - + pthread_rwlock_unlock(&l_blocks_pvt->datums_lock); + return l_datum_processed; } - /** * @brief s_callback_count_atom Gets the number of blocks * @param a_chain Chain object @@ -1372,7 +1221,6 @@ static size_t s_callback_count_atom(dap_chain_t *a_chain){ return l_blocks_pvt->blocks_count; } - /** * @brief s_callback_get_atoms Gets the specified number of blocks with an offset * @param a_chain Chain object @@ -1385,6 +1233,9 @@ static dap_list_t *s_callback_get_atoms(dap_chain_t *a_chain, size_t a_count, si { dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(a_chain); dap_chain_cs_blocks_pvt_t *l_blocks_pvt = PVT(l_blocks); + if (!l_blocks_pvt->blocks) { + return NULL; + } size_t l_offset = a_count * (a_page - 1); size_t l_count = l_blocks_pvt->blocks_count; if (a_page < 2) @@ -1395,9 +1246,7 @@ static dap_list_t *s_callback_get_atoms(dap_chain_t *a_chain, size_t a_count, si dap_list_t *l_list = NULL; size_t l_counter = 0; size_t l_end = l_offset + a_count; - if (!l_blocks_pvt->blocks) { - return NULL; - } + if (a_reverse) { dap_chain_block_cache_t *l_ptr = l_blocks_pvt->blocks->hh.tbl->tail->prev; if (!l_ptr) diff --git a/modules/type/blocks/include/dap_chain_cs_blocks.h b/modules/type/blocks/include/dap_chain_cs_blocks.h index 2bcebb989f66ce878e59460b0b7ec115f2adde51..fa654cce8118eee0157ee63ab79a4667b97276fe 100644 --- a/modules/type/blocks/include/dap_chain_cs_blocks.h +++ b/modules/type/blocks/include/dap_chain_cs_blocks.h @@ -33,7 +33,7 @@ typedef void (*dap_chain_cs_blocks_callback_t)(dap_chain_cs_blocks_t *); typedef void (*dap_chain_cs_blocks_callback_op_results_t)(dap_chain_cs_blocks_t * a_cs_blocks, int a_rc, void * a_arg); typedef int (*dap_chain_cs_blocks_callback_block_t)(dap_chain_cs_blocks_t *, dap_chain_block_t *, size_t); typedef size_t (*dap_chain_cs_blocks_callback_block_sign_t)(dap_chain_cs_blocks_t *, dap_chain_block_t **, size_t); - +typedef dap_chain_block_t *(*dap_chain_cs_block_move_t)(dap_chain_cs_blocks_t *, size_t *); typedef dap_chain_block_t * (*dap_chain_cs_blocks_callback_block_create_t)(dap_chain_cs_blocks_t *, dap_chain_datum_t *, dap_chain_hash_fast_t *, @@ -50,7 +50,7 @@ typedef struct dap_chain_cs_blocks dap_chain_cs_blocks_callback_block_create_t callback_block_create; dap_chain_cs_blocks_callback_block_t callback_block_verify; dap_chain_cs_blocks_callback_block_sign_t callback_block_sign; - dap_chain_cs_blocks_callback_t callback_new_block_del; + dap_chain_cs_block_move_t callback_new_block_move; void * _pvt; void * _inheritor; @@ -64,6 +64,3 @@ 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); - -void dap_chain_cs_new_block_add_datums(dap_chain_t *a_chain,dap_chain_cs_blocks_callback_op_results_t a_callback_op_results, void * a_arg); - diff --git a/modules/type/dag/dap_chain_cs_dag.c b/modules/type/dag/dap_chain_cs_dag.c index 3690f5bb49fcbb2c679d47dfa996db78e0c04a70..735e3ca797b3d5875e11689ed4cb2459b3259e26 100644 --- a/modules/type/dag/dap_chain_cs_dag.c +++ b/modules/type/dag/dap_chain_cs_dag.c @@ -73,6 +73,7 @@ typedef struct dap_chain_cs_dag_pvt { dap_chain_cs_dag_event_item_t * events_treshold; dap_chain_cs_dag_event_item_t * events_treshold_conflicted; dap_chain_cs_dag_event_item_t * events_lasts_unlinked; + dap_interval_timer_t mempool_timer; } dap_chain_cs_dag_pvt_t; #define PVT(a) ((dap_chain_cs_dag_pvt_t *) a->_pvt ) @@ -283,6 +284,7 @@ int dap_chain_cs_dag_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg) byte_t *l_current_round = dap_global_db_get_sync(l_gdb_group, DAG_ROUND_CURRENT_KEY, NULL, NULL, NULL); l_dag->round_current = l_current_round? *(uint64_t *)l_current_round : 0; DAP_DELETE(l_current_round); + PVT(l_dag)->mempool_timer = dap_interval_timer_create(5000, (dap_timer_callback_t)dap_chain_node_mempool_process_all, a_chain); if (l_dag->is_single_line) log_it (L_NOTICE, "DAG chain initialized (single line)"); else @@ -334,7 +336,7 @@ 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); - + dap_interval_timer_delete(PVT(l_dag)->mempool_timer); if(l_dag->callback_delete ) l_dag->callback_delete(l_dag); if(l_dag->_inheritor) @@ -357,33 +359,27 @@ static int s_dap_chain_add_atom_to_ledger(dap_chain_cs_dag_t * a_dag, dap_ledger log_it(L_WARNING, "Corrupted event, too big size %zd in header when event's size max is only %zd", l_datum_size, l_datum_size_max); return -1; } - if(dap_chain_datum_add(a_dag->chain,l_datum, l_datum_size) == 0){ + dap_hash_fast_t l_tx_hash = {}; + if(dap_chain_datum_add(a_dag->chain,l_datum, l_datum_size, &l_tx_hash) == 0) { pthread_rwlock_t * l_events_rwlock = &PVT(a_dag)->events_rwlock; - 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; - dap_hash_fast_t l_tx_hash; - unsigned l_hash_item_hashv; - HASH_VALUE(&l_tx_hash, sizeof(l_tx_hash), l_hash_item_hashv); - dap_chain_cs_dag_event_item_t *l_tx_event; - int l_err = pthread_rwlock_wrlock(l_events_rwlock); - HASH_FIND_BYHASHVALUE(hh, PVT(a_dag)->tx_events, &l_tx_hash, sizeof(l_tx_event->hash), - l_hash_item_hashv, l_tx_event); - if (!l_tx_event) { - l_tx_event = DAP_NEW_Z(dap_chain_cs_dag_event_item_t); - l_tx_event->ts_added = a_event_item->ts_added; - l_tx_event->event = a_event_item->event; - l_tx_event->event_size = a_event_item->event_size; - l_tx_event->hash = l_tx_hash; - HASH_ADD_BYHASHVALUE(hh, PVT(a_dag)->tx_events, hash, sizeof(l_tx_event->hash), - l_hash_item_hashv, l_tx_event); - } - if (l_err != EDEADLK) - pthread_rwlock_unlock(l_events_rwlock); - } break; - case DAP_CHAIN_DATUM_CA: - return DAP_CHAIN_DATUM_CA; - default:; + if (l_datum->header.type_id == DAP_CHAIN_DATUM_TX) { + unsigned l_hash_item_hashv; + HASH_VALUE(&l_tx_hash, sizeof(l_tx_hash), l_hash_item_hashv); + dap_chain_cs_dag_event_item_t *l_tx_event; + int l_err = pthread_rwlock_wrlock(l_events_rwlock); + HASH_FIND_BYHASHVALUE(hh, PVT(a_dag)->tx_events, &l_tx_hash, sizeof(l_tx_event->hash), + l_hash_item_hashv, l_tx_event); + if (!l_tx_event) { + l_tx_event = DAP_NEW_Z(dap_chain_cs_dag_event_item_t); + l_tx_event->ts_added = a_event_item->ts_added; + l_tx_event->event = a_event_item->event; + l_tx_event->event_size = a_event_item->event_size; + l_tx_event->hash = l_tx_hash; + HASH_ADD_BYHASHVALUE(hh, PVT(a_dag)->tx_events, hash, sizeof(l_tx_event->hash), + l_hash_item_hashv, l_tx_event); + } + if (l_err != EDEADLK) + pthread_rwlock_unlock(l_events_rwlock); } return 0; } else @@ -477,10 +473,6 @@ static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_cha break; case ATOM_ACCEPT: { int l_consensus_check = s_dap_chain_add_atom_to_events_table(l_dag, a_chain->ledger, l_event_item); - pthread_rwlock_wrlock(l_events_rwlock); - HASH_ADD(hh, PVT(l_dag)->events,hash, sizeof(l_event_item->hash), l_event_item); - s_dag_events_lasts_process_new_last_event(l_dag, l_event_item); - pthread_rwlock_unlock(l_events_rwlock); switch (l_consensus_check) { case 0: if(s_debug_more) @@ -504,8 +496,11 @@ static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_cha if (s_debug_more) log_it(L_WARNING, "... added with ledger code %d", l_consensus_check); break; - } + pthread_rwlock_wrlock(l_events_rwlock); + HASH_ADD(hh, PVT(l_dag)->events,hash, sizeof(l_event_item->hash), l_event_item); + s_dag_events_lasts_process_new_last_event(l_dag, l_event_item); + pthread_rwlock_unlock(l_events_rwlock); } break; default: DAP_DELETE(l_event_item); // Neither added, nor freed @@ -548,18 +543,6 @@ static size_t s_callback_add_datums(dap_chain_t *a_chain, dap_chain_datum_t **a_ if (!l_datum_size || !l_datum) continue; - // Verify for correctness - dap_chain_net_t *l_net = dap_chain_net_by_id(a_chain->net_id); - int l_verify_datum = dap_chain_net_verify_datum_for_add(l_net, l_datum); - if (l_verify_datum != 0 && - l_verify_datum != DAP_CHAIN_CS_VERIFY_CODE_TX_NO_PREVIOUS && - l_verify_datum != DAP_CHAIN_CS_VERIFY_CODE_TX_NO_EMISSION && - l_verify_datum != DAP_CHAIN_CS_VERIFY_CODE_TX_NO_TOKEN) { - log_it(L_WARNING, "Datum doesn't pass verifications (code %d)", - l_verify_datum); - continue; - } - if (s_chain_callback_datums_pool_proc(a_chain, l_datum)) l_datum_processed++; } @@ -922,14 +905,16 @@ dap_chain_cs_dag_event_item_t* dap_chain_cs_dag_proc_treshold(dap_chain_cs_dag_t } int l_add_res = s_dap_chain_add_atom_to_events_table(a_dag, a_ledger, l_event_item); HASH_DEL(PVT(a_dag)->events_treshold, l_event_item); - HASH_ADD(hh, PVT(a_dag)->events, hash, sizeof(l_event_item->hash), l_event_item); - s_dag_events_lasts_process_new_last_event(a_dag, l_event_item); - res = true; - if(s_debug_more) { - if (!l_add_res) - log_it(L_INFO, "... moved from treshold to main chains"); - else - log_it(L_WARNING, "... moved with ledger code %d", l_add_res); + if (!l_add_res) { + HASH_ADD(hh, PVT(a_dag)->events, hash, sizeof(l_event_item->hash), l_event_item); + s_dag_events_lasts_process_new_last_event(a_dag, l_event_item); + debug_if(s_debug_more, L_INFO, "... moved from treshold to main chains"); + res = true; + } else { + // TODO clear other threshold items linked with this one + debug_if(s_debug_more, L_WARNING, "... rejected with ledger code %d", l_add_res); + DAP_DELETE(l_event_item->event); + DAP_DELETE(l_event_item); } break; } else if (ret == DAP_THRESHOLD_CONFLICTING) { @@ -1700,9 +1685,7 @@ static int s_cli_dag(int argc, char ** argv, char **a_str_reply) DAP_DELETE(l_round_item); }break; case SUBCMD_EVENT_LIST:{ - if( (l_from_events_str == NULL) || - (strcmp(l_from_events_str,"round.new") == 0) ){ - + if (l_from_events_str && strcmp(l_from_events_str,"round.new") == 0) { char * l_gdb_group_events = DAP_CHAIN_CS_DAG(l_chain)->gdb_group_events_round_new; dap_string_t * l_str_tmp = dap_string_new(""); if ( l_gdb_group_events ){ @@ -1730,7 +1713,7 @@ static int s_cli_dag(int argc, char ** argv, char **a_str_reply) } dap_cli_server_cmd_set_reply_text(a_str_reply, l_str_tmp->str); dap_string_free(l_str_tmp,false); - }else if (l_from_events_str && (strcmp(l_from_events_str,"events") == 0) ){ + } else if (!l_from_events_str || (strcmp(l_from_events_str,"events") == 0)) { dap_string_t * l_str_tmp = dap_string_new(NULL); pthread_rwlock_rdlock(&PVT(l_dag)->events_rwlock); dap_chain_cs_dag_event_item_t * l_event_item = NULL,*l_event_item_tmp = NULL; @@ -1889,6 +1872,9 @@ static dap_list_t *s_callback_get_atoms(dap_chain_t *a_chain, size_t a_count, si UNUSED(a_reverse); dap_chain_cs_dag_t *l_dag = DAP_CHAIN_CS_DAG(a_chain); dap_chain_cs_dag_pvt_t *l_dag_pvt = PVT(l_dag); + if (!l_dag_pvt->events) { + return NULL; + } size_t l_offset = a_count * (a_page - 1); pthread_rwlock_rdlock(&PVT(l_dag)->events_rwlock); size_t l_count = HASH_COUNT(l_dag_pvt->events); @@ -1900,9 +1886,7 @@ static dap_list_t *s_callback_get_atoms(dap_chain_t *a_chain, size_t a_count, si dap_list_t *l_list = NULL; size_t l_counter = 0; size_t l_end = l_offset + a_count; - if (!l_dag_pvt->events){ - return NULL; - } + dap_chain_cs_dag_event_item_t *l_ptr = l_dag_pvt->events->hh.tbl->tail->prev; if (!l_ptr) l_ptr = l_dag_pvt->events;