Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • cellframe/cellframe-sdk
  • MIKA83/cellframe-sdk
2 results
Show changes
Commits on Source (28)
Subproject commit 2f34b05c0f69e859315913608937eaf2b101986d
Subproject commit b85e227d3cdb7b8ffbc5ff16b56138e3b37ef23a
......@@ -1264,6 +1264,13 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t *a_ch, void *a_arg)
return false;
}
pkt_test_t *l_request = (pkt_test_t*)l_ch_pkt->data;
if (dap_chain_net_srv_get(l_request->srv_uid) == NULL){
log_it(L_WARNING, "Can't find service with id %"DAP_UINT64_FORMAT_U, l_request->srv_uid);
l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_SERVICE_NOT_FOUND;
dap_stream_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof(l_err));
return false;
}
if (l_request->data_size_recv > DAP_CHAIN_NET_SRV_CH_REQUEST_SIZE_MAX || l_request->data_size > DAP_CHAIN_NET_SRV_CH_REQUEST_SIZE_MAX) {
log_it(L_WARNING, "Too large payload %zu [pkt seq %"DAP_UINT64_FORMAT_U"]", l_request->data_size_recv, l_ch_pkt->hdr.seq_id);
l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_BIG_SIZE;
......
......@@ -3463,6 +3463,7 @@ static int s_tx_cache_check(dap_ledger_t *a_ledger,
uint256_t l_taxed_value = {};
if(a_tag) dap_ledger_deduct_tx_tag(a_ledger, a_tx, NULL, a_tag, a_action);
bool l_tax_check = false;
// find all previous transactions
for (dap_list_t *it = l_list_in; it; it = it->next) {
......@@ -3919,6 +3920,7 @@ static int s_tx_cache_check(dap_ledger_t *a_ledger,
l_bound_item->cond = l_tx_prev_out_cond;
l_value = l_tx_prev_out_cond->header.value;
if (l_tx_prev_out_cond->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE) {
l_tax_check = true;
l_token = a_ledger->net->pub.native_ticker;
// Overflow checked later with overall values sum
SUM_256_256(l_taxed_value, l_value, &l_taxed_value);
......@@ -4005,8 +4007,12 @@ static int s_tx_cache_check(dap_ledger_t *a_ledger,
HASH_ADD_STR(l_values_from_cur_tx, token_ticker, l_value_cur);
}
dap_chain_net_srv_stake_item_t *l_key_item = dap_chain_net_srv_stake_check_pkey_hash(a_ledger->net->pub.id, &l_tx_first_sign_pkey_hash);
bool l_tax_check = l_key_item && !dap_chain_addr_is_blank(&l_key_item->sovereign_addr) && !IS_ZERO_256(l_key_item->sovereign_tax);
dap_chain_net_srv_stake_item_t *l_key_item = NULL;
if (l_tax_check) {
l_key_item = dap_chain_net_srv_stake_check_pkey_hash(a_ledger->net->pub.id, &l_tx_first_sign_pkey_hash);
l_tax_check = l_key_item && !dap_chain_addr_is_blank(&l_key_item->sovereign_addr) && !IS_ZERO_256(l_key_item->sovereign_tax);
}
// find 'out' items
bool l_cross_network = false;
......
......@@ -1192,13 +1192,13 @@ int dap_chain_net_tx_create_by_json(json_object *a_tx_json, dap_chain_net_t *a_n
l_sign_list = dap_list_append(l_sign_list, l_json_item_obj);
break;
}
const char *l_sign_b64_str = json_object_get_string(l_json_item_obj);
const char *l_sign_b64_str = json_object_get_string(l_jobj_sign);
if ( !l_sign_b64_str ) {
json_object_array_add(l_jobj_errors, json_object_new_string("Can't get base64-encoded sign"));
log_it(L_ERROR, "Json TX: Can't get base64-encoded sign!");
break;
}
int64_t l_sign_size = 0, l_sign_b64_strlen = json_object_get_string_len(l_json_item_obj),
int64_t l_sign_size = 0, l_sign_b64_strlen = json_object_get_string_len(l_jobj_sign),
l_sign_decoded_size = DAP_ENC_BASE64_DECODE_SIZE(l_sign_b64_strlen);
if ( !s_json_get_int64(l_json_item_obj, "sig_size", &l_sign_size) )
log_it(L_NOTICE, "Json TX: \"sig_size\" unspecified, will be calculated automatically");
......
......@@ -1750,13 +1750,6 @@ int l_arg_index = 1, l_rc, cmd_num = CMD_NONE;
break;
}
case CMD_WALLET_OUTPUTS: {
if(!l_net) {
dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_TX_WALLET_NET_PARAM_ERR,
"Subcommand info requires parameter '-net'");
json_object_put(json_arr_out);
return DAP_CHAIN_NODE_CLI_COM_TX_WALLET_NET_PARAM_ERR;
}
if ((l_wallet_name && l_addr_str) || (!l_wallet_name && !l_addr_str)) {
dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_TX_WALLET_NAME_ERR,
"You should use either the -w or -addr option for the wallet info command.");
......@@ -1764,6 +1757,12 @@ int l_arg_index = 1, l_rc, cmd_num = CMD_NONE;
return DAP_CHAIN_NODE_CLI_COM_TX_WALLET_NAME_ERR;
}
if(l_wallet_name) {
if(!l_net) {
dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_TX_WALLET_NET_PARAM_ERR,
"Subcommand info requires parameter '-net'");
json_object_put(json_arr_out);
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,
......@@ -1780,6 +1779,15 @@ int l_arg_index = 1, l_rc, cmd_num = CMD_NONE;
}
} else {
l_addr = dap_chain_addr_from_str(l_addr_str);
if (!l_net)
l_net = dap_chain_net_by_id(l_addr->net_id);
if(!l_net) {
dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_TX_WALLET_NET_PARAM_ERR,
"Can't get net from wallet addr");
json_object_put(json_arr_out);
return DAP_CHAIN_NODE_CLI_COM_TX_WALLET_NET_PARAM_ERR;
}
}
const char* l_token_tiker = NULL;
......@@ -1862,7 +1870,7 @@ int l_arg_index = 1, l_rc, cmd_num = CMD_NONE;
l_rc = l_ttl_str ? strtoul(l_ttl_str, NULL, 10) : 60;
l_rc = cmd_num == CMD_WALLET_ACTIVATE
? dap_chain_wallet_activate(l_wallet_name, strlen(l_wallet_name), l_pass_str, strlen(l_pass_str), l_rc)
? dap_chain_wallet_activate(l_wallet_name, strlen(l_wallet_name), NULL, l_pass_str, strlen(l_pass_str), l_rc)
: dap_chain_wallet_deactivate (l_wallet_name, strlen(l_wallet_name));
switch (l_rc) {
......@@ -6261,7 +6269,8 @@ int com_tx_create(int a_argc, char **a_argv, void **a_json_arr_reply)
// int cmd_num = 1;
// const char *value_str = NULL;
const char *addr_base58_to = NULL;
const char *str_tmp = NULL;
const char * l_fee_str = NULL;
const char * l_value_str = NULL;
const char * l_from_wallet_name = NULL;
const char * l_wallet_fee_name = NULL;
const char * l_token_ticker = NULL;
......@@ -6310,14 +6319,14 @@ int com_tx_create(int a_argc, char **a_argv, void **a_json_arr_reply)
l_tx_num = strtoul(l_tx_num_str, NULL, 10);
// Validator's fee
if (dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-fee", &str_tmp)) {
if (!str_tmp) {
if (dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-fee", &l_fee_str)) {
if (!l_fee_str) {
dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_TX_CREATE_REQUIRE_FEE, "tx_create requires parameter '-fee'");
return DAP_CHAIN_NODE_CLI_COM_TX_CREATE_REQUIRE_FEE;
}
l_value_fee = dap_chain_balance_scan(str_tmp);
l_value_fee = dap_chain_balance_scan(l_fee_str);
}
if (IS_ZERO_256(l_value_fee) && (!l_emission_hash_str || (str_tmp && strcmp(str_tmp, "0")))) {
if (IS_ZERO_256(l_value_fee) && (!l_emission_hash_str || (l_fee_str && strcmp(l_fee_str, "0")))) {
dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_TX_CREATE_REQUIRE_FEE_IS_UINT256, "tx_create requires parameter '-fee' to be valid uint256");
return DAP_CHAIN_NODE_CLI_COM_TX_CREATE_REQUIRE_FEE_IS_UINT256;
}
......@@ -6395,17 +6404,17 @@ int com_tx_create(int a_argc, char **a_argv, void **a_json_arr_reply)
return DAP_CHAIN_NODE_CLI_COM_TX_CREATE_TOKEN_NOT_DECLARATED_IN_NET;
}
dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-to_addr", &addr_base58_to);
dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-value", &str_tmp);
dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-value", &l_value_str);
if (!addr_base58_to) {
dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_TX_CREATE_REQUIRE_PARAMETER_TO_ADDR, "tx_create requires parameter '-to_addr'");
return DAP_CHAIN_NODE_CLI_COM_TX_CREATE_REQUIRE_PARAMETER_TO_ADDR;
}
if (!str_tmp) {
if (!l_value_str) {
dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_TX_CREATE_REQUIRE_PARAMETER_VALUE_OR_INVALID_FORMAT_VALUE, "tx_create requires parameter '-value' to be valid uint256 value");
return DAP_CHAIN_NODE_CLI_COM_TX_CREATE_REQUIRE_PARAMETER_VALUE_OR_INVALID_FORMAT_VALUE;
}
l_addr_el_count = dap_str_symbol_count(addr_base58_to, ',') + 1;
l_value_el_count = dap_str_symbol_count(str_tmp, ',') + 1;
l_value_el_count = dap_str_symbol_count(l_value_str, ',') + 1;
if (l_addr_el_count != l_value_el_count) {
dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_TX_CREATE_REQUIRE_PARAMETER_VALUE_OR_INVALID_FORMAT_VALUE, "num of '-to_addr' and '-value' should be equal");
......@@ -6417,7 +6426,7 @@ int com_tx_create(int a_argc, char **a_argv, void **a_json_arr_reply)
dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_GLOBAL_DB_MEMORY_ERR, c_error_memory_alloc);
return DAP_CHAIN_NODE_CLI_COM_GLOBAL_DB_MEMORY_ERR;
}
char **l_value_array = dap_strsplit(str_tmp, ",", l_value_el_count);
char **l_value_array = dap_strsplit(l_value_str, ",", l_value_el_count);
if (!l_value_array) {
DAP_DELETE(l_value);
dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_GLOBAL_DB_PARAM_ERR, "Can't read '-to_addr' arg");
......
......@@ -331,7 +331,7 @@ void dap_chain_node_client_close_unsafe(dap_chain_node_client_t *a_node_client)
if (a_node_client->reconnect_timer)
dap_timerfd_delete_mt(a_node_client->reconnect_timer->worker, a_node_client->reconnect_timer->esocket_uuid);
if (a_node_client->callbacks.delete)
a_node_client->callbacks.delete(a_node_client, a_node_client->net);
a_node_client->callbacks.delete(a_node_client, a_node_client->callbacks_arg);
if (a_node_client->stream_worker) {
dap_stream_ch_t *l_ch = dap_stream_ch_find_by_uuid_unsafe(a_node_client->stream_worker, a_node_client->ch_chain_net_uuid);
......
......@@ -79,6 +79,7 @@ typedef struct xchange_tx_cache {
uint256_t value;
uint256_t value_ammount;
dap_hash_fast_t next_hash;
uint64_t percent_completed;
} order_info;
struct {
dap_hash_fast_t order_hash;
......@@ -996,9 +997,18 @@ uint64_t dap_chain_net_srv_xchange_get_order_completion_rate(dap_chain_net_t *a_
SUBTRACT_256_256(l_out_cond->header.value, l_out_cond_last_tx->header.value, &l_percent_completed);
DIV_256_COIN(l_percent_completed, l_out_cond->header.value, &l_percent_completed);
MULT_256_COIN(l_percent_completed, dap_chain_coins_to_balance("100.0"), &l_percent_completed);
} else
l_percent_completed = dap_chain_coins_to_balance("100.0");
} else {
dap_chain_tx_out_cond_t *l_out_prev_cond_item = NULL;
xchange_tx_type_t tx_type = dap_chain_net_srv_xchange_tx_get_type(a_net->pub.ledger, l_last_tx, NULL, NULL, &l_out_prev_cond_item);
if (tx_type == TX_TYPE_EXCHANGE){
l_percent_completed = dap_chain_coins_to_balance("100.0");
} else if (tx_type == TX_TYPE_INVALIDATE){
SUBTRACT_256_256(l_out_cond->header.value, l_out_prev_cond_item->header.value, &l_percent_completed);
DIV_256_COIN(l_percent_completed, l_out_cond->header.value, &l_percent_completed);
MULT_256_COIN(l_percent_completed, dap_chain_coins_to_balance("100.0"), &l_percent_completed);
}
}
return dap_chain_balance_to_coins_uint64(l_percent_completed);
}
......@@ -1578,16 +1588,19 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, j
if(l_rc == XCHANGE_ORDER_STATUS_UNKNOWN){
json_object_object_add(l_json_obj_order, "WRONG TX", json_object_new_string(l_tx_hash));
}else{
json_object_object_add(l_json_obj_order, "history for order", json_object_new_string(l_order_hash_str));
dap_list_t *l_tx_list = dap_chain_net_get_tx_cond_chain(l_net, &l_order_tx_hash, c_dap_chain_net_srv_xchange_uid );
dap_list_t *l_tx_list_temp = l_tx_list;
json_object* l_json_obj_tx_arr = json_object_new_array();
while(l_tx_list_temp ){
json_object* l_json_obj_cur_tx = json_object_new_object();
dap_chain_datum_tx_t * l_tx_cur = (dap_chain_datum_tx_t*) l_tx_list_temp->data;
dap_hash_fast_t l_hash = {};
dap_hash_fast(l_tx_cur, dap_chain_datum_tx_get_size(l_tx_cur), &l_hash);
s_string_append_tx_cond_info_json(l_json_obj_order, l_net, NULL, NULL, l_tx_cur, &l_hash, TX_STATUS_ALL, true, true, false);
s_string_append_tx_cond_info_json(l_json_obj_cur_tx, l_net, NULL, NULL, l_tx_cur, &l_hash, TX_STATUS_ALL, true, true, false);
json_object_array_add(l_json_obj_tx_arr, l_json_obj_cur_tx);
l_tx_list_temp = l_tx_list_temp->next;
}
json_object_object_add(l_json_obj_order, "history for order", l_json_obj_tx_arr);
dap_list_free(l_tx_list);
}
}
......@@ -1607,10 +1620,13 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, j
dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_HIST_DOES_NO_HISTORY_ERR, "No history");
return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_HIST_DOES_NO_HISTORY_ERR;
}
json_object* l_json_obj_tx_arr = json_object_new_array();
while(l_item){
s_string_append_tx_cond_info_json(l_json_obj_order, l_net, &l_item->seller_addr,
json_object* l_json_obj_cur_tx = json_object_new_object();
s_string_append_tx_cond_info_json(l_json_obj_cur_tx, l_net, &l_item->seller_addr,
l_item->tx_type == TX_TYPE_EXCHANGE ? &l_item->tx_info.exchange_info.buyer_addr : NULL,
l_item->tx, &l_item->hash, TX_STATUS_ALL, true, true, false);
json_object_array_add(l_json_obj_tx_arr, l_json_obj_cur_tx);
switch(l_item->tx_type){
case TX_TYPE_ORDER:{
l_cur_hash = l_item->tx_info.order_info.next_hash;
......@@ -1627,6 +1643,7 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, j
break;
HASH_FIND(hh, l_cache->cache, &l_cur_hash, sizeof(dap_hash_fast_t), l_item);
}
json_object_object_add(l_json_obj_order, "history for order", l_json_obj_tx_arr);
}
}
json_object_array_add(*a_json_arr_reply, l_json_obj_order);
......@@ -1783,12 +1800,7 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, j
l_token_buy = l_item->buy_token;
l_proposed = l_item->tx_info.order_info.value;
uint256_t l_completed = {};
SUBTRACT_256_256(l_item->tx_info.order_info.value, l_item->tx_info.order_info.value_ammount, &l_completed);
DIV_256_COIN(l_completed, l_item->tx_info.order_info.value, &l_completed);
MULT_256_COIN(l_completed, dap_chain_coins_to_balance("100.0"), &l_completed);
l_percent_completed = dap_chain_balance_to_coins_uint64(l_completed);
l_percent_completed = l_item->tx_info.order_info.percent_completed;
l_owner_addr = dap_strdup(dap_chain_addr_to_str(&l_item->seller_addr));
} else {
l_tx = dap_ledger_tx_find_by_hash(l_net->pub.ledger, &l_order_tx_hash);
......@@ -1888,6 +1900,7 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, j
json_object_object_add(json_obj_order, "rate", json_object_new_string(l_cp_rate));
json_object_object_add(json_obj_order, "net", json_object_new_string(l_net->pub.name));
json_object_object_add(json_obj_order, "owner_addr", json_object_new_string(l_owner_addr));
json_object_array_add(*a_json_arr_reply, json_obj_order);
DAP_DELETE(l_owner_addr);
if ( s_xchange_cache_state != XCHANGE_CACHE_ENABLED )
......@@ -2659,12 +2672,7 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **a_str_reply)
l_rate = l_item->rate;
l_amount = l_item->tx_info.order_info.value_ammount;
l_proposed = l_item->tx_info.order_info.value;
uint256_t l_completed = {};
SUBTRACT_256_256(l_item->tx_info.order_info.value, l_item->tx_info.order_info.value_ammount, &l_completed);
DIV_256_COIN(l_completed, l_item->tx_info.order_info.value, &l_completed);
MULT_256_COIN(l_completed, dap_chain_coins_to_balance("100.0"), &l_completed);
l_percent_completed = dap_chain_balance_to_coins_uint64(l_completed);
l_percent_completed = l_item->tx_info.order_info.percent_completed;
} else {
xchange_tx_list_t *l_tx_item = (xchange_tx_list_t*)it->data;
l_tx = l_tx_item->tx;
......@@ -2767,6 +2775,7 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **a_str_reply)
json_object_object_add(json_obj_order, "rate", json_object_new_string(l_cp_rate));
json_object_object_add(json_obj_order, "net", json_object_new_string(l_net->pub.name));
json_object_object_add(json_obj_order, "owner_addr", json_object_new_string(l_owner_addr));
json_object_array_add(*json_arr_reply, json_obj_order);
DAP_DELETE(l_owner_addr);
l_printed_orders_count++;
......@@ -2965,6 +2974,7 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **a_str_reply)
l_show_tx_nr++;
}
}
json_object_array_add(*json_arr_reply, json_arr_bl_out);
} else {
dap_list_t *l_datum_list0 = dap_chain_datum_list(l_net, NULL, s_filter_tx_list, l_time);
size_t l_datum_num = dap_list_length(l_datum_list0);
......@@ -2987,6 +2997,7 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **a_str_reply)
}
l_datum_list = dap_list_next(l_datum_list);
}
json_object_array_add(*json_arr_reply, json_arr_bl_out);
}
dap_list_free_full(l_datum_list0, NULL);
}
......@@ -3328,7 +3339,7 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **a_str_reply)
dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-limit", &l_limit_str);
dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-offset", &l_offset_str);
size_t l_offset = l_offset_str ? strtoul(l_offset_str, NULL, 10) : 0;
size_t l_limit = l_limit_str ? strtoul(l_limit_str, NULL, 10) : 0;
size_t l_limit = l_limit_str ? strtoul(l_limit_str, NULL, 10) : 1000;
char ** l_tickers = NULL;
size_t l_tickers_count = 0;
......@@ -3339,7 +3350,7 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **a_str_reply)
size_t l_arr_start = 0;
size_t l_arr_end = 0;
json_object* json_arr_bl_cache_out = json_object_new_array();
dap_chain_set_offset_limit_json(json_arr_bl_cache_out, &l_arr_start, &l_arr_end, l_limit, l_offset, l_tickers_count);
dap_chain_set_offset_limit_json(json_arr_bl_cache_out, &l_arr_start, &l_arr_end, l_limit, l_offset, l_tickers_count*l_tickers_count);
size_t i_tmp = 0;
for(size_t i = 0; i< l_tickers_count; i++){
......@@ -3665,6 +3676,7 @@ static void s_ledger_tx_add_notify(void *a_arg, dap_ledger_t *a_ledger, dap_chai
l_cache->tx_info.order_info.order_status = XCHANGE_ORDER_STATUS_OPENED;
l_cache->tx_info.order_info.value = l_out_cond_item->header.value;
l_cache->tx_info.order_info.value_ammount = l_cache->tx_info.order_info.value;
l_cache->tx_info.order_info.percent_completed = 0;
} else if (l_tx_type == TX_TYPE_EXCHANGE){
l_cache->rate = l_out_prev_cond_item->subtype.srv_xchange.rate;
dap_strncpy(l_cache->buy_token, l_out_prev_cond_item->subtype.srv_xchange.buy_token, sizeof(l_cache->buy_token));
......@@ -3690,6 +3702,15 @@ static void s_ledger_tx_add_notify(void *a_arg, dap_ledger_t *a_ledger, dap_chai
if(l_cache_order){
if (l_cache_order->tx_type == TX_TYPE_ORDER){
l_cache_order->tx_info.order_info.value_ammount = l_out_cond_item && !IS_ZERO_256(l_out_cond_item->header.value) ? l_out_cond_item->header.value : uint256_0;
if (l_out_cond_item && !IS_ZERO_256(l_out_cond_item->header.value)){
uint256_t l_percent_completed = {};
SUBTRACT_256_256(l_cache_order->tx_info.order_info.value, l_cache_order->tx_info.order_info.value_ammount, &l_percent_completed);
DIV_256_COIN(l_percent_completed, l_cache_order->tx_info.order_info.value, &l_percent_completed);
MULT_256_COIN(l_percent_completed, dap_chain_coins_to_balance("100.0"), &l_percent_completed);
l_cache_order->tx_info.order_info.percent_completed = dap_chain_balance_to_coins_uint64(l_percent_completed);
} else {
l_cache_order->tx_info.order_info.percent_completed = dap_chain_balance_to_coins_uint64(dap_chain_coins_to_balance("100.0"));
}
l_cache_order->tx_info.order_info.order_status = IS_ZERO_256(l_cache_order->tx_info.order_info.value_ammount) ? XCHANGE_ORDER_STATUS_CLOSED : XCHANGE_ORDER_STATUS_OPENED;
if (dap_hash_fast_is_blank(&l_cache_order->tx_info.order_info.next_hash))
l_cache_order->tx_info.order_info.next_hash = *a_tx_hash;
......@@ -3754,9 +3775,15 @@ static void s_ledger_tx_add_notify(void *a_arg, dap_ledger_t *a_ledger, dap_chai
HASH_FIND(hh, l_cache->cache, &l_cache_found->tx_info.exchange_info.order_hash, sizeof(dap_hash_fast_t), l_cache_order);
l_cache_prev_tx->tx_info.exchange_info.next_hash = (dap_hash_fast_t){0};
SUM_256_256(l_cache_order->tx_info.order_info.value_ammount, l_cache_found->tx_info.exchange_info.buy_value, &l_cache_order->tx_info.order_info.value_ammount);
uint256_t l_percent_completed = {};
SUBTRACT_256_256(l_cache_order->tx_info.order_info.value, l_cache_order->tx_info.order_info.value_ammount, &l_percent_completed);
DIV_256_COIN(l_percent_completed, l_cache_order->tx_info.order_info.value, &l_percent_completed);
MULT_256_COIN(l_percent_completed, dap_chain_coins_to_balance("100.0"), &l_percent_completed);
l_cache_order->tx_info.order_info.percent_completed = dap_chain_balance_to_coins_uint64(l_percent_completed);
} else if (l_cache_prev_tx->tx_type == TX_TYPE_ORDER){
l_cache_prev_tx->tx_info.order_info.next_hash = (dap_hash_fast_t){0};
l_cache_prev_tx->tx_info.order_info.value_ammount = l_cache_prev_tx->tx_info.order_info.value;
l_cache_prev_tx->tx_info.order_info.percent_completed = 0;
}
}
} else if (l_tx_type == TX_TYPE_INVALIDATE){
......
......@@ -786,7 +786,7 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply)
// 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));
json_object_object_add(json_obj_inf, "hash", json_object_new_string(l_hash_str));
snprintf(l_hexbuf, sizeof(l_hexbuf), "0x%04X",l_block->hdr.version);
json_object_object_add(json_obj_inf, "version", json_object_new_string(l_hexbuf));
......
......@@ -140,6 +140,7 @@ dap_list_t* dap_chain_wallet_get_local_addr(){
int dap_chain_wallet_activate (
const char *a_name,
ssize_t a_name_len,
const char *a_path,
const char *a_pass,
ssize_t a_pass_len,
unsigned a_ttl
......@@ -197,7 +198,7 @@ char *c_wallets_path;
/*
* Check password by open/close BMF Wallet file
*/
if ( !(c_wallets_path = (char *) dap_chain_wallet_get_path(g_config)) ) /* No path to wallets - nothing to do */
if ( !(c_wallets_path = a_path ? (char *)a_path : (char *) dap_chain_wallet_get_path(g_config)) ) /* No path to wallets - nothing to do */
{
memset(l_prec->pass, 0, l_prec->pass_len), l_prec->pass_len = 0;
return log_it(L_ERROR, "Wallet's path has been not configured"), -EINVAL;
......
......@@ -112,10 +112,9 @@ static dap_s_wallets_cache_type_t s_wallets_cache_type = DAP_WALLET_CACHE_TYPE_L
static dap_wallet_cache_t *s_wallets_cache = NULL;
static pthread_rwlock_t s_wallet_cache_rwlock;
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);
static int s_save_tx_cache_for_addr(dap_chain_t *a_chain, dap_chain_addr_t *a_addr, 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);
static int s_save_tx_cache_for_addr(dap_chain_t *a_chain, dap_chain_addr_t *a_addr, 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, char a_cache_op);
static int s_save_cache_for_addr_in_net(dap_chain_net_t *a_net, dap_chain_addr_t *a_addr);
static void s_callback_datum_notify(void *a_arg, dap_chain_hash_fast_t *a_datum_hash, dap_hash_fast_t *a_atom_hash, void *a_datum,
size_t a_datum_size, int a_ret_code, uint32_t a_action,
......@@ -171,8 +170,9 @@ int dap_chain_wallet_cache_init()
dap_atom_notify_arg_t *l_arg = DAP_NEW_Z(dap_atom_notify_arg_t);
l_arg->chain = l_chain;
l_arg->net = l_net;
dap_chain_add_callback_datum_index_notify(l_chain, s_callback_datum_notify, NULL, l_arg);
dap_chain_add_callback_datum_removed_from_index_notify(l_chain, s_callback_datum_removed_notify, NULL, l_arg);
dap_proc_thread_t *l_pt = dap_proc_thread_get_auto();
dap_chain_add_callback_datum_index_notify(l_chain, s_callback_datum_notify, l_pt, l_arg);
dap_chain_add_callback_datum_removed_from_index_notify(l_chain, s_callback_datum_removed_notify, l_pt, l_arg);
}
}
l_chain=l_chain->next;
......@@ -388,7 +388,7 @@ int dap_chain_wallet_cache_tx_find_outs(dap_chain_net_t *a_net, const char *a_to
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;
......@@ -543,171 +543,6 @@ int dap_chain_wallet_cache_tx_find_outs_with_val(dap_chain_net_t *a_net, const c
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)
{
int l_ret_val = 0;
int l_items_cnt = 0;
bool l_multichannel = false;
int l_out_idx = 0, i = 0;
uint8_t *l_tx_item = NULL;
size_t l_size;
TX_ITEM_ITER_TX_TYPE(l_tx_item, TX_ITEM_TYPE_OUT_ALL, l_size, i, a_tx) {
uint8_t l_out_type = *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*)l_tx_item)->addr;
} break;
case TX_ITEM_TYPE_OUT: {
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*)l_tx_item)->addr;
l_multichannel = true;
} break;
default:{
l_out_idx++;
continue;
}
}
if(!dap_chain_addr_is_blank(&l_addr) &&
((s_wallets_cache_type == DAP_WALLET_CACHE_TYPE_LOCAL &&
dap_chain_wallet_addr_cache_get_name(&l_addr) != NULL) || s_wallets_cache_type == DAP_WALLET_CACHE_TYPE_ALL) &&
l_addr.net_id.uint64 == a_chain->net_id.uint64
){
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);
}
dap_wallet_tx_cache_t *l_wallet_tx_item = NULL;
HASH_FIND(hh, l_wallet_item->wallet_txs, a_tx_hash, sizeof(dap_hash_fast_t), l_wallet_tx_item);
if (!l_wallet_tx_item){
l_wallet_tx_item = DAP_NEW_Z(dap_wallet_tx_cache_t);
l_wallet_tx_item->tx_hash = *a_tx_hash;
l_wallet_tx_item->atom_hash = *a_atom_hash;
l_wallet_tx_item->tx = a_tx;
dap_strncpy(l_wallet_tx_item->token_ticker, a_main_token_ticker ? a_main_token_ticker : "0", DAP_CHAIN_TICKER_SIZE_MAX);
l_wallet_tx_item->ret_code = a_ret_code;
l_wallet_tx_item->srv_uid = a_srv_uid;
l_wallet_tx_item->action = a_action;
HASH_ADD(hh, l_wallet_item->wallet_txs, tx_hash, sizeof(dap_hash_fast_t), l_wallet_tx_item);
}
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 = 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);
// Add unspent out into cache
if (!a_ret_code){
dap_wallet_cache_unspent_outs_t *l_unspent_out = DAP_NEW_Z(dap_wallet_cache_unspent_outs_t);
l_unspent_out->key.tx_hash = *a_tx_hash;
l_unspent_out->key.out_idx = l_out_idx;
l_unspent_out->output = l_out;
if (l_out_type != TX_ITEM_TYPE_OUT_EXT)
dap_strncpy(l_unspent_out->token_ticker, a_main_token_ticker ? a_main_token_ticker : "0", DAP_CHAIN_TICKER_SIZE_MAX);
else
dap_strncpy(l_unspent_out->token_ticker, ((dap_chain_tx_out_ext_t*)l_tx_item)->token, DAP_CHAIN_TICKER_SIZE_MAX);
HASH_ADD(hh, l_wallet_item->unspent_outputs, key, sizeof(unspent_cache_hh_key), l_unspent_out);
}
pthread_rwlock_unlock(&s_wallet_cache_rwlock);
}
l_out_idx++;
}
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*)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_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_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: {
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*)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) && ((s_wallets_cache_type == DAP_WALLET_CACHE_TYPE_LOCAL &&
dap_chain_wallet_addr_cache_get_name(&l_addr_from) != NULL) || s_wallets_cache_type == DAP_WALLET_CACHE_TYPE_ALL) &&
l_addr_from.net_id.uint64 == a_chain->net_id.uint64
){
pthread_rwlock_wrlock(&s_wallet_cache_rwlock);
dap_wallet_cache_t *l_wallet_item = NULL;
HASH_FIND(hh, s_wallets_cache, &l_addr_from, 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_from, sizeof(dap_chain_addr_t));
HASH_ADD(hh, s_wallets_cache, wallet_addr, sizeof(dap_chain_addr_t), l_wallet_item);
}
dap_wallet_tx_cache_t *l_wallet_tx_item = NULL;
HASH_FIND(hh, l_wallet_item->wallet_txs, a_tx_hash, sizeof(dap_hash_fast_t), l_wallet_tx_item);
if (!l_wallet_tx_item){
l_wallet_tx_item = DAP_NEW_Z(dap_wallet_tx_cache_t);
l_wallet_tx_item->tx_hash = *a_tx_hash;
l_wallet_tx_item->atom_hash = *a_atom_hash;
l_wallet_tx_item->tx = a_tx;
dap_strncpy(l_wallet_tx_item->token_ticker, a_main_token_ticker ? a_main_token_ticker : "0", DAP_CHAIN_TICKER_SIZE_MAX);
l_wallet_tx_item->multichannel = l_multichannel;
l_wallet_tx_item->ret_code = a_ret_code;
l_wallet_tx_item->srv_uid = a_srv_uid;
l_wallet_tx_item->action = a_action;
HASH_ADD(hh, l_wallet_item->wallet_txs, tx_hash, sizeof(dap_hash_fast_t), l_wallet_tx_item);
}
dap_wallet_tx_cache_input_t *l_tx_in = DAP_NEW_Z(dap_wallet_tx_cache_input_t);
l_tx_in->tx_prev_hash = l_prev_tx_hash;
l_tx_in->tx_out_prev_idx = l_prev_idx;
l_tx_in->value = l_value;
l_wallet_tx_item->tx_wallet_inputs = dap_list_append(l_wallet_tx_item->tx_wallet_inputs, l_tx_in);
if (!a_ret_code){
unspent_cache_hh_key key = {0};
key.tx_hash = l_prev_tx_hash;
key.out_idx = l_prev_idx;
dap_wallet_cache_unspent_outs_t *l_item = NULL;
HASH_FIND(hh, l_wallet_item->unspent_outputs, &key, sizeof(unspent_cache_hh_key), l_item);
if (l_item){
HASH_DEL(l_wallet_item->unspent_outputs, l_item);
DAP_DELETE(l_item);
}
}
pthread_rwlock_unlock(&s_wallet_cache_rwlock);
}
}
}
return l_ret_val;
}
static int s_save_cache_for_addr_in_net(dap_chain_net_t *a_net, dap_chain_addr_t *a_addr)
{
......@@ -722,7 +557,8 @@ static int s_save_cache_for_addr_in_net(dap_chain_net_t *a_net, dap_chain_addr_t
l_datum = l_chain->callback_datum_iter_get_next(l_iter)){
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);
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, 'a');
}
l_chain->callback_datum_iter_delete(l_iter);
break;
......@@ -734,22 +570,27 @@ static int s_save_cache_for_addr_in_net(dap_chain_net_t *a_net, dap_chain_addr_t
return 0;
}
static void s_callback_datum_notify(void *a_arg, dap_chain_hash_fast_t *a_datum_hash, dap_chain_hash_fast_t *a_atom_hash,void *a_datum,
size_t a_datum_size, int a_ret_code, uint32_t a_action,
dap_chain_net_srv_uid_t a_uid)
static void s_callback_datum_notify(void *a_arg, dap_chain_hash_fast_t *a_datum_hash, dap_chain_hash_fast_t *a_atom_hash, void *a_datum,
size_t a_datum_size, int a_ret_code, uint32_t a_action, dap_chain_net_srv_uid_t a_uid)
{
dap_atom_notify_arg_t *l_arg = (dap_atom_notify_arg_t*)a_arg;
dap_chain_datum_t *l_datum = (dap_chain_datum_t*)a_datum;
if (!l_datum || l_datum->header.type_id != DAP_CHAIN_DATUM_TX)
return;
dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t*)l_datum->data;
s_save_tx_cache_for_addr(l_arg->chain, NULL, (dap_chain_datum_tx_t*)l_datum->data, a_datum_hash, a_atom_hash, a_ret_code,
(char*)dap_ledger_tx_get_token_ticker_by_hash(l_arg->net->pub.ledger, a_datum_hash),
a_uid, a_action, 'a');
}
const char* l_main_token_ticker = NULL;
static void s_callback_datum_removed_notify(void *a_arg, dap_chain_hash_fast_t *a_datum_hash, dap_chain_datum_t *a_datum)
{
if (!a_datum_hash || !a_datum || a_datum->header.type_id != DAP_CHAIN_DATUM_TX)
return;
l_main_token_ticker = dap_ledger_tx_get_token_ticker_by_hash(l_arg->net->pub.ledger, a_datum_hash);
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);
dap_atom_notify_arg_t *l_arg = (dap_atom_notify_arg_t*)a_arg;
s_save_tx_cache_for_addr(l_arg->chain, NULL, (dap_chain_datum_tx_t*)a_datum->data, a_datum_hash, NULL, 0,
NULL, (dap_chain_net_srv_uid_t){ }, DAP_CHAIN_TX_TAG_ACTION_UNKNOWN, 'd');
}
typedef struct wallet_cache_load_args {
......@@ -808,311 +649,207 @@ static void s_wallet_opened_callback(dap_chain_wallet_t *a_wallet, void *a_arg)
}
}
static int s_out_idx_cmp(dap_list_t *a_l1, dap_list_t *a_l2) {
dap_wallet_tx_cache_output_t *o1 = a_l1->data,
*o2 = a_l2->data;
return o1->tx_out_idx != o2->tx_out_idx;
}
static int s_save_tx_cache_for_addr(dap_chain_t *a_chain, dap_chain_addr_t *a_addr, 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)
static int s_save_tx_cache_for_addr(dap_chain_t *a_chain, dap_chain_addr_t *a_addr, 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, char a_cache_op)
{
int l_ret_val = 0;
int l_items_cnt = 0;
int l_ret_val = 0, l_items_cnt = 0, l_out_idx = 0, l_prev_idx;
bool l_multichannel = false;
int l_out_idx = 0;
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*)l_tx_item)->addr;
} break;
case TX_ITEM_TYPE_OUT: {
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*)l_tx_item)->addr;
l_multichannel = true;
} break;
default:{
l_out_idx++;
continue;
}
}
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);
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);
}
dap_wallet_tx_cache_t *l_wallet_tx_item = NULL;
HASH_FIND(hh, l_wallet_item->wallet_txs, a_tx_hash, sizeof(dap_hash_fast_t), l_wallet_tx_item);
if (!l_wallet_tx_item){
l_wallet_tx_item = DAP_NEW_Z(dap_wallet_tx_cache_t);
l_wallet_tx_item->tx_hash = *a_tx_hash;
l_wallet_tx_item->atom_hash = *a_atom_hash;
l_wallet_tx_item->tx = a_tx;
dap_strncpy(l_wallet_tx_item->token_ticker, a_main_token_ticker ? a_main_token_ticker : "0", DAP_CHAIN_TICKER_SIZE_MAX);
l_wallet_tx_item->ret_code = a_ret_code;
l_wallet_tx_item->srv_uid = a_srv_uid;
l_wallet_tx_item->action = a_action;
HASH_ADD(hh, l_wallet_item->wallet_txs, tx_hash, sizeof(dap_hash_fast_t), l_wallet_tx_item);
}
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 = 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);
// Add unspent out into cache
if (!a_ret_code){
dap_wallet_cache_unspent_outs_t *l_unspent_out = DAP_NEW_Z(dap_wallet_cache_unspent_outs_t);
l_unspent_out->key.tx_hash = *a_tx_hash;
l_unspent_out->key.out_idx = l_out_idx;
l_unspent_out->output = l_out;
if (l_out_type != TX_ITEM_TYPE_OUT_EXT)
dap_strncpy(l_unspent_out->token_ticker, a_main_token_ticker ? a_main_token_ticker : "0", DAP_CHAIN_TICKER_SIZE_MAX);
else
dap_strncpy(l_unspent_out->token_ticker, ((dap_chain_tx_out_ext_t*)l_tx_item)->token, DAP_CHAIN_TICKER_SIZE_MAX);
HASH_ADD(hh, l_wallet_item->unspent_outputs, key, sizeof(unspent_cache_hh_key), l_unspent_out);
}
pthread_rwlock_unlock(&s_wallet_cache_rwlock);
}
l_out_idx++;
}
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*)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))
#define m_check_addr(addr) ( \
!dap_chain_addr_is_blank(&addr) && ( \
a_addr ? dap_chain_addr_compare(&addr, a_addr) : \
( (s_wallets_cache_type == DAP_WALLET_CACHE_TYPE_LOCAL && dap_chain_wallet_addr_cache_get_name(&addr)) \
|| s_wallets_cache_type == DAP_WALLET_CACHE_TYPE_ALL ) ) \
&& addr.net_id.uint64 == a_chain->net_id.uint64 \
)
uint8_t *l_tx_item; size_t l_size;
TX_ITEM_ITER_TX(l_tx_item, l_size, a_tx) {
dap_hash_fast_t l_prev_tx_hash;
dap_chain_addr_t l_addr;
uint256_t l_value;
uint8_t *l_prev_item = NULL;
int l_prev_idx;
uint8_t l_item_type = TX_ITEM_TYPE_ANY;
switch(*l_tx_item) {
case TX_ITEM_TYPE_IN: {
l_prev_tx_hash = ((dap_chain_tx_in_t*)l_tx_item)->header.tx_prev_hash;
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_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));
if (!l_tx_prev) {
log_it(L_ERROR, "Can't find previous transaction by 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_ALL, l_prev_idx);
if (!l_prev_item)
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 output %d in tx \"%s\"", l_prev_idx, dap_hash_fast_to_str_static(&l_prev_tx_hash));
continue;
uint8_t l_out_type = *(uint8_t *)l_tx_item;
switch(l_out_type){
case TX_ITEM_TYPE_OUT_OLD: {
l_value = GET_256_FROM_64(((dap_chain_tx_out_old_t*)l_tx_item)->header.value);
l_addr_from = ((dap_chain_tx_out_old_t*)l_tx_item)->addr;
} break;
case TX_ITEM_TYPE_OUT:
case TX_ITEM_TYPE_OUT_EXT: {
l_value = ((dap_chain_tx_out_ext_t*)l_tx_item)->header.value;
l_addr_from = ((dap_chain_tx_out_ext_t*)l_tx_item)->addr;
} break;
default:
continue;
}
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);
dap_wallet_cache_t *l_wallet_item = NULL;
HASH_FIND(hh, s_wallets_cache, &l_addr_from, 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_from, sizeof(dap_chain_addr_t));
HASH_ADD(hh, s_wallets_cache, wallet_addr, sizeof(dap_chain_addr_t), l_wallet_item);
}
dap_wallet_tx_cache_t *l_wallet_tx_item = NULL;
HASH_FIND(hh, l_wallet_item->wallet_txs, a_tx_hash, sizeof(dap_hash_fast_t), l_wallet_tx_item);
if (!l_wallet_tx_item){
l_wallet_tx_item = DAP_NEW_Z(dap_wallet_tx_cache_t);
l_wallet_tx_item->tx_hash = *a_tx_hash;
l_wallet_tx_item->atom_hash = *a_atom_hash;
l_wallet_tx_item->tx = a_tx;
dap_strncpy(l_wallet_tx_item->token_ticker, a_main_token_ticker ? a_main_token_ticker : "0", DAP_CHAIN_TICKER_SIZE_MAX);
l_wallet_tx_item->multichannel = l_multichannel;
l_wallet_tx_item->ret_code = a_ret_code;
l_wallet_tx_item->srv_uid = a_srv_uid;
l_wallet_tx_item->action = a_action;
HASH_ADD(hh, l_wallet_item->wallet_txs, tx_hash, sizeof(dap_hash_fast_t), l_wallet_tx_item);
}
dap_wallet_tx_cache_input_t *l_tx_in = DAP_NEW_Z(dap_wallet_tx_cache_input_t);
l_tx_in->tx_prev_hash = l_prev_tx_hash;
l_tx_in->tx_out_prev_idx = l_prev_idx;
l_tx_in->value = l_value;
l_wallet_tx_item->tx_wallet_inputs = dap_list_append(l_wallet_tx_item->tx_wallet_inputs, l_tx_in);
// Delete unspent out from unspent outs cache
if (!a_ret_code){
unspent_cache_hh_key key;
key.tx_hash = l_prev_tx_hash;
key.out_idx = l_prev_idx;
dap_wallet_cache_unspent_outs_t *l_item = NULL;
HASH_FIND(hh, l_wallet_item->unspent_outputs, &key, sizeof(unspent_cache_hh_key), l_item);
if (l_item){
HASH_DEL(l_wallet_item->unspent_outputs, l_item);
DAP_DELETE(l_item);
}
}
pthread_rwlock_unlock(&s_wallet_cache_rwlock);
switch (*l_prev_item) {
case TX_ITEM_TYPE_OUT_OLD:
l_value = GET_256_FROM_64(((dap_chain_tx_out_old_t*)l_prev_item)->header.value);
l_addr = ((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*)l_prev_item)->header.value;
l_addr = ((dap_chain_tx_out_ext_t*)l_prev_item)->addr;
break;
default:
continue;
}
l_item_type = TX_ITEM_TYPE_IN;
} break;
case TX_ITEM_TYPE_OUT_OLD:
l_addr = ((dap_chain_tx_out_old_t*)l_tx_item)->addr;
l_item_type = TX_ITEM_TYPE_OUT_ALL;
break;
case TX_ITEM_TYPE_OUT:
l_addr = ((dap_chain_tx_out_t*)l_tx_item)->addr;
l_item_type = TX_ITEM_TYPE_OUT_ALL;
break;
case TX_ITEM_TYPE_OUT_EXT:
l_addr = ((dap_chain_tx_out_ext_t*)l_tx_item)->addr;
l_multichannel = true;
l_item_type = TX_ITEM_TYPE_OUT_ALL;
break;
case TX_ITEM_TYPE_OUT_COND:
/* Make it explicit for possible future STAKE_LOCK adoption */
// TODO
++l_out_idx;
default:
continue;
}
}
return l_ret_val;
}
static void s_callback_datum_removed_notify(void *a_arg, dap_chain_hash_fast_t *a_datum_hash, dap_chain_datum_t *a_datum)
{
if (!a_datum_hash || !a_datum || a_datum->header.type_id != DAP_CHAIN_DATUM_TX)
return;
dap_atom_notify_arg_t *l_arg = (dap_atom_notify_arg_t*)a_arg;
dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t*)a_datum->data;
int l_out_idx = 0, i = 0;
uint8_t *l_tx_item = NULL;
size_t l_size;
// remove this tx outs from unspent outs cache
TX_ITEM_ITER_TX_TYPE(l_tx_item, TX_ITEM_TYPE_OUT_ALL, l_size, i, l_tx) {
uint8_t l_out_type = *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*)l_tx_item)->addr;
} break;
case TX_ITEM_TYPE_OUT: {
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*)l_tx_item)->addr;
} break;
default:{
l_out_idx++;
continue;
}
if ( !m_check_addr(l_addr) ) {
l_out_idx += (int)(l_item_type == TX_ITEM_TYPE_OUT_ALL);
continue;
}
if(!dap_chain_addr_is_blank(&l_addr) &&
((s_wallets_cache_type == DAP_WALLET_CACHE_TYPE_LOCAL &&
dap_chain_wallet_addr_cache_get_name(&l_addr) != NULL) || s_wallets_cache_type == DAP_WALLET_CACHE_TYPE_ALL) &&
l_addr.net_id.uint64 == l_arg->chain->net_id.uint64
){
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){
dap_wallet_tx_cache_t *l_wallet_tx_item = NULL;
HASH_FIND(hh, l_wallet_item->wallet_txs, a_datum_hash, sizeof(dap_hash_fast_t), l_wallet_tx_item);
pthread_rwlock_wrlock(&s_wallet_cache_rwlock);
dap_wallet_cache_t *l_wallet_item = NULL;
dap_wallet_tx_cache_t *l_wallet_tx_item = NULL;
HASH_FIND(hh, s_wallets_cache, &l_addr, sizeof(dap_chain_addr_t), l_wallet_item);
switch (a_cache_op) {
case 'a':
if (!l_wallet_item) {
l_wallet_item = DAP_NEW_Z(dap_wallet_cache_t);
l_wallet_item->wallet_addr = l_addr;
HASH_ADD(hh, s_wallets_cache, wallet_addr, sizeof(dap_chain_addr_t), l_wallet_item);
}
HASH_FIND(hh, l_wallet_item->wallet_txs, a_tx_hash, sizeof(dap_hash_fast_t), l_wallet_tx_item);
if (!l_wallet_tx_item) {
l_wallet_tx_item = DAP_NEW(dap_wallet_tx_cache_t);
*l_wallet_tx_item = (dap_wallet_tx_cache_t){ .tx_hash = *a_tx_hash, .atom_hash = *a_atom_hash, .tx = a_tx,
.multichannel = l_multichannel, .ret_code = a_ret_code, .srv_uid = a_srv_uid, .action = a_action };
dap_strncpy(l_wallet_tx_item->token_ticker, a_main_token_ticker ? a_main_token_ticker : "0", DAP_CHAIN_TICKER_SIZE_MAX);
HASH_ADD(hh, l_wallet_item->wallet_txs, tx_hash, sizeof(dap_hash_fast_t), l_wallet_tx_item);
}
break;
case 'd': {
if (l_wallet_item) {
HASH_FIND(hh, l_wallet_item->wallet_txs, a_tx_hash, sizeof(dap_hash_fast_t), l_wallet_tx_item);
if (l_wallet_tx_item){
HASH_DEL(l_wallet_item->wallet_txs, l_wallet_tx_item);
dap_list_free_full(l_wallet_tx_item->tx_wallet_inputs, NULL);
dap_list_free_full(l_wallet_tx_item->tx_wallet_outputs, NULL);
DAP_DEL_Z(l_wallet_tx_item);
DAP_DELETE(l_wallet_tx_item);
}
if (!l_wallet_item->wallet_txs){
HASH_DEL(s_wallets_cache, l_wallet_item);
DAP_DEL_Z(l_wallet_item);
}
}
default: break;
}
switch (l_item_type) {
case TX_ITEM_TYPE_OUT_ALL: {
switch (a_cache_op) {
case 'a': {
dap_wallet_tx_cache_output_t *l_out = DAP_NEW(dap_wallet_tx_cache_output_t);
*l_out = (dap_wallet_tx_cache_output_t){ .tx_out = l_tx_item, .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);
/* Add unspent out to cache */
if (!a_ret_code) {
dap_wallet_cache_unspent_outs_t *l_unspent_out = DAP_NEW(dap_wallet_cache_unspent_outs_t);
*l_unspent_out = (dap_wallet_cache_unspent_outs_t) {
.key = { .tx_hash = *a_tx_hash, .out_idx = l_out_idx },
.output = l_out
};
dap_strncpy(l_unspent_out->token_ticker, *l_tx_item == TX_ITEM_TYPE_OUT_EXT ? ((dap_chain_tx_out_ext_t*)l_tx_item)->token
: a_main_token_ticker ? a_main_token_ticker : "0", DAP_CHAIN_TICKER_SIZE_MAX);
HASH_ADD(hh, l_wallet_item->unspent_outputs, key, sizeof(unspent_cache_hh_key), l_unspent_out);
}
unspent_cache_hh_key key = {0};
key.tx_hash = *a_datum_hash;
key.out_idx = l_out_idx;
++l_out_idx;
} break;
case 'd': {
if ( !l_wallet_item->wallet_txs ) {
HASH_DEL(s_wallets_cache, l_wallet_item);
DAP_DELETE(l_wallet_item);
}
unspent_cache_hh_key key = { .tx_hash = *a_tx_hash, .out_idx = l_out_idx };
dap_wallet_cache_unspent_outs_t *l_item = NULL;
HASH_FIND(hh, l_wallet_item->unspent_outputs, &key, sizeof(unspent_cache_hh_key), l_item);
if (l_item){
if (l_item) {
HASH_DEL(l_wallet_item->unspent_outputs, l_item);
DAP_DELETE(l_item);
}
} break;
default: break;
}
pthread_rwlock_unlock(&s_wallet_cache_rwlock);
}
l_out_idx++;
}
// return previous transactions outs to unspent outs cache
TX_ITEM_ITER_TX_TYPE(l_tx_item, TX_ITEM_TYPE_IN_ALL, l_size, i, l_tx) {
uint8_t l_cond_type = *l_tx_item;
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*)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 *)(l_arg->chain->callback_datum_find_by_hash(l_arg->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_ALL, l_prev_idx);
if (!l_prev_item)
continue;
uint8_t l_out_type = *(uint8_t *)l_prev_item;
switch(l_out_type){
case TX_ITEM_TYPE_OUT_OLD: {
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_addr_from = ((dap_chain_tx_out_ext_t*)l_prev_item)->addr;
} break;
default:
continue;
}
if(!dap_chain_addr_is_blank(&l_addr_from) && ((s_wallets_cache_type == DAP_WALLET_CACHE_TYPE_LOCAL &&
dap_chain_wallet_addr_cache_get_name(&l_addr_from) != NULL) || s_wallets_cache_type == DAP_WALLET_CACHE_TYPE_ALL) &&
l_addr_from.net_id.uint64 == l_arg->chain->net_id.uint64
){
pthread_rwlock_wrlock(&s_wallet_cache_rwlock);
dap_wallet_cache_t *l_wallet_item = NULL;
HASH_FIND(hh, s_wallets_cache, &l_addr_from, sizeof(dap_chain_addr_t), l_wallet_item);
if (l_wallet_item){
dap_wallet_tx_cache_t *l_wallet_tx_item = NULL;
HASH_FIND(hh, l_wallet_item->wallet_txs, a_datum_hash, sizeof(dap_hash_fast_t), l_wallet_tx_item);
if (l_wallet_tx_item){
HASH_DEL(l_wallet_item->wallet_txs, l_wallet_tx_item);
dap_list_free_full(l_wallet_tx_item->tx_wallet_inputs, NULL);
dap_list_free_full(l_wallet_tx_item->tx_wallet_outputs, NULL);
DAP_DEL_Z(l_wallet_tx_item);
} break;
case TX_ITEM_TYPE_IN: {
switch (a_cache_op) {
case 'a': {
dap_wallet_tx_cache_input_t *l_tx_in = DAP_NEW(dap_wallet_tx_cache_input_t);
*l_tx_in = (dap_wallet_tx_cache_input_t) { .tx_prev_hash = l_prev_tx_hash, .tx_out_prev_idx = l_prev_idx, .value = l_value };
l_wallet_tx_item->tx_wallet_inputs = dap_list_append(l_wallet_tx_item->tx_wallet_inputs, l_tx_in);
/* Delete unspent out from cache */
if (!a_ret_code) {
unspent_cache_hh_key key = { .tx_hash = l_prev_tx_hash, .out_idx = l_prev_idx };
dap_wallet_cache_unspent_outs_t *l_item = NULL;
HASH_FIND(hh, l_wallet_item->unspent_outputs, &key, sizeof(unspent_cache_hh_key), l_item);
if (l_item) {
HASH_DEL(l_wallet_item->unspent_outputs, l_item);
DAP_DELETE(l_item);
}
// Add unspent out into cache
dap_wallet_tx_cache_t *l_wallet_prev_tx_item = NULL;
HASH_FIND(hh, l_wallet_item->wallet_txs, &l_prev_tx_hash, sizeof(dap_hash_fast_t), l_wallet_prev_tx_item);
if (l_wallet_prev_tx_item){
if (!l_wallet_prev_tx_item->ret_code){
void *l_out = NULL;
for (dap_list_t *it = l_wallet_prev_tx_item->tx_wallet_outputs; it; it=it->next){
if (((dap_wallet_tx_cache_output_t *)it->data)->tx_out_idx == l_prev_idx)
l_out = ((dap_wallet_tx_cache_output_t *)it->data)->tx_out;
}
if (l_out){
dap_wallet_cache_unspent_outs_t *l_unspent_out = DAP_NEW_Z(dap_wallet_cache_unspent_outs_t);
l_unspent_out->key.tx_hash = l_prev_tx_hash;
l_unspent_out->key.out_idx = l_prev_idx;
l_unspent_out->output = l_out;
if (l_out_type != TX_ITEM_TYPE_OUT_EXT)
dap_strncpy(l_unspent_out->token_ticker, l_wallet_prev_tx_item->token_ticker, DAP_CHAIN_TICKER_SIZE_MAX);
else
dap_strncpy(l_unspent_out->token_ticker, ((dap_chain_tx_out_ext_t*)l_tx_item)->token, DAP_CHAIN_TICKER_SIZE_MAX);
HASH_ADD(hh, l_wallet_item->unspent_outputs, key, sizeof(unspent_cache_hh_key), l_unspent_out);
}
}
}
} break;
case 'd': {
dap_wallet_tx_cache_t *l_wallet_prev_tx_item = NULL;
HASH_FIND(hh, l_wallet_item->wallet_txs, &l_prev_tx_hash, sizeof(dap_hash_fast_t), l_wallet_prev_tx_item);
if ( l_wallet_prev_tx_item && !l_wallet_prev_tx_item->ret_code ) {
dap_wallet_tx_cache_output_t l_sought_out = { .tx_out_idx = l_prev_idx };
void *l_out = dap_list_find(l_wallet_prev_tx_item->tx_wallet_outputs, &l_sought_out, s_out_idx_cmp);
if (l_out) {
dap_wallet_cache_unspent_outs_t *l_unspent_out = DAP_NEW_Z(dap_wallet_cache_unspent_outs_t);
*l_unspent_out = (dap_wallet_cache_unspent_outs_t) { .key = { .tx_hash = l_prev_tx_hash, .out_idx = l_prev_idx },
.output = l_out };
dap_strncpy(l_unspent_out->token_ticker, *l_prev_item == TX_ITEM_TYPE_OUT_EXT ? ((dap_chain_tx_out_ext_t*)l_tx_item)->token
: l_wallet_prev_tx_item->token_ticker, DAP_CHAIN_TICKER_SIZE_MAX);
HASH_ADD(hh, l_wallet_item->unspent_outputs, key, sizeof(unspent_cache_hh_key), l_unspent_out);
}
}
pthread_rwlock_unlock(&s_wallet_cache_rwlock);
}
} break;
default: break;
}
} break;
default: break;
}
}
pthread_rwlock_unlock(&s_wallet_cache_rwlock);
}
return l_ret_val;
}
static void s_wallet_cache_iter_fill(dap_chain_wallet_cache_iter_t *a_cache_iter, dap_wallet_tx_cache_t *a_cache_index)
{
a_cache_iter->cur_item = (void*)a_cache_index;
......
......@@ -88,7 +88,7 @@ uint256_t dap_chain_wallet_get_balance(dap_chain_wallet_t *a_wallet, dap_chain_n
int dap_chain_wallet_save_file( dap_chain_wallet_t * a_wallet);
int dap_chain_wallet_activate (const char *a_name, ssize_t a_name_len, const char *a_pass, ssize_t a_pass_len, unsigned a_ttl);
int dap_chain_wallet_activate (const char *a_name, ssize_t a_name_len, const char *a_path, const char *a_pass, ssize_t a_pass_len, unsigned a_ttl);
int dap_chain_wallet_deactivate (const char *a_name, ssize_t a_name_len);
const char* dap_chain_wallet_check_sign(dap_chain_wallet_t *a_wallet);
......@@ -103,4 +103,4 @@ dap_list_t* dap_chain_wallet_get_local_addr();
#ifdef __cplusplus
}
#endif
\ No newline at end of file
#endif