diff --git a/dap-sdk b/dap-sdk index d53d1ce3bea6a148aad3ea777e46c67f7249cc74..15c9dab8830dabb8f3e31022ea728a251567d7b3 160000 --- a/dap-sdk +++ b/dap-sdk @@ -1 +1 @@ -Subproject commit d53d1ce3bea6a148aad3ea777e46c67f7249cc74 +Subproject commit 15c9dab8830dabb8f3e31022ea728a251567d7b3 diff --git a/modules/chain/dap_chain_cell.c b/modules/chain/dap_chain_cell.c index 2abed7fec520b29250b68ce4f6fd259ebd01303f..f2457f322ea177994fa1668376dbcb0c96f6b808 100644 --- a/modules/chain/dap_chain_cell.c +++ b/modules/chain/dap_chain_cell.c @@ -144,7 +144,7 @@ DAP_STATIC_INLINE int s_cell_map_new_volume(dap_chain_cell_t *a_cell, size_t a_f .QuadPart = l_ssize }; - NTSTATUS err = pfnNtCreateSection(&hSection, SECTION_MAP_READ|SECTION_EXTEND_SIZE|SECTION_MAP_WRITE, + NTSTATUS err = pfnNtCreateSection(&hSection, SECTION_MAP_READ | SECTION_EXTEND_SIZE, NULL, &SectionSize, PAGE_READWRITE, SEC_RESERVE, (HANDLE)_get_osfhandle(fileno(a_cell->file_storage))); if ( !NT_SUCCESS(err) ) return log_it(L_ERROR, "NtCreateSection() failed, status %lx", err), -1; @@ -166,13 +166,13 @@ DAP_STATIC_INLINE int s_cell_map_new_volume(dap_chain_cell_t *a_cell, size_t a_f .QuadPart = l_volume_start }; err = pfnNtMapViewOfSection(hSection, GetCurrentProcess(), (HANDLE)&a_cell->map, 0, 0, - &Offset, &l_map_size, ViewUnmap, MEM_RESERVE, PAGE_WRITECOPY); + &Offset, &l_map_size, ViewUnmap, MEM_RESERVE, PAGE_READONLY); if ( !NT_SUCCESS(err) ) return NtClose(hSection), log_it(L_ERROR, "NtMapViewOfSection() failed, status %lx", err), -1; #else if (a_load) s_cell_reclaim_cur_volume(a_cell); - if (( a_cell->map = mmap(NULL, l_map_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, + if (( a_cell->map = mmap(NULL, l_map_size, PROT_READ, MAP_PRIVATE, fileno(a_cell->file_storage), l_volume_start) ) == MAP_FAILED ) return log_it(L_ERROR, "Chain cell \"%s\" 0x%016"DAP_UINT64_FORMAT_X" cannot be mapped, errno %d", a_cell->file_storage_path, a_cell->id.uint64, errno), -1; @@ -565,7 +565,7 @@ static int s_cell_file_atom_add(dap_chain_cell_t *a_cell, dap_chain_atom_ptr_t a #ifdef DAP_OS_DARWIN fflush(a_cell->file_storage); if (a_cell->chain->is_mapped) { - if ( MAP_FAILED == (a_cell->map = mmap(a_cell->map, dap_page_roundup(DAP_MAPPED_VOLUME_LIMIT), PROT_READ|PROT_WRITE, + if ( MAP_FAILED == (a_cell->map = mmap(a_cell->map, dap_page_roundup(DAP_MAPPED_VOLUME_LIMIT), PROT_READ, MAP_PRIVATE|MAP_FIXED, fileno(a_cell->file_storage), a_cell->cur_vol_start)) ) { log_it(L_ERROR, "Chain cell \"%s\" 0x%016"DAP_UINT64_FORMAT_X" cannot be remapped, errno %d", a_cell->file_storage_path, a_cell->id.uint64, errno); diff --git a/modules/common/dap_chain_datum_tx.c b/modules/common/dap_chain_datum_tx.c index f0891a8569d8fff33d9db4f49d0ec0eec73a88a3..30e6cbc5c441fc3e365deac986d017b672731215 100644 --- a/modules/common/dap_chain_datum_tx.c +++ b/modules/common/dap_chain_datum_tx.c @@ -74,7 +74,8 @@ int dap_chain_datum_tx_add_item(dap_chain_datum_tx_t **a_tx, const void *a_item) { size_t size = 0; dap_return_val_if_pass(!a_tx || !*a_tx || !(size = dap_chain_datum_item_tx_get_size(a_item, 0)), -1 ); - dap_chain_datum_tx_t *tx_new = DAP_REALLOC_RET_VAL_IF_FAIL( *a_tx, dap_chain_datum_tx_get_size(*a_tx) + size, -2 ); + size_t new_size = dap_chain_datum_tx_get_size(*a_tx) + size; + dap_chain_datum_tx_t *tx_new = DAP_REALLOC_RET_VAL_IF_FAIL( *a_tx, new_size, -2 ); memcpy((uint8_t*) tx_new->tx_items + tx_new->header.tx_items_size, a_item, size); tx_new->header.tx_items_size += size; *a_tx = tx_new; @@ -240,24 +241,36 @@ int dap_chain_datum_tx_verify_sign(dap_chain_datum_tx_t *a_tx, int a_sign_num) { dap_return_val_if_pass(!a_tx, -1); int l_ret = -4, l_sign_num = 0; - byte_t *l_item; size_t l_item_size; + byte_t *l_item = NULL; size_t l_item_size; TX_ITEM_ITER_TX(l_item, l_item_size, a_tx) { - if (*l_item != TX_ITEM_TYPE_SIG) - continue; - if (l_sign_num++ != a_sign_num) - continue; - dap_chain_tx_sig_t *l_sign_item = (dap_chain_tx_sig_t *)l_item; - dap_sign_t *l_sign = dap_chain_datum_tx_item_sign_get_sig(l_sign_item); - byte_t *l_data_ptr = l_sign_item->header.version ? (byte_t *)a_tx : a_tx->tx_items; - const size_t l_data_size = (size_t)(l_item - l_data_ptr); - size_t l_tx_items_size = a_tx->header.tx_items_size; - if (l_sign_item->header.version) - a_tx->header.tx_items_size = 0; - l_ret = dap_sign_verify_all(l_sign, l_item_size, l_data_ptr, l_data_size); - a_tx->header.tx_items_size = l_tx_items_size; - if (l_ret < -1) - log_it(L_WARNING, "Incorrect signature header, possible corrupted data"); - break; + if ( *l_item == TX_ITEM_TYPE_SIG && l_sign_num++ == a_sign_num ) + break; + } + if (!l_item || !l_item_size) + return log_it(L_ERROR, "Sign not found in TX"), l_ret; + + dap_chain_tx_sig_t *l_sign_item = (dap_chain_tx_sig_t*)l_item; + dap_sign_t *l_sign = dap_chain_datum_tx_item_sign_get_sig(l_sign_item); + size_t l_tx_items_size = a_tx->header.tx_items_size, l_data_size; + dap_chain_datum_tx_t *l_tx; + byte_t *l_tx_data; + if ( l_sign_item->header.version ) { + l_data_size = (size_t)( l_item - (byte_t*)a_tx ); + l_tx = dap_config_get_item_bool_default(g_config, "ledger", "mapped", true) + ? DAP_DUP_SIZE(a_tx, dap_chain_datum_tx_get_size(a_tx)) : a_tx; + l_tx_data = (byte_t*)l_tx; + l_tx->header.tx_items_size = 0; + } else { + l_tx = a_tx; + l_tx_data = a_tx->tx_items; + l_data_size = (size_t)( l_item - l_tx_data ); + } + l_ret = dap_sign_verify_all(l_sign, l_item_size, l_tx_data, l_data_size); + if (l_sign_item->header.version) { + if ( dap_config_get_item_bool_default(g_config, "ledger", "mapped", true) ) + DAP_DELETE(l_tx); + else + a_tx->header.tx_items_size = l_tx_items_size; } - return l_ret; + return debug_if(l_ret, L_ERROR, "Sign verification error %d", l_ret), l_ret; } diff --git a/modules/common/include/dap_chain_datum_token.h b/modules/common/include/dap_chain_datum_token.h index b92e61446d60dde2d9ffd5048291b5829cc1ace9..8f6d89e63afd5d612b7ae12a6f0a93de8626b856 100644 --- a/modules/common/include/dap_chain_datum_token.h +++ b/modules/common/include/dap_chain_datum_token.h @@ -405,6 +405,7 @@ typedef struct dap_chain_datum_token_emission { #define DAP_CHAIN_DATUM_TOKEN_EMISSION_SOURCE_SUBTYPE_BRIDGE_COMMISSION_OLD "COMISSION" #define DAP_CHAIN_DATUM_TOKEN_EMISSION_SOURCE_SUBTYPE_BRIDGE_COMMISSION "COMMISSION" #define DAP_CHAIN_DATUM_TOKEN_EMISSION_SOURCE_SUBTYPE_BRIDGE_CROSSCHAIN "CROSSCHAIN" +#define DAP_CHAIN_DATUM_TOKEN_EMISSION_SOURCE_SUBTYPE_BRIDGE_OUT "OUT" DAP_STATIC_INLINE const char *dap_chain_datum_emission_type_str(uint8_t a_type) { diff --git a/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c b/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c index dd2472a8fc3530a49ec38495db5ae9bd792b203d..3ba0e8d3367b66847563df3c455116da4114b019 100644 --- a/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c +++ b/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c @@ -858,21 +858,27 @@ static int s_callback_event_verify(dap_chain_cs_dag_t *a_dag, dap_chain_cs_dag_e } uint16_t l_signs_verified_count = 0; if (l_signs_count >= l_certs_count_verify) { - uint16_t l_event_signs_count = a_event->header.signs_count; + dap_chain_cs_dag_event_t * l_event = a_dag->chain->is_mapped + ? DAP_DUP_SIZE(a_event, l_event_size) + : a_event; + uint16_t l_event_signs_count = l_event->header.signs_count; for (size_t i = 0; i < l_signs_count; i++) { dap_sign_t *l_sign = (dap_sign_t *)l_signs[i]; // Compare signature with auth_certs - a_event->header.signs_count = i; + l_event->header.signs_count = i; for (uint16_t j = 0; j < l_poa_pvt->auth_certs_count; j++) { if (!dap_cert_compare_with_sign( l_poa_pvt->auth_certs[j], l_sign) - && !dap_sign_verify(l_sign, a_event, l_offset_from_beginning)){ + && !dap_sign_verify(l_sign, l_event, l_offset_from_beginning)){ l_signs_verified_count++; break; } } } - a_event->header.signs_count = l_event_signs_count; DAP_DELETE(l_signs); + if (a_dag->chain->is_mapped) + DAP_DELETE(l_event); + else + a_event->header.signs_count = l_event_signs_count; if (l_signs_verified_count >= l_certs_count_verify) return 0; } diff --git a/modules/consensus/esbocs/dap_chain_cs_esbocs.c b/modules/consensus/esbocs/dap_chain_cs_esbocs.c index 73831b057d33c6f12f87554f51ce29027feea018..f181e5c9ba03ccffe74144f8968a33bf1c55b803 100644 --- a/modules/consensus/esbocs/dap_chain_cs_esbocs.c +++ b/modules/consensus/esbocs/dap_chain_cs_esbocs.c @@ -2846,7 +2846,10 @@ static int s_callback_block_verify(dap_chain_cs_blocks_t *a_blocks, dap_chain_bl bool l_block_is_emergency = s_block_is_emergency(a_block, l_block_size); // Get the header on signing operation time size_t l_block_original = a_block->hdr.meta_n_datum_n_signs_size; - a_block->hdr.meta_n_datum_n_signs_size = l_block_excl_sign_size - sizeof(a_block->hdr); + dap_chain_block_t *l_block = a_blocks->chain->is_mapped + ? DAP_DUP_SIZE(a_block, l_block_size) + : a_block; + l_block->hdr.meta_n_datum_n_signs_size = l_block_excl_sign_size - sizeof(l_block->hdr); for (size_t i = 0; i < l_signs_count; i++) { dap_sign_t *l_sign = l_signs[i]; dap_chain_addr_t l_signing_addr = { .net_id = a_blocks->chain->net_id }; @@ -2882,7 +2885,7 @@ static int s_callback_block_verify(dap_chain_cs_blocks_t *a_blocks, dap_chain_bl l_ret = -5; break; } else if (l_esbocs_pvt->check_signs_structure && - !s_check_signing_rights(l_esbocs, a_block, l_block_size, &l_signing_addr, true)) { + !s_check_signing_rights(l_esbocs, l_block, l_block_size, &l_signing_addr, true)) { if (l_esbocs_pvt->debug) { char l_block_hash_str[DAP_HASH_FAST_STR_SIZE]; dap_hash_fast_to_str(a_block_hash, l_block_hash_str, DAP_HASH_FAST_STR_SIZE); @@ -2894,7 +2897,7 @@ static int s_callback_block_verify(dap_chain_cs_blocks_t *a_blocks, dap_chain_bl } else { if (l_block_is_emergency && !s_check_emergency_rights(l_esbocs, &l_signing_addr) && l_esbocs_pvt->check_signs_structure && - !s_check_signing_rights(l_esbocs, a_block, l_block_size, &l_signing_addr, false)) { + !s_check_signing_rights(l_esbocs, l_block, l_block_size, &l_signing_addr, false)) { if (l_esbocs_pvt->debug) { char l_block_hash_str[DAP_HASH_FAST_STR_SIZE]; dap_hash_fast_to_str(a_block_hash, l_block_hash_str, DAP_HASH_FAST_STR_SIZE); @@ -2903,7 +2906,7 @@ static int s_callback_block_verify(dap_chain_cs_blocks_t *a_blocks, dap_chain_bl l_ret = -5; break; } else if (l_esbocs_pvt->check_signs_structure && - !s_check_signing_rights(l_esbocs, a_block, l_block_size, &l_signing_addr, false)) { + !s_check_signing_rights(l_esbocs, l_block, l_block_size, &l_signing_addr, false)) { if (l_esbocs_pvt->debug) { char l_block_hash_str[DAP_HASH_FAST_STR_SIZE]; dap_hash_fast_to_str(a_block_hash, l_block_hash_str, DAP_HASH_FAST_STR_SIZE); @@ -2913,13 +2916,15 @@ static int s_callback_block_verify(dap_chain_cs_blocks_t *a_blocks, dap_chain_bl break; } } - if (!dap_sign_verify(l_sign, a_block, l_block_excl_sign_size)) + if (!dap_sign_verify(l_sign, l_block, l_block_excl_sign_size)) l_signs_verified_count++; } DAP_DELETE(l_signs); // Restore the original header - a_block->hdr.meta_n_datum_n_signs_size = l_block_original; - + if ( a_blocks->chain->is_mapped ) + DAP_DELETE(l_block); + else + l_block->hdr.meta_n_datum_n_signs_size = l_block_original; if (l_signs_verified_count < l_esbocs_pvt->min_validators_count) { debug_if(l_esbocs_pvt->debug, L_ERROR, "Corrupted block %s: not enough authorized signs: %u of %u", dap_hash_fast_to_str_static(a_block_hash), l_signs_verified_count, l_esbocs_pvt->min_validators_count); diff --git a/modules/net/dap_chain_ledger.c b/modules/net/dap_chain_ledger.c index 71328097945b49122c491ca4493a4895a4a691df..028edd4b972c85e29ada0c945065c44ea4c200ed 100644 --- a/modules/net/dap_chain_ledger.c +++ b/modules/net/dap_chain_ledger.c @@ -674,7 +674,10 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain } if (!a_apply) break; + uint256_t l_supply_delta = {}; + SUBTRACT_256_256(l_new_supply, a_item_apply_to->total_supply, &l_supply_delta); a_item_apply_to->total_supply = l_new_supply; + SUM_256_256(a_item_apply_to->current_supply, l_supply_delta, &a_item_apply_to->current_supply); } break; // Allowed tx receiver addres list add, remove or clear diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c index a877f86191557ef0f3b15c9a2519903addb30e95..0e8d86b71216119c79d212dc8ba7b5dfae356e54 100644 --- a/modules/net/dap_chain_net.c +++ b/modules/net/dap_chain_net.c @@ -210,6 +210,7 @@ static void s_link_manager_callback_error(dap_link_t *a_link, uint64_t a_net_id, static bool s_link_manager_callback_disconnected(dap_link_t *a_link, uint64_t a_net_id, int a_links_count); static int s_link_manager_fill_net_info(dap_link_t *a_link); static int s_link_manager_link_request(uint64_t a_net_id); +static int s_link_manager_link_count_changed(); static const dap_link_manager_callbacks_t s_link_manager_callbacks = { .connected = s_link_manager_callback_connected, @@ -217,6 +218,7 @@ static const dap_link_manager_callbacks_t s_link_manager_callbacks = { .error = s_link_manager_callback_error, .fill_net_info = s_link_manager_fill_net_info, .link_request = s_link_manager_link_request, + .link_count_changed = s_link_manager_link_count_changed, }; // State machine switchs here @@ -413,14 +415,6 @@ static void s_link_manager_callback_connected(dap_link_t *a_link, uint64_t a_net log_it(L_NOTICE, "Established connection with %s."NODE_ADDR_FP_STR,l_net->pub.name, NODE_ADDR_FP_ARGS_S(a_link->addr)); - struct json_object *l_json = dap_chain_net_states_json_collect(l_net); - char l_err_str[128] = { }; - snprintf(l_err_str, sizeof(l_err_str) - , "Established connection with link " NODE_ADDR_FP_STR - , NODE_ADDR_FP_ARGS_S(a_link->addr)); - json_object_object_add(l_json, "errorMessage", json_object_new_string(l_err_str)); - dap_notify_server_send_mt(json_object_get_string(l_json)); - json_object_put(l_json); if(l_net_pvt->state == NET_STATE_LINKS_CONNECTING ){ l_net_pvt->state = NET_STATE_LINKS_ESTABLISHED; } @@ -521,6 +515,15 @@ int s_link_manager_link_request(uint64_t a_net_id) return dap_worker_exec_callback_on(dap_worker_get_auto(), dap_chain_net_balancer_request, l_arg), 0; } +static int s_link_manager_link_count_changed() +{ + struct json_object *l_json = dap_chain_nets_info_json_collect(); + json_object_object_add(l_json, "errorMessage", json_object_new_string(" ")); // regular notify has no error + dap_notify_server_send_mt(json_object_get_string(l_json)); + json_object_put(l_json); + return 0; +} + struct request_link_info *s_get_permanent_link_info(dap_chain_net_t *a_net, dap_chain_node_addr_t *a_address) { dap_chain_net_pvt_t *l_net_pvt = PVT(a_net); @@ -679,6 +682,22 @@ static void s_net_states_notify(dap_chain_net_t *a_net) json_object_put(l_json); } +/** + * @brief s_net_states_notify + * @param l_net + */ +static bool s_net_states_notify_timer_callback(UNUSED_ARG void *a_arg) +{ + for (dap_chain_net_t *net = s_nets_by_name; net; net = net->hh.next) { + struct json_object *l_json = dap_chain_net_states_json_collect(net); + json_object_object_add(l_json, "errorMessage", json_object_new_string(" ")); // regular notify has no error + dap_notify_server_send_mt(json_object_get_string(l_json)); + json_object_put(l_json); + } + + return true; +} + /** * @brief dap_chain_net_get_role * @param a_net @@ -783,6 +802,7 @@ bool s_net_disk_load_notify_callback(UNUSED_ARG void *a_arg) { json_object_object_add(json_obj, "nets", l_jobj_nets); dap_notify_server_send_mt(json_object_get_string(json_obj)); json_object_put(json_obj); + s_net_states_notify_timer_callback(NULL); return true; } diff --git a/modules/net/dap_chain_net_anchor.c b/modules/net/dap_chain_net_anchor.c index ebc9dedc274d6941d40fd49d366fc91c9f20c97f..c11d222d4ca37f47826c81e94744caa28c81262d 100644 --- a/modules/net/dap_chain_net_anchor.c +++ b/modules/net/dap_chain_net_anchor.c @@ -82,26 +82,31 @@ static int s_anchor_verify(dap_chain_net_t *a_net, dap_chain_datum_anchor_t *a_a return log_it(L_WARNING, "No unique signatures!"), -106; bool l_sign_authorized = false; size_t l_signs_size_original = a_anchor->header.signs_size; - a_anchor->header.signs_size = 0; + dap_chain_datum_anchor_t *l_anchor = a_net->pub.chains->is_mapped + ? DAP_DUP_SIZE(a_anchor, a_data_size) + : a_anchor; + l_anchor->header.signs_size = 0; for (size_t i = 0; i < l_num_of_unique_signs; i++) { dap_chain_net_decree_t *l_net_decree = dap_chain_net_get_net_decree(a_net); for (dap_list_t *it = l_net_decree->pkeys; it; it = it->next) { if (dap_pkey_compare_with_sign(it->data, l_unique_signs[i])) { // TODO make signs verification in s_concate_all_signs_in_array to correctly header.signs_size calculation - size_t l_verify_data_size = a_anchor->header.data_size + sizeof(dap_chain_datum_anchor_t); - if (dap_sign_verify_all(l_unique_signs[i], l_signs_size_original, a_anchor, l_verify_data_size)) + size_t l_verify_data_size = l_anchor->header.data_size + sizeof(dap_chain_datum_anchor_t); + if (dap_sign_verify_all(l_unique_signs[i], l_signs_size_original, l_anchor, l_verify_data_size)) continue; l_sign_authorized = true; break; } } - a_anchor->header.signs_size += dap_sign_get_size(l_unique_signs[i]); + l_anchor->header.signs_size += dap_sign_get_size(l_unique_signs[i]); if (l_sign_authorized) break; } DAP_DELETE(l_unique_signs); - a_anchor->header.signs_size = l_signs_size_original; - + if ( a_net->pub.chains->is_mapped ) + DAP_DELETE(l_anchor); + else + l_anchor->header.signs_size = l_signs_size_original; if (!l_sign_authorized) { log_it(L_WARNING, "Anchor signs verify failed"); return -108; diff --git a/modules/net/dap_chain_net_balancer.c b/modules/net/dap_chain_net_balancer.c index a215cfa4b85e8b584e495a26eb3c933836062950..c9235a873bab26cb5624c53caa73de5fb1c8abc9 100644 --- a/modules/net/dap_chain_net_balancer.c +++ b/modules/net/dap_chain_net_balancer.c @@ -149,10 +149,6 @@ static void s_balancer_link_prepare_success(dap_chain_net_t* a_net, dap_chain_ne if (dap_chain_net_link_add(a_net, &l_link_info->node_addr, l_link_info->uplink_addr, l_link_info->uplink_port)) continue; l_json = s_balancer_states_json_collect(a_net, a_host_addr, a_host_port); - snprintf(l_err_str, sizeof(l_err_str) - , "Link " NODE_ADDR_FP_STR " prepared" - , NODE_ADDR_FP_ARGS_S(l_link_info->node_addr)); - json_object_object_add(l_json, "errorMessage", json_object_new_string(l_err_str)); dap_notify_server_send_mt(json_object_get_string(l_json)); json_object_put(l_json); } diff --git a/modules/net/dap_chain_net_decree.c b/modules/net/dap_chain_net_decree.c index ff0023527ee8a42261e98185fa31849a4586ee5e..92efb30620732e0d54484dec0cfa515178908e0f 100644 --- a/modules/net/dap_chain_net_decree.c +++ b/modules/net/dap_chain_net_decree.c @@ -154,13 +154,13 @@ static int s_decree_verify(dap_chain_net_t *a_net, dap_chain_datum_decree_t *a_d // Find unique pkeys in pkeys set from previous step and check that number of signs > min size_t l_num_of_unique_signs = 0; dap_sign_t **l_unique_signs = dap_sign_get_unique_signs(l_signs_block, l_signs_size, &l_num_of_unique_signs); - dap_chain_net_decree_t *l_decree = dap_chain_net_get_net_decree(a_net); - if (!l_decree) { + dap_chain_net_decree_t *l_net_decree = dap_chain_net_get_net_decree(a_net); + if (!l_net_decree) { log_it(L_ERROR, "Decree module hasn't been initialized yet"); return -404; } - uint16_t l_min_signs = l_decree->min_num_of_owners; + uint16_t l_min_signs = l_net_decree->min_num_of_owners; if (l_num_of_unique_signs < l_min_signs) { log_it(L_WARNING, "Not enough unique signatures, get %zu from %hu", l_num_of_unique_signs, l_min_signs); return -106; @@ -168,32 +168,33 @@ static int s_decree_verify(dap_chain_net_t *a_net, dap_chain_datum_decree_t *a_d // Verify all keys and its signatures uint16_t l_signs_size_for_current_sign = 0, l_signs_verify_counter = 0; - a_decree->header.signs_size = 0; - size_t l_verify_data_size = a_decree->header.data_size + sizeof(dap_chain_datum_decree_t); + dap_chain_datum_decree_t *l_decree = a_net->pub.chains->is_mapped + ? DAP_DUP_SIZE(a_decree, a_data_size) + : a_decree; + l_decree->header.signs_size = 0; + size_t l_verify_data_size = l_decree->header.data_size + sizeof(dap_chain_datum_decree_t); for (size_t i = 0; i < l_num_of_unique_signs; i++) { size_t l_sign_max_size = dap_sign_get_size(l_unique_signs[i]); if (s_verify_pkey(l_unique_signs[i], a_net)) { // 3. verify sign - if(!dap_sign_verify_all(l_unique_signs[i], l_sign_max_size, a_decree, l_verify_data_size)) + if(!dap_sign_verify_all(l_unique_signs[i], l_sign_max_size, l_decree, l_verify_data_size)) l_signs_verify_counter++; } else { dap_hash_fast_t l_sign_pkey_hash = {0}; size_t l_pkey_size = 0; uint8_t *l_pkey = dap_sign_get_pkey(l_unique_signs[i], &l_pkey_size); - dap_hash_fast(l_pkey, l_pkey_size, &l_sign_pkey_hash); - char *l_sign_hash_str = dap_hash_fast_to_str_new(&l_sign_pkey_hash); - log_it(L_WARNING, "Signature [%zu] %s failed public key verification.", i, l_sign_hash_str); - DAP_DELETE(l_sign_hash_str); + log_it(L_WARNING, "Signature [%zu] %s failed public key verification.", i, dap_get_data_hash_str(l_pkey, l_pkey_size).s); } // Each sign change the sign_size field by adding its size after signing. So we need to change this field in header for each sign. l_signs_size_for_current_sign += l_sign_max_size; - a_decree->header.signs_size = l_signs_size_for_current_sign; + l_decree->header.signs_size = l_signs_size_for_current_sign; } - a_decree->header.signs_size = l_signs_size; - -// DAP_DELETE(l_signs_arr); + if ( a_net->pub.chains->is_mapped ) + DAP_DELETE(l_decree); + else + l_decree->header.signs_size = l_signs_size; DAP_DELETE(l_unique_signs); if (l_signs_verify_counter < l_min_signs) { @@ -373,6 +374,19 @@ static int s_common_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain switch (a_decree->header.sub_type) { case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_FEE: + // if (dap_chain_datum_decree_get_fee_addr(a_decree, &l_addr)) { + // if (dap_chain_addr_is_blank(&a_net->pub.fee_addr)) { + // log_it(L_WARNING, "Fee wallet address not set."); + // return -111; + // } else + // l_addr = a_net->pub.fee_addr; + // } + if (dap_chain_datum_decree_get_fee(a_decree, &l_value)) { + log_it(L_WARNING,"Can't get fee value from decree."); + return -103; + } + if (!a_anchored) + break; if (dap_chain_datum_decree_get_fee_addr(a_decree, &l_addr)) { if (dap_chain_addr_is_blank(&a_net->pub.fee_addr)) { log_it(L_WARNING, "Fee wallet address not set."); @@ -380,10 +394,6 @@ static int s_common_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain } else l_addr = a_net->pub.fee_addr; } - if (dap_chain_datum_decree_get_fee(a_decree, &l_value)) { - log_it(L_WARNING,"Can't get fee value from decree."); - return -103; - } if (!a_apply) break; if (!dap_chain_net_tx_set_fee(a_net->pub.id, l_value, l_addr)) diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c index ab7eee0ea539d22885b7bca9800ef97fcd2c8ec8..1b03e1f25bceb493ba60a74ad7a29e9263175d87 100644 --- a/modules/net/dap_chain_node_cli_cmd.c +++ b/modules/net/dap_chain_node_cli_cmd.c @@ -104,11 +104,13 @@ #include "dap_json_rpc_request.h" #include "dap_client_pvt.h" #include "dap_enc.h" - +#include "dap_notify_srv.h" #define LOG_TAG "chain_node_cli_cmd" int _cmd_mempool_add_ca(dap_chain_net_t *a_net, dap_chain_t *a_chain, dap_cert_t *a_cert, void **a_str_reply); +static void s_new_wallet_info_notify(const char *a_wallet_name); +struct json_object *wallet_list_json_collect(); dap_chain_t *s_get_chain_with_datum(dap_chain_net_t *a_net, const char *a_datum_hash) { dap_chain_t *l_chain = NULL; @@ -1741,7 +1743,19 @@ int l_arg_index = 1, l_rc, cmd_num = CMD_NONE; return DAP_CHAIN_NODE_CLI_COM_TX_WALLET_NET_PARAM_ERR; } l_wallet = dap_chain_wallet_open(l_wallet_name, c_wallets_path, NULL); + if (!l_wallet){ + dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_TX_WALLET_NET_PARAM_ERR, + "Can't find wallet (%s)", l_wallet_name); + json_object_put(json_arr_out); + return DAP_CHAIN_NODE_CLI_COM_TX_WALLET_NET_PARAM_ERR; + } l_addr = (dap_chain_addr_t *) dap_chain_wallet_get_addr(l_wallet, l_net->pub.id ); + if (!l_addr){ + dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_TX_WALLET_NET_PARAM_ERR, + "Can't get addr from wallet (%s)", l_wallet_name); + json_object_put(json_arr_out); + return DAP_CHAIN_NODE_CLI_COM_TX_WALLET_NET_PARAM_ERR; + } } else { l_addr = dap_chain_addr_from_str(l_addr_str); } @@ -1763,28 +1777,37 @@ int l_arg_index = 1, l_rc, cmd_num = CMD_NONE; uint256_t l_value_sum = uint256_0; if (l_value_str){ uint256_t l_value_datoshi = dap_chain_balance_scan(l_value_str); - l_outs_list = dap_ledger_get_list_tx_outs_with_val(l_net->pub.ledger, l_token_tiker, l_addr, l_value_datoshi, &l_value_sum); + if (dap_chain_wallet_cache_tx_find_outs_with_val(l_net, l_token_tiker, l_addr, &l_outs_list, l_value_datoshi, &l_value_sum)) + l_outs_list = dap_ledger_get_list_tx_outs_with_val(l_net->pub.ledger, l_token_tiker, l_addr, l_value_datoshi, &l_value_sum); } else { - l_outs_list = dap_ledger_get_list_tx_outs(l_net->pub.ledger, l_token_tiker, l_addr, &l_value_sum); - } - - json_object_object_add(json_obj_wall, "total_value", json_object_new_string(dap_uint256_to_char(l_value_sum, NULL))); + if (dap_chain_wallet_cache_tx_find_outs(l_net, l_token_tiker, l_addr, &l_outs_list, &l_value_sum)) + l_outs_list = dap_ledger_get_list_tx_outs(l_net->pub.ledger, l_token_tiker, l_addr, &l_value_sum); + } + json_object_object_add(json_obj_wall, "wallet_addr", json_object_new_string(dap_chain_addr_to_str_static(l_addr))); + const char *l_out_total_value_str = dap_chain_balance_print(l_value_sum); + const char *l_out_total_value_coins_str = dap_chain_balance_to_coins(l_value_sum); + json_object_object_add(json_obj_wall, "total_value_coins", json_object_new_string(l_out_total_value_coins_str)); + json_object_object_add(json_obj_wall, "total_value_datoshi", json_object_new_string(l_out_total_value_str)); + DAP_DEL_Z(l_out_total_value_str); + DAP_DEL_Z(l_out_total_value_coins_str); struct json_object *l_json_outs_arr = json_object_new_array(); for (dap_list_t *l_temp = l_outs_list; l_temp; l_temp = l_temp->next){ dap_chain_tx_used_out_item_t *l_item = l_temp->data; json_object* json_obj_item = json_object_new_object(); - const char *l_out_value_str = dap_uint256_to_char(l_item->value, NULL); + const char *l_out_value_str = dap_chain_balance_print(l_item->value); + const char *l_out_value_coins_str = dap_chain_balance_to_coins(l_item->value); json_object_object_add(json_obj_item,"item_type", json_object_new_string("unspent_out")); - json_object_object_add(json_obj_item,"value", json_object_new_string(l_out_value_str)); + json_object_object_add(json_obj_item,"value_coins", json_object_new_string(l_out_value_coins_str)); + json_object_object_add(json_obj_item,"value_datosi", json_object_new_string(l_out_value_str)); json_object_object_add(json_obj_item,"prev_hash", json_object_new_string(dap_hash_fast_to_str_static(&l_item->tx_hash_fast))); json_object_object_add(json_obj_item,"out_prev_idx", json_object_new_int64(l_item->num_idx_out)); json_object_array_add(l_json_outs_arr, json_obj_item); + DAP_DEL_Z(l_out_value_str); + DAP_DEL_Z(l_out_value_coins_str); } dap_list_free_full(l_outs_list, NULL); json_object_object_add(json_obj_wall, "outs", l_json_outs_arr); json_object_array_add(json_arr_out, json_obj_wall); - - } break; default: { if( !l_wallet_name ) { @@ -1823,6 +1846,11 @@ int l_arg_index = 1, l_rc, cmd_num = CMD_NONE; json_object_object_add(json_obj_wall, "Wallet name", json_object_new_string(l_wallet_name)); json_object_object_add(json_obj_wall, "protection", cmd_num == CMD_WALLET_ACTIVATE ? json_object_new_string("is activated") : json_object_new_string("is deactivated")); + // Notify about wallet + s_new_wallet_info_notify(l_wallet_name); + struct json_object *l_json_wallets = wallet_list_json_collect(); + dap_notify_server_send_mt(json_object_get_string(l_json_wallets)); + json_object_put(l_json_wallets); break; case -EBUSY: dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_TX_WALLET_ALREADY_ERR, @@ -1909,6 +1937,12 @@ int l_arg_index = 1, l_rc, cmd_num = CMD_NONE; json_object_object_add(json_obj_wall, "Status", json_object_new_string("successfully converted")); dap_chain_wallet_close(l_wallet); json_object_array_add(json_arr_out, json_obj_wall); + + // Notify about wallet + s_new_wallet_info_notify(l_wallet_name); + struct json_object *l_json_wallets = wallet_list_json_collect(); + dap_notify_server_send_mt(json_object_get_string(l_json_wallets)); + json_object_put(l_json_wallets); break; } // new wallet @@ -2053,6 +2087,11 @@ int l_arg_index = 1, l_rc, cmd_num = CMD_NONE; } json_object_array_add(json_arr_out, json_obj_wall); dap_chain_wallet_close(l_wallet); + // Notify about wallet + s_new_wallet_info_notify(l_wallet_name); + struct json_object *l_json_wallets = wallet_list_json_collect(); + dap_notify_server_send_mt(json_object_get_string(l_json_wallets)); + json_object_put(l_json_wallets); break; } } @@ -6084,6 +6123,7 @@ int com_tx_create_json(int a_argc, char ** a_argv, void **a_json_arr_reply) const char *l_json_str = NULL; const char *l_native_token = NULL; const char *l_main_token = NULL; + bool l_multichanel = false; dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-net", &l_net_name); // optional parameter dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-chain", &l_chain_name); // optional parameter @@ -6188,11 +6228,41 @@ int com_tx_create_json(int a_argc, char ** a_argv, void **a_json_arr_reply) size_t l_items_ready = 0; dap_list_t *l_sign_list = NULL;// list 'sing' items dap_list_t *l_in_list = NULL;// list 'in' items - // dap_list_t *l_tsd_list = NULL;// list tsd sections uint256_t l_value_need = { };// how many tokens are needed in the 'out' item uint256_t l_value_need_fee = {}; json_object *l_jobj_errors = json_object_new_array(); -// dap_string_t *l_err_str = dap_string_new("Errors: \n"); + // First iteration in input file. Check the tx will be multichannel or not + for(size_t i = 0; i < l_items_count; ++i) { + struct json_object *l_json_item_obj = json_object_array_get_idx(l_json_items, i); + if(!l_json_item_obj || !json_object_is_type(l_json_item_obj, json_type_object)) { + continue; + } + struct json_object *l_json_item_type = json_object_object_get(l_json_item_obj, "type"); + if(!l_json_item_type && json_object_is_type(l_json_item_type, json_type_string)) { + log_it(L_WARNING, "Item %zu without type", i); + continue; + } + const char *l_item_type_str = json_object_get_string(l_json_item_type); + dap_chain_tx_item_type_t l_item_type = dap_chain_datum_tx_item_str_to_type(l_item_type_str); + if(l_item_type == TX_ITEM_TYPE_UNKNOWN) { + log_it(L_WARNING, "Item %zu has invalid type '%s'", i, l_item_type_str); + continue; + } + + switch (l_item_type) { + case TX_ITEM_TYPE_IN: { + const char *l_json_item_token = s_json_get_text(l_json_item_obj, "token"); + if (l_json_item_token && dap_strcmp(l_json_item_token, l_native_token)){ + l_multichanel = true; + l_main_token = l_json_item_token; + } + }break; + default: continue; + } + if(l_multichanel) + break; + } + // Creating and adding items to the transaction for(size_t i = 0; i < l_items_count; ++i) { struct json_object *l_json_item_obj = json_object_array_get_idx(l_json_items, i); @@ -6253,44 +6323,59 @@ int com_tx_create_json(int a_argc, char ** a_argv, void **a_json_arr_reply) uint256_t l_value = { }; const char *l_json_item_addr_str = s_json_get_text(l_json_item_obj, "addr"); bool l_is_value = s_json_get_uint256(l_json_item_obj, "value", &l_value); + const char *l_token = s_json_get_text(l_json_item_obj, "token"); if(l_is_value && l_json_item_addr_str) { dap_chain_addr_t *l_addr = dap_chain_addr_from_str(l_json_item_addr_str); if(l_addr && !IS_ZERO_256(l_value)) { if(l_item_type == TX_ITEM_TYPE_OUT) { // Create OUT item - dap_chain_tx_out_t *l_out_item = dap_chain_datum_tx_item_out_create(l_addr, l_value); + const uint8_t *l_out_item = NULL; + if(l_multichanel) + l_out_item = (const uint8_t *)dap_chain_datum_tx_item_out_ext_create(l_addr, l_value, l_token ? l_token : (l_main_token ? l_main_token : l_native_token)); + else + l_out_item = (const uint8_t *)dap_chain_datum_tx_item_out_create(l_addr, l_value); if (!l_out_item) { json_object *l_jobj_err = json_object_new_string("Failed to create transaction out. " "There may not be enough funds in the wallet."); json_object_array_add(l_jobj_errors, l_jobj_err); } l_item = (const uint8_t*) l_out_item; - } - else if(l_item_type == TX_ITEM_TYPE_OUT_EXT) { + if (l_item){ + if (l_multichanel && !dap_strcmp(((dap_chain_tx_out_ext_t*)l_out_item)->token, l_native_token)) + SUM_256_256(l_value_need_fee, l_value, &l_value_need_fee); + else + SUM_256_256(l_value_need, l_value, &l_value_need); + } + + } else if(l_item_type == TX_ITEM_TYPE_OUT_EXT) { // Read address and value - const char *l_token = s_json_get_text(l_json_item_obj, "token"); - l_main_token = l_token; if(l_token) { // Create OUT_EXT item - dap_chain_tx_out_ext_t *l_out_ext_item = dap_chain_datum_tx_item_out_ext_create(l_addr, l_value, l_token); - if (!l_out_ext_item) { + const uint8_t *l_out_item = NULL; + if(l_multichanel) + l_out_item = (const uint8_t *)dap_chain_datum_tx_item_out_ext_create(l_addr, l_value, l_token); + else + l_out_item = (const uint8_t *)dap_chain_datum_tx_item_out_create(l_addr, l_value); + if (!l_out_item) { json_object *l_jobj_err = json_object_new_string("Failed to create a out ext" "for a transaction. There may not be enough funds " "on the wallet or the wrong ticker token " "is indicated."); json_object_array_add(l_jobj_errors, l_jobj_err); } - l_item = (const uint8_t*) l_out_ext_item; + l_item = (const uint8_t*) l_out_item; + if (l_item){ + if (l_multichanel && !dap_strcmp(l_token, l_native_token)) + SUM_256_256(l_value_need_fee, l_value, &l_value_need_fee); + else + SUM_256_256(l_value_need, l_value, &l_value_need); + } } else { log_it(L_WARNING, "Invalid 'out_ext' item %zu", i); continue; } } - // Save value for using in In item - if(l_item) { - SUM_256_256(l_value_need, l_value, &l_value_need); - } } else { if(l_item_type == TX_ITEM_TYPE_OUT) { log_it(L_WARNING, "Invalid 'out' item %zu", i); @@ -6736,7 +6821,10 @@ int com_tx_create_json(int a_argc, char ** a_argv, void **a_json_arr_reply) uint256_t l_value_back; SUBTRACT_256_256(l_value_got, l_value_need, &l_value_back); if(!IS_ZERO_256(l_value_back)) { - dap_chain_datum_tx_add_out_item(&l_tx, l_addr_from, l_value_back); + if (l_multichanel) + dap_chain_datum_tx_add_out_ext_item(&l_tx, l_addr_from, l_value_back, l_main_token); + else + dap_chain_datum_tx_add_out_item(&l_tx, l_addr_from, l_value_back); l_items_ready++; } } @@ -8611,6 +8699,17 @@ void dap_notify_new_client_send_info(dap_events_socket_t *a_es, UNUSED_ARG void } } +static void s_new_wallet_info_notify(const char *a_wallet_name) +{ + struct json_object *l_json = json_object_new_object(); + json_object_object_add(l_json, "class", json_object_new_string("WalletInfo")); + struct json_object *l_json_wallet_info = json_object_new_object(); + json_object_object_add(l_json_wallet_info, a_wallet_name, dap_chain_wallet_info_to_json(a_wallet_name, dap_chain_wallet_get_path(g_config))); + json_object_object_add(l_json, "wallet", l_json_wallet_info); + dap_notify_server_send_mt(json_object_get_string(l_json)); + json_object_put(l_json); +} + static void s_stage_connected_callback(dap_client_t* a_client, void * a_arg) { dap_chain_node_client_t *l_node_client = DAP_CHAIN_NODE_CLIENT(a_client); UNUSED(a_arg); diff --git a/modules/service/bridge/dap_chain_net_srv_bridge.c b/modules/service/bridge/dap_chain_net_srv_bridge.c index 439d0556d046e6b02be8511127dc2a2944e1a82c..04d696727c03f152d7a5773d78e241d6b23aec59 100644 --- a/modules/service/bridge/dap_chain_net_srv_bridge.c +++ b/modules/service/bridge/dap_chain_net_srv_bridge.c @@ -135,14 +135,38 @@ static bool s_tag_check_bridge(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_t //crosschain bridge AUTH emissions - if (!a_items_grp->items_in_ems) + if (a_items_grp->items_in_ems){ + dap_chain_tx_in_ems_t *l_tx_in_ems = a_items_grp->items_in_ems->data; + dap_hash_fast_t ems_hash = l_tx_in_ems->header.token_emission_hash; + dap_chain_datum_token_emission_t *l_emission = dap_ledger_token_emission_find(a_ledger, &ems_hash); + if(l_emission) + return s_get_ems_bridge_action(l_emission, a_action); + } + + if (!a_items_grp->items_tsd) return false; - dap_chain_tx_in_ems_t *l_tx_in_ems = a_items_grp->items_in_ems->data; - dap_hash_fast_t ems_hash = l_tx_in_ems->header.token_emission_hash; - dap_chain_datum_token_emission_t *l_emission = dap_ledger_token_emission_find(a_ledger, &ems_hash); - if(l_emission) - return s_get_ems_bridge_action(l_emission, a_action); + bool src_bridge = false; + bool subtype_out = false; + for (dap_list_t *it = a_items_grp->items_tsd; it; it = it->next) { + dap_chain_tx_tsd_t *l_tx_tsd = it->data; + int l_type; + size_t l_size; + byte_t *l_data = dap_chain_datum_tx_item_get_data(l_tx_tsd, &l_type, &l_size); + + + if (l_type == DAP_CHAIN_DATUM_EMISSION_TSD_TYPE_SOURCE && s_tsd_str_cmp(l_data, l_size, DAP_CHAIN_DATUM_TOKEN_EMISSION_SOURCE_BRIDGE) == 0) + src_bridge = true; + + if (l_type == DAP_CHAIN_DATUM_EMISSION_TSD_TYPE_SOURCE_SUBTYPE && s_tsd_str_cmp(l_data, l_size, DAP_CHAIN_DATUM_TOKEN_EMISSION_SOURCE_SUBTYPE_BRIDGE_OUT) == 0) + subtype_out = true; + } + if (src_bridge && subtype_out) + { + if(a_action) *a_action = DAP_CHAIN_TX_TAG_ACTION_CLOSE; + return true; + } + return false; } diff --git a/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c b/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c index b9a9b5772e807bbe08fa085797efe4c5afc4b8ea..5494b0ee718bac1e07545f504e1d01572a2bc551 100644 --- a/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c +++ b/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c @@ -33,6 +33,7 @@ #include "dap_chain_net_srv_emit_delegate.h" #include "dap_chain_node_cli_cmd.h" + enum emit_delegation_error { DAP_NO_ERROR = 0, ERROR_MEMORY, @@ -287,7 +288,7 @@ static bool s_is_key_present(dap_chain_tx_out_cond_t *a_cond, dap_enc_key_t *a_e return false; } -static dap_chain_datum_tx_t *s_taking_tx_create(json_object *a_json_arr_reply, dap_chain_net_t *a_net, dap_enc_key_t *a_enc_key, +dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_create(json_object *a_json_arr_reply, dap_chain_net_t *a_net, dap_enc_key_t *a_enc_key, dap_chain_addr_t *a_addr_to, uint256_t a_value, uint256_t a_fee, dap_hash_fast_t *a_tx_in_hash) { // create empty transaction @@ -355,7 +356,8 @@ static dap_chain_datum_tx_t *s_taking_tx_create(json_object *a_json_arr_reply, d if (!l_out_cond) m_tx_fail(ERROR_COMPOSE, c_error_memory_alloc); l_out_cond->header.value = l_value_back; - dap_chain_datum_tx_add_item(&l_tx, (const uint8_t *)l_out_cond); + if (-1 == dap_chain_datum_tx_add_item(&l_tx, (const uint8_t *)l_out_cond)) + m_tx_fail(ERROR_COMPOSE, "Cant add emission cond output"); DAP_DELETE(l_out_cond); } @@ -390,7 +392,7 @@ static dap_chain_datum_tx_t *s_taking_tx_create(json_object *a_json_arr_reply, d #undef m_tx_fail -static dap_chain_datum_tx_t *s_taking_tx_sign(json_object *a_json_arr_reply, dap_chain_net_t *a_net, dap_enc_key_t *a_enc_key, dap_chain_datum_tx_t *a_tx_in) +dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_sign(json_object *a_json_arr_reply, dap_chain_net_t *a_net, dap_enc_key_t *a_enc_key, dap_chain_datum_tx_t *a_tx_in) { int l_cond_idx = 0; 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_EMIT_DELEGATE, &l_cond_idx); @@ -614,7 +616,7 @@ static int s_cli_take(int a_argc, char **a_argv, int a_arg_index, json_object ** return ERROR_VALUE; } // Create emission from conditional transaction - dap_chain_datum_tx_t *l_tx = s_taking_tx_create(*a_json_arr_reply, a_net, l_enc_key, l_addr, l_value, l_fee, &l_tx_in_hash); + dap_chain_datum_tx_t *l_tx = dap_chain_net_srv_emit_delegate_taking_tx_create(*a_json_arr_reply, a_net, l_enc_key, l_addr, l_value, l_fee, &l_tx_in_hash); DAP_DEL_MULTY(l_enc_key, l_addr); if (!l_tx) { dap_json_rpc_error_add(*a_json_arr_reply, ERROR_CREATE, "Can't compose transaction for delegated emission"); @@ -669,7 +671,7 @@ static int s_cli_sign(int a_argc, char **a_argv, int a_arg_index, json_object ** dap_chain_wallet_close(l_wallet); // Create emission from conditional transaction - dap_chain_datum_tx_t *l_tx = s_taking_tx_sign(*a_json_arr_reply, a_net, l_enc_key, (dap_chain_datum_tx_t *)l_tx_in->data); + dap_chain_datum_tx_t *l_tx = dap_chain_net_srv_emit_delegate_taking_tx_sign(*a_json_arr_reply, a_net, l_enc_key, (dap_chain_datum_tx_t *)l_tx_in->data); DAP_DELETE(l_enc_key); if (!l_tx) { dap_json_rpc_error_add(*a_json_arr_reply, ERROR_CREATE, "Can't compose transaction for delegated emission"); diff --git a/modules/service/emit-delegate/include/dap_chain_net_srv_emit_delegate.h b/modules/service/emit-delegate/include/dap_chain_net_srv_emit_delegate.h index bbe35ccf9121ce1f7a285bb72f98d181f3730b18..210f73c531198bce14b6c75f02408b10f2d9dc88 100644 --- a/modules/service/emit-delegate/include/dap_chain_net_srv_emit_delegate.h +++ b/modules/service/emit-delegate/include/dap_chain_net_srv_emit_delegate.h @@ -3,6 +3,15 @@ #define DAP_CHAIN_NET_SRV_EMIT_DELEGATE_ID 0x07 #define DAP_CHAIN_NET_SRV_EMIT_DELEGATE_TSD_WRITEOFF 0x14 +#include "dap_chain_datum_tx.h" +#include "dap_chain_mempool.h" + int dap_chain_net_srv_emit_delegate_init(); -void dap_chain_net_srv_bridge_deinit(); +void dap_chain_net_srv_emit_delegate_deinit(); + + +dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_create(json_object *a_json_arr_rweply, dap_chain_net_t *a_net, dap_enc_key_t *a_enc_key, + dap_chain_addr_t *a_addr_to, uint256_t a_value, uint256_t a_fee, dap_hash_fast_t *a_tx_in_hash); + +dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_sign(json_object *a_json_arr_reply, dap_chain_net_t *a_net, dap_enc_key_t *a_enc_key, dap_chain_datum_tx_t *a_tx_in); diff --git a/modules/type/blocks/dap_chain_cs_blocks.c b/modules/type/blocks/dap_chain_cs_blocks.c index 562d0455663f4e6b7692493c4af55dc94cc6f0d1..888beac875856f3e2f21503e50c0e06532d0f1fd 100644 --- a/modules/type/blocks/dap_chain_cs_blocks.c +++ b/modules/type/blocks/dap_chain_cs_blocks.c @@ -396,11 +396,7 @@ static char *s_blocks_decree_set_reward(dap_chain_net_t *a_net, dap_chain_t *a_c // Create decree size_t l_tsd_total_size = sizeof(dap_tsd_t) + sizeof(uint256_t); size_t l_decree_size = sizeof(dap_chain_datum_decree_t) + l_tsd_total_size; - dap_chain_datum_decree_t *l_decree = DAP_NEW_Z_SIZE(dap_chain_datum_decree_t, l_decree_size); - if (!l_decree) { - log_it(L_CRITICAL, "%s", c_error_memory_alloc); - return NULL; - } + dap_chain_datum_decree_t *l_decree = DAP_NEW_Z_SIZE_RET_VAL_IF_FAIL(dap_chain_datum_decree_t, l_decree_size, NULL); // Fill the header l_decree->decree_version = DAP_CHAIN_DATUM_DECREE_VERSION; l_decree->header.ts_created = dap_time_now(); diff --git a/modules/wallet/dap_chain_wallet.c b/modules/wallet/dap_chain_wallet.c index e972ea0a8e2fc24f2775a4e9c0a617fb55aa657b..6b4cdd3c08a2ef0d634da56b3f29fd9900a690bb 100644 --- a/modules/wallet/dap_chain_wallet.c +++ b/modules/wallet/dap_chain_wallet.c @@ -1185,12 +1185,12 @@ json_object *dap_chain_wallet_info_to_json(const char *a_name, const char *a_pat json_object_object_add(l_balance_data, "description", l_description ? json_object_new_string(l_description) : json_object_new_null()); - json_object_object_add(l_balance_data, "coin", json_object_new_string(l_balance_coins)); + json_object_object_add(l_balance_data, "coins", json_object_new_string(l_balance_coins)); json_object_object_add(l_balance_data, "datoshi", json_object_new_string(l_balance_datoshi)); json_object_array_add(l_arr_balance, l_balance_data); DAP_DELETE(l_addr_tokens[i]); } - json_object_object_add(l_jobj_net, "balance", l_arr_balance); + json_object_object_add(l_jobj_net, "tokens", l_arr_balance); DAP_DELETE(l_addr_tokens); } json_object_object_add(l_json_ret, "networks", l_jobj_network); diff --git a/modules/wallet/dap_chain_wallet_cache.c b/modules/wallet/dap_chain_wallet_cache.c index a0ef35e1ffc2bd7c5cff9c5542e6c7e2b3bbfa51..3b3f7ea6c07f0c22f54b27aae065251cb2eff6af 100644 --- a/modules/wallet/dap_chain_wallet_cache.c +++ b/modules/wallet/dap_chain_wallet_cache.c @@ -84,6 +84,7 @@ typedef struct dap_wallet_tx_cache { typedef struct dap_s_wallets_cache { dap_chain_addr_t wallet_addr; dap_wallet_tx_cache_t *wallet_txs; + _Atomic bool is_loading; UT_hash_handle hh; } dap_wallet_cache_t; @@ -92,7 +93,7 @@ typedef struct dap_atom_notify_arg { dap_chain_net_t *net; } dap_atom_notify_arg_t; -static dap_s_wallets_cache_type_t s_wallets_cache_type = DAP_WALLET_CACHE_TYPE_ALL; +static dap_s_wallets_cache_type_t s_wallets_cache_type = DAP_WALLET_CACHE_TYPE_LOCAL; static dap_wallet_cache_t *s_wallets_cache = NULL; static pthread_rwlock_t s_wallet_cache_rwlock; @@ -202,7 +203,7 @@ int dap_chain_wallet_cache_tx_find(dap_chain_addr_t *a_addr, char *a_token, dap_ pthread_rwlock_rdlock(&s_wallet_cache_rwlock); HASH_FIND(hh, s_wallets_cache, a_addr, sizeof(dap_chain_addr_t), l_wallet_item); - if (!l_wallet_item){ + if (!l_wallet_item || l_wallet_item->is_loading){ log_it(L_ERROR, "Can't find wallet with address %s", dap_chain_addr_to_str_static(a_addr)); pthread_rwlock_unlock(&s_wallet_cache_rwlock); return -101; @@ -290,7 +291,7 @@ int dap_chain_wallet_cache_tx_find_in_history(dap_chain_addr_t *a_addr, char **a pthread_rwlock_rdlock(&s_wallet_cache_rwlock); HASH_FIND(hh, s_wallets_cache, a_addr, sizeof(dap_chain_addr_t), l_wallet_item); - if (!l_wallet_item){ + if (!l_wallet_item || l_wallet_item->is_loading){ log_it(L_ERROR, "Can't find wallet with address %s", dap_chain_addr_to_str_static(a_addr)); pthread_rwlock_unlock(&s_wallet_cache_rwlock); return -101; @@ -382,7 +383,7 @@ int dap_chain_wallet_cache_tx_find_outs_with_val(dap_chain_net_t *a_net, const c dap_wallet_cache_t *l_wallet_item = NULL; pthread_rwlock_rdlock(&s_wallet_cache_rwlock); HASH_FIND(hh, s_wallets_cache, a_addr, sizeof(dap_chain_addr_t), l_wallet_item); - if (!l_wallet_item){ + if (!l_wallet_item || l_wallet_item->is_loading){ log_it(L_ERROR, "Can't find wallet with address %s", dap_chain_addr_to_str_static(a_addr)); pthread_rwlock_unlock(&s_wallet_cache_rwlock); return -101; @@ -497,6 +498,129 @@ int dap_chain_wallet_cache_tx_find_outs_with_val(dap_chain_net_t *a_net, const c return 0; } +int dap_chain_wallet_cache_tx_find_outs(dap_chain_net_t *a_net, const char *a_token_ticker, const dap_chain_addr_t *a_addr, + dap_list_t **a_outs_list, uint256_t *a_value_transfer) +{ + + dap_list_t *l_list_used_out = NULL; // list of transaction with 'out' items + uint256_t l_value_transfer = { }; + dap_chain_datum_tx_t *l_tx; + + if (!a_token_ticker){ + log_it(L_ERROR, "Token ticker is not specified."); + return -100; + } + + if(!a_addr || dap_chain_addr_is_blank(a_addr)){ + log_it(L_ERROR, "Wallet addr is not specified."); + return -100; + } + + if (a_outs_list == NULL){ + log_it(L_ERROR, "a_outs_list is NULL"); + return -100; + } + + dap_wallet_cache_t *l_wallet_item = NULL; + pthread_rwlock_rdlock(&s_wallet_cache_rwlock); + HASH_FIND(hh, s_wallets_cache, a_addr, sizeof(dap_chain_addr_t), l_wallet_item); + if (!l_wallet_item || l_wallet_item->is_loading){ + log_it(L_ERROR, "Can't find wallet with address %s", dap_chain_addr_to_str_static(a_addr)); + pthread_rwlock_unlock(&s_wallet_cache_rwlock); + return -101; + } + dap_wallet_tx_cache_t *l_current_wallet_tx = l_wallet_item->wallet_txs; + + // Go iterate wallet txs + dap_wallet_tx_cache_t *l_current_wallet_tx_iter = NULL, *l_tmp = NULL; + HASH_ITER(hh, l_current_wallet_tx, l_current_wallet_tx_iter, l_tmp) { + if (l_current_wallet_tx_iter->ret_code != DAP_LEDGER_CHECK_OK) + continue; + + + if (*l_current_wallet_tx_iter->token_ticker && + dap_strcmp(l_current_wallet_tx_iter->token_ticker, a_token_ticker) && + !l_current_wallet_tx_iter->multichannel) + continue; + else if (*l_current_wallet_tx_iter->token_ticker && dap_strcmp(l_current_wallet_tx_iter->token_ticker, a_token_ticker) && + l_current_wallet_tx_iter->multichannel){ + + bool skip = true; + for (dap_list_t *l_temp = l_current_wallet_tx_iter->tx_wallet_outputs; l_temp; l_temp=l_temp->next){ + dap_wallet_tx_cache_output_t *l_out_cur = (dap_wallet_tx_cache_output_t*)l_temp->data; + dap_chain_tx_item_type_t l_type = *(dap_chain_tx_item_type_t*)l_out_cur->tx_out; + uint256_t l_value = { }; + switch (l_type) { + case TX_ITEM_TYPE_OUT_EXT: { + dap_chain_tx_out_ext_t *l_out_ext = (dap_chain_tx_out_ext_t*)l_out_cur->tx_out; + if (dap_strcmp(l_out_ext->token, a_token_ticker)) + continue; + if (IS_ZERO_256(l_out_ext->header.value) ) + continue; + l_value = l_out_ext->header.value; + } break; + default: + continue; + } + // Check whether used 'out' items + if ( !dap_ledger_tx_hash_is_used_out_item (a_net->pub.ledger, &l_current_wallet_tx_iter->tx_hash, l_out_cur->tx_out_idx, NULL) ) { + dap_chain_tx_used_out_item_t *l_item = DAP_NEW_Z(dap_chain_tx_used_out_item_t); + *l_item = (dap_chain_tx_used_out_item_t) { l_current_wallet_tx_iter->tx_hash, (uint32_t)l_out_cur->tx_out_idx, l_value }; + l_list_used_out = dap_list_append(l_list_used_out, l_item); + SUM_256_256(l_value_transfer, l_item->value, &l_value_transfer); + } + } + } else { + bool skip = true; + for (dap_list_t *l_temp = l_current_wallet_tx_iter->tx_wallet_outputs; l_temp; l_temp=l_temp->next){ + dap_wallet_tx_cache_output_t *l_out_cur = (dap_wallet_tx_cache_output_t*)l_temp->data; + dap_chain_tx_item_type_t l_type = *(dap_chain_tx_item_type_t*)l_out_cur->tx_out; + uint256_t l_value = { }; + switch (l_type) { + case TX_ITEM_TYPE_OUT_OLD: { + dap_chain_tx_out_old_t *l_out = (dap_chain_tx_out_old_t*)l_out_cur->tx_out; + if (!l_out->header.value) + continue; + l_value = GET_256_FROM_64(l_out->header.value); + } break; + case TX_ITEM_TYPE_OUT: { + dap_chain_tx_out_t *l_out = (dap_chain_tx_out_t*)l_out_cur->tx_out; + if (IS_ZERO_256(l_out->header.value) ) + continue; + l_value = l_out->header.value; + } break; + case TX_ITEM_TYPE_OUT_EXT: { + // TODO: check ticker + dap_chain_tx_out_ext_t *l_out_ext = (dap_chain_tx_out_ext_t*)l_out_cur->tx_out; + if (dap_strcmp(l_out_ext->token, a_token_ticker)) + continue; + if (IS_ZERO_256(l_out_ext->header.value) ) + continue; + l_value = l_out_ext->header.value; + } break; + default: + continue; + } + // Check whether used 'out' items + + if ( !dap_ledger_tx_hash_is_used_out_item (a_net->pub.ledger, &l_current_wallet_tx_iter->tx_hash, l_out_cur->tx_out_idx, NULL) ) { + dap_chain_tx_used_out_item_t *l_item = DAP_NEW_Z(dap_chain_tx_used_out_item_t); + *l_item = (dap_chain_tx_used_out_item_t) { l_current_wallet_tx_iter->tx_hash, (uint32_t)l_out_cur->tx_out_idx, l_value }; + l_list_used_out = dap_list_append(l_list_used_out, l_item); + SUM_256_256(l_value_transfer, l_item->value, &l_value_transfer); + } + } + } + } + pthread_rwlock_unlock(&s_wallet_cache_rwlock); + + *a_outs_list = l_list_used_out; + if (a_value_transfer) + *a_value_transfer = l_value_transfer; + + return 0; +} + static int s_save_tx_into_wallet_cache(dap_chain_t *a_chain, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash, dap_hash_fast_t *a_atom_hash, int a_ret_code, char* a_main_token_ticker, dap_chain_net_srv_uid_t a_srv_uid, dap_chain_tx_tag_action_type_t a_action) { @@ -568,13 +692,18 @@ static int s_save_tx_into_wallet_cache(dap_chain_t *a_chain, dap_chain_datum_tx_ dap_hash_fast_t l_prev_tx_hash = ((dap_chain_tx_in_t*)it->data)->header.tx_prev_hash; int l_prev_idx = ((dap_chain_tx_in_t*)it->data)->header.tx_out_prev_idx; if (dap_hash_fast_is_blank(&l_prev_tx_hash)) + continue; + dap_chain_datum_t *l_prev_datum = a_chain->callback_datum_find_by_hash(a_chain, &l_prev_tx_hash, NULL, NULL); + dap_chain_datum_tx_t *l_tx_prev = l_prev_datum ? (dap_chain_datum_tx_t *)(l_prev_datum->data) : NULL; + if (!l_tx_prev){ + log_it(L_ERROR, "Can't find previous transactions (hash=%s)", dap_hash_fast_to_str_static(&l_prev_tx_hash)); continue; - dap_chain_datum_tx_t *l_tx_prev = (dap_chain_datum_tx_t *)(a_chain->callback_datum_find_by_hash(a_chain, &l_prev_tx_hash, NULL, NULL)->data); - if (!l_tx_prev) - continue; - uint8_t* l_prev_item = dap_chain_datum_tx_item_get_nth(l_tx_prev, TX_ITEM_TYPE_OUT, l_prev_idx); - if (!l_prev_item) + } + uint8_t* l_prev_item = dap_chain_datum_tx_item_get_nth(l_tx_prev, TX_ITEM_TYPE_OUT_ALL, l_prev_idx); + if (!l_prev_item){ + log_it(L_ERROR, "Can't find out with index %d in transaction %s", l_prev_idx, dap_hash_fast_to_str_static(&l_prev_tx_hash)); continue; + } uint8_t l_out_type = *(uint8_t *)l_prev_item; switch(l_out_type){ case TX_ITEM_TYPE_OUT_OLD: { @@ -639,11 +768,6 @@ static int s_save_tx_into_wallet_cache(dap_chain_t *a_chain, dap_chain_datum_tx_ static int s_save_cache_for_addr_in_net(dap_chain_net_t *a_net, dap_chain_addr_t *a_addr) { - // Find chain with transactions - dap_hash_fast_t l_curr_tx_hash = {0}; - if (dap_chain_wallet_cache_tx_find_in_history(a_addr, NULL, NULL, NULL, NULL, NULL, &l_curr_tx_hash) == 0) - return 0; - dap_chain_t *l_chain = a_net->pub.chains; while (l_chain){ for(int i = 0; i < l_chain->datum_types_count; i++) { @@ -654,8 +778,10 @@ static int s_save_cache_for_addr_in_net(dap_chain_net_t *a_net, dap_chain_addr_t l_datum; l_datum = l_chain->callback_datum_iter_get_next(l_iter)){ - s_save_tx_cache_for_addr(l_chain, a_addr, (dap_chain_datum_tx_t*)l_datum->data, l_iter->cur_hash, l_iter->cur_atom_hash, l_iter->ret_code, l_iter->token_ticker, l_iter->uid, l_iter->action); + if (l_datum->header.type_id == DAP_CHAIN_DATUM_TX) + s_save_tx_cache_for_addr(l_chain, a_addr, (dap_chain_datum_tx_t*)l_datum->data, l_iter->cur_hash, l_iter->cur_atom_hash, l_iter->ret_code, l_iter->token_ticker, l_iter->uid, l_iter->action); } + l_chain->callback_datum_iter_delete(l_iter); break; } } @@ -683,22 +809,59 @@ static void s_callback_datum_notify(void *a_arg, dap_chain_hash_fast_t *a_datum_ s_save_tx_into_wallet_cache(l_arg->chain, l_tx, a_datum_hash, a_atom_hash, a_ret_code, (char*)l_main_token_ticker, a_uid, a_action); } +typedef struct wallet_cache_load_args { + dap_chain_net_t *net; + dap_chain_addr_t addr; + dap_wallet_cache_t *wallet_item; +} wallet_cache_load_args_t; + +static void *s_wallet_load(void *a_arg) +{ + wallet_cache_load_args_t *l_args = (wallet_cache_load_args_t*)a_arg; + + s_save_cache_for_addr_in_net(l_args->net, &l_args->addr); + + l_args->wallet_item->is_loading = false; + DAP_DEL_Z(a_arg); + + return NULL; +} + + static void s_wallet_opened_callback(dap_chain_wallet_t *a_wallet, void *a_arg) { + for(dap_chain_net_t *l_net = dap_chain_net_iter_start(); l_net; l_net=dap_chain_net_iter_next(l_net)){ + if (dap_chain_net_get_load_mode(l_net)) + continue; // get wallet addr in current net dap_chain_addr_t *l_addr = dap_chain_wallet_get_addr(a_wallet, l_net->pub.id); pthread_rwlock_wrlock(&s_wallet_cache_rwlock); dap_wallet_cache_t *l_wallet_item = NULL; HASH_FIND(hh, s_wallets_cache, l_addr, sizeof(dap_chain_addr_t), l_wallet_item); - if (!l_wallet_item){ - l_wallet_item = DAP_NEW_Z(dap_wallet_cache_t); - memcpy (&l_wallet_item->wallet_addr, l_addr, sizeof(dap_chain_addr_t)); - HASH_ADD(hh, s_wallets_cache, wallet_addr, sizeof(dap_chain_addr_t), l_wallet_item); - pthread_rwlock_unlock(&s_wallet_cache_rwlock); - s_save_cache_for_addr_in_net(l_net, l_addr); - } else + if (l_wallet_item){ pthread_rwlock_unlock(&s_wallet_cache_rwlock); + continue; + } + + l_wallet_item = DAP_NEW_Z(dap_wallet_cache_t); + memcpy (&l_wallet_item->wallet_addr, l_addr, sizeof(dap_chain_addr_t)); + l_wallet_item->is_loading = true; + HASH_ADD(hh, s_wallets_cache, wallet_addr, sizeof(dap_chain_addr_t), l_wallet_item); + pthread_rwlock_unlock(&s_wallet_cache_rwlock); + + wallet_cache_load_args_t *l_args = DAP_NEW_Z(wallet_cache_load_args_t); + l_args->net = l_net; + l_args->addr = *l_addr; + l_args->wallet_item = l_wallet_item; + + pthread_t l_tid; + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + pthread_create(&l_tid, &attr, s_wallet_load, l_args); + + // s_save_cache_for_addr_in_net(l_net, l_addr); } } @@ -708,29 +871,32 @@ static int s_save_tx_cache_for_addr(dap_chain_t *a_chain, dap_chain_addr_t *a_ad { int l_ret_val = 0; int l_items_cnt = 0; - - dap_list_t *l_out_list = dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_OUT_ALL, &l_items_cnt); bool l_multichannel = false; int l_out_idx = 0; - for (dap_list_t *it=l_out_list; it; it=it->next, l_out_idx++){ - uint8_t l_out_type = *(uint8_t *)it->data; + uint8_t *l_tx_item = NULL; + size_t l_size; int i; + TX_ITEM_ITER_TX_TYPE(l_tx_item, TX_ITEM_TYPE_OUT_ALL, l_size, i, a_tx) { + uint8_t l_out_type = *(uint8_t *)l_tx_item; dap_chain_addr_t l_addr = {}; switch(l_out_type){ case TX_ITEM_TYPE_OUT_OLD: { - l_addr = ((dap_chain_tx_out_old_t*)it->data)->addr; + l_addr = ((dap_chain_tx_out_old_t*)l_tx_item)->addr; } break; case TX_ITEM_TYPE_OUT: { - l_addr = ((dap_chain_tx_out_t*)it->data)->addr; + l_addr = ((dap_chain_tx_out_t*)l_tx_item)->addr; } break; case TX_ITEM_TYPE_OUT_EXT: { - l_addr = ((dap_chain_tx_out_ext_t*)it->data)->addr; + l_addr = ((dap_chain_tx_out_ext_t*)l_tx_item)->addr; l_multichannel = true; } break; - default: + default:{ + l_out_idx++; continue; + } } - if(!dap_chain_addr_is_blank(&l_addr) && dap_chain_addr_compare(&l_addr, a_addr) && + if(!dap_chain_addr_is_blank(&l_addr) && + dap_chain_addr_compare(&l_addr, a_addr) && l_addr.net_id.uint64 == a_chain->net_id.uint64 ){ pthread_rwlock_wrlock(&s_wallet_cache_rwlock); @@ -756,45 +922,52 @@ static int s_save_tx_cache_for_addr(dap_chain_t *a_chain, dap_chain_addr_t *a_ad } l_wallet_tx_item->multichannel = l_multichannel; dap_wallet_tx_cache_output_t *l_out = DAP_NEW_Z(dap_wallet_tx_cache_output_t); - l_out->tx_out = it->data; + l_out->tx_out = l_tx_item; l_out->tx_out_idx = l_out_idx; l_wallet_tx_item->tx_wallet_outputs = dap_list_append(l_wallet_tx_item->tx_wallet_outputs, l_out); pthread_rwlock_unlock(&s_wallet_cache_rwlock); } + l_out_idx++; } - dap_list_t *l_in_list = dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_IN_ALL, &l_items_cnt); - for (dap_list_t *it=l_out_list; it; it=it->next ){ - uint8_t l_cond_type = *(uint8_t *)it->data; + l_tx_item = NULL; + TX_ITEM_ITER_TX_TYPE(l_tx_item, TX_ITEM_TYPE_IN_ALL, l_size, i, a_tx) { + uint8_t l_cond_type = *l_tx_item; uint256_t l_value = {}; dap_chain_addr_t l_addr_from = {}; if(l_cond_type == TX_ITEM_TYPE_IN){ - dap_hash_fast_t l_prev_tx_hash = ((dap_chain_tx_in_t*)it->data)->header.tx_prev_hash; - int l_prev_idx = ((dap_chain_tx_in_t*)it->data)->header.tx_out_prev_idx; + dap_hash_fast_t l_prev_tx_hash = ((dap_chain_tx_in_t*)l_tx_item)->header.tx_prev_hash; + int l_prev_idx = ((dap_chain_tx_in_t*)l_tx_item)->header.tx_out_prev_idx; if (dap_hash_fast_is_blank(&l_prev_tx_hash)) continue; - dap_chain_datum_tx_t *l_tx_prev = (dap_chain_datum_tx_t *)(a_chain->callback_datum_find_by_hash(a_chain, &l_prev_tx_hash, NULL, NULL)->data); - if (!l_tx_prev) + dap_chain_datum_t *l_prev_datum = a_chain->callback_datum_find_by_hash(a_chain, &l_prev_tx_hash, NULL, NULL); + dap_chain_datum_tx_t *l_tx_prev = l_prev_datum ? (dap_chain_datum_tx_t *)(l_prev_datum->data) : NULL; + if (!l_tx_prev){ + log_it(L_ERROR, "Can't find previous transactions (hash=%s)", dap_hash_fast_to_str_static(&l_prev_tx_hash)); continue; + } uint8_t* l_prev_item = dap_chain_datum_tx_item_get_nth(l_tx_prev, TX_ITEM_TYPE_OUT, l_prev_idx); - if (!l_prev_item) + if (!l_prev_item){ + log_it(L_ERROR, "Can't find out with index %d in transaction %s", l_prev_idx, dap_hash_fast_to_str_static(&l_prev_tx_hash)); continue; - uint8_t l_out_type = *(uint8_t *)it->data; + } + uint8_t l_out_type = *(uint8_t *)l_prev_item; switch(l_out_type){ case TX_ITEM_TYPE_OUT_OLD: { - l_value = GET_256_FROM_64(((dap_chain_tx_out_old_t*)it->data)->header.value); - l_addr_from = ((dap_chain_tx_out_old_t*)it->data)->addr; + l_value = GET_256_FROM_64(((dap_chain_tx_out_old_t*)l_prev_item)->header.value); + l_addr_from = ((dap_chain_tx_out_old_t*)l_prev_item)->addr; } break; case TX_ITEM_TYPE_OUT: case TX_ITEM_TYPE_OUT_EXT: { - l_value = ((dap_chain_tx_out_ext_t*)it->data)->header.value; - l_addr_from = ((dap_chain_tx_out_ext_t*)it->data)->addr; + l_value = ((dap_chain_tx_out_ext_t*)l_prev_item)->header.value; + l_addr_from = ((dap_chain_tx_out_ext_t*)l_prev_item)->addr; } break; default: continue; } - if(!dap_chain_addr_is_blank(&l_addr_from) && dap_chain_addr_compare(&l_addr_from, a_addr) && + if(!dap_chain_addr_is_blank(&l_addr_from) && + dap_chain_addr_compare(&l_addr_from, a_addr) && l_addr_from.net_id.uint64 == a_chain->net_id.uint64 ){ pthread_rwlock_wrlock(&s_wallet_cache_rwlock); @@ -830,12 +1003,6 @@ static int s_save_tx_cache_for_addr(dap_chain_t *a_chain, dap_chain_addr_t *a_ad } } - if (l_out_list) - dap_list_free(l_out_list); - - if (l_in_list) - dap_list_free(l_in_list); - return l_ret_val; } diff --git a/modules/wallet/include/dap_chain_wallet_cache.h b/modules/wallet/include/dap_chain_wallet_cache.h index 1be93e6468336411318833230552f8bf9c5f23c9..222543606932bf6cbea9639cb9e0d5a85e19587a 100644 --- a/modules/wallet/include/dap_chain_wallet_cache.h +++ b/modules/wallet/include/dap_chain_wallet_cache.h @@ -95,7 +95,9 @@ int dap_chain_wallet_cache_tx_find_in_history(dap_chain_addr_t *a_addr, char **a int dap_chain_wallet_cache_tx_find_outs_with_val(dap_chain_net_t *a_net, const char *a_token_ticker, const dap_chain_addr_t *a_addr, dap_list_t **a_outs_list, uint256_t a_value_needed, uint256_t *a_value_transfer); - +int dap_chain_wallet_cache_tx_find_outs(dap_chain_net_t *a_net, const char *a_token_ticker, const dap_chain_addr_t *a_addr, + dap_list_t **a_outs_list, uint256_t *a_value_transfer); + dap_chain_wallet_cache_iter_t *dap_chain_wallet_cache_iter_create(dap_chain_addr_t a_addr); void dap_chain_wallet_cache_iter_delete(dap_chain_wallet_cache_iter_t *a_iter); dap_chain_datum_tx_t *dap_chain_wallet_cache_iter_get(dap_chain_wallet_cache_iter_t *a_iter, dap_chain_wallet_getting_type_t a_type); \ No newline at end of file