diff --git a/dap-sdk b/dap-sdk index 648afd3a17e1f0705740641d007e396a72f24cc0..fb43e24152da3868bafacf5c1b41f4b1b70d3b3c 160000 --- a/dap-sdk +++ b/dap-sdk @@ -1 +1 @@ -Subproject commit 648afd3a17e1f0705740641d007e396a72f24cc0 +Subproject commit fb43e24152da3868bafacf5c1b41f4b1b70d3b3c diff --git a/modules/chain/dap_chain_policy.c b/modules/chain/dap_chain_policy.c index 0fcf85b11faf6623b07679a15d059670db62033d..5f687069319ab8dc9f780d70e4e80d6e65bf64ad 100644 --- a/modules/chain/dap_chain_policy.c +++ b/modules/chain/dap_chain_policy.c @@ -94,15 +94,17 @@ int dap_chain_policy_net_add(uint64_t a_net_id) int dap_chain_policy_net_remove(uint64_t a_net_id) { dap_return_val_if_pass(!a_net_id, -1); - struct policy_net_list_item *l_net_item = s_net_find(a_net_id); + dap_list_t *l_net_item = dap_list_first(s_net_list); + for ( ; l_net_item && ((struct policy_net_list_item *)(l_net_item->data))->net_id != a_net_id; l_net_item = l_net_item->next) {}; + if (!l_net_item) { log_it(L_ERROR, "Can't find net %"DAP_UINT64_FORMAT_X" in policy list", a_net_id); return -2; } s_net_list = dap_list_remove_link(s_net_list, l_net_item); - dap_list_free_full(l_net_item->policies, NULL); - dap_list_free(l_net_item->exception_list); - DAP_DELETE(l_net_item); + dap_list_free_full(((struct policy_net_list_item *)(l_net_item->data))->policies, NULL); + dap_list_free(((struct policy_net_list_item *)(l_net_item->data))->exception_list); + DAP_DEL_MULTY(l_net_item->data, l_net_item); return 0; } @@ -127,11 +129,11 @@ int dap_chain_policy_add(dap_chain_policy_t *a_policy, uint64_t a_net_id) l_net_item->policies = dap_list_insert_sorted(l_net_item->policies, a_policy, s_policy_num_compare); for (size_t i = 0; i < a_policy->deactivate.count; ++i) { uint32_t l_policy_num = a_policy->deactivate.nums[i]; - if (dap_list_find(l_net_item->exception_list, (const void *)l_policy_num, NULL)) { + if (dap_list_find(l_net_item->exception_list, (const void *)(uintptr_t)l_policy_num, NULL)) { log_it(L_ERROR, "CN-%u already added to exception list net %"DAP_UINT64_FORMAT_X, l_policy_num, a_net_id); continue; } - l_net_item->exception_list = dap_list_append(l_net_item->exception_list, (const void *)l_policy_num); + l_net_item->exception_list = dap_list_append(l_net_item->exception_list, (void *)(uintptr_t)l_policy_num); } l_net_item->last_num_policy = dap_max(a_policy->activate.num, l_net_item->last_num_policy); return 0; @@ -150,11 +152,11 @@ int dap_chain_policy_add_to_exception_list(uint32_t a_policy_num, uint64_t a_net log_it(L_ERROR, "Can't find net %"DAP_UINT64_FORMAT_X" in policy list", a_net_id); return -2; } - if (dap_list_find(l_net_item->exception_list, (const void *)a_policy_num, NULL)) { + if (dap_list_find(l_net_item->exception_list, (const void *)(uintptr_t)a_policy_num, NULL)) { log_it(L_ERROR, "CN-%u already added to exception list net %"DAP_UINT64_FORMAT_X, a_policy_num, a_net_id); return -3; } - l_net_item->exception_list = dap_list_append(l_net_item->exception_list, (const void *)a_policy_num); + l_net_item->exception_list = dap_list_append(l_net_item->exception_list, (void *)(uintptr_t)a_policy_num); return 0; } @@ -172,7 +174,7 @@ bool dap_chain_policy_activated(uint32_t a_policy_num, uint64_t a_net_id) if (l_net_item->last_num_policy < a_policy_num) return l_ret; // exception list check - if (dap_list_find(l_net_item->exception_list, (const void *)a_policy_num, NULL)) + if (dap_list_find(l_net_item->exception_list, (const void *)(uintptr_t)a_policy_num, NULL)) return l_ret; // seach politics to condition check dap_chain_policy_t l_to_search = { @@ -244,18 +246,24 @@ json_object *dap_chain_policy_list(uint64_t a_net_id) dap_return_val_if_pass(!l_net_item, NULL); json_object *l_ret = json_object_new_object(); - dap_string_t *l_add_str = dap_string_new(""); + dap_string_t *l_active_str = dap_string_new(""); + dap_string_t *l_inactive_str = dap_string_new(""); for (dap_list_t *l_iter = dap_list_first(l_net_item->policies); l_iter; l_iter = l_iter->next) { - dap_string_append_printf(l_add_str, "CN-%u ", ((dap_chain_policy_t *)l_iter->data)->activate.num); + if (dap_chain_policy_activated(((dap_chain_policy_t *)l_iter->data)->activate.num, a_net_id)) + dap_string_append_printf(l_active_str, "CN-%u ", ((dap_chain_policy_t *)l_iter->data)->activate.num); + else + dap_string_append_printf(l_inactive_str, "CN-%u ", ((dap_chain_policy_t *)l_iter->data)->activate.num); } - json_object_object_add(l_ret, "active", json_object_new_string(l_add_str->str)); + json_object_object_add(l_ret, "active", json_object_new_string(l_active_str->str)); + json_object_object_add(l_ret, "inactive", json_object_new_string(l_inactive_str->str)); - dap_string_erase(l_add_str, 0, -1); + dap_string_free(l_active_str, true); + dap_string_erase(l_inactive_str, 0, -1); for (dap_list_t *l_iter = dap_list_first(l_net_item->exception_list); l_iter; l_iter = l_iter->next) { - dap_string_append_printf(l_add_str, "CN-%u ", (uint32_t)l_iter->data); + dap_string_append_printf(l_inactive_str, "CN-%u ", (uint32_t)(uintptr_t)l_iter->data); } - json_object_object_add(l_ret, "inactive", json_object_new_string(l_add_str->str)); - dap_string_free(l_add_str, true); + json_object_object_add(l_ret, "in exception list", json_object_new_string(l_inactive_str->str)); + dap_string_free(l_inactive_str, true); return l_ret; } diff --git a/modules/datum/dap_chain_datum_tx_items.c b/modules/datum/dap_chain_datum_tx_items.c index e900d2a22b813eba67ff43ba4151b7378ea50004..23ff6f240fb089de18f1c0824be865a585a221b6 100644 --- a/modules/datum/dap_chain_datum_tx_items.c +++ b/modules/datum/dap_chain_datum_tx_items.c @@ -104,7 +104,7 @@ dap_chain_tx_out_cond_subtype_t dap_chain_tx_out_cond_subtype_from_str(const cha */ size_t dap_chain_datum_item_tx_get_size(const byte_t *a_item, size_t a_max_size) { - dap_return_val_if_fail(a_item, TX_ITEM_TYPE_UNKNOWN); + dap_return_val_if_fail(a_item, 0); size_t l_ret = 0; #define m_tx_item_size(t) ( !a_max_size || sizeof(t) <= a_max_size ? sizeof(t) : 0 ) #define m_tx_item_size_ext(t, size_field) \ diff --git a/modules/datum/include/dap_chain_datum_token.h b/modules/datum/include/dap_chain_datum_token.h index a36b5ee5acece83ca9f1d7d6fef133c230add795..9c331e3844f1f5fd194b955e6b695e645a4ace21 100644 --- a/modules/datum/include/dap_chain_datum_token.h +++ b/modules/datum/include/dap_chain_datum_token.h @@ -341,6 +341,7 @@ typedef struct dap_chain_datum_token_emission { #define DAP_CHAIN_DATUM_EMISSION_TSD_TYPE_SIGNATURS 0x000E #define DAP_CHAIN_DATUM_EMISSION_TSD_TYPE_UNIQUE_ID 0x000F #define DAP_CHAIN_DATUM_EMISSION_TSD_TYPE_BASE_TX_HASH 0x0010 +#define DAP_CHAIN_DATUM_EMISSION_TSD_TYPE_TAG 0x0011 // TSD sections with transfer additional params #define DAP_CHAIN_DATUM_TRANSFER_TSD_TYPE_OUT_COUNT 0x0013 diff --git a/modules/ledger/dap_chain_ledger.c b/modules/ledger/dap_chain_ledger.c index 1781764b02c892b6b8092a20b78367cd2dc8b82f..5b5d7481e73f2d80b1250fdd26acbb99cb3f4398 100644 --- a/modules/ledger/dap_chain_ledger.c +++ b/modules/ledger/dap_chain_ledger.c @@ -834,6 +834,9 @@ const char *dap_ledger_tx_action_str(dap_chain_tx_tag_action_type_t a_tag) if (a_tag == DAP_CHAIN_TX_TAG_ACTION_CHANGE) return "change"; if (a_tag == DAP_CHAIN_TX_TAG_ACTION_VOTING) return "voting"; if (a_tag == DAP_CHAIN_TX_TAG_ACTION_VOTE) return "vote"; + if (a_tag == DAP_CHAIN_TX_TAG_ACTION_EMIT_DELEGATE_HOLD) return "hold"; + if (a_tag == DAP_CHAIN_TX_TAG_ACTION_EMIT_DELEGATE_TAKE) return "take"; + if (a_tag == DAP_CHAIN_TX_TAG_ACTION_EMIT_DELEGATE_REFILL) return "refill"; return "WTFSUBTAG"; @@ -856,6 +859,9 @@ dap_chain_tx_tag_action_type_t dap_ledger_tx_action_str_to_action_t(const char * if (strcmp("change", a_str) == 0) return DAP_CHAIN_TX_TAG_ACTION_CHANGE; if (strcmp("voting", a_str) == 0) return DAP_CHAIN_TX_TAG_ACTION_VOTING; if (strcmp("vote", a_str) == 0) return DAP_CHAIN_TX_TAG_ACTION_VOTE; + if (strcmp("hold", a_str) == 0) return DAP_CHAIN_TX_TAG_ACTION_EMIT_DELEGATE_HOLD; + if (strcmp("take", a_str) == 0) return DAP_CHAIN_TX_TAG_ACTION_EMIT_DELEGATE_TAKE; + if (strcmp("refill", a_str) == 0) return DAP_CHAIN_TX_TAG_ACTION_EMIT_DELEGATE_REFILL; return DAP_CHAIN_TX_TAG_ACTION_UNKNOWN; diff --git a/modules/ledger/include/dap_chain_ledger.h b/modules/ledger/include/dap_chain_ledger.h index 771792c27298ee3e6b56c61283500aad1d19d995..ad3a3a3f2647e0d7dd5c9dd382c5e584661e8990 100644 --- a/modules/ledger/include/dap_chain_ledger.h +++ b/modules/ledger/include/dap_chain_ledger.h @@ -156,6 +156,10 @@ typedef enum dap_chain_tx_tag_action_type { DAP_CHAIN_TX_TAG_ACTION_VOTING = 1 << 11, DAP_CHAIN_TX_TAG_ACTION_VOTE = 1 << 12, + + DAP_CHAIN_TX_TAG_ACTION_EMIT_DELEGATE_HOLD = 1 << 13, + DAP_CHAIN_TX_TAG_ACTION_EMIT_DELEGATE_TAKE = 1 << 14, + DAP_CHAIN_TX_TAG_ACTION_EMIT_DELEGATE_REFILL = 1 << 15, DAP_CHAIN_TX_TAG_ACTION_ALL = ~0, } dap_chain_tx_tag_action_type_t; diff --git a/modules/node-cli/dap_chain_node_cli.c b/modules/node-cli/dap_chain_node_cli.c index 5d63e388b8dda05e75acaa38a7b9a8abbc18f0a5..b4492e3f95e3245e0c57e90c52b1746edf8d82c3 100644 --- a/modules/node-cli/dap_chain_node_cli.c +++ b/modules/node-cli/dap_chain_node_cli.c @@ -384,8 +384,8 @@ int dap_chain_node_cli_init(dap_config_t * g_config) dap_cli_server_cmd_add ("policy", com_policy, "Policy commands", "policy [execute] - prepare or create policy execute decree\n" "\t-net <net_name> - net name to policy apply\n" "\t-num <policy_num> - policy num\n" - "\t[-ts_start <dd/mm/YY-H:M:S>] - date to start policy\n" - "\t[-ts_stop <dd/mm/YY-H:M:S>] - date to stop policy\n" + "\t[-ts_start <dd/mm/yy-H:M:S>] - date to start policy\n" + "\t[-ts_stop <dd/mm/yy-H:M:S>] - date to stop policy\n" "\t{\n\t\t[-block_start <block_num>] - block num to start policy\n" "\t\t[-block_stop <block_num>] - block num to stop policy\n" "\t\t-chain <chain_name> - chain name to check blocks num\n\t}\n" diff --git a/modules/node-cli/dap_chain_node_cli_cmd.c b/modules/node-cli/dap_chain_node_cli_cmd.c index 4fc6f43312061da6d46a540556a778ae02382091..455ac9f06db69a7f5328d2e5e628b19c9dc3a31c 100644 --- a/modules/node-cli/dap_chain_node_cli_cmd.c +++ b/modules/node-cli/dap_chain_node_cli_cmd.c @@ -86,6 +86,7 @@ #include "dap_chain_wallet_cache.h" #include "dap_chain_net_srv_stake_pos_delegate.h" #include "dap_chain_policy.h" +#include "dap_time.h" #define LOG_TAG "chain_node_cli_cmd" @@ -6030,17 +6031,21 @@ int com_policy(int argc, char **argv, void **reply) { if (l_ts_start_str) { - struct tm l_tm = { }; - strptime(l_ts_start_str, "%d/%m/%Y-%H:%M:%S", &l_tm); - l_tm.tm_year += 2000; - l_policy->activate.ts_start = mktime(&l_tm); + l_policy->activate.ts_start = dap_time_from_str_custom(l_ts_start_str, "%d/%m/%y-%H:%M:%S"); + if (!l_policy->activate.ts_start) { + dap_json_rpc_error_add(*a_json_arr_reply, -13, "Can't read ts_start \"%s\"", l_ts_start_str); + DAP_DELETE(l_policy); + return -13; + } } if (l_ts_stop_str) { - struct tm l_tm = { }; - strptime(l_ts_stop_str, "%d/%m/%Y-%H:%M:%S", &l_tm); - l_tm.tm_year += 2000; - l_policy->activate.ts_stop = mktime(&l_tm); + l_policy->activate.ts_stop = dap_time_from_str_custom(l_ts_stop_str, "%d/%m/%y-%H:%M:%S"); + if (!l_policy->activate.ts_stop) { + dap_json_rpc_error_add(*a_json_arr_reply, -14, "Can't read ts_stop \"%s\"", l_ts_stop_str); + DAP_DELETE(l_policy); + return -14; + } if (l_policy->activate.ts_stop <= l_policy->activate.ts_start) { dap_json_rpc_error_add(*a_json_arr_reply, -12, "ts_start should less than ts_stop"); DAP_DELETE(l_policy); diff --git a/modules/node-cli/dap_chain_node_cli_cmd_tx.c b/modules/node-cli/dap_chain_node_cli_cmd_tx.c index 023785c05e0501092fcb498fed1a3464a1eefc93..9fe0571014fbd153ff241e29e3f822a73c95eddc 100644 --- a/modules/node-cli/dap_chain_node_cli_cmd_tx.c +++ b/modules/node-cli/dap_chain_node_cli_cmd_tx.c @@ -450,7 +450,7 @@ json_object* dap_db_history_addr(json_object* a_json_arr_reply, dap_chain_addr_t int l_src_subtype = DAP_CHAIN_TX_OUT_COND_SUBTYPE_UNDEFINED; uint8_t *l_tx_item = NULL; size_t l_size; int i, q = 0; - // Проход по входам + // Check all INs TX_ITEM_ITER_TX_TYPE(l_tx_item, TX_ITEM_TYPE_IN_ALL, l_size, i, l_tx) { dap_chain_hash_fast_t *l_tx_prev_hash = NULL; int l_tx_prev_out_idx; @@ -573,7 +573,7 @@ json_object* dap_db_history_addr(json_object* a_json_arr_reply, dap_chain_addr_t case TX_ITEM_TYPE_OUT_COND: l_value = ((dap_chain_tx_out_cond_t *)it->data)->header.value; if (((dap_chain_tx_out_cond_t *)it->data)->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE) { - SUM_256_256(l_fee_sum, ((dap_chain_tx_out_cond_t *)it->data)->header.value, &l_fee_sum); + SUM_256_256(l_fee_sum, l_value, &l_fee_sum); l_dst_token = l_native_ticker; } else l_dst_token = l_src_token; @@ -725,7 +725,6 @@ json_object* dap_db_history_addr(json_object* a_json_arr_reply, dap_chain_addr_t json_object *l_cond_send_value_obj = json_object_object_get(l_cond_send_object, "send_datoshi"); const char *l_cond_send_value_str = json_object_get_string(l_cond_send_value_obj); uint256_t l_cond_send_value = dap_uint256_scan_uninteger(l_cond_send_value_str); - assert(!IS_ZERO_256(l_cond_recv_value) && !IS_ZERO_256(l_cond_send_value)); int l_direction = compare256(l_cond_recv_value, l_cond_send_value); if (l_direction > 0) { SUBTRACT_256_256(l_cond_recv_value, l_cond_send_value, &l_cond_recv_value); 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 4b2e0769f388cc9dead37cf9b9d22d8fda6df377..465ebb9e37859de3a002d25ae8b2990c424592ed 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 @@ -45,7 +45,8 @@ enum emit_delegation_error { ERROR_COMPOSE, ERROR_CREATE, ERROR_PLACE, - ERROR_SUBCOMMAND + ERROR_SUBCOMMAND, + ERROR_NETWORK }; #define LOG_TAG "dap_chain_net_srv_emit_delegate" @@ -58,6 +59,7 @@ static int s_emit_delegate_verificator(dap_ledger_t *a_ledger, dap_chain_datum_t uint256_t l_writeoff_value = uint256_0; dap_chain_tx_out_cond_t *l_cond_out = NULL; dap_chain_addr_t l_net_fee_addr; + uint16_t l_change_type = 0; bool l_net_fee_used = dap_chain_net_tx_get_fee(a_ledger->net->pub.id, NULL, &l_net_fee_addr); byte_t *l_item; size_t l_tx_item_size; TX_ITEM_ITER_TX(l_item, l_tx_item_size, a_tx_in) { @@ -74,7 +76,7 @@ static int s_emit_delegate_verificator(dap_ledger_t *a_ledger, dap_chain_datum_t break; case TX_ITEM_TYPE_TSD: { dap_tsd_t *l_tsd = (dap_tsd_t *)((dap_chain_tx_tsd_t *)l_item)->tsd; - if (l_tsd->type != DAP_CHAIN_NET_SRV_EMIT_DELEGATE_TSD_WRITEOFF) + if (l_tsd->type != DAP_CHAIN_NET_SRV_EMIT_DELEGATE_TSD_WRITEOFF && l_tsd->type != DAP_CHAIN_NET_SRV_EMIT_DELEGATE_TSD_REFILL) break; // Skip it if (l_tsd->size != sizeof(uint256_t)) { log_it(L_ERROR, "TSD section size control error"); @@ -85,6 +87,7 @@ static int s_emit_delegate_verificator(dap_ledger_t *a_ledger, dap_chain_datum_t return -5; } l_writeoff_value = dap_tsd_get_scalar(l_tsd, uint256_t); + l_change_type = l_tsd->type; break; } // Verify signs @@ -123,13 +126,22 @@ static int s_emit_delegate_verificator(dap_ledger_t *a_ledger, dap_chain_datum_t } uint256_t l_change_value; - if (SUBTRACT_256_256(a_cond->header.value, l_writeoff_value, &l_change_value)) { + if (l_change_type == DAP_CHAIN_NET_SRV_EMIT_DELEGATE_TSD_WRITEOFF && SUBTRACT_256_256(a_cond->header.value, l_writeoff_value, &l_change_value)) { char *l_balance = dap_uint256_decimal_to_char(a_cond->header.value); - const char *l_writeoff; dap_uint256_to_char(l_writeoff_value, &l_writeoff); + const char *l_writeoff = NULL; + dap_uint256_to_char(l_change_value, &l_writeoff); log_it(L_ERROR, "Write-off value %s is greater than account balance %s", l_writeoff, l_balance); DAP_DELETE(l_balance); return -7; } + if (l_change_type == DAP_CHAIN_NET_SRV_EMIT_DELEGATE_TSD_REFILL && SUM_256_256(a_cond->header.value, l_writeoff_value, &l_change_value)) { + char *l_balance = dap_uint256_decimal_to_char(a_cond->header.value); + const char *l_refill = NULL; + dap_uint256_to_char(l_change_value, &l_refill); + log_it(L_ERROR, "Sum of re-fill value %s and account balance %s is owerflow 256 bit num", l_refill, l_balance); + DAP_DELETE(l_balance); + return -9; + } if (!IS_ZERO_256(l_change_value)) { if (!l_cond_out) { log_it(L_ERROR, "Changeback on conditional output is need but not found"); @@ -146,9 +158,6 @@ static int s_emit_delegate_verificator(dap_ledger_t *a_ledger, dap_chain_datum_t log_it(L_ERROR, "Condtional output in current TX have different TSD sections vs previous TX's one"); return -11; } - } else if (l_cond_out) { - log_it(L_ERROR, "Changeback on conditional output is not need but found"); - return -10; } if (l_signs_verified < a_cond->subtype.srv_emit_delegate.signers_minimum) { @@ -161,7 +170,17 @@ static int s_emit_delegate_verificator(dap_ledger_t *a_ledger, dap_chain_datum_t static bool s_tag_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_datum_tx_item_groups_t *a_items_grp, dap_chain_tx_tag_action_type_t *a_action) { - return a_items_grp->items_out_cond_srv_emit_delegate; + if (!a_items_grp->items_out_cond_srv_emit_delegate) + return false; + if (a_action) { + if (dap_chain_datum_tx_item_get_tsd_by_type(a_tx, DAP_CHAIN_NET_SRV_EMIT_DELEGATE_TSD_WRITEOFF)) + *a_action = DAP_CHAIN_TX_TAG_ACTION_EMIT_DELEGATE_TAKE; + else if (dap_chain_datum_tx_item_get_tsd_by_type(a_tx, DAP_CHAIN_NET_SRV_EMIT_DELEGATE_TSD_REFILL)) + *a_action = DAP_CHAIN_TX_TAG_ACTION_EMIT_DELEGATE_REFILL; + else + *a_action = DAP_CHAIN_TX_TAG_ACTION_EMIT_DELEGATE_HOLD; + } + return true; } // Put a transaction to the mempool @@ -185,7 +204,7 @@ static char *s_tx_put(dap_chain_datum_tx_t *a_tx, dap_chain_t *a_chain, const ch static dap_chain_datum_tx_t *s_emitting_tx_create(json_object *a_json_arr_reply, dap_chain_net_t *a_net, dap_enc_key_t *a_enc_key, const char *a_token_ticker, uint256_t a_value, uint256_t a_fee, - uint32_t a_signs_min, dap_hash_fast_t *a_pkey_hashes, size_t a_pkey_hashes_count) + uint32_t a_signs_min, dap_hash_fast_t *a_pkey_hashes, size_t a_pkey_hashes_count, const char *a_tag_str) { const char *l_native_ticker = a_net->pub.native_ticker; bool l_delegate_native = !dap_strcmp(l_native_ticker, a_token_ticker); @@ -265,6 +284,131 @@ static dap_chain_datum_tx_t *s_emitting_tx_create(json_object *a_json_arr_reply, m_tx_fail(ERROR_COMPOSE, "Cant add fee back output"); } + if (a_tag_str) { + dap_chain_tx_tsd_t *tsd_tag_item = dap_chain_datum_tx_item_tsd_create(a_tag_str, DAP_CHAIN_DATUM_EMISSION_TSD_TYPE_TAG, strlen(a_tag_str) + 1); + if (!tsd_tag_item) + m_tx_fail(ERROR_COMPOSE, "Can't compose the transaction tag"); + if (dap_chain_datum_tx_add_item(&l_tx, tsd_tag_item) != 1) { + DAP_DELETE(tsd_tag_item); + m_tx_fail(ERROR_COMPOSE, "Can't add the transaction tag"); + } + DAP_DELETE(tsd_tag_item); + } + // add 'sign' item + if (dap_chain_datum_tx_add_sign_item(&l_tx, a_enc_key) != 1) + m_tx_fail(ERROR_COMPOSE, "Can't add sign output"); + + + return l_tx; +} + + +dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_refilling_tx_create(json_object *a_json_arr_reply, dap_chain_net_t *a_net, dap_enc_key_t *a_enc_key, + uint256_t a_value, uint256_t a_fee, dap_hash_fast_t *a_tx_in_hash, dap_list_t* tsd_items) +{ + dap_return_val_if_pass(!a_net || IS_ZERO_256(a_value) || IS_ZERO_256(a_fee), NULL); + // create empty transaction + dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create(); + + dap_ledger_t *l_ledger = a_net->pub.ledger; + const char *l_tx_ticker = dap_ledger_tx_get_token_ticker_by_hash(a_net->pub.ledger, a_tx_in_hash); + bool l_taking_native = !dap_strcmp(a_net->pub.native_ticker, l_tx_ticker); + + uint256_t l_value = a_value, l_value_transfer = {}; // how many coins to refill + uint256_t l_net_fee, l_fee_total = a_fee; + dap_chain_addr_t l_net_fee_addr; + + bool l_net_fee_used = dap_chain_net_tx_get_fee(a_net->pub.id, &l_net_fee, &l_net_fee_addr); + if (l_net_fee_used && SUM_256_256(l_fee_total, l_net_fee, &l_fee_total)) + m_tx_fail(ERROR_OVERFLOW, "Integer overflow in TX composer"); + if (SUM_256_256(l_value, l_fee_total, &l_value)) + m_tx_fail(ERROR_OVERFLOW, "Integer overflow in TX composer"); + + dap_chain_addr_t l_owner_addr; + dap_chain_addr_fill_from_key(&l_owner_addr, a_enc_key, a_net->pub.id); + dap_list_t *l_list_fee_out = dap_chain_wallet_get_list_tx_outs_with_val(l_ledger, a_net->pub.native_ticker, + &l_owner_addr, l_value, &l_value_transfer); + if (!l_list_fee_out) + m_tx_fail(ERROR_FUNDS, "Nothing to pay for fee (not enough funds)"); + // add 'in' items to pay fee + uint256_t l_value_fee_items = dap_chain_datum_tx_add_in_item_list(&l_tx, l_list_fee_out); + dap_list_free_full(l_list_fee_out, NULL); + if (!EQUAL_256(l_value_fee_items, l_value_transfer)) + m_tx_fail(ERROR_COMPOSE, "Can't compose the fee transaction input"); + + dap_hash_fast_t l_final_tx_hash = dap_ledger_get_final_chain_tx_hash(l_ledger, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_EMIT_DELEGATE, a_tx_in_hash, false); + if (dap_hash_fast_is_blank(&l_final_tx_hash)) + m_tx_fail(ERROR_FUNDS, "Nothing to refill, can't find tx"); + + log_it(L_NOTICE, "Actual TX hash %s will be used for refill TX composing", dap_hash_fast_to_str_static(&l_final_tx_hash)); + dap_chain_datum_tx_t *l_tx_in = dap_ledger_tx_find_by_hash(l_ledger, &l_final_tx_hash); + assert(l_tx_in); + int l_prev_cond_idx = 0; + dap_chain_tx_out_cond_t *l_cond_prev = dap_chain_datum_tx_out_cond_get(l_tx_in, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_EMIT_DELEGATE, &l_prev_cond_idx); + if (!l_cond_prev) + m_tx_fail(ERROR_TX_MISMATCH, "Requested conditional transaction requires conditional output"); + + if (dap_ledger_tx_hash_is_used_out_item(l_ledger, &l_final_tx_hash, l_prev_cond_idx, NULL)) + m_tx_fail(ERROR_TX_MISMATCH, "Requested conditional transaction is already used out"); + + // add 'in_cond' item + if (dap_chain_datum_tx_add_in_cond_item(&l_tx, &l_final_tx_hash, l_prev_cond_idx, -1) != 1) { + log_it(L_ERROR, "Can't compose the transaction conditional input"); + m_tx_fail(ERROR_COMPOSE, "Cant add conditionsl input"); + } + + // coin back + uint256_t l_value_back = {}; + if(SUM_256_256(l_cond_prev->header.value, a_value, &l_value_back)) { + m_tx_fail(ERROR_OVERFLOW, "Integer overflow in TX composer"); + } + + dap_chain_tx_out_cond_t *l_out_cond = DAP_DUP_SIZE(l_cond_prev, sizeof(dap_chain_tx_out_cond_t) + l_cond_prev->tsd_size); + if (!l_out_cond) + m_tx_fail(ERROR_MEMORY, c_error_memory_alloc); + l_out_cond->header.value = l_value_back; + if (dap_chain_datum_tx_add_item(&l_tx, (const uint8_t *)l_out_cond) < 0) { + m_tx_fail(ERROR_COMPOSE, "Cant add refill cond output"); + DAP_DELETE(l_out_cond); + } + DAP_DELETE(l_out_cond); + + + // add track for takeoff from conditional value + dap_chain_tx_tsd_t *l_refill_tsd = dap_chain_datum_tx_item_tsd_create(&a_value, DAP_CHAIN_NET_SRV_EMIT_DELEGATE_TSD_REFILL, sizeof(uint256_t)); + if (dap_chain_datum_tx_add_item(&l_tx, l_refill_tsd) != 1) { + DAP_DELETE(l_refill_tsd); + m_tx_fail(ERROR_COMPOSE, "Can't add TSD section item with withdraw value"); + } + DAP_DELETE(l_refill_tsd); + + //add other tsd if available + for ( dap_list_t *l_tsd = tsd_items; l_tsd; l_tsd = l_tsd->next ) { + if ( dap_chain_datum_tx_add_item(&l_tx, l_tsd->data) != 1 ) + m_tx_fail(ERROR_COMPOSE, "Can't add custom TSD section item "); + } + + // add fee items + if (l_net_fee_used) { + int rc = l_taking_native ? dap_chain_datum_tx_add_out_item(&l_tx, &l_net_fee_addr, l_net_fee) + : dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_net_fee_addr, l_net_fee, a_net->pub.native_ticker); + if (rc != 1) + m_tx_fail(ERROR_COMPOSE, "Cant add net fee output"); + } + if (!IS_ZERO_256(a_fee) && dap_chain_datum_tx_add_fee_item(&l_tx, a_fee) != 1) + m_tx_fail(ERROR_COMPOSE, "Cant add validator fee output"); + + uint256_t l_fee_back = {}; + // fee coin back + SUBTRACT_256_256(l_value_transfer, l_value, &l_fee_back); + + if (!IS_ZERO_256(l_fee_back)) { + int rc = l_taking_native ? dap_chain_datum_tx_add_out_item(&l_tx, &l_owner_addr, l_fee_back) + : dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_owner_addr, l_fee_back, a_net->pub.native_ticker); + if (rc != 1) + m_tx_fail(ERROR_COMPOSE, "Cant add fee back output"); + } + // add 'sign' item if (dap_chain_datum_tx_add_sign_item(&l_tx, a_enc_key) != 1) m_tx_fail(ERROR_COMPOSE, "Can't add sign output"); @@ -288,8 +432,9 @@ static bool s_is_key_present(dap_chain_tx_out_cond_t *a_cond, dap_enc_key_t *a_e } 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, dap_list_t *a_tsd_items) + dap_chain_addr_t **a_to_addr, uint256_t *a_value, size_t a_addr_count, uint256_t a_fee, dap_hash_fast_t *a_tx_in_hash, dap_list_t* a_tsd_items) { + dap_return_val_if_pass(!a_to_addr || !a_value || !a_addr_count || !a_enc_key || !a_tx_in_hash, NULL ); // create empty transaction dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create(); @@ -297,10 +442,18 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_create(json_obje const char *l_tx_ticker = dap_ledger_tx_get_token_ticker_by_hash(a_net->pub.ledger, a_tx_in_hash); bool l_taking_native = !dap_strcmp(a_net->pub.native_ticker, l_tx_ticker); - uint256_t l_value = a_value, l_fee_transfer = {}; // how many coins to transfer + uint256_t l_value = {}, l_fee_transfer = {}; // how many coins to transfer uint256_t l_net_fee, l_fee_total = a_fee; dap_chain_addr_t l_net_fee_addr; + for (size_t i = 0; i < a_addr_count; ++i) { + if(IS_ZERO_256(a_value[i])) { + m_tx_fail(ERROR_VALUE, "Format -value <256 bit integer> and not equal zero"); + } + if (SUM_256_256(l_value, a_value[i], &l_value)) + m_tx_fail(ERROR_OVERFLOW, "Integer overflow in TX composer"); + } + bool l_net_fee_used = dap_chain_net_tx_get_fee(a_net->pub.id, &l_net_fee, &l_net_fee_addr); if (l_net_fee_used && SUM_256_256(l_fee_total, l_net_fee, &l_fee_total)) m_tx_fail(ERROR_OVERFLOW, "Integer overflow in TX composer"); @@ -345,22 +498,26 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_create(json_obje } // add 'out' or 'out_ext' item for emission - int rc = l_taking_native ? dap_chain_datum_tx_add_out_item(&l_tx, a_addr_to, a_value) : - dap_chain_datum_tx_add_out_ext_item(&l_tx, a_addr_to, a_value, l_tx_ticker); - if (rc != 1) - m_tx_fail(ERROR_COMPOSE, "Cant add emission output"); + for (size_t i = 0; i < a_addr_count; ++i) { + int rc = l_taking_native ? dap_chain_datum_tx_add_out_item(&l_tx, a_to_addr[i], a_value[i]) : + dap_chain_datum_tx_add_out_ext_item(&l_tx, a_to_addr[i], a_value[i], l_tx_ticker); + if (rc != 1) + m_tx_fail(ERROR_COMPOSE, "Cant add tx output"); + } // coin back uint256_t l_value_back = {}; SUBTRACT_256_256(l_cond_prev->header.value, l_value, &l_value_back); - if (!IS_ZERO_256(l_value_back)) { - dap_chain_tx_out_cond_t *l_out_cond = DAP_DUP_SIZE(l_cond_prev, sizeof(dap_chain_tx_out_cond_t) + l_cond_prev->tsd_size); - if (!l_out_cond) - 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); + dap_chain_tx_out_cond_t *l_out_cond = DAP_DUP_SIZE(l_cond_prev, sizeof(dap_chain_tx_out_cond_t) + l_cond_prev->tsd_size); + if (!l_out_cond) + m_tx_fail(ERROR_MEMORY, c_error_memory_alloc); + l_out_cond->header.value = l_value_back; + if (-1 == dap_chain_datum_tx_add_item(&l_tx, (const uint8_t *)l_out_cond)) { DAP_DELETE(l_out_cond); + m_tx_fail(ERROR_COMPOSE, "Cant add emission cond output"); } + DAP_DELETE(l_out_cond); + // add track for takeoff from conditional value dap_chain_tx_tsd_t *l_takeoff_tsd = dap_chain_datum_tx_item_tsd_create(&l_value, DAP_CHAIN_NET_SRV_EMIT_DELEGATE_TSD_WRITEOFF, sizeof(uint256_t)); @@ -377,7 +534,7 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_create(json_obje // add fee items if (l_net_fee_used) { int rc = l_taking_native ? dap_chain_datum_tx_add_out_item(&l_tx, &l_net_fee_addr, l_net_fee) - : dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_net_fee_addr, l_net_fee, a_net->pub.native_ticker); + : dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_net_fee_addr, l_net_fee, a_net->pub.native_ticker); if (rc != 1) m_tx_fail(ERROR_COMPOSE, "Cant add net fee output"); } @@ -388,10 +545,10 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_create(json_obje // fee coin back SUBTRACT_256_256(l_fee_transfer, l_fee_total, &l_fee_back); if (!IS_ZERO_256(l_fee_back)) { - int rc = l_taking_native ? dap_chain_datum_tx_add_out_item(&l_tx, &l_owner_addr, l_fee_back) - : dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_owner_addr, l_fee_back, a_net->pub.native_ticker); - if (rc != 1) - m_tx_fail(ERROR_COMPOSE, "Cant add fee back output"); + int rc = l_taking_native ? dap_chain_datum_tx_add_out_item(&l_tx, &l_owner_addr, l_fee_back) + : dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_owner_addr, l_fee_back, a_net->pub.native_ticker); + if (rc != 1) + m_tx_fail(ERROR_COMPOSE, "Cant add fee back output"); } // add 'sign' item @@ -401,6 +558,7 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_create(json_obje return l_tx; } + #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) @@ -433,7 +591,7 @@ static dap_chain_datum_tx_t *s_taking_tx_sign(json_object *a_json_arr_reply, dap } dap_chain_datum_tx_t *l_tx = DAP_DUP_SIZE(a_tx_in, dap_chain_datum_tx_get_size(a_tx_in)); if (!l_tx) - m_sign_fail(ERROR_FUNDS, c_error_memory_alloc); + m_sign_fail(ERROR_MEMORY, c_error_memory_alloc); // add 'sign' item if (dap_chain_datum_tx_add_sign_item(&l_tx, a_enc_key) != 1) m_sign_fail(ERROR_COMPOSE, "Can't add sign output"); @@ -444,7 +602,14 @@ static dap_chain_datum_tx_t *s_taking_tx_sign(json_object *a_json_arr_reply, dap static int s_cli_hold(int a_argc, char **a_argv, int a_arg_index, json_object **a_json_arr_reply, dap_chain_net_t *a_net, dap_chain_t *a_chain, const char *a_hash_out_type) { - const char *l_token_str = NULL, *l_value_str = NULL, *l_wallet_str = NULL, *l_fee_str = NULL, *l_signs_min_str = NULL, *l_pkeys_str = NULL; + const char *l_token_str = NULL, + *l_value_str = NULL, + *l_wallet_str = NULL, + *l_fee_str = NULL, + *l_signs_min_str = NULL, + *l_pkeys_str = NULL, + *l_tag_str = NULL; + dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-token", &l_token_str); if (!l_token_str) { dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Emitting delegation holding requires parameter -token"); @@ -461,7 +626,7 @@ static int s_cli_hold(int a_argc, char **a_argv, int a_arg_index, json_object ** } uint256_t l_value = dap_chain_balance_scan(l_value_str); if (IS_ZERO_256(l_value)) { - dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Format -value <256 bit integer>"); + dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Format -value <256 bit integer> and not equal zero"); return ERROR_VALUE; } dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-fee", &l_fee_str); @@ -471,7 +636,7 @@ static int s_cli_hold(int a_argc, char **a_argv, int a_arg_index, json_object ** } uint256_t l_fee = dap_chain_balance_scan(l_fee_str); if (IS_ZERO_256(l_fee)) { - dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Format -fee <256 bit integer>"); + dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Format -fee <256 bit integer> and not equal zer"); return ERROR_VALUE; } dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-signs_minimum", &l_signs_min_str); @@ -489,11 +654,15 @@ static int s_cli_hold(int a_argc, char **a_argv, int a_arg_index, json_object ** dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Emitting delegation holding requires parameter -w"); return ERROR_PARAM; } + dap_chain_wallet_t *l_wallet = dap_chain_wallet_open(l_wallet_str, dap_chain_wallet_get_path(g_config), NULL); if (!l_wallet) { dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Specified wallet %s not found", l_wallet_str); return ERROR_VALUE; } + + dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-tag", &l_tag_str); + const char *l_sign_str = dap_chain_wallet_check_sign(l_wallet); dap_enc_key_t *l_enc_key = dap_chain_wallet_get_key(l_wallet, 0); dap_chain_wallet_close(l_wallet); @@ -524,6 +693,13 @@ static int s_cli_hold(int a_argc, char **a_argv, int a_arg_index, json_object ** DAP_DEL_MULTY(l_enc_key, l_pkey_hashes); return ERROR_VALUE; } + for (size_t j = 0; j < i; ++j) { + if (!memcmp(l_pkey_hashes + j, l_pkey_hashes + i, sizeof(dap_chain_hash_fast_t))){ + dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Find pkey hash %s dublicate", l_hash_str_buf); + DAP_DEL_MULTY(l_enc_key, l_pkey_hashes); + return ERROR_VALUE; + } + } if (*l_cur_ptr == 0) { l_hashes_count = i + 1; break; @@ -541,7 +717,7 @@ static int s_cli_hold(int a_argc, char **a_argv, int a_arg_index, json_object ** return ERROR_VALUE; } // Create conditional transaction for delegated emissions - dap_chain_datum_tx_t *l_tx = s_emitting_tx_create(*a_json_arr_reply, a_net, l_enc_key, l_token_str, l_value, l_fee, l_signs_min, l_pkey_hashes, l_hashes_count); + dap_chain_datum_tx_t *l_tx = s_emitting_tx_create(*a_json_arr_reply, a_net, l_enc_key, l_token_str, l_value, l_fee, l_signs_min, l_pkey_hashes, l_hashes_count, l_tag_str); DAP_DEL_MULTY(l_enc_key, l_pkey_hashes); if (!l_tx) { dap_json_rpc_error_add(*a_json_arr_reply, ERROR_CREATE, "Can't compose transaction for delegated emission"); @@ -563,12 +739,39 @@ static int s_cli_hold(int a_argc, char **a_argv, int a_arg_index, json_object ** return DAP_NO_ERROR; } -static int s_cli_take(int a_argc, char **a_argv, int a_arg_index, json_object **a_json_arr_reply, dap_chain_net_t *a_net, dap_chain_t *a_chain, const char *a_hash_out_type) +static int s_cli_refill(int a_argc, char **a_argv, int a_arg_index, json_object **a_json_arr_reply, dap_chain_net_t *a_net, dap_chain_t *a_chain, const char *a_hash_out_type) { - const char *l_tx_in_hash_str = NULL, *l_addr_str = NULL, *l_value_str = NULL, *l_wallet_str = NULL, *l_fee_str = NULL; + const char *l_token_str = NULL, *l_value_str = NULL, *l_wallet_str = NULL, *l_fee_str = NULL, *l_tx_in_hash_str = NULL; + dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-value", &l_value_str); + if (!l_value_str) { + dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Refill command requires parameter -value"); + return ERROR_PARAM; + } + uint256_t l_value = dap_chain_balance_scan(l_value_str); + if (IS_ZERO_256(l_value)) { + dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Format -value <256 bit integer> and not equal zero"); + return ERROR_VALUE; + } + dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-fee", &l_fee_str); + if (!l_fee_str) { + dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Refill command requires parameter -fee"); + return ERROR_PARAM; + } + uint256_t l_fee = dap_chain_balance_scan(l_fee_str); + if (IS_ZERO_256(l_fee)) { + dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Format -fee <256 bit integer> and not equal zer"); + return ERROR_VALUE; + } + + dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-w", &l_wallet_str); + if (!l_wallet_str) { + dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Refill command requires parameter -w"); + return ERROR_PARAM; + } + dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-tx", &l_tx_in_hash_str); if (!l_tx_in_hash_str) { - dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Emitting delegation taking requires parameter -tx"); + dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Refill command requires parameter -tx"); return ERROR_PARAM; } dap_hash_fast_t l_tx_in_hash; @@ -580,16 +783,66 @@ static int s_cli_take(int a_argc, char **a_argv, int a_arg_index, json_object ** dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "TX %s not found in ledger", l_tx_in_hash_str); return ERROR_VALUE; } - dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-value", &l_value_str); - if (!l_value_str) { - dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Emitting delegation taking requires parameter -value"); + + + dap_chain_wallet_t *l_wallet = dap_chain_wallet_open(l_wallet_str, dap_chain_wallet_get_path(g_config), NULL); + if (!l_wallet) { + dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Specified wallet %s not found", l_wallet_str); + return ERROR_VALUE; + } + const char *l_sign_str = dap_chain_wallet_check_sign(l_wallet); + dap_enc_key_t *l_enc_key = dap_chain_wallet_get_key(l_wallet, 0); + dap_chain_wallet_close(l_wallet); + + // Create conditional transaction for refill + dap_chain_datum_tx_t *l_tx = dap_chain_net_srv_emit_delegate_refilling_tx_create(*a_json_arr_reply, a_net, l_enc_key, l_value, l_fee, &l_tx_in_hash, NULL); + DAP_DELETE(l_enc_key); + if (!l_tx) { + dap_json_rpc_error_add(*a_json_arr_reply, ERROR_CREATE, "Can't compose transaction for refill shared funds tx"); + return ERROR_CREATE; + } + char *l_tx_hash_str = s_tx_put(l_tx, a_chain, a_hash_out_type); + DAP_DELETE(l_tx); + if (!l_tx_hash_str) { + dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PLACE, "Can't place transaction for refill shared funds tx in mempool"); + return ERROR_PLACE; + } + json_object * l_json_obj_create_val = json_object_new_object(); + json_object_object_add(l_json_obj_create_val, "status", json_object_new_string("success")); + if (dap_strcmp(l_sign_str, "")) + json_object_object_add(l_json_obj_create_val, "sign", json_object_new_string(l_sign_str)); + json_object_object_add(l_json_obj_create_val, "tx_hash", json_object_new_string(l_tx_hash_str)); + json_object_array_add(*a_json_arr_reply, l_json_obj_create_val); + DAP_DELETE(l_tx_hash_str); + return DAP_NO_ERROR; +} + +static int s_cli_take(int a_argc, char **a_argv, int a_arg_index, json_object **a_json_arr_reply, dap_chain_net_t *a_net, dap_chain_t *a_chain, const char *a_hash_out_type) +{ + const char *l_tx_in_hash_str = NULL, *l_addr_str = NULL, *l_value_str = NULL, *l_wallet_str = NULL, *l_fee_str = NULL; + + uint256_t *l_value = NULL; + dap_chain_addr_t **l_to_addr = NULL; + uint32_t + l_addr_el_count = 0, // not change type! use in batching TSD section + l_value_el_count = 0; + dap_list_t *l_tsd_list = NULL; + + dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-tx", &l_tx_in_hash_str); + if (!l_tx_in_hash_str) { + dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Emitting delegation taking requires parameter -tx"); return ERROR_PARAM; } - uint256_t l_value = dap_chain_balance_scan(l_value_str); - if (IS_ZERO_256(l_value)) { - dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Format -value <256 bit integer>"); + dap_hash_fast_t l_tx_in_hash; + if (dap_chain_hash_fast_from_str(l_tx_in_hash_str, &l_tx_in_hash)) { + dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Can't recognize %s as a hex or base58 format hash", l_tx_in_hash_str); return ERROR_VALUE; } + if (!dap_ledger_tx_find_by_hash(a_net->pub.ledger, &l_tx_in_hash)) { + dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "TX %s not found in ledger", l_tx_in_hash_str); + return ERROR_VALUE; + } + dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-fee", &l_fee_str); if (!l_fee_str) { dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Emitting delegation taking requires parameter -fee"); @@ -597,7 +850,7 @@ static int s_cli_take(int a_argc, char **a_argv, int a_arg_index, json_object ** } uint256_t l_fee = dap_chain_balance_scan(l_fee_str); if (IS_ZERO_256(l_fee)) { - dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Format -fee <256 bit integer>"); + dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Format -fee <256 bit integer> and not equal zer"); return ERROR_VALUE; } @@ -614,21 +867,88 @@ static int s_cli_take(int a_argc, char **a_argv, int a_arg_index, json_object ** const char *l_sign_str = dap_chain_wallet_check_sign(l_wallet); dap_enc_key_t *l_enc_key = dap_chain_wallet_get_key(l_wallet, 0); dap_chain_wallet_close(l_wallet); - dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-addr_to", &l_addr_str); + + dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-value", &l_value_str); if (!l_value_str) { - DAP_DELETE(l_enc_key); - dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Emitting delegation taking requires parameter -addr_to"); + dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Emitting delegation taking requires parameter -value"); return ERROR_PARAM; } - dap_chain_addr_t *l_addr = dap_chain_addr_from_str(l_addr_str); - if (!l_addr) { + dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-to_addr", &l_addr_str); + if (!l_addr_str) { DAP_DELETE(l_enc_key); - dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Incorrect addr format for string %s", l_addr_str); + dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Emitting delegation taking requires parameter -to_addr"); + return ERROR_PARAM; + } + + l_addr_el_count = dap_str_symbol_count(l_addr_str, ',') + 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, ERROR_VALUE, "num of '-to_addr' and '-value' should be equal"); return ERROR_VALUE; } - // Create emission from conditional transaction - 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, NULL); - DAP_DEL_MULTY(l_enc_key, l_addr); + + l_value = DAP_NEW_Z_COUNT(uint256_t, l_value_el_count); + if (!l_value) { + dap_json_rpc_error_add(*a_json_arr_reply, ERROR_MEMORY, c_error_memory_alloc); + return ERROR_MEMORY; + } + 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, ERROR_PARAM, "Can't read '-to_addr' arg"); + return ERROR_PARAM; + } + for (size_t i = 0; i < l_value_el_count; ++i) { + l_value[i] = dap_chain_balance_scan(l_value_array[i]); + if(IS_ZERO_256(l_value[i])) { + DAP_DELETE(l_value); + dap_strfreev(l_value_array); + dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Format -value <256 bit integer> and not equal zero"); + return ERROR_VALUE; + } + } + dap_strfreev(l_value_array); + + l_to_addr = DAP_NEW_Z_COUNT(dap_chain_addr_t *, l_addr_el_count); + if (!l_to_addr) { + log_it(L_CRITICAL, "%s", c_error_memory_alloc); + DAP_DELETE(l_value); + dap_json_rpc_error_add(*a_json_arr_reply, ERROR_MEMORY, c_error_memory_alloc); + return ERROR_MEMORY; + } + char **l_to_addr_str_array = dap_strsplit(l_addr_str, ",", l_addr_el_count); + if (!l_to_addr_str_array) { + DAP_DEL_MULTY(l_to_addr, l_value); + dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Can't read '-to_addr' arg"); + return ERROR_PARAM; + } + for (size_t i = 0; i < l_addr_el_count; ++i) { + l_to_addr[i] = dap_chain_addr_from_str(l_to_addr_str_array[i]); + if(!l_to_addr[i]) { + DAP_DEL_ARRAY(l_to_addr, i); + DAP_DEL_MULTY(l_to_addr, l_value); + dap_strfreev(l_to_addr_str_array); + dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Incorrect addr format for string %s", l_addr_str); + return ERROR_VALUE; + } + } + dap_strfreev(l_to_addr_str_array); + + + if (l_addr_el_count > 1) { + l_tsd_list = dap_list_append(l_tsd_list, dap_chain_datum_tx_item_tsd_create(&l_addr_el_count, DAP_CHAIN_DATUM_TRANSFER_TSD_TYPE_OUT_COUNT, sizeof(uint32_t))); + if (!l_tsd_list) { + dap_json_rpc_error_add(*a_json_arr_reply, ERROR_COMPOSE, "Internal error in tsd list creation"); + return ERROR_COMPOSE; + } + } + + // Create emission from conditional transaction + 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_to_addr, l_value, l_addr_el_count, l_fee, &l_tx_in_hash, l_tsd_list); + DAP_DEL_ARRAY(l_to_addr, l_addr_el_count); + DAP_DEL_MULTY(l_value, l_to_addr, l_enc_key); + dap_list_free_full(l_tsd_list, NULL); if (!l_tx) { dap_json_rpc_error_add(*a_json_arr_reply, ERROR_CREATE, "Can't compose transaction for delegated emission"); return ERROR_CREATE; @@ -651,7 +971,7 @@ static int s_cli_take(int a_argc, char **a_argv, int a_arg_index, json_object ** static int s_cli_sign(int a_argc, char **a_argv, int a_arg_index, json_object **a_json_arr_reply, dap_chain_net_t *a_net, dap_chain_t *a_chain, const char *a_hash_out_type) { - const char *l_tx_in_hash_str = NULL, *l_wallet_str = NULL; + const char *l_tx_in_hash_str = NULL, *l_wallet_str = NULL, *l_cert_str = NULL; dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-tx", &l_tx_in_hash_str); if (!l_tx_in_hash_str) { dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Emitting delegation taking requires parameter -tx"); @@ -667,19 +987,37 @@ static int s_cli_sign(int a_argc, char **a_argv, int a_arg_index, json_object ** dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "TX %s not found in mempool", l_tx_in_hash_str); return ERROR_VALUE; } + + dap_enc_key_t *l_enc_key = NULL; + const char *l_sign_str = NULL; + dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-w", &l_wallet_str); - if (!l_wallet_str) { - dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Emitting delegation taking requires parameter -w"); + dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-cert", &l_cert_str); + if (!l_wallet_str && !l_cert_str) { + dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Emitting delegation sign requires parameter -w or -cert"); return ERROR_PARAM; } - dap_chain_wallet_t *l_wallet = dap_chain_wallet_open(l_wallet_str, dap_chain_wallet_get_path(g_config), NULL); - if (!l_wallet) { - dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Specified wallet %s not found", l_wallet_str); - return ERROR_VALUE; + if (l_wallet_str) { + dap_chain_wallet_t *l_wallet = dap_chain_wallet_open(l_wallet_str, dap_chain_wallet_get_path(g_config), NULL); + if (!l_wallet) { + dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Specified wallet %s not found", l_wallet_str); + return ERROR_VALUE; + } + l_sign_str = dap_chain_wallet_check_sign(l_wallet); + l_enc_key = dap_chain_wallet_get_key(l_wallet, 0); + dap_chain_wallet_close(l_wallet); + } else if (l_cert_str) { + dap_cert_t *l_cert = dap_cert_find_by_name(l_cert_str); + if (!l_cert) { + dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Specified certificate %s not found", l_cert_str); + return ERROR_VALUE; + } + if (dap_sign_type_is_depricated(dap_sign_type_from_key_type(l_cert->enc_key->type))) + l_sign_str = "The Bliss, Picnic and Tesla signatures is deprecated. We recommend you to create a new wallet with another available signature and transfer funds there.\n"; + else + l_sign_str = ""; + l_enc_key = dap_cert_get_keys_from_certs(&l_cert, 1, 0); } - const char *l_sign_str = dap_chain_wallet_check_sign(l_wallet); - dap_enc_key_t *l_enc_key = dap_chain_wallet_get_key(l_wallet, 0); - dap_chain_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); @@ -707,6 +1045,65 @@ static int s_cli_sign(int a_argc, char **a_argv, int a_arg_index, json_object ** return DAP_NO_ERROR; } +static int s_cli_info(int a_argc, char **a_argv, int a_arg_index, json_object **a_json_arr_reply, dap_chain_net_t *a_net, dap_chain_t *a_chain, const char *a_hash_out_type) +{ + const char *l_tx_hash_str = NULL, *l_wallet_str = NULL; + dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-tx", &l_tx_hash_str); + if (!l_tx_hash_str) { + dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Emitting delegation taking requires parameter -tx"); + return ERROR_PARAM; + } + dap_hash_fast_t l_tx_hash; + if (dap_chain_hash_fast_from_str(l_tx_hash_str, &l_tx_hash)) { + dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Can't recognize %s as a hex or base58 format hash", l_tx_hash_str); + return ERROR_VALUE; + } + dap_hash_fast_t l_final_tx_hash = dap_ledger_get_final_chain_tx_hash(a_net->pub.ledger, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_EMIT_DELEGATE, &l_tx_hash, false); + dap_chain_datum_tx_t *l_tx = dap_ledger_tx_find_by_hash(a_net->pub.ledger, &l_final_tx_hash); + dap_chain_tx_out_cond_t *l_cond = dap_chain_datum_tx_out_cond_get(l_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_EMIT_DELEGATE, NULL); + if (!l_cond) { + dap_json_rpc_error_add(*a_json_arr_reply, ERROR_TX_MISMATCH, "Can't find final tx_out_cond"); + return ERROR_TX_MISMATCH; + } + + const char *l_tx_ticker = dap_ledger_tx_get_token_ticker_by_hash(a_net->pub.ledger, &l_final_tx_hash); + const char *l_balance_coins, *l_balance_datoshi = dap_uint256_to_char(l_cond->header.value, &l_balance_coins); + + json_object *l_jobj_balance = json_object_new_object(); + json_object *l_jobj_token = json_object_new_object(); + json_object *l_jobj_take_verify = json_object_new_object(); + json_object *l_jobj_pkey_hashes = json_object_new_array(); + json_object *l_json_jobj_info = json_object_new_object(); + + bool l_is_base_hash_type = dap_strcmp(a_hash_out_type, "hex"); + // tocken block + const char *l_description = dap_ledger_get_description_by_ticker(a_net->pub.ledger, l_tx_ticker); + json_object *l_jobj_description = l_description ? json_object_new_string(l_description) + : json_object_new_null(); + json_object_object_add(l_jobj_token, "ticker", json_object_new_string(l_tx_ticker)); + json_object_object_add(l_jobj_token, "description", l_jobj_description); + // balance block + json_object_object_add(l_jobj_balance, "coins", json_object_new_string(l_balance_coins)); + json_object_object_add(l_jobj_balance, "datoshi", json_object_new_string(l_balance_datoshi)); + // verify block + json_object_object_add(l_jobj_take_verify, "signs_minimum", json_object_new_uint64(l_cond->subtype.srv_emit_delegate.signers_minimum)); + dap_tsd_t *l_tsd = NULL; size_t l_tsd_size = 0; + dap_tsd_iter(l_tsd, l_tsd_size, l_cond->tsd, l_cond->tsd_size) { + if (l_tsd->type == DAP_CHAIN_TX_OUT_COND_TSD_HASH && l_tsd->size == sizeof(dap_hash_fast_t)) { + json_object_array_add(l_jobj_pkey_hashes, json_object_new_string(l_is_base_hash_type ? dap_enc_base58_encode_hash_to_str_static((const dap_chain_hash_fast_t *)l_tsd->data) : dap_hash_fast_to_str_static((const dap_chain_hash_fast_t *)l_tsd->data))); + } + } + json_object_object_add(l_jobj_take_verify, "owner_hashes", l_jobj_pkey_hashes); + // result block + json_object_object_add(l_json_jobj_info, "tx_hash", json_object_new_string(l_is_base_hash_type ? dap_enc_base58_encode_hash_to_str_static(&l_tx_hash) : dap_hash_fast_to_str_static(&l_tx_hash))); + json_object_object_add(l_json_jobj_info, "tx_hash_final", json_object_new_string(l_is_base_hash_type ? dap_enc_base58_encode_hash_to_str_static(&l_final_tx_hash) : dap_hash_fast_to_str_static(&l_final_tx_hash))); + json_object_object_add(l_json_jobj_info, "balance", l_jobj_balance); + json_object_object_add(l_json_jobj_info, "take_verify", l_jobj_take_verify); + json_object_object_add(l_json_jobj_info, "token", l_jobj_token); + json_object_array_add(*a_json_arr_reply, l_json_jobj_info); + return DAP_NO_ERROR; +} + /** * @brief s_cli_stake_lock * @param a_argc @@ -717,9 +1114,6 @@ static int s_cli_sign(int a_argc, char **a_argv, int a_arg_index, json_object ** static int s_cli_emit_delegate(int a_argc, char **a_argv, void **a_str_reply) { json_object **a_json_arr_reply = (json_object **)a_str_reply; - enum { - CMD_NONE, CMD_HOLD, CMD_TAKE, CMD_SIGN - }; int l_arg_index = 1; dap_chain_net_t *l_net = NULL; dap_chain_t *l_chain = NULL; @@ -727,7 +1121,7 @@ static int s_cli_emit_delegate(int a_argc, char **a_argv, void **a_str_reply) dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-H", &l_hash_out_type); if (!l_hash_out_type) l_hash_out_type = "hex"; - else if (dap_strcmp(l_hash_out_type," hex") && dap_strcmp(l_hash_out_type, "base58")) { + else if (dap_strcmp(l_hash_out_type,"hex") && dap_strcmp(l_hash_out_type, "base58")) { dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Invalid parameter -H, valid values: -H <hex | base58>"); return ERROR_PARAM; @@ -736,13 +1130,21 @@ static int s_cli_emit_delegate(int a_argc, char **a_argv, void **a_str_reply) if (l_err_net_chain) return l_err_net_chain; - int l_cmd_num = CMD_NONE; + if (dap_chain_net_get_load_mode(l_net)) { + dap_json_rpc_error_add(*a_json_arr_reply, ERROR_NETWORK, "Can't apply command while network in load mode"); + return ERROR_NETWORK; + } + if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "hold", NULL)) return s_cli_hold(a_argc, a_argv, l_arg_index + 1, a_json_arr_reply, l_net, l_chain, l_hash_out_type); + else if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "refill", NULL)) + return s_cli_refill(a_argc, a_argv, l_arg_index + 1, a_json_arr_reply, l_net, l_chain, l_hash_out_type); else if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "take", NULL)) return s_cli_take(a_argc, a_argv, l_arg_index + 1, a_json_arr_reply, l_net, l_chain, l_hash_out_type); else if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "sign", NULL)) return s_cli_sign(a_argc, a_argv, l_arg_index + 1, a_json_arr_reply, l_net, l_chain, l_hash_out_type); + else if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "info", NULL)) + return s_cli_info(a_argc, a_argv, l_arg_index + 1, a_json_arr_reply, l_net, l_chain, l_hash_out_type); else { dap_json_rpc_error_add(*a_json_arr_reply, ERROR_SUBCOMMAND, "Subcommand %s not recognized", a_argv[l_arg_index]); return ERROR_SUBCOMMAND; @@ -753,13 +1155,43 @@ int dap_chain_net_srv_emit_delegate_init() { dap_ledger_verificator_add(DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_EMIT_DELEGATE, s_emit_delegate_verificator, NULL, NULL, NULL, NULL, NULL); dap_cli_server_cmd_add("emit_delegate", s_cli_emit_delegate, "Emitting delegation service commands", - "emit_delegate hold -net <net_name> -w <wallet_name> -token <ticker> -value <value> -fee <value>" - "-signs_minimum <value_int> -pkey_hashes <hash1[,hash2,...,hashN]> [-chain <chain_name>] [-H {hex(default) | base58}]\n" - "emit_delegate take -net <net_name> -w <wallet_name> -tx <transaction_hash> -addr_to <addr> -value <value> -fee <value> [-chain <chain_name>] [-H {hex(default) | base58}]\n" - "emit_delegate sign -net <net_name> -w <wallet_name> -tx <transaction_hash> [-chain <chain_name>] [-H {hex(default) | base58}]\n\n" - "Hint:\n" - "\texample value_coins (only natural) 1.0 123.4567\n" - "\texample value_datoshi (only integer) 1 20 0.4321e+4\n" + "emit_delegate hold - to create new delegation\n" + "\t-net <net_name>\n" + "\t-w <wallet_name> - wallet to writeoff value, pay fee and sign tx\n" + "\t-token <ticker> - token ticker to hold\n" + "\t-value <value> - value to hold\n" + "\t-fee <value> - fee value\n" + "\t-signs_minimum <value_int> - minimum signs count needed to verify take datum\n" + "\t-pkey_hashes <hash1[,hash2,...,hashN]> - owners pkey hashes, who can sign take datum\n" + "\t[-tag \"<str>\"] - additional info about tx\n" + "\t[-H {hex(default) | base58}] - datum hash return format\n" + "emit_delegate refill - to refill value\n" + "\t-net <net_name>\n" + "\t-w <wallet_name> - wallet to writeoff value and pay fee\n" + "\t-value <value> - value to refill\n" + "\t-fee <value> - fee value\n" + "\t-tx <transaction_hash> - shared funds tx hash to refill\n" + "\t[-H {hex(default) | base58}] - datum hash return format\n" + "emit_delegate take - create take datum to writeoff value from0 shared funds tx\n" + "\t-net <net_name>\n" + "\t-w <wallet_name> - wallet to pay fee\n" + "\t-tx <transaction_hash> - shared funds tx hash to writeoff\n" + "\t-to_addr <addr1[,addr2,...,addrN]> - recipient addresses, count should be equal values count\n" + "\t-value <value1[,value2,...,valueN]> - value sent to each recipient, count should be equal addresses count\n" + "\t-fee <value> - fee value\n" + "\t[-H {hex(default) | base58}] - datum hash return format\n" + "emit_delegate sign - add wallet sign to take datum\n" + "\t-net <net_name>\n" + "\t-w <wallet_name> | -cert <cert_name> - wallet or cert to sign\n" + "\t-tx <transaction_hash> - shared funds tx hash to sign\n" + "\t[-H {hex(default) | base58}] - datum hash return format\n" + "emit_delegate info - get info about shared funds tx by hash\n" + "\t-net <net_name>\n" + "\t-tx <transaction_hash> - shared funds tx hash to get info\n" + "\t[-H {hex(default) | base58}] - tx hash format\n" + "Hint:\n" + "\texample value_coins (only natural) 1.0 123.4567\n" + "\texample value_datoshi (only integer) 1 20 0.4321e+4\n" ); dap_chain_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_EMIT_DELEGATE_ID }; 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 bf891ab3f0a6a391d86f4a3285e4ea131113561f..1e14d527bfe61b6d64b9a3a222462ac3bc1c37de 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 @@ -1,5 +1,9 @@ #pragma once +#define DAP_CHAIN_NET_SRV_EMIT_DELEGATE_ID 0x07 +#define DAP_CHAIN_NET_SRV_EMIT_DELEGATE_TSD_WRITEOFF 0x14 +#define DAP_CHAIN_NET_SRV_EMIT_DELEGATE_TSD_REFILL 0x15 + #include "dap_chain_datum_tx.h" #include "dap_chain_mempool.h" @@ -10,7 +14,9 @@ int dap_chain_net_srv_emit_delegate_init(); 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_list_t *a_tsd_items); + dap_chain_addr_t **a_addr_to, uint256_t *a_value, size_t a_addr_count, uint256_t a_fee, dap_hash_fast_t *a_tx_in_hash, dap_list_t *tsd_items); +dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_refilling_tx_create(json_object *a_json_arr_reply, dap_chain_net_t *a_net, dap_enc_key_t *a_enc_key, + uint256_t a_value, uint256_t a_fee, dap_hash_fast_t *a_tx_in_hash, dap_list_t* tsd_items); 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/wallet/dap_chain_wallet.c b/modules/wallet/dap_chain_wallet.c index 36af7b3f33fc8e8e593a775e0277b6cb522e73f8..a0db1addc38f12a2cfffd04e9225347a3683fb84 100644 --- a/modules/wallet/dap_chain_wallet.c +++ b/modules/wallet/dap_chain_wallet.c @@ -1179,7 +1179,7 @@ const char* dap_chain_wallet_check_sign(dap_chain_wallet_t *a_wallet) { for (size_t i = 0; i < l_wallet_internal->certs_count; ++i) { dap_return_val_if_pass(!l_wallet_internal->certs[i], "The wallet contains an undefined certificate.\n"); dap_sign_type_t l_sign_type = dap_sign_type_from_key_type(l_wallet_internal->certs[i]->enc_key->type); - if (SIG_TYPE_BLISS == l_sign_type.type || SIG_TYPE_PICNIC == l_sign_type.type || SIG_TYPE_TESLA == l_sign_type.type) { + if (dap_sign_type_is_depricated(l_sign_type)) { return "The Bliss, Picnic and Tesla signatures is deprecated. We recommend you to create a new wallet with another available signature and transfer funds there.\n"; } }