diff --git a/cellframe-sdk.pro b/cellframe-sdk.pro index e553962e9ab90730f0664d36b8f575024c09db5c..3e1b5e1eaf9b031230e2263a0825adb993fa12a8 100644 --- a/cellframe-sdk.pro +++ b/cellframe-sdk.pro @@ -9,24 +9,24 @@ linux: !android { win32 { - CONFIG(release, debug | release): sdk_build.commands = "$$shell_path($$PWD/../cellframe-sdk/prod_build/build.sh)" --target windows release -DINSTALL_SDK=1 -DCMAKE_INSTALL_PREFIX=/ - CONFIG(debug, debug | release): sdk_build.commands = "$$shell_path($$PWD/../cellframe-sdk/prod_build/build.sh)" --target windows rwd -DINSTALL_SDK=1 -DCMAKE_INSTALL_PREFIX=/ + CONFIG(release, debug | release): sdk_build.commands = "$$shell_path($$PWD/../cellframe-sdk/prod_build/build.sh)" --target windows release -DINSTALL_SDK=1 -DCMAKE_INSTALL_PREFIX=/ -DCELLFRAME_NO_OPTIMIZATION=1 + CONFIG(debug, debug | release): sdk_build.commands = "$$shell_path($$PWD/../cellframe-sdk/prod_build/build.sh)" --target windows rwd -DINSTALL_SDK=1 -DCMAKE_INSTALL_PREFIX=/ -DCELLFRAME_NO_OPTIMIZATION=1 } android { for (AABI, ANDROID_ABIS) { message("Requested ABI: $$AABI") - CONFIG(release, debug | release): sdk_build_$${AABI}.commands += $$PWD/../cellframe-sdk/prod_build/build.sh -b $$AABI --target android release -DANDROID_PLATFORM=android-21 -DANDROID_ABI=$$AABI -DANDROID_NATIVE_API_LEVEL=29 -DINSTALL_SDK=1 -DCMAKE_INSTALL_PREFIX=/ -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON - CONFIG(debug, debug | release): sdk_build_$${AABI}.commands += $$PWD/../cellframe-sdk/prod_build/build.sh -b $$AABI --target android release -DANDROID_PLATFORM=android-21 -DANDROID_ABI=$$AABI -DANDROID_NATIVE_API_LEVEL=29 -DINSTALL_SDK=1 -DCMAKE_INSTALL_PREFIX=/ -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON + CONFIG(release, debug | release): sdk_build_$${AABI}.commands += $$PWD/../cellframe-sdk/prod_build/build.sh -b $$AABI --target android release -DANDROID_PLATFORM=android-21 -DANDROID_ABI=$$AABI -DANDROID_NATIVE_API_LEVEL=29 -DINSTALL_SDK=1 -DCMAKE_INSTALL_PREFIX=/ -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -DCELLFRAME_NO_OPTIMIZATION=1 + CONFIG(debug, debug | release): sdk_build_$${AABI}.commands += $$PWD/../cellframe-sdk/prod_build/build.sh -b $$AABI --target android release -DANDROID_PLATFORM=android-21 -DANDROID_ABI=$$AABI -DANDROID_NATIVE_API_LEVEL=29 -DINSTALL_SDK=1 -DCMAKE_INSTALL_PREFIX=/ -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -DCELLFRAME_NO_OPTIMIZATION=1 } } mac { - CONFIG(release, debug | release): sdk_build.commands = $$PWD/../cellframe-sdk/prod_build/build.sh --target osx release -DINSTALL_SDK=1 -DCMAKE_INSTALL_PREFIX=/ - CONFIG(debug, debug | release): sdk_build.commands = $$PWD/../cellframe-sdk/prod_build/build.sh --target osx rwd -DINSTALL_SDK=1 -DCMAKE_INSTALL_PREFIX=/ + CONFIG(release, debug | release): sdk_build.commands = $$PWD/../cellframe-sdk/prod_build/build.sh --target osx release -DINSTALL_SDK=1 -DCMAKE_INSTALL_PREFIX=/ -DCELLFRAME_NO_OPTIMIZATION=1 + CONFIG(debug, debug | release): sdk_build.commands = $$PWD/../cellframe-sdk/prod_build/build.sh --target osx rwd -DINSTALL_SDK=1 -DCMAKE_INSTALL_PREFIX=/ -DCELLFRAME_NO_OPTIMIZATION=1 } diff --git a/modules/chain/dap_chain_ch.c b/modules/chain/dap_chain_ch.c index 661cffe6df1deb570d75247854259a8feb223170..6c71b25332bd29758646d05ce2a4b1fb115d39db 100644 --- a/modules/chain/dap_chain_ch.c +++ b/modules/chain/dap_chain_ch.c @@ -877,7 +877,7 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) if (l_missed_hash) { l_chain->callback_atom_iter_get(l_iter, DAP_CHAIN_ITER_OP_LAST, NULL); dap_chain_ch_miss_info_t l_miss_info = { .missed_hash = l_request->hash_from, - .last_hash = *l_iter->cur_hash, + .last_hash = l_iter->cur_hash ? *l_iter->cur_hash : (dap_hash_fast_t){ }, .last_num = l_iter->cur_num }; dap_chain_ch_pkt_write_unsafe(a_ch, DAP_CHAIN_CH_PKT_TYPE_CHAIN_MISS, l_chain_pkt->hdr.net_id, l_chain_pkt->hdr.chain_id, diff --git a/modules/consensus/esbocs/dap_chain_cs_esbocs.c b/modules/consensus/esbocs/dap_chain_cs_esbocs.c index 9ec843ca7105ac76258eb40e2b6e84c60f4aea18..7c9334ad83915cb1464839646254392dbb790f64 100644 --- a/modules/consensus/esbocs/dap_chain_cs_esbocs.c +++ b/modules/consensus/esbocs/dap_chain_cs_esbocs.c @@ -427,7 +427,6 @@ static void s_new_atom_notifier(void *a_arg, dap_chain_t *a_chain, dap_chain_cel { dap_chain_esbocs_session_t *l_session = a_arg; assert(l_session->chain == a_chain); - //pthread_mutex_lock(&l_session->mutex); dap_chain_hash_fast_t l_last_block_hash; dap_chain_get_atom_last_hash(l_session->chain, a_id, &l_last_block_hash); if (!dap_hash_fast_compare(&l_last_block_hash, &l_session->cur_round.last_block_hash) && @@ -435,7 +434,6 @@ static void s_new_atom_notifier(void *a_arg, dap_chain_t *a_chain, dap_chain_cel l_session->new_round_enqueued = true; s_session_round_new(l_session); } - //pthread_mutex_unlock(&l_session->mutex); if (!PVT(l_session->esbocs)->collecting_addr) return; dap_chain_esbocs_block_collect_t l_block_collect_params = (dap_chain_esbocs_block_collect_t){ @@ -593,7 +591,6 @@ static int s_callback_created(dap_chain_t *a_chain, dap_config_t *a_chain_net_cf log_it(L_ERROR, "This validator is not allowed to work in emergency mode. Use special decree to supply it"); return -5; } - //pthread_mutex_init(&l_session->mutex, NULL); dap_chain_add_callback_notify(a_chain, s_new_atom_notifier, l_session); s_session_round_new(l_session); @@ -789,7 +786,6 @@ static void s_callback_delete(dap_chain_cs_blocks_t *a_blocks) log_it(L_INFO, "No session found"); return; } - //pthread_mutex_lock(&l_session->mutex); DL_DELETE(s_session_items, l_session); s_session_round_clear(l_session); dap_chain_esbocs_sync_item_t *l_sync_item, *l_sync_tmp; @@ -803,8 +799,6 @@ static void s_callback_delete(dap_chain_cs_blocks_t *a_blocks) HASH_DEL(l_session->penalty, l_pen_item); DAP_DELETE(l_pen_item); } - //pthread_mutex_unlock(&l_session->mutex); - //pthread_mutex_destroy(&l_session->mutex); DAP_DEL_MULTY(l_session, a_blocks->_inheritor); // a_blocks->_inheritor - l_esbocs } @@ -1032,10 +1026,8 @@ static void s_session_send_startsync(dap_chain_esbocs_session_t *a_session) static bool s_session_send_startsync_on_timer(void *a_arg) { dap_chain_esbocs_session_t *l_session = a_arg; - //pthread_mutex_lock(&l_session->mutex); s_session_send_startsync(l_session); l_session->sync_timer = NULL; - //pthread_mutex_unlock(&l_session->mutex); return false; } @@ -1476,8 +1468,6 @@ static void s_session_proc_state(void *a_arg) dap_chain_esbocs_session_t *l_session = a_arg; if (!l_session->cs_timer) return; // Timer is inactive - //if (pthread_mutex_trylock(&l_session->mutex) != 0) - // return; // Session is busy bool l_cs_debug = PVT(l_session->esbocs)->debug; dap_time_t l_time = dap_time_now(); switch (l_session->state) { @@ -1582,8 +1572,6 @@ static void s_session_proc_state(void *a_arg) default: break; } - - //pthread_mutex_unlock(&l_session->mutex); } static void s_message_chain_add(dap_chain_esbocs_session_t *a_session, @@ -2219,10 +2207,8 @@ static void s_session_packet_in(dap_chain_esbocs_session_t *a_session, dap_chain dap_hash_fast(l_message, a_data_size, &l_data_hash); if (a_sender_node_addr) { //Process network messages only - //pthread_mutex_lock(&l_session->mutex); if (l_message->hdr.chain_id.uint64 != l_session->chain->id.uint64) { debug_if(l_cs_debug, L_MSG, "Invalid chain ID %"DAP_UINT64_FORMAT_U, l_message->hdr.chain_id.uint64); - //goto session_unlock; return; } // check hash message dup @@ -2233,7 +2219,6 @@ static void s_session_packet_in(dap_chain_esbocs_session_t *a_session, dap_chain " Message rejected: message hash is exists in chain (duplicate)", l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id, l_message->hdr.attempt_num); - //goto session_unlock; return; } l_message->hdr.sign_size = 0; // restore header on signing time @@ -2242,7 +2227,6 @@ static void s_session_packet_in(dap_chain_esbocs_session_t *a_session, dap_chain " 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, l_session->cur_round.attempt_num, NODE_ADDR_FP_ARGS(a_sender_node_addr)); - //goto session_unlock; return; } l_message->hdr.sign_size = l_sign_size; // restore original header @@ -2255,7 +2239,6 @@ static void s_session_packet_in(dap_chain_esbocs_session_t *a_session, dap_chain l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id); s_session_sync_queue_add(l_session, l_message, a_data_size); - //goto session_unlock; return; } } else if (l_message->hdr.round_id != l_session->cur_round.id) { @@ -2291,7 +2274,6 @@ static void s_session_packet_in(dap_chain_esbocs_session_t *a_session, dap_chain l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id, l_message->hdr.attempt_num, s_voting_msg_type_to_str(l_message->hdr.type)); - //goto session_unlock; return; } } @@ -2328,7 +2310,6 @@ static void s_session_packet_in(dap_chain_esbocs_session_t *a_session, dap_chain " Message rejected: validator key:%s not in the current validators list or not synced yet", l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id, l_message->hdr.attempt_num, l_validator_addr_str); - //goto session_unlock; return; } @@ -2468,7 +2449,6 @@ static void s_session_packet_in(dap_chain_esbocs_session_t *a_session, dap_chain l_store = DAP_NEW_Z(dap_chain_esbocs_store_t); if (!l_store) { log_it(L_CRITICAL, "%s", c_error_memory_alloc); - //goto session_unlock; return; } l_store->candidate_size = l_candidate_size; @@ -2695,9 +2675,6 @@ static void s_session_packet_in(dap_chain_esbocs_session_t *a_session, dap_chain default: break; } -//session_unlock: - //if (a_sender_node_addr) //Process network message - // pthread_mutex_unlock(&l_session->mutex); } static void s_message_send(dap_chain_esbocs_session_t *a_session, uint8_t a_message_type, dap_hash_fast_t *a_block_hash, @@ -2743,7 +2720,7 @@ static void s_message_send(dap_chain_esbocs_session_t *a_session, uint8_t a_mess a_message_type, l_message, l_message_size + l_sign_size); continue; } - /*struct esbocs_msg_args *l_args = DAP_NEW_SIZE(struct esbocs_msg_args, + struct esbocs_msg_args *l_args = DAP_NEW_SIZE(struct esbocs_msg_args, sizeof(struct esbocs_msg_args) + l_message_size + l_sign_size); if (!l_args) { log_it(L_CRITICAL, "%s", c_error_memory_alloc); @@ -2754,8 +2731,7 @@ static void s_message_send(dap_chain_esbocs_session_t *a_session, uint8_t a_mess l_args->session = a_session; l_args->message_size = l_message_size + l_sign_size; memcpy(l_args->message, l_message, l_message_size + l_sign_size); - dap_proc_thread_callback_add(a_session->proc_thread, s_process_incoming_message, l_args);*/ - s_session_packet_in(a_session, &a_session->my_addr, (byte_t*)l_message, l_message_size + l_sign_size); + dap_proc_thread_callback_add(a_session->proc_thread, s_process_incoming_message, l_args); } } DAP_DELETE(l_message); @@ -3108,7 +3084,7 @@ static int s_cli_esbocs(int a_argc, char **a_argv, void **a_str_reply) dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_ESBOCS_PARAM_ERR,"Command '%s' requires parameter -val_count", l_subcmd_strs[l_subcmd]); return -DAP_CHAIN_NODE_CLI_COM_ESBOCS_PARAM_ERR; } - uint256_t l_value = dap_chain_balance_scan(l_value_str); + uint256_t l_value = dap_uint256_scan_uninteger(l_value_str); if (IS_ZERO_256(l_value)) { dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_ESBOCS_UNREC_COM_ERR,"Unrecognized number in '-val_count' param"); return -DAP_CHAIN_NODE_CLI_COM_ESBOCS_UNREC_COM_ERR; diff --git a/modules/net/dap_chain_ledger.c b/modules/net/dap_chain_ledger.c index b59f1894a4f24330f60e12903278a50c6bd339fd..5c1ef173ea5bb7446083f1002a4b31aab26f2f39 100644 --- a/modules/net/dap_chain_ledger.c +++ b/modules/net/dap_chain_ledger.c @@ -64,7 +64,7 @@ typedef struct dap_ledger_verificator { int subtype; // hash key dap_ledger_verificator_callback_t callback; dap_ledger_updater_callback_t callback_added; - dap_ledger_updater_callback_t callback_deleted; + dap_ledger_delete_callback_t callback_deleted; UT_hash_handle hh; } dap_ledger_verificator_t; @@ -4444,7 +4444,7 @@ int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_ha 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_bound_item->cond); + l_verificator->callback_added(a_ledger, a_tx, a_tx_hash, l_bound_item->cond); } break; default: @@ -4497,7 +4497,7 @@ int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_ha 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); + l_verificator->callback_added(a_ledger, a_tx, a_tx_hash, NULL); continue; // balance raise will be with next conditional transaction } @@ -4650,7 +4650,7 @@ FIN: return l_ret; } -void dap_leger_load_end(dap_ledger_t *a_ledger) +void dap_ledger_load_end(dap_ledger_t *a_ledger) { pthread_rwlock_wrlock(&PVT(a_ledger)->ledger_rwlock); HASH_SORT(PVT(a_ledger)->ledger_items, s_sort_ledger_tx_item); @@ -5610,7 +5610,7 @@ dap_list_t *dap_ledger_get_list_tx_outs(dap_ledger_t *a_ledger, const char *a_to // Add new verificator callback with associated subtype. Returns 1 if callback replaced, -1 error, overwise returns 0 -int dap_ledger_verificator_add(dap_chain_tx_out_cond_subtype_t a_subtype, dap_ledger_verificator_callback_t a_callback, dap_ledger_updater_callback_t a_callback_added, dap_ledger_updater_callback_t a_callback_deleted) +int dap_ledger_verificator_add(dap_chain_tx_out_cond_subtype_t a_subtype, dap_ledger_verificator_callback_t a_callback, dap_ledger_updater_callback_t a_callback_added, dap_ledger_delete_callback_t a_callback_deleted) { dap_ledger_verificator_t *l_new_verificator = NULL; int l_tmp = (int)a_subtype; diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c index 9fd5effec1b3d730b82298d46d5a686196bdeb97..25fd42f600447960bb6822659f30d3e613b140cb 100644 --- a/modules/net/dap_chain_net.c +++ b/modules/net/dap_chain_net.c @@ -2031,9 +2031,8 @@ int s_net_init(const char *a_net_name, uint16_t a_acl_idx) } if (!l_chain->callback_get_poa_certs) continue; - l_net->pub.keys = l_chain->callback_get_poa_certs(l_chain, NULL, NULL); - if (l_net->pub.keys) - break; + if (!l_net->pub.keys) + l_net->pub.keys = l_chain->callback_get_poa_certs(l_chain, NULL, NULL); } if (!l_net->pub.keys) log_it(L_WARNING, "PoA certificates for net %s not found", l_net->pub.name); @@ -2111,7 +2110,7 @@ bool s_net_load(void *a_arg) l_chain = l_chain->next; } l_net_pvt->load_mode = false; - dap_leger_load_end(l_net->pub.ledger); + dap_ledger_load_end(l_net->pub.ledger); // Do specific role actions post-chain created l_net_pvt->state_target = NET_STATE_OFFLINE; @@ -3209,10 +3208,10 @@ static dap_chain_t *s_switch_sync_chain(dap_chain_net_t *a_net) } l_net_pvt->sync_context.cur_chain = l_curr_chain; if (l_curr_chain) { - log_it(L_DEBUG, "Go to chain \"%s\" for net %s", l_curr_chain->name, l_curr_chain->net_name); + debug_if(s_debug_more, L_DEBUG, "Go to chain \"%s\" for net %s", l_curr_chain->name, l_curr_chain->net_name); return l_curr_chain; } - log_it(L_DEBUG, "Go to next chain: <NULL>"); + debug_if(s_debug_more, L_DEBUG, "Go to next chain: <NULL>"); if (l_net_pvt->state_target != NET_STATE_ONLINE) { dap_chain_net_state_go_to(a_net, NET_STATE_OFFLINE); return NULL; @@ -3221,7 +3220,7 @@ static dap_chain_t *s_switch_sync_chain(dap_chain_net_t *a_net) l_net_pvt->state = NET_STATE_ONLINE; s_net_states_proc(a_net); if(l_prev_state == NET_STATE_SYNC_CHAINS) - dap_leger_load_end(a_net->pub.ledger); + dap_ledger_load_end(a_net->pub.ledger); return NULL; } @@ -3315,7 +3314,7 @@ static bool s_net_states_proc(void *a_arg) assert(l_net_pvt); if (l_net_pvt->state_target == NET_STATE_OFFLINE) { if(l_net_pvt->state == NET_STATE_SYNC_CHAINS) - dap_leger_load_end(l_net->pub.ledger); + dap_ledger_load_end(l_net->pub.ledger); l_net_pvt->state = NET_STATE_OFFLINE; } @@ -3401,4 +3400,4 @@ DAP_INLINE dap_chain_net_state_t dap_chain_net_get_target_state(dap_chain_net_t return PVT(a_net)->state_target; } -/*------------------------------------State machine block end---------------------------------*/ \ No newline at end of file +/*------------------------------------State machine block end---------------------------------*/ diff --git a/modules/net/dap_chain_net_node_list.c b/modules/net/dap_chain_net_node_list.c index 52119f83ee1dcbfbf77d5bbeab3e3543c96f8ac2..a4d6cb70db35f5732cd880609480a4fded514e3c 100644 --- a/modules/net/dap_chain_net_node_list.c +++ b/modules/net/dap_chain_net_node_list.c @@ -124,7 +124,7 @@ void dap_chain_net_node_check_http_issue_link(dap_http_simple_t *a_http_simple, uint8_t l_response = ERR_UNKNOWN; switch (l_issue_method) { case 'a': { - uint8_t l_host_size = dap_min(INET6_ADDRSTRLEN, (int)dap_strlen(a_http_simple->es_hostaddr) + 1); + uint8_t l_host_size = (uint8_t)dap_strlen(a_http_simple->es_hostaddr) + 1; l_node_info = DAP_NEW_STACK_SIZE(dap_chain_node_info_t, sizeof(dap_chain_node_info_t) + l_host_size); *l_node_info = (dap_chain_node_info_t) { .address.uint64 = addr, @@ -133,8 +133,7 @@ void dap_chain_net_node_check_http_issue_link(dap_http_simple_t *a_http_simple, }; l_response = !dap_chain_net_balancer_handshake(l_node_info, l_net) ? s_dap_chain_net_node_list_add(l_net, l_node_info) - : ( log_it(L_DEBUG, "Can't do handshake with %s [ %s : %u ]", l_key, l_node_info->ext_host, l_node_info->ext_port), - ERR_HANDSHAKE ); + : ( log_it(L_DEBUG, "Can't do handshake with %s [ %s : %u ]", l_key, l_node_info->ext_host, l_node_info->ext_port), ERR_HANDSHAKE ); *l_return_code = Http_Status_OK; } break; @@ -148,10 +147,8 @@ void dap_chain_net_node_check_http_issue_link(dap_http_simple_t *a_http_simple, *l_return_code = Http_Status_Forbidden; } else { l_response = !dap_global_db_del_sync(l_net->pub.gdb_nodes, l_key) - ? ( log_it(L_DEBUG, "Node %s successfully deleted from nodelist", l_key), - DELETED_OK ) - : ( log_it(L_DEBUG, "Can't delete node %s from nodelist", l_key), - ERR_EXISTS ); + ? ( log_it(L_DEBUG, "Node %s successfully deleted from nodelist", l_key), DELETED_OK ) + : ( log_it(L_DEBUG, "Can't delete node %s from nodelist", l_key), ERR_EXISTS ); *l_return_code = Http_Status_OK; } DAP_DELETE(l_node_info); @@ -159,11 +156,9 @@ void dap_chain_net_node_check_http_issue_link(dap_http_simple_t *a_http_simple, } break; default: - log_it(L_ERROR, "Unsupported protocol version/method in the request to dap_chain_net_node_list module"); - *l_return_code = Http_Status_MethodNotAllowed; - return; + return *l_return_code = Http_Status_MethodNotAllowed, log_it(L_ERROR, "Unsupported protocol version/method"); } - + dap_http_simple_reply(a_http_simple, &l_response, sizeof(uint8_t)); } @@ -171,79 +166,110 @@ static void s_net_node_link_prepare_success(void *a_response, size_t a_response_ http_status_code_t http_status_code) { (void)http_status_code; struct node_link_request *l_node_list_request = (struct node_link_request *)a_arg; +#ifdef DAP_OS_WINDOWS + EnterCriticalSection(&l_node_list_request->wait_crit_sec); + l_node_list_request->response = *(uint8_t*)a_response; + WakeConditionVariable(&l_node_list_request->wait_cond); + LeaveCriticalSection(&l_node_list_request->wait_crit_sec); +#else pthread_mutex_lock(&l_node_list_request->wait_mutex); l_node_list_request->response = *(uint8_t*)a_response; pthread_cond_signal(&l_node_list_request->wait_cond); pthread_mutex_unlock(&l_node_list_request->wait_mutex); +#endif } + static void s_net_node_link_prepare_error(int a_error_code, void *a_arg){ struct node_link_request * l_node_list_request = (struct node_link_request *)a_arg; dap_chain_node_info_t *l_node_info = l_node_list_request->link_info; - if (!l_node_info) { - log_it(L_WARNING, "Link prepare error, code %d", a_error_code); - return; - } + if (!l_node_info) + return log_it(L_WARNING, "Link prepare error, code %d", a_error_code); +#ifdef DAP_OS_WINDOWS + EnterCriticalSection(&l_node_list_request->wait_crit_sec); + l_node_list_request->response = a_error_code; + WakeConditionVariable(&l_node_list_request->wait_cond); + LeaveCriticalSection(&l_node_list_request->wait_crit_sec); +#else pthread_mutex_lock(&l_node_list_request->wait_mutex); l_node_list_request->response = a_error_code; pthread_cond_signal(&l_node_list_request->wait_cond); pthread_mutex_unlock(&l_node_list_request->wait_mutex); +#endif log_it(L_WARNING, "Link from "NODE_ADDR_FP_STR" [ %s : %u ] prepare error with code %d", NODE_ADDR_FP_ARGS_S(l_node_info->address), l_node_info->ext_host, l_node_info->ext_port, a_error_code); } -static struct node_link_request *s_node_list_request_init () + +static struct node_link_request* s_node_list_request_init() { struct node_link_request *l_node_list_request = DAP_NEW_Z(struct node_link_request); - if(!l_node_list_request){ + if (!l_node_list_request) return NULL; - } - l_node_list_request->worker = dap_events_worker_get_auto(); - l_node_list_request->response = 0; - - pthread_condattr_t attr; - pthread_condattr_init(&attr); +#ifdef DAP_OS_WINDOWS + InitializeCriticalSection(&l_node_list_request->wait_crit_sec); + InitializeConditionVariable(&l_node_list_request->wait_cond); +#else + pthread_mutex_init(&l_node_list_request->wait_mutex, NULL); #ifdef DAP_OS_DARWIN - struct timespec ts; - ts.tv_sec = 8; - ts.tv_nsec = 0; - pthread_cond_timedwait_relative_np(&l_node_list_request->wait_cond, &l_node_list_request->wait_mutex, - &ts); + pthread_cond_init(&l_node_list_request->wait_cond, NULL); #else + pthread_condattr_t attr; + pthread_condattr_init(&attr); pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); + pthread_cond_init(&l_node_list_request->wait_cond, &attr); +#endif #endif - pthread_cond_init(&l_node_list_request->wait_cond, &attr); - pthread_mutex_init(&l_node_list_request->wait_mutex, NULL); return l_node_list_request; } static void s_node_list_request_deinit (struct node_link_request *a_node_list_request) { +#ifdef DAP_OS_WINDOWS + DeleteCriticalSection(&a_node_list_request->wait_crit_sec); +#else pthread_cond_destroy(&a_node_list_request->wait_cond); pthread_mutex_destroy(&a_node_list_request->wait_mutex); +#endif DAP_DEL_Z(a_node_list_request->link_info); } -static int dap_chain_net_node_list_wait(struct node_link_request *a_node_list_request, int a_timeout_ms){ + +static int dap_chain_net_node_list_wait(struct node_link_request *a_node_list_request, int a_timeout_ms) { +#ifdef DAP_OS_WINDOWS + EnterCriticalSection(&a_node_list_request->wait_crit_sec); + if (a_node_list_request->response) + return LeaveCriticalSection(&a_node_list_request->wait_crit_sec), a_node_list_request->response; + while (!a_node_list_request->response) { + if ( !SleepConditionVariableCS(&a_node_list_request->wait_cond, &a_node_list_request->wait_crit_sec, a_timeout_ms) ) + a_node_list_request->response = GetLastError() == ERROR_TIMEOUT ? ERR_WAIT_TIMEOUT : ERR_UNKNOWN; + } + return LeaveCriticalSection(&a_node_list_request->wait_crit_sec), a_node_list_request->response; +#else pthread_mutex_lock(&a_node_list_request->wait_mutex); if(a_node_list_request->response) - { - pthread_mutex_unlock(&a_node_list_request->wait_mutex); - return a_node_list_request->response; - } + return pthread_mutex_unlock(&a_node_list_request->wait_mutex), a_node_list_request->response; struct timespec l_cond_timeout; - clock_gettime(CLOCK_REALTIME, &l_cond_timeout); - l_cond_timeout.tv_sec += a_timeout_ms/1000; +#ifdef DAP_OS_DARWIN + l_cond_timeout = (struct timespec){ .tv_sec = a_timeout_ms / 1000 }; +#else + clock_gettime(CLOCK_MONOTONIC, &l_cond_timeout); + l_cond_timeout.tv_sec += a_timeout_ms / 1000; +#endif while (!a_node_list_request->response) { - int l_wait = pthread_cond_timedwait(&a_node_list_request->wait_cond, &a_node_list_request->wait_mutex, &l_cond_timeout); - if (l_wait == ETIMEDOUT) { - log_it(L_NOTICE, "Waiting for status timeout"); + switch ( +#ifdef DAP_OS_DARWIN + pthread_cond_timedwait_relative_np(&a_node_list_request->wait_cond, &a_node_list_request->wait_mutex, &l_cond_timeout) +#else + pthread_cond_timedwait(&a_node_list_request->wait_cond, &a_node_list_request->wait_mutex, &l_cond_timeout) +#endif + ) { + case ETIMEDOUT: a_node_list_request->response = ERR_WAIT_TIMEOUT; - break; - } else { + default: break; } } - pthread_mutex_unlock(&a_node_list_request->wait_mutex); - return a_node_list_request->response; + return pthread_mutex_unlock(&a_node_list_request->wait_mutex), a_node_list_request->response; +#endif } static int s_cb_node_addr_compare(dap_list_t *a_list_elem, dap_list_t *a_addr_elem) { @@ -258,10 +284,8 @@ int dap_chain_net_node_list_request(dap_chain_net_t *a_net, uint16_t a_port, boo return -1; struct node_link_request *l_link_node_request = s_node_list_request_init(); - if (!l_link_node_request) { - log_it(L_CRITICAL, "%s", c_error_memory_alloc); - return -4; - }; + if (!l_link_node_request) + return log_it(L_CRITICAL, "%s", c_error_memory_alloc), -4; char *l_request = dap_strdup_printf( "%s/%s?version=1,method=%c,addr=%zu,port=%hu,net=%s", DAP_UPLINK_PATH_NODE_LIST, DAP_NODE_LIST_URI_HASH, a_cmd, @@ -273,7 +297,7 @@ int dap_chain_net_node_list_request(dap_chain_net_t *a_net, uint16_t a_port, boo dap_chain_node_info_t *l_remote = dap_chain_node_info_read(a_net, l_seeds_addrs + i); if (!l_remote) continue; - if ( dap_client_http_request(l_link_node_request->worker, l_remote->ext_host, l_remote->ext_port, + if ( dap_client_http_request(dap_worker_get_auto(), l_remote->ext_host, l_remote->ext_port, "GET", "text/text", l_request, NULL, 0, NULL, s_net_node_link_prepare_success, s_net_node_link_prepare_error, l_link_node_request, NULL) ) @@ -311,9 +335,6 @@ int dap_chain_net_node_list_request(dap_chain_net_t *a_net, uint16_t a_port, boo int dap_chain_net_node_list_init() { - /*for (dap_chain_net_t *it = dap_chain_net_iter_start(); it; it = dap_chain_net_iter_next(it)) { - dap_chain_net_add_nodelist_notify_callback(it, s_node_list_callback_notify, it); - }*/ return 0; } diff --git a/modules/net/dap_chain_node_cli_cmd_tx.c b/modules/net/dap_chain_node_cli_cmd_tx.c index e2f6091f28841d4aefb7fed3f9df2c9aad7ba51d..1cf0ce1536edac7e4357f6e0f5a80e3e8e490789 100644 --- a/modules/net/dap_chain_node_cli_cmd_tx.c +++ b/modules/net/dap_chain_node_cli_cmd_tx.c @@ -652,7 +652,7 @@ json_object* dap_db_history_addr(dap_chain_addr_t *a_addr, dap_chain_t *a_chain, SUM_256_256(l_corr_value, l_fee_sum, &l_corr_value); const char *l_coins_str, *l_value_str = dap_uint256_to_char(l_corr_value, &l_coins_str); json_object_object_add(l_corr_object, "recv_coins", json_object_new_string(l_coins_str)); - json_object_object_add(l_corr_object, "recv_datoshi", json_object_new_string(l_value_str)); + json_object_object_add(l_corr_object, "recv_datoshi", json_object_new_string(l_value_str)); json_object * j_arr_correct = json_object_new_object(); json_object_object_add(j_arr_correct, "correction", l_corr_object); json_object_array_add(json_obj_datum, j_arr_correct); diff --git a/modules/net/include/dap_chain_ledger.h b/modules/net/include/dap_chain_ledger.h index 6c5c487316371532bc920e335429b1b1a552f555..9074e4dcf58da3255a763fcbac0d874c7d7c9c5e 100644 --- a/modules/net/include/dap_chain_ledger.h +++ b/modules/net/include/dap_chain_ledger.h @@ -201,7 +201,8 @@ typedef struct dap_ledger_datum_iter { } dap_ledger_datum_iter_t; typedef int (*dap_ledger_verificator_callback_t)(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_t *a_tx_out_cond, dap_chain_datum_tx_t *a_tx_in, bool a_owner); -typedef void (*dap_ledger_updater_callback_t)(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_tx_out_cond_t *a_prev_cond); +typedef void (*dap_ledger_updater_callback_t)(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx_in, dap_hash_fast_t *a_tx_in_hash, dap_chain_tx_out_cond_t *a_prev_cond); +typedef void (*dap_ledger_delete_callback_t)(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx_in, dap_chain_tx_out_cond_t *a_prev_cond); typedef void (* dap_ledger_tx_add_notify_t)(void *a_arg, dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chan_ledger_notify_opcodes_t a_opcode); typedef void (* dap_ledger_bridged_tx_notify_t)(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash, void *a_arg, dap_chan_ledger_notify_opcodes_t a_opcode); typedef bool (*dap_ledger_cache_tx_check_callback_t)(dap_ledger_t *a_ledger, dap_hash_fast_t *a_tx_hash); @@ -433,7 +434,7 @@ dap_list_t *dap_ledger_get_list_tx_cond_outs(dap_ledger_t *a_ledger, const char dap_chain_tx_out_cond_subtype_t a_subtype, uint256_t *a_value_transfer); // Add new verificator callback with associated subtype. Returns 1 if callback replaced, overwise returns 0 int dap_ledger_verificator_add(dap_chain_tx_out_cond_subtype_t a_subtype, dap_ledger_verificator_callback_t a_callback, - dap_ledger_updater_callback_t a_callback_added, dap_ledger_updater_callback_t a_callback_deleted); + dap_ledger_updater_callback_t a_callback_added, dap_ledger_delete_callback_t a_callback_deleted); // Add new verificator callback for voting. Returns 1 if callback replaced, overwise returns 0 int dap_chain_ledger_voting_verificator_add(dap_chain_ledger_voting_callback_t a_callback, dap_chain_ledger_voting_delete_callback_t a_callback_delete); // Getting a list of transactions from the ledger. @@ -454,4 +455,4 @@ void dap_ledger_bridged_tx_notify_add(dap_ledger_t *a_ledger, dap_ledger_bridged bool dap_ledger_cache_enabled(dap_ledger_t *a_ledger); void dap_ledger_set_cache_tx_check_callback(dap_ledger_t *a_ledger, dap_ledger_cache_tx_check_callback_t a_callback); dap_chain_tx_out_cond_t* dap_chain_ledger_get_tx_out_cond_linked_to_tx_in_cond(dap_ledger_t *a_ledger, dap_chain_tx_in_cond_t *a_in_cond); -void dap_leger_load_end(dap_ledger_t *a_ledger); +void dap_ledger_load_end(dap_ledger_t *a_ledger); diff --git a/modules/net/include/dap_chain_net_node_list.h b/modules/net/include/dap_chain_net_node_list.h index cacbd70f2cb535eabad94cd54c84c746067aab16..8fe6dd6b1b62ef57f0f31f2885210b454b1fa54c 100644 --- a/modules/net/include/dap_chain_net_node_list.h +++ b/modules/net/include/dap_chain_net_node_list.h @@ -32,18 +32,22 @@ along with any CellFrame SDK based project. If not, see <http://www.gnu.org/lic struct node_link_request { dap_chain_node_info_t *link_info; dap_chain_net_t *net; - dap_worker_t *worker; - int link_replace_tries; - int response; +#ifdef DAP_OS_WINDOWS + CONDITION_VARIABLE wait_cond; + CRITICAL_SECTION wait_crit_sec; +#else pthread_cond_t wait_cond; pthread_mutex_t wait_mutex; +#endif + int response; }; + /** * @brief dap_chain_net_node_list_get_gdb_group * @param a_net * @return */ -DAP_STATIC_INLINE char * dap_chain_net_node_list_get_gdb_group(dap_chain_net_t * a_net) +DAP_STATIC_INLINE char* dap_chain_net_node_list_get_gdb_group(dap_chain_net_t * a_net) { return a_net ? dap_strdup_printf("%s.service.orders",a_net->pub.gdb_groups_prefix) : NULL; } diff --git a/modules/service/stake/dap_chain_net_srv_stake_lock.c b/modules/service/stake/dap_chain_net_srv_stake_lock.c index 53a216607537db1cbf3f2d8f92c4b1ea1852b6d6..627defb078f38f725e0d69e3f087ef2b7e9cc688 100644 --- a/modules/service/stake/dap_chain_net_srv_stake_lock.c +++ b/modules/service/stake/dap_chain_net_srv_stake_lock.c @@ -107,7 +107,7 @@ dap_chain_datum_t *s_stake_unlock_datum_create(dap_chain_net_t *a_net, dap_enc_k uint256_t a_value_fee, const char *a_delegated_ticker_str, uint256_t a_delegated_value,int *res); // Callbacks -static void s_stake_lock_callback_updater(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_tx_out_cond_t *a_prev_out_item); +static void s_stake_lock_callback_updater(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx_in, dap_hash_fast_t *a_tx_in_hash, dap_chain_tx_out_cond_t *a_prev_out_item); static int s_stake_lock_callback_verificator(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_t *a_cond, dap_chain_datum_tx_t *a_tx_in, bool a_owner); static inline int s_tsd_str_cmp(const byte_t *a_tsdata, size_t a_tsdsize, const char *str ) { @@ -1105,17 +1105,14 @@ static int s_stake_lock_callback_verificator(dap_ledger_t *a_ledger, dap_chain_t * @param a_tx_item_idx * @return */ -static void s_stake_lock_callback_updater(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_tx_out_cond_t *a_prev_out_item) +static void s_stake_lock_callback_updater(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx_in, dap_hash_fast_t *a_tx_in_hash, dap_chain_tx_out_cond_t *a_prev_out_item) { if (a_prev_out_item) // this is IN_COND tx return; 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_tx_cond_hash; - dap_hash_fast(a_tx, dap_chain_datum_tx_get_size(a_tx), &l_tx_cond_hash); - dap_ledger_emission_for_stake_lock_item_add(a_ledger, &l_tx_cond_hash); - } + dap_chain_tx_out_cond_t *l_cond = dap_chain_datum_tx_out_cond_get(a_tx_in, 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_ledger_emission_for_stake_lock_item_add(a_ledger, a_tx_in_hash); } static dap_chain_datum_t *s_stake_lock_datum_create(dap_chain_net_t *a_net, dap_enc_key_t *a_key_from, diff --git a/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c b/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c index 2efa8490bfb650e3268f9e8e8e4595c6a79d508c..6ae42e529b82481abac1dc6d1753efeff1f19e62 100644 --- a/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c +++ b/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c @@ -50,7 +50,7 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, void **a_str_reply); static int s_stake_verificator_callback(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_t *a_cond, dap_chain_datum_tx_t *a_tx_in, bool a_owner); -static void s_stake_updater_callback(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_tx_out_cond_t *a_cond); +static void s_stake_updater_callback(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx_in, dap_hash_fast_t *a_tx_in_hash, dap_chain_tx_out_cond_t *a_cond); static void s_stake_deleted_callback(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_tx_out_cond_t *a_cond); @@ -105,33 +105,34 @@ int dap_chain_net_srv_stake_pos_delegate_init() " [-addr <for_tax_collecting>] [-cert <for_order_signing>] [-H {hex(default) | base58}]\n" "\tCreates an order allowing the validator to delegate it's key with specified params\n" "srv_stake order update -net <net_name> -order <order_hash> [-params]\n" - "\tUpdates an order with specified hash\n" + "\tUpdates an order with specified hash\n" "srv_stake order list [fee | validator | staker] -net <net_name>\n" - "\tGet orders list of specified type within specified net name\n" + "\tGet orders list of specified type within specified net name\n" "srv_stake order remove -net <net_name> -order <order_hash>\n" - "\tRemove order with specified hash\n" + "\tRemove order with specified hash\n" "\t\t === Commands for work with stake delegate ===\n" "srv_stake delegate {-cert <pub_cert_name> -value <datoshi> | " "-order <order_hash> {[-tax_addr <wallet_addr_for_tax_collecting>] | " "-cert <priv_cert_name> [-node_addr <for_validator_node>]}}" " -net <net_name> -w <wallet_name> -fee <value>\n" - "\tDelegate public key in specified certificate or order with specified net name. Pay with specified value of m-tokens of native net token.\n" - "srv_stake invalidate -net <net_name> {-tx <transaction_hash> | -cert <delegated_cert> | -siging_pkey_hash <pkey_hash> -signing_pkey_type <pkey_type>}" - " {-w <wallet_name> -fee <value> | -poa_cert <cert_name>}\n" - "\tInvalidate requested delegated stake transaction by hash or cert name or cert pkey hash within net name and" - " return m-tokens to specified wallet (if any)\n" + "\tDelegate public key in specified certificate or order with specified net name. Pay with specified value of m-tokens of native net token.\n" + "srv_stake update -net <net_name> {-tx <transaction_hash> | -cert <delegated_cert>} -w <wallet_name> -value <new_delegation_value> -fee <value>\n" + "\tUpdate public key delegation value for specified certificate or transaction hash with specified net name. Pay or cacheback the difference of m-tokens of native net token.\n" + "srv_stake invalidate -net <net_name> {-tx <transaction_hash> -w <wallet_name> -fee <value> | -siging_pkey_hash <pkey_hash> -signing_pkey_type <pkey_type> -poa_cert <cert_name>}\n" + "\tInvalidate requested delegated stake transaction by hash or cert name or cert pkey hash within net name and" + " return m-tokens to specified wallet (if any)\n" "srv_stake approve -net <net_name> -tx <transaction_hash> -poa_cert <priv_cert_name>\n" - "\tApprove stake transaction by root node certificate within specified net name\n" + "\tApprove stake transaction by root node certificate within specified net name\n" "srv_stake list keys -net <net_name> [-cert <delegated_cert> | -pkey <pkey_hash_str>]\n" - "\tShow the list of active stake keys (optional delegated with specified cert).\n" + "\tShow the list of active stake keys (optional delegated with specified cert).\n" "srv_stake list tx -net <net_name> \n" - "\tShow the list of key delegation transactions.\n" + "\tShow the list of key delegation transactions.\n" "srv_stake min_value -net <net_name> [-chain <chain_name>] -poa_cert <poa_cert_name> -value <value>\n" - "\tSets the minimum stake value\n" + "\tSets the minimum stake value\n" "srv_stake max_weight -net <net_name> [-chain <chain_name>] -poa_cert <poa_cert_name> -percent <value>\n" "\tSets maximum validator related weight (in percent)\n" "srv_stake check -net <net_name> -tx <tx_hash>\n" - "\tCheck remote validator" + "\tCheck remote validator" ); dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_STAKE_POS_DELEGATE_ID }; @@ -202,75 +203,119 @@ void dap_chain_net_srv_stake_pos_delegate_deinit() static int s_stake_verificator_callback(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_t *a_cond, dap_chain_datum_tx_t *a_tx_in, bool a_owner) { + dap_return_val_if_fail(a_ledger && a_cond && a_tx_in, -1); dap_chain_net_srv_stake_t *l_srv_stake = s_srv_stake_by_net_id(a_ledger->net->pub.id); - dap_return_val_if_fail(l_srv_stake, -1); + dap_return_val_if_fail(l_srv_stake, -2); + +#define m_cond_check() \ +( \ + { \ + if (l_tx_new_cond->header.subtype != a_cond->header.subtype || \ + l_tx_new_cond->header.ts_expires != a_cond->header.ts_expires || \ + !dap_chain_net_srv_uid_compare(l_tx_new_cond->header.srv_uid, \ + a_cond->header.srv_uid) \ + ) { \ + log_it(L_WARNING, "Conditional out and conditional in have different headers"); \ + return -3; \ + } \ + if (l_tx_new_cond->tsd_size != a_cond->tsd_size || \ + memcmp(l_tx_new_cond->tsd, a_cond->tsd, a_cond->tsd_size)) { \ + log_it(L_WARNING, "Conditional out and conditional in have different TSD sections"); \ + return -4; \ + } \ + if (dap_chain_addr_is_blank(&l_tx_new_cond->subtype.srv_stake_pos_delegate.signing_addr) || \ + l_tx_new_cond->subtype.srv_stake_pos_delegate.signer_node_addr.uint64 == 0) { \ + log_it(L_WARNING, "Not blank address or key fields in order conditional tx"); \ + return -5; \ + } \ + } \ +) + int l_out_idx = 0; + dap_chain_tx_out_cond_t *l_tx_new_cond = dap_chain_datum_tx_out_cond_get( + a_tx_in, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE, &l_out_idx); // It's a order conditional TX if (dap_chain_addr_is_blank(&a_cond->subtype.srv_stake_pos_delegate.signing_addr) || a_cond->subtype.srv_stake_pos_delegate.signer_node_addr.uint64 == 0) { if (a_owner) return 0; - int l_out_idx = 0; - dap_chain_tx_out_cond_t *l_tx_out_cond = dap_chain_datum_tx_out_cond_get(a_tx_in, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE, &l_out_idx); - if (!l_tx_out_cond) { + if (!l_tx_new_cond) { log_it(L_ERROR, "Condition not found in conditional tx"); - return -2; - } - if (compare256(l_tx_out_cond->header.value, a_cond->header.value)) { - char *l_in_value = dap_chain_balance_to_coins(l_tx_out_cond->header.value); - char *l_out_value = dap_chain_balance_to_coins(a_cond->header.value); - log_it(L_WARNING, "In value %s is not equal to out value %s", l_in_value, l_out_value); - DAP_DELETE(l_in_value); - DAP_DELETE(l_out_value); - return -3; - } - if (l_tx_out_cond->tsd_size != a_cond->tsd_size || - memcmp(l_tx_out_cond->tsd, a_cond->tsd, a_cond->tsd_size)) { - log_it(L_WARNING, "Conditional out and conditional in have different TSD sections"); - return -4; + return -13; } - if (dap_chain_addr_is_blank(&l_tx_out_cond->subtype.srv_stake_pos_delegate.signing_addr) || - l_tx_out_cond->subtype.srv_stake_pos_delegate.signer_node_addr.uint64 == 0) { - log_it(L_WARNING, "Not blank address or key fields in order conditional tx"); - return -5; + m_cond_check(); + + if (compare256(l_tx_new_cond->header.value, a_cond->header.value)) { + log_it(L_WARNING, "Conditional out and conditional in have different values"); + return -14; } return 0; } - // It's a delegation conitional TX - dap_chain_tx_in_cond_t *l_tx_in_cond = (dap_chain_tx_in_cond_t *)dap_chain_datum_tx_item_get(a_tx_in, NULL, NULL, TX_ITEM_TYPE_IN_COND, NULL); - if (!l_tx_in_cond) { - log_it(L_ERROR, "Conditional in item not found in checking tx"); - return -6; - } - // ATTENTION: It's correct only with single IN_COND TX item - dap_hash_fast_t *l_prev_hash = &l_tx_in_cond->header.tx_prev_hash; - if (dap_hash_fast_is_blank(l_prev_hash)) { - log_it(L_ERROR, "Blank hash of prev tx in tx_in_cond"); - return -7; - } if (!a_owner) { - log_it(L_WARNING, "Trying to spend conditional tx not by owner"); + log_it(L_WARNING, "Trying to spend conditional tx by not a owner"); return -11; } - if (a_tx_in->header.ts_created < 1706227200) // Jan 26 2024 00:00:00 GMT, old policy rules - return 0; - dap_chain_net_srv_stake_item_t *l_stake = NULL; - HASH_FIND(ht, l_srv_stake->tx_itemlist, l_prev_hash, sizeof(dap_hash_t), l_stake); - if (l_stake) { - log_it(L_WARNING, "Key is active with delegation decree, need to revoke it first"); - return -12; + // Delegation value update (dynamic weight feature) + if (l_tx_new_cond) { + + m_cond_check(); + + if (!dap_chain_addr_compare(&l_tx_new_cond->subtype.srv_stake_pos_delegate.signing_addr, + &a_cond->subtype.srv_stake_pos_delegate.signing_addr)) { + log_it(L_WARNING, "Conditional out and conditional in have different signer key hashes"); + return -15; + } + if (l_tx_new_cond->subtype.srv_stake_pos_delegate.signer_node_addr.uint64 != + a_cond->subtype.srv_stake_pos_delegate.signer_node_addr.uint64) { + log_it(L_WARNING, "Conditional out and conditional in have different node addresses"); + return -16; + } + if (compare256(l_tx_new_cond->header.value, + dap_chain_net_srv_stake_get_allowed_min_value(a_ledger->net->pub.id)) == -1) { + log_it(L_WARNING, "New conditional out have value %s lower than minimum service required", + dap_uint256_to_char(l_tx_new_cond->header.value, NULL)); + return -17; + } + } else { + // It's a delegation conitional TX + dap_chain_tx_in_cond_t *l_tx_in_cond = (dap_chain_tx_in_cond_t *) + dap_chain_datum_tx_item_get(a_tx_in, NULL, NULL, TX_ITEM_TYPE_IN_COND, NULL); + if (!l_tx_in_cond) { + log_it(L_ERROR, "Conditional in item not found in current tx"); + return -6; + } + // ATTENTION: It's correct only with single IN_COND TX item + dap_hash_fast_t *l_prev_hash = &l_tx_in_cond->header.tx_prev_hash; + if (dap_hash_fast_is_blank(l_prev_hash)) { + log_it(L_ERROR, "Blank hash of prev tx in tx_in_cond"); + return -7; + } + if (a_tx_in->header.ts_created < 1706227200) // Jan 26 2024 00:00:00 GMT, old policy rules + return 0; + dap_chain_net_srv_stake_item_t *l_stake = NULL; + HASH_FIND(ht, l_srv_stake->tx_itemlist, l_prev_hash, sizeof(dap_hash_t), l_stake); + if (l_stake) { + log_it(L_WARNING, "Key %s is empowered for now, need to revoke it first", + dap_hash_fast_to_str_static(&l_stake->signing_addr.data.hash_fast)); + return -12; + } } return 0; } -static void s_stake_updater_callback(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_tx_out_cond_t *a_cond) +static void s_stake_updater_callback(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx_in, dap_hash_fast_t *a_tx_in_hash, dap_chain_tx_out_cond_t *a_cond) { + dap_return_if_fail(a_ledger && a_tx_in); dap_chain_net_srv_stake_t *l_srv_stake = s_srv_stake_by_net_id(a_ledger->net->pub.id); dap_return_if_fail(l_srv_stake); if (!a_cond) return; + dap_chain_tx_out_cond_t *l_tx_new_cond = dap_chain_datum_tx_out_cond_get(a_tx_in, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE, NULL); dap_chain_addr_t *l_signing_addr = &a_cond->subtype.srv_stake_pos_delegate.signing_addr; - dap_chain_net_srv_stake_key_invalidate(l_signing_addr); - s_cache_data(a_ledger, a_tx, l_signing_addr); + if (l_tx_new_cond) + dap_chain_net_srv_stake_key_update(l_signing_addr, l_tx_new_cond->header.value, a_tx_in_hash); + else + dap_chain_net_srv_stake_key_invalidate(l_signing_addr); + s_cache_data(a_ledger, a_tx_in, l_signing_addr); } static void s_stake_deleted_callback(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_tx_out_cond_t *a_cond) @@ -327,6 +372,7 @@ static bool s_weights_truncate(dap_chain_net_srv_stake_t *l_srv_stake, const uin } return l_exceeds_count; } +#undef LIMIT_DELTA static void s_stake_recalculate_weights(dap_chain_net_id_t a_net_id) { @@ -384,35 +430,49 @@ void dap_chain_net_srv_stake_key_delegate(dap_chain_net_t *a_net, dap_chain_addr } } dap_chain_esbocs_add_validator_to_clusters(a_net->pub.id, a_node_addr); - char l_key_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE]; - dap_chain_hash_fast_to_str(&a_signing_addr->data.hash_fast, - l_key_hash_str, DAP_CHAIN_HASH_FAST_STR_SIZE); const char *l_value_str; dap_uint256_to_char(a_value, &l_value_str); - log_it(L_NOTICE, "Added key with fingerprint %s and locked value %s for node "NODE_ADDR_FP_STR, - l_key_hash_str, l_value_str, NODE_ADDR_FP_ARGS(a_node_addr)); + log_it(L_NOTICE, "Added key with fingerprint %s and locked value %s for node " NODE_ADDR_FP_STR, + dap_chain_hash_fast_to_str_static(&a_signing_addr->data.hash_fast), l_value_str, NODE_ADDR_FP_ARGS(a_node_addr)); s_stake_recalculate_weights(a_signing_addr->net_id); } void dap_chain_net_srv_stake_key_invalidate(dap_chain_addr_t *a_signing_addr) { - if (!a_signing_addr) - return; + dap_return_if_fail(a_signing_addr); dap_chain_net_srv_stake_t *l_srv_stake = s_srv_stake_by_net_id(a_signing_addr->net_id); dap_return_if_fail(l_srv_stake); dap_chain_net_srv_stake_item_t *l_stake = NULL; HASH_FIND(hh, l_srv_stake->itemlist, &a_signing_addr->data.hash_fast, sizeof(dap_hash_fast_t), l_stake); - if (l_stake) { - dap_chain_esbocs_remove_validator_from_clusters(l_stake->signing_addr.net_id, &l_stake->node_addr); - HASH_DEL(l_srv_stake->itemlist, l_stake); - HASH_DELETE(ht, l_srv_stake->tx_itemlist, l_stake); - char l_key_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE]; - dap_chain_hash_fast_to_str(&a_signing_addr->data.hash_fast, - l_key_hash_str, DAP_CHAIN_HASH_FAST_STR_SIZE); - const char *l_value_str; dap_uint256_to_char(l_stake->locked_value, &l_value_str); - log_it(L_NOTICE, "Removed key with fingerprint %s and locked value %s for node "NODE_ADDR_FP_STR, - l_key_hash_str, l_value_str, NODE_ADDR_FP_ARGS_S(l_stake->node_addr)); - DAP_DELETE(l_stake); - } + dap_return_if_fail(l_stake); + dap_chain_esbocs_remove_validator_from_clusters(l_stake->signing_addr.net_id, &l_stake->node_addr); + HASH_DEL(l_srv_stake->itemlist, l_stake); + HASH_DELETE(ht, l_srv_stake->tx_itemlist, l_stake); + const char *l_value_str; dap_uint256_to_char(l_stake->locked_value, &l_value_str); + log_it(L_NOTICE, "Removed key with fingerprint %s and locked value %s for node " NODE_ADDR_FP_STR, + dap_chain_hash_fast_to_str_static(&a_signing_addr->data.hash_fast), l_value_str, NODE_ADDR_FP_ARGS_S(l_stake->node_addr)); + DAP_DELETE(l_stake); + s_stake_recalculate_weights(a_signing_addr->net_id); +} + +void dap_chain_net_srv_stake_key_update(dap_chain_addr_t *a_signing_addr, uint256_t a_new_value, dap_hash_fast_t *a_new_tx_hash) +{ + dap_return_if_fail(a_signing_addr && a_new_tx_hash); + dap_chain_net_srv_stake_t *l_srv_stake = s_srv_stake_by_net_id(a_signing_addr->net_id); + dap_return_if_fail(l_srv_stake); + dap_chain_net_srv_stake_item_t *l_stake = NULL; + HASH_FIND(hh, l_srv_stake->itemlist, &a_signing_addr->data.hash_fast, sizeof(dap_hash_fast_t), l_stake); + if (!l_stake) + return; // It's update for non delegated key, it's OK + HASH_DELETE(ht, l_srv_stake->tx_itemlist, l_stake); + l_stake->locked_value = l_stake->value = a_new_value; + l_stake->tx_hash = *a_new_tx_hash; + HASH_ADD(ht, l_srv_stake->tx_itemlist, tx_hash, sizeof(dap_hash_fast_t), l_stake); + char *l_old_value_str = dap_chain_balance_to_coins(l_stake->locked_value); + const char *l_new_value_str; dap_uint256_to_char(a_new_value, &l_new_value_str); + log_it(L_NOTICE, "Updated key with fingerprint %s and locked value %s to new locked value %s for node " NODE_ADDR_FP_STR, + dap_chain_hash_fast_to_str_static(&a_signing_addr->data.hash_fast), l_old_value_str, + l_new_value_str, NODE_ADDR_FP_ARGS_S(l_stake->node_addr)); + DAP_DELETE(l_old_value_str); s_stake_recalculate_weights(a_signing_addr->net_id); } @@ -423,7 +483,7 @@ void dap_chain_net_srv_stake_set_allowed_min_value(dap_chain_net_id_t a_net_id, l_srv_stake->delegate_allowed_min = a_value; for (dap_chain_net_srv_stake_item_t *it = l_srv_stake->itemlist; it; it = it->hh.next) if (dap_hash_fast_is_blank(&it->tx_hash)) - it->value = a_value; + it->locked_value = it->value = a_value; } void dap_chain_net_srv_stake_set_percent_max(dap_chain_net_id_t a_net_id, uint256_t a_value) @@ -655,7 +715,7 @@ static dap_chain_datum_tx_t *s_stake_tx_create(dap_chain_net_t * a_net, dap_enc_ &l_owner_addr, a_value, &l_value_transfer); if (!l_list_used_out) { log_it(L_WARNING, "Nothing to pay for delegate (not enough funds)"); - return NULL; + goto tx_fail; } // add 'in' items to pay for delegate uint256_t l_value_to_items = dap_chain_datum_tx_add_in_item_list(&l_tx, l_list_used_out); @@ -741,6 +801,134 @@ tx_fail: return NULL; } +// Updates staker's funds with delegated key +static dap_chain_datum_tx_t *s_stake_tx_update(dap_chain_net_t *a_net, dap_hash_fast_t *a_prev_tx_hash, uint256_t a_new_value, uint256_t a_fee, dap_enc_key_t *a_key) +{ + dap_return_val_if_fail(a_net && a_key && a_prev_tx_hash && !IS_ZERO_256(a_new_value), NULL); + + const char *l_native_ticker = a_net->pub.native_ticker; + char l_delegated_ticker[DAP_CHAIN_TICKER_SIZE_MAX]; + dap_chain_datum_token_get_delegated_ticker(l_delegated_ticker, l_native_ticker); + dap_ledger_t *l_ledger = dap_ledger_by_net_name(a_net->pub.name); + uint256_t l_value_transfer = {}, l_fee_transfer = {}; // how many coins to transfer + // list of transaction with 'out' items to sell + dap_chain_addr_t l_owner_addr; + dap_chain_addr_fill_from_key(&l_owner_addr, a_key, a_net->pub.id); + uint256_t l_net_fee, l_fee_total = a_fee; + dap_chain_addr_t l_net_fee_addr; + bool l_net_fee_used = dap_chain_net_tx_get_fee(a_net->pub.id, &l_net_fee, &l_net_fee_addr); + if (l_net_fee_used) + SUM_256_256(l_fee_total, l_net_fee, &l_fee_total); + dap_list_t *l_list_fee_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, l_native_ticker, + &l_owner_addr, l_fee_total, &l_fee_transfer); + if (!l_list_fee_out) { + log_it(L_WARNING, "Nothing to pay for fee (not enough funds)"); + return NULL; + } + dap_chain_datum_tx_t *l_tx_prev = dap_ledger_tx_find_by_hash(l_ledger, a_prev_tx_hash); + if (!l_tx_prev) { + log_it(L_ERROR, "Transaction %s not found", dap_hash_fast_to_str_static(a_prev_tx_hash)); + return NULL; + } + int l_out_num = 0; + dap_chain_tx_out_cond_t *l_cond_prev = dap_chain_datum_tx_out_cond_get(l_tx_prev, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE, &l_out_num); + if (!l_cond_prev) { + log_it(L_ERROR, "Transaction %s is invalid", dap_hash_fast_to_str_static(a_prev_tx_hash)); + return NULL; + } + + // create empty transaction + dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create(); + + // add 'in' item to buy from conditional transaction + if (1 != dap_chain_datum_tx_add_in_cond_item(&l_tx, a_prev_tx_hash, l_out_num, -1)) { + log_it(L_ERROR, "Can't compose the transaction conditional input"); + goto tx_fail; + } + + // add 'in' items to pay 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_fee_out, NULL); + if (!EQUAL_256(l_value_fee_items, l_fee_transfer)) { + log_it(L_ERROR, "Can't compose the fee transaction input"); + goto tx_fail; + } + uint256_t l_value_prev = l_cond_prev->header.value, l_value_back = {}; + bool l_increasing = compare256(a_new_value, l_value_prev) == 1; + if (l_increasing) { + uint256_t l_refund_value = {}; + SUBTRACT_256_256(a_new_value, l_value_prev, &l_refund_value); + dap_list_t *l_list_used_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, l_delegated_ticker, + &l_owner_addr, l_refund_value, &l_value_transfer); + if (!l_list_used_out) { + log_it(L_WARNING, "Nothing to pay for delegate (not enough funds)"); + return NULL; + } + // add 'in' items to pay for delegate + 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_value_transfer)) { + log_it(L_ERROR, "Can't compose the transaction input"); + goto tx_fail; + } + SUBTRACT_256_256(l_value_transfer, l_refund_value, &l_value_back); + } else + SUBTRACT_256_256(l_value_prev, a_new_value, &l_value_back); + + // add 'out_cond' & 'out_ext' items + dap_chain_tx_out_cond_t *l_out_cond = DAP_DUP_SIZE(l_cond_prev, sizeof(dap_chain_tx_out_cond_t) + l_cond_prev->tsd_size); + if (!l_out_cond) { + log_it(L_CRITICAL, "%s", c_error_memory_alloc); + goto tx_fail; + } + l_out_cond->header.value = a_new_value; + dap_chain_datum_tx_add_item(&l_tx, (const uint8_t *)l_out_cond); + DAP_DELETE(l_out_cond); + + // coin back + if (!IS_ZERO_256(l_value_back)) { + if (dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_owner_addr, l_value_back, l_delegated_ticker) != 1) { + log_it(L_ERROR, "Cant add coin back output"); + goto tx_fail; + } + } + + // add fee items + 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) { + log_it(L_ERROR, "Cant add net fee output"); + goto tx_fail; + } + } + if (!IS_ZERO_256(a_fee)) { + if (dap_chain_datum_tx_add_fee_item(&l_tx, a_fee) != 1) { + log_it(L_ERROR, "Cant add validator fee output"); + goto tx_fail; + } + } + uint256_t l_fee_back = {}; + // fee coin back + SUBTRACT_256_256(l_fee_transfer, l_fee_total, &l_fee_back); + if (!IS_ZERO_256(l_fee_back)) { + if (dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_owner_addr, l_fee_back, l_native_ticker) != 1) { + log_it(L_ERROR, "Cant add fee back output"); + goto tx_fail; + } + } + + // add 'sign' item + if (dap_chain_datum_tx_add_sign_item(&l_tx, a_key) != 1) { + log_it(L_ERROR, "Can't add sign output"); + goto tx_fail; + } + + return l_tx; + +tx_fail: + dap_chain_datum_tx_delete(l_tx); + return NULL; +} + static dap_chain_datum_tx_t *s_order_tx_create(dap_chain_net_t * a_net, dap_enc_key_t *a_key, uint256_t a_value, uint256_t a_fee, uint256_t a_sovereign_tax, dap_chain_addr_t *a_sovereign_addr) @@ -799,10 +987,6 @@ dap_chain_datum_decree_t *dap_chain_net_srv_stake_decree_approve(dap_chain_net_t log_it(L_WARNING, "Requested conditional transaction have another ticker (not %s)", l_delegated_ticker); return NULL; } - if (compare256(l_tx_out_cond->header.value, dap_chain_net_srv_stake_get_allowed_min_value(a_net->pub.id)) == -1) { - log_it(L_WARNING, "Requested conditional transaction have not enough funds"); - return NULL; - } if(dap_chain_net_srv_stake_verify_key_and_node(&l_tx_out_cond->subtype.srv_stake_pos_delegate.signing_addr, &l_tx_out_cond->subtype.srv_stake_pos_delegate.signer_node_addr)){ log_it(L_WARNING, "Key and node verification error"); @@ -1896,7 +2080,7 @@ static int s_cli_srv_stake_delegate(int a_argc, char **a_argv, int a_arg_index, uint256_t l_allowed_min = dap_chain_net_srv_stake_get_allowed_min_value(l_net->pub.id); if (compare256(l_value, l_allowed_min) == -1) { const char *l_coin_min_str, *l_value_min_str = dap_uint256_to_char(l_allowed_min, &l_coin_min_str); - dap_cli_server_cmd_set_reply_text(a_str_reply, "Number in '-value' param %s is lower than minimum allowed value %s(%s)", + dap_cli_server_cmd_set_reply_text(a_str_reply, "Number in '-value' param %s is lower than service minimum allowed value %s(%s)", l_value_str, l_coin_min_str, l_value_min_str); dap_enc_key_delete(l_enc_key); return -11; @@ -1931,13 +2115,149 @@ static int s_cli_srv_stake_delegate(int a_argc, char **a_argv, int a_arg_index, return 0; } +static int s_cli_srv_stake_update(int a_argc, char **a_argv, int a_arg_index, void **a_str_reply, const char *a_hash_out_type) +{ + const char *l_net_str = NULL, + *l_wallet_str = NULL, + *l_value_str, + *l_fee_str = NULL, + *l_tx_hash_str = NULL, + *l_cert_str = NULL; + dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-net", &l_net_str); + if (!l_net_str) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'update' requires parameter -net"); + return -3; + } + dap_chain_net_t *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 -4; + } + uint256_t l_fee = {}; + dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-w", &l_wallet_str); + if (!l_wallet_str) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'update' requires parameter -w"); + return -17; + } + dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-fee", &l_fee_str); + if (!l_fee_str) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'update' requires parameter -fee"); + return -5; + } + l_fee = dap_chain_balance_scan(l_fee_str); + if (IS_ZERO_256(l_fee)) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Unrecognized number in '-fee' param"); + return -6; + } + uint256_t l_value = {}; + dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-value", &l_value_str); + if (!l_value_str) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'update' requires parameter -value"); + return -7; + } + l_value = dap_chain_balance_scan(l_value_str); + if (IS_ZERO_256(l_value)) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Unrecognized number in '-value' param"); + return -8; + } + uint256_t l_value_min = dap_chain_net_srv_stake_get_allowed_min_value(l_net->pub.id); + if (compare256(l_value, l_value_min) == -1) { + const char *l_value_min_str; dap_uint256_to_char(l_value_min, &l_value_min_str); + dap_cli_server_cmd_set_reply_text(a_str_reply, "New delegation value should be not less than service required minimum %s", l_value_min_str); + return -25; + } + + dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-tx", &l_tx_hash_str); + if (!l_tx_hash_str) { + dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-cert", &l_cert_str); + if (!l_cert_str) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'update' requires parameter -tx or -cert"); + return -13; + } + } + dap_hash_fast_t l_tx_hash = {}; + if (l_tx_hash_str) { + dap_chain_hash_fast_from_str(l_tx_hash_str, &l_tx_hash); + } else { + dap_chain_addr_t l_signing_addr; + dap_cert_t *l_cert = dap_cert_find_by_name(l_cert_str); + if (!l_cert) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified certificate not found"); + return -18; + } + if (!l_cert->enc_key->priv_key_data || l_cert->enc_key->priv_key_data_size == 0) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "It is not possible to update a stake using a public key."); + return -31; + } + if (dap_chain_addr_fill_from_key(&l_signing_addr, l_cert->enc_key, l_net->pub.id)) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified certificate is wrong"); + return -22; + } + dap_chain_net_srv_stake_t *l_srv_stake = s_srv_stake_by_net_id(l_net->pub.id); + if (!l_srv_stake) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified net have no stake service activated"); + return -25; + } + dap_chain_net_srv_stake_item_t *l_stake = NULL; + HASH_FIND(hh, l_srv_stake->itemlist, &l_signing_addr.data.hash_fast, sizeof(dap_hash_fast_t), l_stake); + if (!l_stake) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified certificate/pkey hash is not delegated nor this delegating is approved." + " Try to update with tx hash instead"); + return -24; + } + l_tx_hash = l_stake->tx_hash; + } + + const char *l_tx_hash_str_tmp = l_tx_hash_str ? l_tx_hash_str : dap_hash_fast_to_str_static(&l_tx_hash); + dap_chain_datum_tx_t *l_tx = dap_ledger_tx_find_by_hash(l_net->pub.ledger, &l_tx_hash); + if (!l_tx) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Transaction %s not found", l_tx_hash_str_tmp); + return -21; + } + int l_out_num = 0; + if (!dap_chain_datum_tx_out_cond_get(l_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE, &l_out_num)) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Transaction %s is invalid", l_tx_hash_str_tmp); + return -22; + } + dap_hash_fast_t l_spender_hash = {}; + if (dap_ledger_tx_hash_is_used_out_item(l_net->pub.ledger, &l_tx_hash, l_out_num, &l_spender_hash)) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Transaction %s is spent", l_tx_hash_str_tmp); + return -23; + } + + const char* l_sign_str = ""; + dap_chain_wallet_t *l_wallet = dap_chain_wallet_open(l_wallet_str, dap_chain_wallet_get_path(g_config), NULL); + if (!l_wallet) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified wallet %s not found", l_wallet_str); + return -18; + } else { + l_sign_str = dap_chain_wallet_check_sign(l_wallet); + } + dap_enc_key_t *l_enc_key = dap_chain_wallet_get_key(l_wallet, 0); + dap_chain_datum_tx_t *l_tx_new = s_stake_tx_update(l_net, &l_tx_hash, l_value, l_fee, l_enc_key); + dap_chain_wallet_close(l_wallet); + dap_enc_key_delete(l_enc_key); + char *l_out_hash_str = NULL; + if (l_tx_new && (l_out_hash_str = s_stake_tx_put(l_tx_new, l_net, a_hash_out_type))) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "%sDelegated m-tokens value will change. Updating tx hash is %s.", l_sign_str, l_out_hash_str); + DAP_DELETE(l_out_hash_str); + DAP_DELETE(l_tx_new); + } else { + l_tx_hash_str = dap_chain_hash_fast_to_str_static(&l_tx_hash); + dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't compose updating transaction %s, examine log files for details", l_tx_hash_str); + DAP_DEL_Z(l_tx_new); + return -21; + } + return 0; +} + + static int s_cli_srv_stake_invalidate(int a_argc, char **a_argv, int a_arg_index, void **a_str_reply, const char *a_hash_out_type) { const char *l_net_str = NULL, *l_wallet_str = NULL, *l_fee_str = NULL, *l_tx_hash_str = NULL, - *l_cert_str = NULL, *l_poa_cert_str = NULL, *l_signing_pkey_hash_str = NULL, *l_signing_pkey_type_str = NULL; @@ -1962,7 +2282,7 @@ static int s_cli_srv_stake_invalidate(int a_argc, char **a_argv, int a_arg_index } else { dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-fee", &l_fee_str); if (!l_fee_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'delegate' requires parameter -fee"); + dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'invalidate' requires parameter -fee"); return -5; } l_fee = dap_chain_balance_scan(l_fee_str); @@ -1973,22 +2293,19 @@ static int s_cli_srv_stake_invalidate(int a_argc, char **a_argv, int a_arg_index } dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-tx", &l_tx_hash_str); if (!l_tx_hash_str) { - dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-cert", &l_cert_str); - if (!l_cert_str) { - dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-signing_pkey_hash", &l_signing_pkey_hash_str); - if (!l_signing_pkey_hash_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'invalidate' requires parameter -tx or -cert or -signing_pkey_hash"); - return -13; - } - dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-signing_pkey_type", &l_signing_pkey_type_str); - if (!l_signing_pkey_type_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'invalidate' requires parameter -signing_pkey_type"); - return -14; - } - if (dap_sign_type_from_str(l_signing_pkey_type_str).type == SIG_TYPE_NULL) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Invalid signing_pkey_type %s", l_signing_pkey_type_str); - return -15; - } + dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-signing_pkey_hash", &l_signing_pkey_hash_str); + if (!l_signing_pkey_hash_str) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'invalidate' requires parameter -tx or -signing_pkey_hash"); + return -13; + } + dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-signing_pkey_type", &l_signing_pkey_type_str); + if (!l_signing_pkey_type_str) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'invalidate' requires parameter -signing_pkey_type"); + return -14; + } + if (dap_sign_type_from_str(l_signing_pkey_type_str).type == SIG_TYPE_NULL) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Invalid signing_pkey_type %s", l_signing_pkey_type_str); + return -15; } } @@ -1996,29 +2313,13 @@ static int s_cli_srv_stake_invalidate(int a_argc, char **a_argv, int a_arg_index if (l_tx_hash_str) { dap_chain_hash_fast_from_str(l_tx_hash_str, &l_tx_hash); } else { - dap_chain_addr_t l_signing_addr; - if (l_cert_str) { - dap_cert_t *l_cert = dap_cert_find_by_name(l_cert_str); - if (!l_cert) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified certificate not found"); - return -18; - } - if (!l_cert->enc_key->priv_key_data || l_cert->enc_key->priv_key_data_size == 0) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "It is not possible to invalidate a stake using a public key."); - return -31; - } - if (dap_chain_addr_fill_from_key(&l_signing_addr, l_cert->enc_key, l_net->pub.id)) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified certificate is wrong"); - return -22; - } - } else { - dap_hash_fast_t l_pkey_hash = {}; - if (dap_chain_hash_fast_from_str(l_signing_pkey_hash_str, &l_pkey_hash)) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Invalid pkey hash format"); - return -23; - } - dap_chain_addr_fill(&l_signing_addr, dap_sign_type_from_str(l_signing_pkey_type_str), &l_pkey_hash, l_net->pub.id); + dap_hash_fast_t l_pkey_hash = {}; + if (dap_chain_hash_fast_from_str(l_signing_pkey_hash_str, &l_pkey_hash)) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Invalid pkey hash format"); + return -23; } + dap_chain_addr_t l_signing_addr; + dap_chain_addr_fill(&l_signing_addr, dap_sign_type_from_str(l_signing_pkey_type_str), &l_pkey_hash, l_net->pub.id); dap_chain_net_srv_stake_t *l_srv_stake = s_srv_stake_by_net_id(l_net->pub.id); if (!l_srv_stake) { dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified net have no stake service activated"); @@ -2048,14 +2349,10 @@ static int s_cli_srv_stake_invalidate(int a_argc, char **a_argv, int a_arg_index } dap_hash_fast_t l_spender_hash = {}; if (dap_ledger_tx_hash_is_used_out_item(l_net->pub.ledger, &l_tx_hash, l_out_num, &l_spender_hash)) { - l_tx_hash = l_spender_hash; - l_tx_hash_str_tmp = dap_hash_fast_to_str_static(&l_spender_hash); - if (!dap_ledger_tx_find_by_hash(l_net->pub.ledger, &l_tx_hash)) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Previous transaction %s is not found", l_tx_hash_str_tmp); - return -21; - } + dap_cli_server_cmd_set_reply_text(a_str_reply, "Transaction %s is spent", l_tx_hash_str_tmp); + return -23; } - if (l_tx_hash_str || l_cert_str) { + if (l_tx_hash_str) { dap_chain_net_srv_stake_t *l_srv_stake = s_srv_stake_by_net_id(l_net->pub.id); if (!l_srv_stake) { dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified net have no stake service activated"); @@ -2087,13 +2384,13 @@ static int s_cli_srv_stake_invalidate(int a_argc, char **a_argv, int a_arg_index dap_enc_key_delete(l_enc_key); char *l_out_hash_str = NULL; if (l_tx && (l_out_hash_str = s_stake_tx_put(l_tx, l_net, a_hash_out_type))) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "%sAll m-tokens successfully returned to " + dap_cli_server_cmd_set_reply_text(a_str_reply, "%sAll m-tokens will be returned to " "owner. Returning tx hash %s.", l_sign_str, l_out_hash_str); DAP_DELETE(l_out_hash_str); DAP_DELETE(l_tx); } else { l_tx_hash_str = dap_chain_hash_fast_to_str_static(&l_tx_hash); - dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't invalidate transaction %s, examine log files for details", l_tx_hash_str); + dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't compose invalidation transaction %s, examine log files for details", l_tx_hash_str); DAP_DEL_Z(l_tx); return -21; } @@ -2131,7 +2428,8 @@ static void s_srv_stake_print(dap_chain_net_srv_stake_item_t *a_stake, uint256_t char l_tx_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE], l_pkey_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE]; dap_chain_hash_fast_to_str(&a_stake->tx_hash, l_tx_hash_str, sizeof(l_tx_hash_str)); dap_chain_hash_fast_to_str(&a_stake->signing_addr.data.hash_fast, l_pkey_hash_str, sizeof(l_pkey_hash_str)); - char *l_balance = dap_chain_balance_to_coins(a_stake->value); + char *l_balance = dap_chain_balance_to_coins(a_stake->locked_value); + char *l_effective_weight = dap_chain_balance_to_coins(a_stake->value); uint256_t l_rel_weight, l_tmp; MULT_256_256(a_stake->value, GET_256_FROM_64(100), &l_tmp); DIV_256_COIN(l_tmp, a_total_weight, &l_rel_weight); @@ -2146,16 +2444,18 @@ static void s_srv_stake_print(dap_chain_net_srv_stake_item_t *a_stake, uint256_t char *l_sov_tax_str = dap_chain_balance_to_coins(l_sov_tax_percent); dap_string_append_printf(a_string, "Pkey hash: %s\n" "\tStake value: %s\n" + "\tEffective value: %s\n" "\tRelated weight: %s%%\n" "\tTx hash: %s\n" "\tNode addr: "NODE_ADDR_FP_STR"\n" "\tSovereign addr: %s\n" "\tSovereign tax: %s%%\n" "%s\n", - l_pkey_hash_str, l_balance, l_rel_weight_str, + l_pkey_hash_str, l_balance, l_effective_weight, l_rel_weight_str, l_tx_hash_str, NODE_ADDR_FP_ARGS_S(a_stake->node_addr), l_sov_addr_str, l_sov_tax_str, l_active_str); DAP_DELETE(l_balance); + DAP_DELETE(l_effective_weight); DAP_DELETE(l_rel_weight_str); DAP_DELETE(l_sov_tax_str); } @@ -2298,7 +2598,7 @@ int dap_chain_net_srv_stake_check_validator(dap_chain_net_t * a_net, dap_hash_fa return l_overall_correct; } -uint256_t dap_chain_net_srv_stake_get_total_weight(dap_chain_net_id_t a_net_id) +uint256_t dap_chain_net_srv_stake_get_total_weight(dap_chain_net_id_t a_net_id, uint256_t *a_locked_weight) { dap_chain_net_srv_stake_t *l_srv_stake = s_srv_stake_by_net_id(a_net_id); dap_return_val_if_fail(l_srv_stake, uint256_0); @@ -2307,6 +2607,8 @@ uint256_t dap_chain_net_srv_stake_get_total_weight(dap_chain_net_id_t a_net_id) if (it->signing_addr.net_id.uint64 != a_net_id.uint64) continue; SUM_256_256(l_total_weight, it->value, &l_total_weight); + if (a_locked_weight) + SUM_256_256(*a_locked_weight, it->locked_value, a_locked_weight); } return l_total_weight; } @@ -2314,7 +2616,7 @@ uint256_t dap_chain_net_srv_stake_get_total_weight(dap_chain_net_id_t a_net_id) static int s_cli_srv_stake(int a_argc, char **a_argv, void **a_str_reply) { enum { - CMD_NONE, CMD_ORDER, CMD_DELEGATE, CMD_APPROVE, CMD_LIST, CMD_INVALIDATE, CMD_MIN_VALUE, CMD_CHECK, CMD_MAX_WEIGHT + CMD_NONE, CMD_ORDER, CMD_DELEGATE, CMD_UPDATE, CMD_APPROVE, CMD_LIST, CMD_INVALIDATE, CMD_MIN_VALUE, CMD_CHECK, CMD_MAX_WEIGHT }; int l_arg_index = 1; @@ -2334,6 +2636,10 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, void **a_str_reply) else if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "delegate", NULL)) { l_cmd_num = CMD_DELEGATE; } + // Create tx to change staker's funds for delegated key (if any) + else if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "update", NULL)) { + l_cmd_num = CMD_UPDATE; + } // Create tx to approve staker's funds freeze else if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "approve", NULL)) { l_cmd_num = CMD_APPROVE; @@ -2365,6 +2671,9 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, void **a_str_reply) case CMD_DELEGATE: return s_cli_srv_stake_delegate(a_argc, a_argv, l_arg_index + 1, a_str_reply, l_hash_out_type); + case CMD_UPDATE: + return s_cli_srv_stake_update(a_argc, a_argv, l_arg_index + 1, a_str_reply, l_hash_out_type); + case CMD_INVALIDATE: return s_cli_srv_stake_invalidate(a_argc, a_argv, l_arg_index + 1, a_str_reply, l_hash_out_type); @@ -2555,7 +2864,7 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, void **a_str_reply) dap_string_t *l_reply_str = dap_string_new(""); size_t l_inactive_count = 0, l_total_count = 0; - uint256_t l_total_weight = dap_chain_net_srv_stake_get_total_weight(l_net->pub.id); + uint256_t l_total_locked_weight = {}, l_total_weight = dap_chain_net_srv_stake_get_total_weight(l_net->pub.id, &l_total_locked_weight); if (l_stake) s_srv_stake_print(l_stake, l_total_weight, l_reply_str); else @@ -2572,9 +2881,10 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, void **a_str_reply) dap_string_append_printf(l_reply_str, "Total keys count: %zu\n", l_total_count); if (dap_chain_esbocs_started(l_net->pub.id)) dap_string_append_printf(l_reply_str, "Inactive keys count: %zu\n", l_inactive_count); - const char *l_total_weight_coins, *l_total_weight_str = - dap_uint256_to_char(l_total_weight, &l_total_weight_coins); + const char *l_total_weight_coins, *l_total_weight_str = dap_uint256_to_char(l_total_locked_weight, &l_total_weight_coins); dap_string_append_printf(l_reply_str, "Total weight: %s (%s)\n", l_total_weight_coins, l_total_weight_str); + l_total_weight_str = dap_uint256_to_char(l_total_weight, &l_total_weight_coins); + dap_string_append_printf(l_reply_str, "Total effective weight: %s (%s)\n", l_total_weight_coins, l_total_weight_str); } const char *l_delegate_min_str; dap_uint256_to_char(dap_chain_net_srv_stake_get_allowed_min_value(l_net->pub.id), diff --git a/modules/service/stake/include/dap_chain_net_srv_stake_pos_delegate.h b/modules/service/stake/include/dap_chain_net_srv_stake_pos_delegate.h index 19ca297c30461b77eaabcba70e1fca5096f64dfe..00449f6e4980fd11f0fd7f25267b6a68e5975594 100644 --- a/modules/service/stake/include/dap_chain_net_srv_stake_pos_delegate.h +++ b/modules/service/stake/include/dap_chain_net_srv_stake_pos_delegate.h @@ -72,6 +72,7 @@ int dap_chain_net_srv_stake_net_add(dap_chain_net_id_t a_net_id); void dap_chain_net_srv_stake_key_delegate(dap_chain_net_t *a_net, dap_chain_addr_t *a_signing_addr, dap_hash_fast_t *a_stake_tx_hash, uint256_t a_value, dap_chain_node_addr_t *a_node_addr); void dap_chain_net_srv_stake_key_invalidate(dap_chain_addr_t *a_signing_addr); +void dap_chain_net_srv_stake_key_update(dap_chain_addr_t *a_signing_addr, uint256_t a_new_value, dap_hash_fast_t *a_new_tx_hash); void dap_chain_net_srv_stake_set_allowed_min_value(dap_chain_net_id_t a_net_id, uint256_t a_value); uint256_t dap_chain_net_srv_stake_get_allowed_min_value(dap_chain_net_id_t a_net_id); void dap_chain_net_srv_stake_set_percent_max(dap_chain_net_id_t a_net_id, uint256_t a_value); @@ -98,5 +99,5 @@ dap_chain_datum_decree_t *dap_chain_net_srv_stake_decree_approve(dap_chain_net_t int dap_chain_net_srv_stake_mark_validator_active(dap_chain_addr_t *a_signing_addr, bool a_on_off); dap_chain_net_srv_stake_item_t *dap_chain_net_srv_stake_check_pkey_hash(dap_chain_net_id_t a_net_id, dap_hash_fast_t *a_pkey_hash); -uint256_t dap_chain_net_srv_stake_get_total_weight(dap_chain_net_id_t a_net_id); +uint256_t dap_chain_net_srv_stake_get_total_weight(dap_chain_net_id_t a_net_id, uint256_t *a_locked_weight); size_t dap_chain_net_srv_stake_get_total_keys(dap_chain_net_id_t a_net_id, size_t *a_in_active_count); diff --git a/modules/service/xchange/dap_chain_net_srv_xchange.c b/modules/service/xchange/dap_chain_net_srv_xchange.c index 42cea326359093a8f25eeb79c879444c329ebb39..7e8c19c190c14370b73f1ad8b1a185f8ffa95cd0 100644 --- a/modules/service/xchange/dap_chain_net_srv_xchange.c +++ b/modules/service/xchange/dap_chain_net_srv_xchange.c @@ -1795,7 +1795,8 @@ static bool s_string_append_tx_cond_info( dap_string_t * a_reply_str, xchange_tx_type_t l_tx_type = dap_chain_net_srv_xchange_tx_get_type(a_net->pub.ledger, a_tx, &l_out_cond_item, &l_cond_idx, &l_out_prev_cond_item); bool l_is_closed = dap_ledger_tx_hash_is_used_out_item(a_net->pub.ledger, &l_tx_hash, l_cond_idx, NULL); - if ((a_filter_by_status == TX_STATUS_ACTIVE && l_is_closed) || (a_filter_by_status == TX_STATUS_INACTIVE && !l_is_closed)) + if ((a_filter_by_status == TX_STATUS_ACTIVE && l_is_closed) || (a_filter_by_status == TX_STATUS_INACTIVE && !l_is_closed) + || (a_filter_by_status == TX_STATUS_ACTIVE && l_tx_type == TX_TYPE_INVALIDATE)) return false; if(l_out_prev_cond_item && l_out_prev_cond_item->header.subtype != DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE) diff --git a/modules/type/blocks/dap_chain_cs_blocks.c b/modules/type/blocks/dap_chain_cs_blocks.c index 0b76090d0f15515fc5362c0e5996f22da9e20602..a0feca9322aeb6f880bc3fb2371735949987a467 100644 --- a/modules/type/blocks/dap_chain_cs_blocks.c +++ b/modules/type/blocks/dap_chain_cs_blocks.c @@ -471,12 +471,11 @@ static void s_cli_meta_hash_print(json_object* a_json_obj_out, const char *a_met */ static void s_cli_meta_hex_print(json_object* a_json_obj_out, const char * a_meta_title, dap_chain_block_meta_t * a_meta) { - char *l_data_hex = DAP_NEW_Z_SIZE(char, a_meta->hdr.data_size * 2 + 3); - dap_bin2hex(l_data_hex, a_meta->data, a_meta->hdr.data_size); - char l_tmp_buff[70]={0}; - sprintf(l_tmp_buff,"0x%s\n", l_data_hex); - json_object_object_add(a_json_obj_out, a_meta_title, json_object_new_string(l_tmp_buff)); - DAP_DELETE(l_data_hex); + int l_len = a_meta->hdr.data_size * 2 + 5; + char *l_str = DAP_NEW_STACK_SIZE(char, l_len); + snprintf(l_str, 2, "0x"); + dap_bin2hex(l_str + 2, a_meta->data, a_meta->hdr.data_size); + json_object_object_add(a_json_obj_out, a_meta_title, json_object_new_string(l_str)); } static void s_print_autocollect_table(dap_chain_net_t *a_net, json_object *a_json_obj_out, const char *a_table_name) @@ -498,9 +497,9 @@ static void s_print_autocollect_table(dap_chain_net_t *a_net, json_object *a_jso json_object_array_add(json_arr_out, json_obj_t); SUM_256_256(l_total_value, l_cur_value, &l_total_value); } - char l_tmp_buff[256]; - sprintf(l_tmp_buff,"Autocollect tables content for === %s ===", a_table_name); - json_object_object_add(a_json_obj_out, l_tmp_buff, json_arr_out); + char *l_val = dap_strdup_printf("Autocollect tables content for === %s ===", a_table_name); + json_object_object_add(a_json_obj_out, l_val, json_arr_out); + DAP_DEL_Z(l_val); if (l_objs_count) { dap_global_db_objs_delete(l_objs, l_objs_count); uint256_t l_collect_fee = dap_chain_esbocs_get_fee(a_net->pub.id); @@ -522,14 +521,13 @@ static void s_print_autocollect_table(dap_chain_net_t *a_net, json_object *a_jso char *l_profit_str = dap_chain_balance_to_coins(l_collect_value); char *l_tax_str = dap_chain_balance_to_coins(l_collect_tax); char *l_fee_str = dap_chain_balance_to_coins(l_collect_fee); - sprintf(l_tmp_buff,"Total prepared value: %s %s, where profit is %s, tax is %s, fee is %s\n", + l_val = dap_strdup_printf("Total prepared value: %s %s, where profit is %s, tax is %s, fee is %s\n", l_total_str, a_net->pub.native_ticker, l_profit_str, l_tax_str, l_fee_str); DAP_DEL_MULTY(l_total_str, l_profit_str, l_tax_str, l_fee_str); - } else - strcpy(l_tmp_buff, "Empty"); - char l_status_buf[32]; - sprintf(l_status_buf, "%s status", a_table_name); - json_object_object_add(a_json_obj_out, l_status_buf, json_object_new_string(l_tmp_buff)); + } + char *l_key = dap_strdup_printf("%s status", a_table_name); + json_object_object_add(a_json_obj_out, l_key, json_object_new_string(l_val ? l_val : "Empty")); + DAP_DEL_MULTY(l_key, l_val); } /** @@ -710,20 +708,20 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply) return DAP_CHAIN_NODE_CLI_COM_BLOCK_FIND_ERR; } dap_chain_block_t *l_block = l_block_cache->block; - char l_tmp_buff[70]={0}; - char l_time_buf[DAP_TIME_STR_SIZE]; - dap_time_to_str_rfc822(l_time_buf, DAP_TIME_STR_SIZE, l_block->hdr.ts_created); + char l_time_buf[DAP_TIME_STR_SIZE], l_hexbuf[32] = { '\0' }; // Header json_object* json_obj_inf = json_object_new_object(); json_object_object_add(json_obj_inf, "Block number", json_object_new_uint64(l_block_cache->block_number)); json_object_object_add(json_obj_inf, "hash", json_object_new_string(l_subcmd_str_arg)); - sprintf(l_tmp_buff,"0x%04X",l_block->hdr.version); - json_object_object_add(json_obj_inf, "version", json_object_new_string(l_tmp_buff)); - sprintf(l_tmp_buff,"0x%016"DAP_UINT64_FORMAT_X"",l_block->hdr.cell_id.uint64); - json_object_object_add(json_obj_inf, "cell_id", json_object_new_string(l_tmp_buff)); - sprintf(l_tmp_buff,"0x%016"DAP_UINT64_FORMAT_X"",l_block->hdr.chain_id.uint64); - json_object_object_add(json_obj_inf, "chain_id", json_object_new_string(l_tmp_buff)); + sprintf(l_hexbuf,"0x%04X",l_block->hdr.version); + + json_object_object_add(json_obj_inf, "version", json_object_new_string(l_hexbuf)); + sprintf(l_hexbuf,"0x%016"DAP_UINT64_FORMAT_X"",l_block->hdr.cell_id.uint64); + json_object_object_add(json_obj_inf, "cell_id", json_object_new_string(l_hexbuf)); + sprintf(l_hexbuf,"0x%016"DAP_UINT64_FORMAT_X"",l_block->hdr.chain_id.uint64); + json_object_object_add(json_obj_inf, "chain_id", json_object_new_string(l_hexbuf)); + dap_time_to_str_rfc822(l_time_buf, DAP_TIME_STR_SIZE, l_block->hdr.ts_created); json_object_object_add(json_obj_inf, "ts_created", json_object_new_string(l_time_buf)); // Dump Metadata @@ -754,14 +752,13 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply) s_cli_meta_hex_print(json_obj_meta, "NONCE2", l_meta); break; default: { - char * l_data_hex = DAP_NEW_Z_SIZE(char,l_meta->hdr.data_size*2+3); - dap_bin2hex(l_data_hex, l_meta->data, l_meta->hdr.data_size); - sprintf(l_tmp_buff,"0x%0X",i); - json_object_object_add(json_obj_meta, "# -", json_object_new_string(l_tmp_buff)); - sprintf(l_tmp_buff,"0x%s",l_data_hex); - json_object_object_add(json_obj_meta, "Data hex - ", json_object_new_string(l_tmp_buff)); - DAP_DELETE(l_data_hex); - } + sprintf(l_hexbuf, "0x%0X", i); + json_object_object_add(json_obj_meta, "# -", json_object_new_string(l_hexbuf)); + int l_len = l_meta->hdr.data_size * 2 + 5; + char *l_data_hex = DAP_NEW_STACK_SIZE(char, l_len); + snprintf(l_data_hex, 2, "0x"); + dap_bin2hex(l_data_hex + 2, l_meta->data, l_meta->hdr.data_size); + json_object_object_add(json_obj_meta, "Data hex - ", json_object_new_string(l_data_hex)); } } json_object_array_add(json_arr_meta_out, json_obj_meta); l_offset += sizeof(l_meta->hdr) + l_meta->hdr.data_size; @@ -772,7 +769,6 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply) json_object_array_add(*json_arr_reply, json_obj_datum); json_object* json_arr_datum_out = json_object_new_array(); for (uint32_t i=0; i < l_block_cache->datum_count ; i++){ - char buf[70]; json_object* json_obj_tx = json_object_new_object(); dap_chain_datum_t * l_datum = l_block_cache->datum[i]; size_t l_datum_size = dap_chain_datum_size(l_datum); @@ -783,13 +779,13 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply) break; } // Nested datums - sprintf(l_tmp_buff,"0x%02X",l_datum->header.version_id); - json_object_object_add(json_obj_tx, "version",json_object_new_string(l_tmp_buff)); - const char * l_datum_type_str="UNKNOWN"; + sprintf(l_hexbuf,"0x%02X",l_datum->header.version_id); + json_object_object_add(json_obj_tx, "version",json_object_new_string(l_hexbuf)); + const char * l_datum_type_str = "UNKNOWN"; DAP_DATUM_TYPE_STR(l_datum->header.type_id, l_datum_type_str); json_object_object_add(json_obj_tx, "type_id",json_object_new_string(l_datum_type_str)); - dap_time_to_str_rfc822(buf, DAP_TIME_STR_SIZE, l_datum->header.ts_create); - json_object_object_add(json_obj_tx, "ts_create",json_object_new_string(buf)); + dap_time_to_str_rfc822(l_time_buf, DAP_TIME_STR_SIZE, l_datum->header.ts_create); + json_object_object_add(json_obj_tx, "ts_create",json_object_new_string(l_time_buf)); json_object_object_add(json_obj_tx, "data_size",json_object_new_int(l_datum->header.data_size)); dap_chain_datum_dump_json(json_obj_tx,l_datum,l_hash_out_type,l_net->pub.id); json_object_array_add(json_arr_datum_out, json_obj_tx); @@ -824,8 +820,6 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply) dap_pkey_t * l_pub_key = NULL; dap_hash_fast_t l_from_hash = {}, l_to_hash = {}, l_pkey_hash = {}; dap_time_t l_from_time = 0, l_to_time = 0; - char l_tmp_buff[150]={0}; - l_signed_flag = dap_cli_server_cmd_check_option(a_argv, 1, a_argc, "signed") > 0; l_first_signed_flag = dap_cli_server_cmd_check_option(a_argv, 1, a_argc, "first_signed") > 0; l_unspent_flag = dap_cli_server_cmd_check_option(a_argv, 1, a_argc, "-unspent") > 0; @@ -996,12 +990,12 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply) json_object* json_obj_out = json_object_new_object(); if (l_cert_name || l_pkey_hash_str || l_from_hash_str || l_to_hash_str || l_from_date_str || l_to_date_str) l_filtered_criteria = " filtered according to the specified criteria"; - sprintf(l_tmp_buff,"%s.%s with filter - %s, have blocks",l_net->pub.name,l_chain->name,l_filtered_criteria); - json_object_object_add(json_obj_out, l_tmp_buff, json_object_new_uint64(i_tmp)); + char *l_key = dap_strdup_printf("%s.%s with filter - %s, have blocks",l_net->pub.name,l_chain->name,l_filtered_criteria); + json_object_object_add(json_obj_out, l_key, json_object_new_uint64(i_tmp)); + DAP_DELETE(l_key); json_object_array_add(*json_arr_reply,json_obj_out); } break; case SUBCMD_LAST: { - char l_tmp_buff[70]={0}; json_object* json_obj_out = json_object_new_object(); dap_chain_block_cache_t *l_last_block = HASH_LAST(PVT(l_blocks)->blocks); char l_buf[DAP_TIME_STR_SIZE]; @@ -1011,8 +1005,9 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply) json_object_object_add(json_obj_out, "Last block hash", json_object_new_string(l_last_block ? l_last_block->block_hash_str : "empty")); json_object_object_add(json_obj_out, "ts_created", json_object_new_string(l_last_block ? l_buf : "never")); - sprintf(l_tmp_buff,"%s.%s has blocks", l_net->pub.name, l_chain->name); - json_object_object_add(json_obj_out, l_tmp_buff, json_object_new_uint64(PVT(l_blocks)->blocks_count)); + char *l_key = dap_strdup_printf("%s.%s has blocks", l_net->pub.name, l_chain->name); + json_object_object_add(json_obj_out, l_key, json_object_new_uint64(PVT(l_blocks)->blocks_count)); + DAP_DELETE(l_key); json_object_array_add(*json_arr_reply, json_obj_out); } break; case SUBCMD_FIND: { @@ -1045,10 +1040,10 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply) json_object_array_add(*json_arr_reply, json_obj_out); } break; case SUBCMD_COUNT: { - char l_tmp_buff[70]={0}; json_object* json_obj_out = json_object_new_object(); - sprintf(l_tmp_buff,"%s.%s has blocks - ",l_net->pub.name,l_chain->name); - json_object_object_add(json_obj_out, l_tmp_buff, json_object_new_uint64(PVT(l_blocks)->blocks_count)); + char *l_key = dap_strdup_printf("%s.%s has blocks - ", l_net->pub.name,l_chain->name); + json_object_object_add(json_obj_out, l_key, json_object_new_uint64(PVT(l_blocks)->blocks_count)); + DAP_DELETE(l_key); json_object_array_add(*json_arr_reply, json_obj_out); } break; @@ -1060,7 +1055,6 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply) const char * l_addr_str = NULL; const char * l_hash_out_type = NULL; const char * l_hash_str = NULL; - char l_tmp_buff[70]={0}; uint256_t l_fee_value = {}; size_t l_hashes_count = 0; @@ -1098,9 +1092,13 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply) } char *l_decree_hash_str = s_blocks_decree_set_reward(l_net, l_chain, l_value, l_cert); if (l_decree_hash_str) { - //добавить вывод - dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_OK, "Decree with hash %s created to set basic block sign reward", l_decree_hash_str); + //dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_OK, "Decree with hash %s created to set basic block sign reward", l_decree_hash_str); + json_object* json_obj_out = json_object_new_object(); + char *l_val = dap_strdup_printf("Decree with hash %s created to set basic block sign reward", l_decree_hash_str); DAP_DELETE(l_decree_hash_str); + json_object_object_add(json_obj_out, "status", json_object_new_string(l_val)); + DAP_DELETE(l_val); + json_object_array_add(*json_arr_reply, json_obj_out); } else { dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_SIGN_ERR, "Basic block sign reward setting failed. Examine log file for details"); return DAP_CHAIN_NODE_CLI_COM_BLOCK_SIGN_ERR; @@ -1110,8 +1108,9 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply) uint256_t l_cur_reward = dap_chain_net_get_reward(l_net, UINT64_MAX); const char *l_reward_str; dap_uint256_to_char(l_cur_reward, &l_reward_str); json_object* json_obj_out = json_object_new_object(); - sprintf(l_tmp_buff,"Current base block reward is %s\n", l_reward_str); - json_object_object_add(json_obj_out, "status", json_object_new_string(l_tmp_buff)); + char *l_val = dap_strdup_printf("Current base block reward is %s\n", l_reward_str); + json_object_object_add(json_obj_out, "status", json_object_new_string(l_val)); + DAP_DELETE(l_val); json_object_array_add(*json_arr_reply, json_obj_out); break; } else if (dap_cli_server_cmd_check_option(a_argv, arg_index, a_argc, "collect") == -1) { @@ -1177,15 +1176,14 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply) return DAP_CHAIN_NODE_CLI_COM_BLOCK_HASH_ERR; } - char *l_hash_tx = NULL; - if (l_subcmd == SUBCMD_FEE) - l_hash_tx = dap_chain_mempool_tx_coll_fee_create(l_blocks, l_cert->enc_key, l_addr, l_block_list, l_fee_value, l_hash_out_type); - else - l_hash_tx = dap_chain_mempool_tx_reward_create(l_blocks, l_cert->enc_key, l_addr, l_block_list, l_fee_value, l_hash_out_type); + char *l_hash_tx = l_subcmd == SUBCMD_FEE + ? dap_chain_mempool_tx_coll_fee_create(l_blocks, l_cert->enc_key, l_addr, l_block_list, l_fee_value, l_hash_out_type) + : dap_chain_mempool_tx_reward_create(l_blocks, l_cert->enc_key, l_addr, l_block_list, l_fee_value, l_hash_out_type); if (l_hash_tx) { json_object* json_obj_out = json_object_new_object(); - sprintf(l_tmp_buff, "TX for %s collection created successfully, hash = %s\n", l_subcmd_str, l_hash_tx); - json_object_object_add(json_obj_out, "status", json_object_new_string(l_tmp_buff)); + char *l_val = dap_strdup_printf(l_val, "TX for %s collection created successfully, hash = %s\n", l_subcmd_str, l_hash_tx); + json_object_object_add(json_obj_out, "status", json_object_new_string(l_val)); + DAP_DELETE(l_val); json_object_array_add(*json_arr_reply, json_obj_out); DAP_DELETE(l_hash_tx); } else { @@ -1200,7 +1198,6 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply) const char *l_cert_name = NULL, *l_addr_str = NULL; dap_hash_fast_t l_pkey_hash = {}; size_t l_block_count = 0; - char l_tmp_buff[128]={0}; if (dap_cli_server_cmd_check_option(a_argv, arg_index,a_argc, "renew") > 0) { dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-cert", &l_cert_name); if(!l_cert_name) { @@ -1277,8 +1274,9 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply) char l_buf[DAP_TIME_STR_SIZE]; json_object* json_obj_bl = json_object_new_object(); dap_time_to_str_rfc822(l_buf, DAP_TIME_STR_SIZE, l_ts); - sprintf(l_tmp_buff, "fee - \t%s: ts_create=%s\n", l_block_cache->block_hash_str, l_buf); - json_object_object_add(json_obj_bl, "block", json_object_new_string(l_tmp_buff)); + char *l_val = dap_strdup_printf("fee - \t%s: ts_create=%s\n", l_block_cache->block_hash_str, l_buf); + json_object_object_add(json_obj_bl, "block", json_object_new_string(l_val)); + DAP_DELETE(l_val); json_object_array_add(json_arr_bl_out, json_obj_bl); l_block_count++; break; @@ -1308,18 +1306,20 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply) char l_buf[DAP_TIME_STR_SIZE]; json_object* json_obj_bl = json_object_new_object(); dap_time_to_str_rfc822(l_buf, DAP_TIME_STR_SIZE, l_ts); - sprintf(l_tmp_buff, "rewards - \t%s: ts_create=%s\n", l_block_cache->block_hash_str, l_buf); - json_object_object_add(json_obj_bl, "block", json_object_new_string(l_tmp_buff)); + char *l_val = dap_strdup_printf("rewards - \t%s: ts_create=%s\n", l_block_cache->block_hash_str, l_buf); + json_object_object_add(json_obj_bl, "block", json_object_new_string(l_val)); + DAP_DELETE(l_val); json_object_array_add(json_arr_bl_out, json_obj_bl); l_block_count++; } json_object_array_add(*json_arr_reply, json_arr_bl_out); json_object* json_obj_out = json_object_new_object(); - sprintf(l_tmp_buff, "%s.%s: Have %"DAP_UINT64_FORMAT_U" blocks\n", + char *l_val = dap_strdup_printf("%s.%s: Have %"DAP_UINT64_FORMAT_U" blocks\n", l_net->pub.name, l_chain->name, l_block_count); - json_object_object_add(json_obj_out, "status", json_object_new_string(l_tmp_buff)); + json_object_object_add(json_obj_out, "status", json_object_new_string(l_val)); + DAP_DELETE(l_val); json_object_array_add(*json_arr_reply, json_obj_out); - }else{ + } else { if (dap_cli_server_cmd_check_option(a_argv, arg_index, a_argc, "status") == -1) { dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_PARAM_ERR, "Command 'block autocollect' requires subcommand 'status'"); @@ -1328,10 +1328,10 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply) json_object* json_obj_out = json_object_new_object(); json_object_array_add(*json_arr_reply, json_obj_out); bool l_status = dap_chain_esbocs_get_autocollect_status(l_net->pub.id); - char l_tmp_buff[150]={0}; - sprintf(l_tmp_buff, "for network %s is %s\n", l_net->pub.name, - l_status ? "active" : "inactive, cause the network config or consensus starting problems"); - json_object_object_add(json_obj_out, "Autocollect status", json_object_new_string(l_tmp_buff)); + char *l_val = dap_strdup_printf("for network %s is %s\n", l_net->pub.name, + l_status ? "active" : "inactive cause of the network config or consensus starting problems"); + json_object_object_add(json_obj_out, "Autocollect status", json_object_new_string(l_val)); + DAP_DELETE(l_val); if (!l_status) break; s_print_autocollect_table(l_net, json_obj_out, "Fees"); @@ -1341,13 +1341,12 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply) case SUBCMD_UNDEFINED: default: { - char l_tmp_buff[70]={0}; json_object* json_obj_out = json_object_new_object(); - snprintf(l_tmp_buff, sizeof(l_tmp_buff), "Undefined block subcommand \"%s\" ", - l_subcmd_str); - json_object_object_add(json_obj_out, "status", json_object_new_string(l_tmp_buff)); + char *l_val = dap_strdup_printf("Undefined block subcommand \"%s\" ", l_subcmd_str); + json_object_object_add(json_obj_out, "status", json_object_new_string(l_val)); + DAP_DELETE(l_val); json_object_array_add(*json_arr_reply, json_obj_out); - ret=DAP_CHAIN_NODE_CLI_COM_BLOCK_UNKNOWN; + ret = DAP_CHAIN_NODE_CLI_COM_BLOCK_UNKNOWN; } break; }