From 34c40eb43f705cff7054dc7d6d89269b1b09324f Mon Sep 17 00:00:00 2001 From: Roman Khlopkov <roman.khlopkov@demlabs.net> Date: Sat, 13 Jan 2024 14:42:01 +0000 Subject: [PATCH] feature-10082 --- modules/common/dap_chain_datum_tx.c | 15 + modules/common/include/dap_chain_datum_tx.h | 2 + .../consensus/esbocs/dap_chain_cs_esbocs.c | 15 + .../esbocs/include/dap_chain_cs_esbocs.h | 1 + modules/net/dap_chain_ledger.c | 4 +- modules/net/dap_chain_node_cli_cmd.c | 4 +- modules/net/srv/dap_chain_net_srv.c | 2 +- .../dap_chain_net_srv_stake_pos_delegate.c | 1101 ++++++++++------- .../xchange/dap_chain_net_srv_xchange.c | 2 +- modules/type/blocks/dap_chain_cs_blocks.c | 8 +- 10 files changed, 685 insertions(+), 469 deletions(-) diff --git a/modules/common/dap_chain_datum_tx.c b/modules/common/dap_chain_datum_tx.c index 0f2310fb97..7da9de1563 100644 --- a/modules/common/dap_chain_datum_tx.c +++ b/modules/common/dap_chain_datum_tx.c @@ -203,6 +203,21 @@ int dap_chain_datum_tx_get_fee_value(dap_chain_datum_tx_t *a_tx, uint256_t *a_va return l_ret; } +dap_sign_t *dap_chain_datum_tx_get_sign(dap_chain_datum_tx_t *a_tx, int a_sign_num) +{ + dap_return_val_if_fail(a_tx, NULL); + if (!a_sign_num) { + dap_chain_tx_sig_t *l_tx_sig = (dap_chain_tx_sig_t *)dap_chain_datum_tx_item_get(a_tx, NULL, TX_ITEM_TYPE_SIG, NULL); + return dap_chain_datum_tx_item_sign_get_sig(l_tx_sig); + } + dap_list_t *l_items_list = dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_SIG, NULL); + if (dap_list_length(l_items_list) <= (uint64_t)a_sign_num) + return NULL; + dap_sign_t *l_ret = dap_list_nth_data(l_items_list, a_sign_num); + dap_list_free(l_items_list); + return l_ret; +} + /** * Create 'out' item and insert to transaction * diff --git a/modules/common/include/dap_chain_datum_tx.h b/modules/common/include/dap_chain_datum_tx.h index f2cc1c7e4e..33d37f5142 100644 --- a/modules/common/include/dap_chain_datum_tx.h +++ b/modules/common/include/dap_chain_datum_tx.h @@ -144,6 +144,8 @@ int dap_chain_datum_tx_add_out_cond_item(dap_chain_datum_tx_t **a_tx, dap_pkey_t */ int dap_chain_datum_tx_add_sign_item(dap_chain_datum_tx_t **a_tx, dap_enc_key_t *a_key); +dap_sign_t *dap_chain_datum_tx_get_sign(dap_chain_datum_tx_t *a_tx, int a_sign_num); + /** * Verify all sign item in transaction * diff --git a/modules/consensus/esbocs/dap_chain_cs_esbocs.c b/modules/consensus/esbocs/dap_chain_cs_esbocs.c index b7e065545b..5ce9425bc6 100644 --- a/modules/consensus/esbocs/dap_chain_cs_esbocs.c +++ b/modules/consensus/esbocs/dap_chain_cs_esbocs.c @@ -397,6 +397,21 @@ static void s_new_atom_notifier(void *a_arg, dap_chain_t *a_chain, dap_chain_cel } } +bool dap_chain_esbocs_get_autocollect_status(dap_chain_net_id_t a_net_id) +{ + dap_chain_esbocs_session_t *l_session; + DL_FOREACH(s_session_items, l_session) { + if (l_session->chain->net_id.uint64 == a_net_id.uint64) { + if (l_session->esbocs && l_session->esbocs->_pvt && + !dap_chain_addr_is_blank(PVT(l_session->esbocs)->collecting_addr)) + return true; + else + return false; + } + } + return false; +} + static int s_callback_created(dap_chain_t *a_chain, dap_config_t *a_chain_net_cfg) { dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(a_chain); diff --git a/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h b/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h index 0f9d9a5544..914c430414 100644 --- a/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h +++ b/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h @@ -214,3 +214,4 @@ void dap_chain_esbocs_stop_timer(dap_chain_net_id_t a_net_id); void dap_chain_esbocs_start_timer(dap_chain_net_id_t a_net_id); dap_pkey_t *dap_chain_esbocs_get_sign_pkey(dap_chain_net_id_t a_net_id); uint256_t dap_chain_esbocs_get_fee(dap_chain_net_id_t a_net_id); +bool dap_chain_esbocs_get_autocollect_status(dap_chain_net_id_t a_net_id); diff --git a/modules/net/dap_chain_ledger.c b/modules/net/dap_chain_ledger.c index 5b73b08c88..f6d78a3b01 100644 --- a/modules/net/dap_chain_ledger.c +++ b/modules/net/dap_chain_ledger.c @@ -3360,7 +3360,7 @@ bool s_tx_match_sign(dap_chain_datum_token_emission_t *a_datum_emission, dap_cha // Get sign from sign item dap_sign_t *l_tx_sign = dap_chain_datum_tx_item_sign_get_sig((dap_chain_tx_sig_t*) l_tx_sig); // Compare signs - if(dap_sign_match_pkey_signs(l_emission_sign, l_tx_sign)) { + if(dap_sign_compare_pkeys(l_emission_sign, l_tx_sign)) { dap_list_free(l_list_sig); return true; } @@ -3920,7 +3920,7 @@ int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx dap_chain_tx_out_cond_t *l_tx_prev_out_cond = NULL; l_tx_prev_out_cond = (dap_chain_tx_out_cond_t *)l_tx_prev_out; bool l_owner = false; - l_owner = dap_sign_match_pkey_signs(l_prev_sign, l_sign); + l_owner = dap_sign_compare_pkeys(l_prev_sign, l_sign); // 5b. Call verificator for conditional output dap_ledger_verificator_t *l_verificator; diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c index 130757998c..a247fed056 100644 --- a/modules/net/dap_chain_node_cli_cmd.c +++ b/modules/net/dap_chain_node_cli_cmd.c @@ -3196,8 +3196,8 @@ void s_com_mempool_list_print_for_chain(dap_chain_net_t * a_net, dap_chain_t * a dap_global_db_objs_delete(l_objs, l_objs_count); json_object_object_add(l_obj_chain, "datums", l_jobj_datums); - char * l_net_chain_count_total[64] = {0}; - sprintf(l_net_chain_count_total, "%s.%s: %d", a_net->pub.name, a_chain->name, l_objs_count); + char l_net_chain_count_total[64] = {0}; + sprintf(l_net_chain_count_total, "%s.%s: %zu", a_net->pub.name, a_chain->name, l_objs_count); json_object * l_object_total = json_object_new_string(l_net_chain_count_total); if (!l_object_total) { json_object_put(l_obj_chain); diff --git a/modules/net/srv/dap_chain_net_srv.c b/modules/net/srv/dap_chain_net_srv.c index 37da291861..a8b7d359f6 100644 --- a/modules/net/srv/dap_chain_net_srv.c +++ b/modules/net/srv/dap_chain_net_srv.c @@ -687,7 +687,7 @@ static bool s_fee_verificator_callback(dap_ledger_t *a_ledger, dap_chain_tx_out_ // TX sign is already verified, just compare pkeys dap_chain_tx_sig_t *l_tx_sig = (dap_chain_tx_sig_t *)dap_chain_datum_tx_item_get(a_tx_in, NULL, TX_ITEM_TYPE_SIG, NULL); dap_sign_t *l_sign_tx = dap_chain_datum_tx_item_sign_get_sig(l_tx_sig); - return dap_sign_match_pkey_signs(l_sign_block, l_sign_tx); + return dap_sign_compare_pkeys(l_sign_block, l_sign_tx); } return false; } diff --git a/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c b/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c index 9abdc13bc7..b2eecedb98 100644 --- a/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c +++ b/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c @@ -71,7 +71,7 @@ int dap_chain_net_srv_stake_pos_delegate_init() "srv_stake order create validator -net <net_name> -value_min <minimum_stake_value> -value_max <maximum_stake_value>" " -tax <percent> -cert <priv_cert_name> [-H {hex(default) | base58}]\n" "\tCreates an order declaring wanted tax and minimum/maximum stake value that the validator agrees to work.\n" - "srv_stake order create staker -net <net_name> -w <wallet_wtih_m_tokens> -value <stake_value> -tax <percent>" + "srv_stake order create staker -net <net_name> -w <wallet_with_m_tokens> -value <stake_value> -fee <value> -tax <percent>" " [-addr <for_tax_collecting>] [-cert <priv_cert_name>] [-H {hex(default) | base58}]\n" "\tCreates an order allowing the validator to delegate it's key with specified params\n" "srv_stake order update -net <net_name> -order <order_hash> [-params]\n" @@ -156,22 +156,61 @@ void dap_chain_net_srv_stake_pos_delegate_deinit() DAP_DEL_Z(s_srv_stake); } -static bool s_stake_verificator_callback(dap_ledger_t UNUSED_ARG *a_ledger, dap_chain_tx_out_cond_t UNUSED_ARG *a_cond, +static bool s_stake_verificator_callback(dap_ledger_t UNUSED_ARG *a_ledger, dap_chain_tx_out_cond_t *a_cond, dap_chain_datum_tx_t *a_tx_in, bool a_owner) { assert(s_srv_stake); - if (!a_owner) - return false; - if (a_tx_in->header.ts_created < 1705104000) // Jan 13 2024 00:00:00 GMT + // It's a order conditional TX + if (dap_chain_addr_is_blank(&a_cond->subtype.srv_stake_pos_delegate.signing_addr) || + a_cond->subtype.srv_stake_pos_delegate.signer_node_addr.uint64 == 0) { + if (a_owner) + return true; + int l_out_idx = 0; + dap_chain_tx_out_cond_t *l_tx_out_cond = dap_chain_datum_tx_out_cond_get(a_tx_in, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE, &l_out_idx); + if (!l_tx_out_cond) + return false; + if (compare256(l_tx_out_cond->header.value, a_cond->header.value)) + return false; + if (l_tx_out_cond->tsd_size != a_cond->tsd_size || + memcmp(l_tx_out_cond->tsd, a_cond->tsd, a_cond->tsd_size)) + return false; + if (dap_chain_addr_is_blank(&l_tx_out_cond->subtype.srv_stake_pos_delegate.signing_addr) || + l_tx_out_cond->subtype.srv_stake_pos_delegate.signer_node_addr.uint64 == 0) + return false; return true; + } + // It's a delegation conitional TX dap_chain_tx_in_cond_t *l_tx_in_cond = (dap_chain_tx_in_cond_t *)dap_chain_datum_tx_item_get(a_tx_in, 0, TX_ITEM_TYPE_IN_COND, 0); if (!l_tx_in_cond) return false; - if (dap_hash_fast_is_blank(&l_tx_in_cond->header.tx_prev_hash)) + dap_hash_fast_t *l_prev_hash = &l_tx_in_cond->header.tx_prev_hash; + if (dap_hash_fast_is_blank(l_prev_hash)) + return false; + dap_chain_datum_tx_t *l_prev_tx = dap_ledger_tx_find_by_hash(a_ledger, l_prev_hash); + if (!l_prev_tx) return false; + bool l_owner = false; + dap_chain_tx_in_cond_t *l_tx_prev_in_cond = (dap_chain_tx_in_cond_t *)dap_chain_datum_tx_item_get(l_prev_tx, 0, TX_ITEM_TYPE_IN_COND, 0); + if (!l_tx_prev_in_cond) + l_owner = a_owner; + else { + dap_hash_fast_t *l_owner_tx_hash = &l_tx_prev_in_cond->header.tx_prev_hash; + dap_chain_datum_tx_t *l_owner_tx = dap_ledger_tx_find_by_hash(a_ledger, l_owner_tx_hash); + dap_sign_t *l_owner_sign = dap_chain_datum_tx_get_sign(l_owner_tx, 0); + if (!l_owner_sign) + return false; + dap_sign_t *l_taker_sign = dap_chain_datum_tx_get_sign(a_tx_in, 0); + if (!l_taker_sign) + return false; + l_owner = dap_sign_compare_pkeys(l_taker_sign, l_owner_sign); + } + if (!l_owner) + return false; + if (a_tx_in->header.ts_created < 1705104000) // Jan 13 2024 00:00:00 GMT, old policy rules + return true; dap_chain_net_srv_stake_item_t *l_stake; - HASH_FIND(hh, s_srv_stake->tx_itemlist, &l_tx_in_cond->header.tx_prev_hash, sizeof(dap_hash_t), l_stake); - if (l_stake) + HASH_FIND(hh, s_srv_stake->tx_itemlist, l_prev_hash, sizeof(dap_hash_t), l_stake); + if (l_stake) // Key is active with delegation decree, need to revoke it first return false; return true; } @@ -227,7 +266,7 @@ void dap_chain_net_srv_stake_key_delegate(dap_chain_net_t *a_net, dap_chain_addr dap_chain_datum_tx_t *l_tx = dap_ledger_tx_find_by_hash(a_net->pub.ledger, a_stake_tx_hash); if (l_tx) { dap_chain_tx_out_cond_t *l_cond = dap_chain_datum_tx_out_cond_get(l_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE, NULL); - if (l_cond && l_cond->tsd_size) { + if (l_cond && l_cond->tsd_size == sizeof(dap_chain_addr_t) + sizeof(uint256_t) + sizeof(dap_tsd_t) * 2) { dap_tsd_t *l_tsd = dap_tsd_find(l_cond->tsd, l_cond->tsd_size, DAP_CHAIN_TX_OUT_COND_TSD_ADDR); l_stake->sovereign_addr = dap_tsd_get_scalar(l_tsd, dap_chain_addr_t); l_tsd = dap_tsd_find(l_cond->tsd, l_cond->tsd_size, DAP_CHAIN_TX_OUT_COND_TSD_VALUE); @@ -329,7 +368,12 @@ int dap_chain_net_srv_stake_verify_key_and_node(dap_chain_addr_t *a_signing_addr log_it(L_WARNING, "Bad srv_stake_verify arguments"); return -100; } -return 0; //TODO rmv + + if (dap_chain_addr_is_blank(a_signing_addr) || a_node_addr->uint64 == 0) { + log_it(L_WARNING, "Trying to approve bad delegating TX. Node or key addr is blank"); + return -103; + } + dap_chain_net_srv_stake_item_t *l_stake = NULL, *l_tmp = NULL; HASH_ITER(hh, s_srv_stake->itemlist, l_stake, l_tmp){ //check key not activated for other node @@ -414,58 +458,68 @@ void dap_chain_net_srv_stake_purge(dap_chain_net_t *a_net) // Freeze staker's funds when delegating a key -static dap_chain_datum_tx_t *s_stake_tx_create(dap_chain_net_t * a_net, dap_chain_wallet_t *a_wallet, +static dap_chain_datum_tx_t *s_stake_tx_create(dap_chain_net_t * a_net, dap_enc_key_t *a_key, uint256_t a_value, uint256_t a_fee, dap_chain_addr_t *a_signing_addr, dap_chain_node_addr_t *a_node_addr, - dap_chain_addr_t *a_sovereign_addr, uint256_t a_sovereign_tax) + dap_chain_addr_t *a_sovereign_addr, uint256_t a_sovereign_tax, + dap_chain_datum_tx_t *a_prev_tx) { - if (!a_net || !a_wallet || IS_ZERO_256(a_value) || !a_signing_addr || !a_node_addr) + if (!a_net || !a_key || IS_ZERO_256(a_value) || !a_signing_addr || !a_node_addr) return NULL; - - const char *l_native_ticker = a_net->pub.native_ticker; char l_delegated_ticker[DAP_CHAIN_TICKER_SIZE_MAX]; dap_chain_datum_token_get_delegated_ticker(l_delegated_ticker, l_native_ticker); dap_ledger_t *l_ledger = dap_ledger_by_net_name(a_net->pub.name); uint256_t l_value_transfer = {}, l_fee_transfer = {}; // how many coins to transfer // list of transaction with 'out' items to sell - dap_chain_addr_t *l_owner_addr = (dap_chain_addr_t *)dap_chain_wallet_get_addr(a_wallet, a_net->pub.id); + dap_chain_addr_t l_owner_addr; + dap_chain_addr_fill_from_key(&l_owner_addr, a_key, a_net->pub.id); uint256_t l_net_fee, l_fee_total = a_fee; dap_chain_addr_t l_net_fee_addr; bool l_net_fee_used = dap_chain_net_tx_get_fee(a_net->pub.id, &l_net_fee, &l_net_fee_addr); if (l_net_fee_used) SUM_256_256(l_fee_total, l_net_fee, &l_fee_total); - dap_list_t *l_list_used_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, l_delegated_ticker, - l_owner_addr, a_value, &l_value_transfer); - if (!l_list_used_out) { - log_it(L_WARNING, "Nothing to pay for delegate (not enough funds)"); - DAP_DELETE(l_owner_addr); - return NULL; - } dap_list_t *l_list_fee_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, l_native_ticker, - l_owner_addr, l_fee_total, &l_fee_transfer); + &l_owner_addr, l_fee_total, &l_fee_transfer); if (!l_list_fee_out) { log_it(L_WARNING, "Nothing to pay for fee (not enough funds)"); - DAP_DELETE(l_owner_addr); return NULL; } // create empty transaction dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create(); - // add 'in' items to pay for delegate - uint256_t l_value_to_items = dap_chain_datum_tx_add_in_item_list(&l_tx, l_list_used_out); - dap_list_free_full(l_list_used_out, NULL); - if (!EQUAL_256(l_value_to_items, l_value_transfer)) { - log_it(L_ERROR, "Can't compose the transaction input"); - goto tx_fail; + if (!a_prev_tx) { + dap_list_t *l_list_used_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, l_delegated_ticker, + &l_owner_addr, a_value, &l_value_transfer); + if (!l_list_used_out) { + log_it(L_WARNING, "Nothing to pay for delegate (not enough funds)"); + return NULL; + } + // add 'in' items to pay for delegate + uint256_t l_value_to_items = dap_chain_datum_tx_add_in_item_list(&l_tx, l_list_used_out); + dap_list_free_full(l_list_used_out, NULL); + if (!EQUAL_256(l_value_to_items, l_value_transfer)) { + log_it(L_ERROR, "Can't compose the transaction input"); + goto tx_fail; + } + } else { + dap_hash_fast_t l_prev_tx_hash; + dap_hash_fast(a_prev_tx, dap_chain_datum_tx_get_size(a_prev_tx), &l_prev_tx_hash); + int l_out_num = 0; + dap_chain_datum_tx_out_cond_get(a_prev_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE, &l_out_num); + // add 'in' item to buy from conditional transaction + if (dap_chain_datum_tx_add_in_cond_item(&l_tx, &l_prev_tx_hash, l_out_num, -1)) { + log_it(L_ERROR, "Can't compose the transaction conditional input"); + goto tx_fail; + } } // add 'in' items to pay fee uint256_t l_value_fee_items = dap_chain_datum_tx_add_in_item_list(&l_tx, l_list_fee_out); dap_list_free_full(l_list_fee_out, NULL); if (!EQUAL_256(l_value_fee_items, l_fee_transfer)) { - log_it(L_ERROR, "Can't compose the transaction input"); + log_it(L_ERROR, "Can't compose the fee transaction input"); goto tx_fail; } @@ -479,53 +533,51 @@ static dap_chain_datum_tx_t *s_stake_tx_create(dap_chain_net_t * a_net, dap_chai } dap_chain_datum_tx_add_item(&l_tx, (const uint8_t *)l_tx_out); DAP_DELETE(l_tx_out); - // coin back - uint256_t l_value_back = {}; - SUBTRACT_256_256(l_value_transfer, a_value, &l_value_back); - if (!IS_ZERO_256(l_value_back)) { - if (dap_chain_datum_tx_add_out_ext_item(&l_tx, l_owner_addr, l_value_back, l_delegated_ticker) != 1) { - log_it(L_ERROR, "Cant add coin back output"); - goto tx_fail; + if (!a_prev_tx) { + // coin back + uint256_t l_value_back = {}; + SUBTRACT_256_256(l_value_transfer, a_value, &l_value_back); + if (!IS_ZERO_256(l_value_back)) { + if (dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_owner_addr, l_value_back, l_delegated_ticker) != 1) { + log_it(L_ERROR, "Cant add coin back output"); + goto tx_fail; + } } } // add fee items if (l_net_fee_used) { if (dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_net_fee_addr, l_net_fee, l_native_ticker) != 1) { - dap_chain_datum_tx_delete(l_tx); - return NULL; + log_it(L_ERROR, "Cant add net fee output"); + goto tx_fail; } } if (!IS_ZERO_256(a_fee)) { if (dap_chain_datum_tx_add_fee_item(&l_tx, a_fee) != 1) { - dap_chain_datum_tx_delete(l_tx); - return NULL; + log_it(L_ERROR, "Cant add validator fee output"); + goto tx_fail; } } uint256_t l_fee_back = {}; // fee coin back SUBTRACT_256_256(l_fee_transfer, l_fee_total, &l_fee_back); if(!IS_ZERO_256(l_fee_back)) { - if(dap_chain_datum_tx_add_out_ext_item(&l_tx, l_owner_addr, l_fee_back, l_native_ticker) != 1) { - dap_chain_datum_tx_delete(l_tx); - return NULL; + if(dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_owner_addr, l_fee_back, l_native_ticker) != 1) { + log_it(L_ERROR, "Cant add fee back output"); + goto tx_fail; } } // add 'sign' item - dap_enc_key_t *l_enc_key = dap_chain_wallet_get_key(a_wallet, 0); - if(dap_chain_datum_tx_add_sign_item(&l_tx, l_enc_key) != 1) { + if(dap_chain_datum_tx_add_sign_item(&l_tx, a_key) != 1) { log_it(L_ERROR, "Can't add sign output"); - dap_enc_key_delete(l_enc_key); goto tx_fail; } - dap_enc_key_delete(l_enc_key); - DAP_DELETE(l_owner_addr); + return l_tx; tx_fail: dap_chain_datum_tx_delete(l_tx); - DAP_DELETE(l_owner_addr); return NULL; } @@ -533,20 +585,26 @@ static dap_chain_datum_tx_t *s_order_tx_create(dap_chain_net_t * a_net, dap_enc_ uint256_t a_value, uint256_t a_fee, uint256_t a_sovereign_tax, dap_chain_addr_t *a_sovereign_addr) { - return NULL; + dap_chain_node_addr_t l_node_addr = {}; + return s_stake_tx_create(a_net, a_key, a_value, a_fee, + (dap_chain_addr_t *)&c_dap_chain_addr_blank, &l_node_addr, + a_sovereign_addr, a_sovereign_tax, NULL); } // Put the transaction to mempool -static char *s_stake_tx_put(dap_chain_datum_tx_t *a_tx, dap_chain_net_t *a_net) +static char *s_stake_tx_put(dap_chain_datum_tx_t *a_tx, dap_chain_net_t *a_net, const char *a_hash_out_type) { + dap_chain_t *l_chain = dap_chain_net_get_default_chain_by_chain_type(a_net, CHAIN_TYPE_TX); + if (!l_chain) + return NULL; size_t l_tx_size = dap_chain_datum_tx_get_size(a_tx); dap_chain_datum_t *l_datum = dap_chain_datum_create(DAP_CHAIN_DATUM_TX, a_tx, l_tx_size); - dap_chain_t *l_chain = dap_chain_net_get_default_chain_by_chain_type(a_net, CHAIN_TYPE_TX); - if (!l_chain) { + if (!l_datum) { + log_it(L_CRITICAL, "Not enough memory"); return NULL; } // Processing will be made according to autoprocess policy - char *l_ret = dap_chain_mempool_datum_add(l_datum, l_chain, "hex"); + char *l_ret = dap_chain_mempool_datum_add(l_datum, l_chain, a_hash_out_type); DAP_DELETE(l_datum); return l_ret; } @@ -737,7 +795,7 @@ static dap_chain_datum_tx_t *s_stake_tx_invalidate(dap_chain_net_t *a_net, dap_h dap_chain_tx_out_cond_t *l_tx_out_cond = dap_chain_datum_tx_out_cond_get(l_cond_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE, &l_prev_cond_idx); if (!l_tx_out_cond) { - log_it(L_WARNING, "Requested conditional transaction has no requires conditional output"); + log_it(L_WARNING, "Requested conditional transaction requires conditional output"); return NULL; } dap_hash_fast_t l_spender_hash = { }; @@ -747,6 +805,14 @@ static dap_chain_datum_tx_t *s_stake_tx_invalidate(dap_chain_net_t *a_net, dap_h log_it(L_WARNING, "Requested conditional transaction is already used out by %s", l_hash_str); return NULL; } + dap_chain_tx_in_cond_t *l_in_cond = (dap_chain_tx_in_cond_t *)dap_chain_datum_tx_item_get(l_cond_tx, 0, TX_ITEM_TYPE_IN_COND, 0); + if (l_in_cond) { + l_cond_tx = dap_ledger_tx_find_by_hash(l_ledger, &l_in_cond->header.tx_prev_hash); + if (!l_cond_tx) { + log_it(L_ERROR, "Requested conditional transaction is unchained"); + return NULL; + } + } // Get sign item dap_chain_tx_sig_t *l_tx_sig = (dap_chain_tx_sig_t*) dap_chain_datum_tx_item_get(l_cond_tx, NULL, TX_ITEM_TYPE_SIG, NULL); @@ -1026,7 +1092,7 @@ char *s_fee_order_create(dap_chain_net_t *a_net, uint256_t *a_fee, dap_enc_key_t } struct validator_odrer_ext { - uint256_t value_min; + uint256_t tax; uint256_t value_max; } DAP_ALIGN_PACKED; @@ -1035,12 +1101,13 @@ char *s_validator_order_create(dap_chain_net_t *a_net, uint256_t a_value_min, ui { dap_chain_hash_fast_t l_tx_hash = {}; dap_chain_net_srv_order_direction_t l_dir = SERV_DIR_SELL; - const char *l_native_ticker = a_net->pub.native_ticker; + char l_delegated_ticker[DAP_CHAIN_TICKER_SIZE_MAX]; + dap_chain_datum_token_get_delegated_ticker(l_delegated_ticker, a_net->pub.native_ticker); dap_chain_net_srv_price_unit_uid_t l_unit = { .uint32 = SERV_UNIT_PCS}; dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_STAKE_POS_DELEGATE_ORDERS }; - struct validator_odrer_ext l_order_ext = { a_value_min, a_value_max }; + struct validator_odrer_ext l_order_ext = { a_tax, a_value_max }; dap_chain_net_srv_order_t *l_order = dap_chain_net_srv_order_compose(a_net, l_dir, l_uid, g_node_addr, - l_tx_hash, &a_tax, l_unit, l_native_ticker, 0, + l_tx_hash, &a_value_min, l_unit, l_delegated_ticker, 0, (const uint8_t *)&l_order_ext, sizeof(l_order_ext), 1, NULL, 0, a_key); if (!l_order) @@ -1055,21 +1122,16 @@ char *s_validator_order_create(dap_chain_net_t *a_net, uint256_t a_value_min, ui return l_order_hash_str; } -char *s_staker_order_create(dap_chain_net_t *a_net, uint256_t a_value, uint256_t a_tax, dap_hash_fast_t *a_tx_hash, - dap_chain_addr_t *a_addr, dap_enc_key_t *a_key, const char *a_hash_out_type) +char *s_staker_order_create(dap_chain_net_t *a_net, uint256_t a_value, dap_hash_fast_t *a_tx_hash, dap_enc_key_t *a_key, const char *a_hash_out_type) { dap_chain_net_srv_order_direction_t l_dir = SERV_DIR_BUY; - const char *l_native_ticker = a_net->pub.native_ticker; + char l_delegated_ticker[DAP_CHAIN_TICKER_SIZE_MAX]; + dap_chain_datum_token_get_delegated_ticker(l_delegated_ticker, a_net->pub.native_ticker); dap_chain_net_srv_price_unit_uid_t l_unit = { .uint32 = SERV_UNIT_PCS}; dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_STAKE_POS_DELEGATE_ORDERS }; - struct odrer_ext { - uint256_t value; - dap_chain_addr_t addr; - } DAP_ALIGN_PACKED l_order_ext = { a_value, *a_addr }; dap_chain_net_srv_order_t *l_order = dap_chain_net_srv_order_compose(a_net, l_dir, l_uid, g_node_addr, - *a_tx_hash, &a_tax, l_unit, l_native_ticker, 0, - (const uint8_t *)&l_order_ext, sizeof(l_order_ext), - 1, NULL, 0, a_key); + *a_tx_hash, &a_value, l_unit, l_delegated_ticker, 0, + NULL, 0, 1, NULL, 0, a_key); if (!l_order) return NULL; char *l_order_hash_str = dap_chain_net_srv_order_save(a_net, l_order, true); @@ -1198,6 +1260,13 @@ static int s_cli_srv_stake_order(int a_argc, char **a_argv, int a_arg_index, voi dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't load cert %s", l_cert_str); return -8; } + dap_chain_addr_t l_signing_addr; + dap_chain_addr_fill_from_key(&l_signing_addr, l_cert->enc_key, l_net->pub.id); + int l_result = dap_chain_net_srv_stake_verify_key_and_node(&l_signing_addr, &g_node_addr); + if (l_result) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Key and node verification error"); + return l_result; + } // Create the order & put it in GDB char *l_order_hash_str = s_validator_order_create(l_net, l_value_min, l_value_max, l_tax, l_cert->enc_key, a_hash_out_type); if (l_order_hash_str) { @@ -1275,14 +1344,15 @@ static int s_cli_srv_stake_order(int a_argc, char **a_argv, int a_arg_index, voi dap_chain_wallet_close(l_wallet); DAP_DEL_Z(l_enc_key); char *l_tx_hash_str = NULL; - /*if (!l_tx || !(l_tx_hash_str = s_stake_tx_put(l_tx, l_net))) { + if (!l_tx || !(l_tx_hash_str = s_stake_tx_put(l_tx, l_net, a_hash_out_type))) { dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't compose transaction for order, examine log files for details"); DAP_DEL_Z(l_tx); return -21; - }*/ // TODO - make conditional transaction with specified params + } + DAP_DELETE(l_tx); // Create the order & put it in GDB dap_hash_fast_t l_tx_hash = {}; - dap_chain_hash_fast_from_hex_str(l_tx_hash_str, &l_tx_hash); + dap_chain_hash_fast_from_str(l_tx_hash_str, &l_tx_hash); char *l_cert_str = NULL, *l_default_cert_str = NULL; dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-cert", (const char **)&l_cert_str); if (!l_cert_str) @@ -1291,17 +1361,19 @@ static int s_cli_srv_stake_order(int a_argc, char **a_argv, int a_arg_index, voi if (!l_cert) { dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't load cert %s", l_cert_str); DAP_DEL_Z(l_default_cert_str); + DAP_DELETE(l_tx_hash_str); return -8; } DAP_DEL_Z(l_default_cert_str); - char *l_order_hash_str = s_staker_order_create(l_net, l_value, l_tax, &l_tx_hash, &l_addr, l_cert->enc_key, a_hash_out_type); - if (l_order_hash_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "%sSuccessfully created order %s", l_sign_str, l_order_hash_str); - DAP_DELETE(l_order_hash_str); - } else { + char *l_order_hash_str = s_staker_order_create(l_net, l_value, &l_tx_hash, l_cert->enc_key, a_hash_out_type); + if (!l_order_hash_str) { dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't compose the order"); + DAP_DELETE(l_tx_hash_str); return -9; } + dap_cli_server_cmd_set_reply_text(a_str_reply, "%sSuccessfully created order %s\nSAVE TO TAKE ===>>> Order tx hash = %s", l_sign_str, l_order_hash_str, l_tx_hash_str); + DAP_DELETE(l_order_hash_str); + DAP_DELETE(l_tx_hash_str); } break; case CMD_REMOVE: @@ -1422,6 +1494,468 @@ static int s_cli_srv_stake_order(int a_argc, char **a_argv, int a_arg_index, voi return 0; } +static int s_cli_srv_stake_delegate(int a_argc, char **a_argv, int a_arg_index, void **a_str_reply, const char *a_hash_out_type) +{ + const char *l_net_str = NULL, + *l_wallet_str = NULL, + *l_cert_str = NULL, + *l_value_str = NULL, + *l_fee_str = NULL, + *l_node_addr_str = NULL, + *l_order_hash_str = NULL; + dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-net", &l_net_str); + if (!l_net_str) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'delegate' requires parameter -net"); + return -3; + } + dap_chain_net_t *l_net = dap_chain_net_by_name(l_net_str); + if (!l_net) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Network %s not found", l_net_str); + return -4; + } + dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-w", &l_wallet_str); + if (!l_wallet_str) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'delegate' requires parameter -w"); + return -17; + } + const char* l_sign_str = ""; + dap_chain_wallet_t *l_wallet = dap_chain_wallet_open(l_wallet_str, dap_chain_wallet_get_path(g_config)); + if (!l_wallet) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified wallet not found"); + return -18; + } else + l_sign_str = dap_chain_wallet_check_sign(l_wallet); + dap_enc_key_t *l_enc_key = dap_chain_wallet_get_key(l_wallet, 0); + dap_chain_wallet_close(l_wallet); + dap_chain_addr_t l_signing_addr, l_sovereign_addr = {}; + uint256_t l_sovereign_tax = uint256_0; + dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-cert", &l_cert_str); + dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-order", &l_order_hash_str); + if (!l_cert_str && !l_order_hash_str) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'delegate' requires parameter -cert and/or -order"); + dap_enc_key_delete(l_enc_key); + return -13; + } + dap_chain_node_addr_t l_node_addr = { .uint64 = 0 }; + uint256_t l_value = uint256_0; + dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-value", &l_value_str); + if (!l_value_str) { + if (!l_order_hash_str) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'delegate' requires parameter -value"); + dap_enc_key_delete(l_enc_key); + return -9; + } + } else { + l_value = dap_chain_balance_scan(l_value_str); + if (IS_ZERO_256(l_value)) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Unrecognized number in '-value' param"); + dap_enc_key_delete(l_enc_key); + return -10; + } + } + dap_chain_datum_tx_t *l_prev_tx = NULL; + if (l_cert_str) { + dap_cert_t *l_signing_cert = dap_cert_find_by_name(l_cert_str); + if (!l_signing_cert) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified certificate not found"); + dap_enc_key_delete(l_enc_key); + return -19; + } + if (dap_chain_addr_fill_from_key(&l_signing_addr, l_signing_cert->enc_key, l_net->pub.id)) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified certificate is wrong"); + dap_enc_key_delete(l_enc_key); + return -20; + } + dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-node_addr", &l_node_addr_str); + if (l_node_addr_str) { + if (dap_chain_node_addr_from_str(&l_node_addr, l_node_addr_str)) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Unrecognized node addr %s", l_node_addr_str); + dap_enc_key_delete(l_enc_key); + return -14; + } + } else + l_node_addr.uint64 = dap_chain_net_get_cur_addr_int(l_net); + } + if (l_order_hash_str) { + dap_chain_net_srv_order_t *l_order = dap_chain_net_srv_order_find_by_hash_str(l_net, l_order_hash_str); + if (!l_order) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified order not found"); + dap_enc_key_delete(l_enc_key); + return -25; + } + if (l_order->direction == SERV_DIR_BUY) { // Staker order + if (!l_cert_str) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'delegate' requires parameter -cert with this order type"); + dap_enc_key_delete(l_enc_key); + return -22; + } + if (l_order->ext_size != 0) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified order has invalid size"); + dap_enc_key_delete(l_enc_key); + DAP_DELETE(l_order); + return -26; + } + l_prev_tx = dap_ledger_tx_find_by_hash(l_net->pub.ledger, &l_order->tx_cond_hash); + if (l_prev_tx) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "The order's conditional transaction not found in ledger"); + dap_enc_key_delete(l_enc_key); + DAP_DELETE(l_order); + return -30; + } + int l_out_num = 0; + dap_chain_tx_out_cond_t *l_cond = dap_chain_datum_tx_out_cond_get(l_prev_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE, &l_out_num); + if (!l_cond) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "The order's conditional transaction has invalid type"); + dap_enc_key_delete(l_enc_key); + DAP_DELETE(l_order); + return -31; + } + if (dap_ledger_tx_hash_is_used_out_item(l_net->pub.ledger, &l_order->tx_cond_hash, l_out_num, NULL)) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "The order's conditional transaction is already spent"); + dap_enc_key_delete(l_enc_key); + DAP_DELETE(l_order); + return -32; + } + char l_delegated_ticker[DAP_CHAIN_TICKER_SIZE_MAX]; + dap_chain_datum_token_get_delegated_ticker(l_delegated_ticker, l_net->pub.native_ticker); + const char *l_tx_ticker = dap_ledger_tx_get_token_ticker_by_hash(l_net->pub.ledger, &l_order->tx_cond_hash); + if (dap_strcmp(l_tx_ticker, l_delegated_ticker)) { + log_it(L_WARNING, "Requested conditional transaction have another ticker (not %s)", l_delegated_ticker); + return -38; + } + if (l_cond->tsd_size != sizeof(dap_chain_addr_t) + sizeof(uint256_t) + sizeof(dap_tsd_t) * 2) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "The order's conditional transaction has invalid format"); + dap_enc_key_delete(l_enc_key); + DAP_DELETE(l_order); + return -33; + } + if (compare256(l_cond->header.value, l_order->price)) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "The order's conditional transaction has different value"); + dap_enc_key_delete(l_enc_key); + DAP_DELETE(l_order); + return -34; + } + if (!dap_chain_addr_is_blank(&l_cond->subtype.srv_stake_pos_delegate.signing_addr) || + l_cond->subtype.srv_stake_pos_delegate.signer_node_addr.uint64) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "The order's conditional transaction gas not blank address or key"); + dap_enc_key_delete(l_enc_key); + DAP_DELETE(l_order); + return -35; + } + l_value = l_order->price; + dap_tsd_t *l_tsd = dap_tsd_find(l_cond->tsd, l_cond->tsd_size, DAP_CHAIN_TX_OUT_COND_TSD_ADDR); + l_sovereign_addr = dap_tsd_get_scalar(l_tsd, dap_chain_addr_t); + l_tsd = dap_tsd_find(l_cond->tsd, l_cond->tsd_size, DAP_CHAIN_TX_OUT_COND_TSD_VALUE); + l_sovereign_tax = dap_tsd_get_scalar(l_tsd, uint256_t); + } else { + if (!l_value_str) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'delegate' requires parameter -value with this order type"); + dap_enc_key_delete(l_enc_key); + return -23; + } + const char *l_sovereign_addr_str = NULL; + dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-tax_addr", &l_sovereign_addr_str); + if (l_sovereign_addr_str) { + dap_chain_addr_t *l_spec_addr = dap_chain_addr_from_str(l_sovereign_addr_str); + if (!l_spec_addr) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified address is ivalid"); + return -24; + } + l_sovereign_addr = *l_spec_addr; + DAP_DELETE(l_spec_addr); + } else + dap_chain_addr_fill_from_key(&l_sovereign_addr, l_enc_key, l_net->pub.id); + + if (l_order->ext_size != sizeof(struct validator_odrer_ext)) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified order has invalid size"); + dap_enc_key_delete(l_enc_key); + DAP_DELETE(l_order); + return -26; + } + struct validator_odrer_ext *l_ext = (struct validator_odrer_ext *)l_order->ext_n_sign; + l_sovereign_tax = l_ext->tax; + if (l_order_hash_str && compare256(l_value, l_order->price) == -1) { + char *l_coin_str = dap_chain_balance_to_coins(l_value); + char *l_value_min_str = dap_chain_balance_print(l_order->price); + char *l_coin_min_str = dap_chain_balance_to_coins(l_order->price); + dap_cli_server_cmd_set_reply_text(a_str_reply, "Number in '-value' param %s(%s) is lower than order minimum allowed value %s(%s)", + l_coin_str, l_value_str, l_coin_min_str, l_value_min_str); + DAP_DELETE(l_coin_str); + DAP_DELETE(l_value_min_str); + DAP_DELETE(l_coin_min_str); + dap_enc_key_delete(l_enc_key); + return -13; + } + if (l_order_hash_str && compare256(l_value, l_ext->value_max) == 1) { + char *l_coin_str = dap_chain_balance_to_coins(l_value); + char *l_value_max_str = dap_chain_balance_print(l_ext->value_max); + char *l_coin_max_str = dap_chain_balance_to_coins(l_ext->value_max); + dap_cli_server_cmd_set_reply_text(a_str_reply, "Number in '-value' param %s(%s) is higher than order minimum allowed value %s(%s)", + l_coin_str, l_value_str, l_coin_max_str, l_value_max_str); + DAP_DELETE(l_coin_str); + DAP_DELETE(l_value_max_str); + DAP_DELETE(l_coin_max_str); + dap_enc_key_delete(l_enc_key); + return -14; + } + dap_sign_t *l_sign = (dap_sign_t *)(l_order->ext_n_sign + l_order->ext_size); + if (l_sign->header.type.type == SIG_TYPE_NULL) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified order is unsigned"); + dap_enc_key_delete(l_enc_key); + DAP_DELETE(l_order); + return -27; + } + dap_chain_addr_fill_from_sign(&l_signing_addr, l_sign, l_net->pub.id); + if (dap_strcmp(l_order->price_ticker, l_net->pub.native_ticker)) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified order is invalid"); + dap_enc_key_delete(l_enc_key); + DAP_DELETE(l_order); + return -28; + } + l_node_addr = l_order->node_addr; + } + DAP_DELETE(l_order); + if (compare256(l_sovereign_tax, dap_chain_coins_to_balance("100.0")) == 1 || + compare256(l_sovereign_tax, GET_256_FROM_64(100)) == -1) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Tax must be lower or eqal than 100%% and higher or eqal than 1.0e-16%%"); + dap_enc_key_delete(l_enc_key); + return -29; + } + DIV_256(l_sovereign_tax, GET_256_FROM_64(100), &l_sovereign_tax); + } + if (dap_chain_net_srv_stake_key_delegated(&l_signing_addr)) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified certificate is already delegated"); + dap_enc_key_delete(l_enc_key); + return -21; + } + + if (compare256(l_value, s_srv_stake->delegate_allowed_min) == -1) { + char *l_coin_str = dap_chain_balance_to_coins(l_value); + char *l_value_min_str = dap_chain_balance_print(s_srv_stake->delegate_allowed_min); + char *l_coin_min_str = dap_chain_balance_to_coins(s_srv_stake->delegate_allowed_min); + dap_cli_server_cmd_set_reply_text(a_str_reply, "Number in '-value' param %s(%s) is lower than minimum allowed value %s(%s)", + l_coin_str, l_value_str, l_coin_min_str, l_value_min_str); + DAP_DELETE(l_coin_str); + DAP_DELETE(l_value_min_str); + DAP_DELETE(l_coin_min_str); + dap_enc_key_delete(l_enc_key); + return -11; + } + + dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-fee", &l_fee_str); + if (!l_fee_str) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'delegate' requires parameter -fee"); + dap_enc_key_delete(l_enc_key); + return -15; + } + uint256_t l_fee = dap_chain_balance_scan(l_fee_str); + if (IS_ZERO_256(l_fee)) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Unrecognized number in '-fee' param"); + dap_enc_key_delete(l_enc_key); + return -16; + } + int ret_val = 0; + if((ret_val = dap_chain_net_srv_stake_verify_key_and_node(&l_signing_addr, &l_node_addr)) != 0){ + dap_cli_server_cmd_set_reply_text(a_str_reply, "Key and node verification error"); + dap_enc_key_delete(l_enc_key); + return ret_val; + } + + // Create conditional transaction + dap_chain_datum_tx_t *l_tx = s_stake_tx_create(l_net, l_enc_key, l_value, l_fee, &l_signing_addr, &l_node_addr, + l_order_hash_str ? &l_sovereign_addr : NULL, l_sovereign_tax, l_prev_tx); + dap_enc_key_delete(l_enc_key); + char *l_tx_hash_str; + if (!l_tx || !(l_tx_hash_str = s_stake_tx_put(l_tx, l_net, a_hash_out_type))) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Stake transaction error"); + DAP_DEL_Z(l_tx); + return -12; + } + DAP_DELETE(l_tx); + const char *c_save_to_take = l_prev_tx ? "" : "SAVE TO TAKE ===>>> "; + dap_cli_server_cmd_set_reply_text(a_str_reply, "%s%sStake transaction %s has done", l_sign_str, c_save_to_take, l_tx_hash_str); + DAP_DELETE(l_tx_hash_str); + return 0; +} + +static int s_cli_srv_stake_invalidate(int a_argc, char **a_argv, int a_arg_index, void **a_str_reply, const char *a_hash_out_type) +{ + const char *l_net_str = NULL, + *l_wallet_str = NULL, + *l_fee_str = NULL, + *l_tx_hash_str = NULL, + *l_cert_str = NULL, + *l_poa_cert_str = NULL, + *l_signing_pkey_hash_str = NULL, + *l_signing_pkey_type_str = NULL; + dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-net", &l_net_str); + if (!l_net_str) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'invalidate' requires parameter -net"); + return -3; + } + dap_chain_net_t *l_net = dap_chain_net_by_name(l_net_str); + if (!l_net) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Network %s not found", l_net_str); + return -4; + } + uint256_t l_fee = {}; + dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-w", &l_wallet_str); + if (!l_wallet_str) { + dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-poa_cert", &l_poa_cert_str); + if (!l_poa_cert_str) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'invalidate' requires parameter -w or -poa_cert"); + return -17; + } + } else { + dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-fee", &l_fee_str); + if (!l_fee_str) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'delegate' requires parameter -fee"); + return -5; + } + l_fee = dap_chain_balance_scan(l_fee_str); + if (IS_ZERO_256(l_fee)) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Unrecognized number in '-fee' param"); + return -6; + } + } + dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-tx", &l_tx_hash_str); + if (!l_tx_hash_str) { + dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-cert", &l_cert_str); + if (!l_cert_str) { + dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-signing_pkey_hash", &l_signing_pkey_hash_str); + if (!l_signing_pkey_hash_str) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'invalidate' requires parameter -tx or -cert or -signing_pkey_hash"); + return -13; + } + dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-signing_pkey_type", &l_signing_pkey_type_str); + if (!l_signing_pkey_type_str) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'invalidate' requires parameter -signing_pkey_type"); + return -14; + } + if (dap_sign_type_from_str(l_signing_pkey_type_str).type == SIG_TYPE_NULL) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Invalid signing_pkey_type %s", l_signing_pkey_type_str); + return -15; + } + } + } + + dap_hash_fast_t l_tx_hash = {}; + if (l_tx_hash_str) { + dap_chain_hash_fast_from_str(l_tx_hash_str, &l_tx_hash); + dap_chain_datum_tx_t *l_tx = dap_ledger_tx_find_by_hash(l_net->pub.ledger, &l_tx_hash); + if (!l_tx) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Transaction %s is not found", l_tx_hash_str); + return -21; + } + int l_out_num = 0; + if (!dap_chain_datum_tx_out_cond_get(l_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE, &l_out_num)) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Transaction %s is invalid", l_tx_hash_str); + return -22; + } + dap_hash_fast_t l_spender_hash = {}; + if (dap_ledger_tx_hash_is_used_out_item(l_net->pub.ledger, &l_tx_hash, l_out_num, &l_spender_hash)) { + l_tx_hash = l_spender_hash; + if (!dap_ledger_tx_find_by_hash(l_net->pub.ledger, &l_tx_hash)) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Previous transaction %s is not found", l_tx_hash_str); + return -21; + } + } + dap_chain_net_srv_stake_item_t *l_stake; + HASH_FIND(hh, s_srv_stake->tx_itemlist, &l_tx_hash, sizeof(dap_hash_t), l_stake); + if (l_stake) { + char *l_delegated_hash_str = dap_hash_fast_is_blank(&l_spender_hash) ? dap_strdup(l_tx_hash_str) + : dap_hash_fast_to_str_new(&l_spender_hash); + char l_pkey_hash_str[DAP_HASH_FAST_STR_SIZE]; + dap_hash_fast_to_str(&l_stake->signing_addr.data.hash_fast, l_pkey_hash_str, DAP_HASH_FAST_STR_SIZE); + dap_cli_server_cmd_set_reply_text(a_str_reply, "Transaction %s has active delegated key %s, need to revoke it first", + l_delegated_hash_str, l_pkey_hash_str); + DAP_DELETE(l_delegated_hash_str); + return -30; + } + } else { + dap_chain_addr_t l_signing_addr; + if (l_cert_str) { + dap_cert_t *l_cert = dap_cert_find_by_name(l_cert_str); + if (!l_cert) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified certificate not found"); + return -18; + } + if (dap_chain_addr_fill_from_key(&l_signing_addr, l_cert->enc_key, l_net->pub.id)) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified certificate is wrong"); + return -22; + } + } else { + dap_hash_fast_t l_pkey_hash = {}; + if (dap_chain_hash_fast_from_str(l_signing_pkey_hash_str, &l_pkey_hash)) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Invalid pkey hash format"); + return -23; + } + dap_chain_addr_fill(&l_signing_addr, dap_sign_type_from_str(l_signing_pkey_type_str), &l_pkey_hash, l_net->pub.id); + } + dap_chain_net_srv_stake_item_t *l_stake; + HASH_FIND(hh, s_srv_stake->itemlist, &l_signing_addr, sizeof(dap_chain_addr_t), l_stake); + if (!l_stake) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified certificate/pkey hash is not delegated nor this delegating is approved." + " Try to invalidate with tx hash instead"); + return -24; + } + l_tx_hash = l_stake->tx_hash; + } + if (l_wallet_str) { + const char* l_sign_str = ""; + dap_chain_wallet_t *l_wallet = dap_chain_wallet_open(l_wallet_str, dap_chain_wallet_get_path(g_config)); + if (!l_wallet) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified wallet not found"); + return -18; + } else { + l_sign_str = dap_chain_wallet_check_sign(l_wallet); + } + dap_enc_key_t *l_enc_key = dap_chain_wallet_get_key(l_wallet, 0); + dap_chain_datum_tx_t *l_tx = s_stake_tx_invalidate(l_net, &l_tx_hash, l_fee, l_enc_key); + dap_chain_wallet_close(l_wallet); + dap_enc_key_delete(l_enc_key); + char *l_out_hash_str = NULL; + if (l_tx && (l_out_hash_str = s_stake_tx_put(l_tx, l_net, a_hash_out_type))) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "%sAll m-tokens successfully returned to " + "owner. Returning tx hash %s.", l_sign_str, l_out_hash_str); + DAP_DELETE(l_out_hash_str); + DAP_DELETE(l_tx); + } else { + l_tx_hash_str = dap_chain_hash_fast_to_str_new(&l_tx_hash); + dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't invalidate transaction %s, examine log files for details", l_tx_hash_str); + DAP_DELETE(l_tx_hash_str); + DAP_DEL_Z(l_tx); + return -21; + } + } else { + dap_cert_t *l_poa_cert = dap_cert_find_by_name(l_poa_cert_str); + if (!l_poa_cert) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified certificate not found"); + return -25; + } + if (!s_srv_stake_is_poa_cert(l_net, l_poa_cert->enc_key)) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified certificate is not PoA root one"); + return -26; + } + dap_chain_datum_decree_t *l_decree = s_stake_decree_invalidate(l_net, &l_tx_hash, l_poa_cert); + char *l_decree_hash_str = NULL; + if (l_decree && (l_decree_hash_str = s_stake_decree_put(l_decree, l_net))) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified delegated key invalidated. " + "Created key invalidation decree %s." + "Try to execute this command with -w to return m-tokens to owner", l_decree_hash_str); + DAP_DELETE(l_decree); + DAP_DELETE(l_decree_hash_str); + } else { + char l_tx_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE]; + dap_chain_hash_fast_to_str(&l_tx_hash, l_tx_hash_str, sizeof(l_tx_hash_str)); + dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't invalidate transaction %s, examine log files for details", l_tx_hash_str); + DAP_DEL_Z(l_decree); + return -21; + } + } + return 0; +} + DAP_STATIC_INLINE bool s_chain_esbocs_started(dap_chain_net_t *a_net) { dap_chain_t *l_chain; @@ -1487,22 +2021,21 @@ static void s_get_tx_filter_callback(dap_chain_net_t* a_net, dap_chain_datum_tx_ { struct get_tx_cond_pos_del_from_tx * l_args = (struct get_tx_cond_pos_del_from_tx* ) a_arg; int l_out_idx_tmp = 0; - dap_chain_tx_out_cond_t *l_tx_out_cond = NULL; + dap_chain_tx_out_cond_t *l_tx_out_cond = dap_chain_datum_tx_out_cond_get(a_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE, + &l_out_idx_tmp); + if (!l_tx_out_cond) + return; + if (dap_chain_addr_is_blank(&l_tx_out_cond->subtype.srv_stake_pos_delegate.signing_addr) || + l_tx_out_cond->subtype.srv_stake_pos_delegate.signer_node_addr.uint64 == 0) + return; dap_hash_fast_t l_datum_hash; - - if (NULL != (l_tx_out_cond = dap_chain_datum_tx_out_cond_get(a_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE, - &l_out_idx_tmp))) - { - dap_hash_fast(a_tx, dap_chain_datum_tx_get_size(a_tx), &l_datum_hash); - if (!dap_ledger_tx_hash_is_used_out_item(a_net->pub.ledger, &l_datum_hash, l_out_idx_tmp, NULL)) { - dap_chain_net_srv_stake_item_t *l_stake = NULL; - HASH_FIND(ht, s_srv_stake->tx_itemlist, &l_datum_hash, sizeof(dap_hash_fast_t), l_stake); - if(!l_stake){ - l_args->ret = dap_list_append(l_args->ret,a_tx); - } - } - } - return; + dap_hash_fast(a_tx, dap_chain_datum_tx_get_size(a_tx), &l_datum_hash); + if (dap_ledger_tx_hash_is_used_out_item(a_net->pub.ledger, &l_datum_hash, l_out_idx_tmp, NULL)) + return; + dap_chain_net_srv_stake_item_t *l_stake = NULL; + HASH_FIND(ht, s_srv_stake->tx_itemlist, &l_datum_hash, sizeof(dap_hash_fast_t), l_stake); + if (!l_stake) + l_args->ret = dap_list_append(l_args->ret,a_tx); } static int s_callback_compare_tx_list(dap_list_t *a_datum1, dap_list_t *a_datum2) @@ -1669,6 +2202,16 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, void **a_str_reply) } switch (l_cmd_num) { + + case CMD_ORDER: + return s_cli_srv_stake_order(a_argc, a_argv, l_arg_index + 1, a_str_reply, l_hash_out_type); + + case CMD_DELEGATE: + return s_cli_srv_stake_delegate(a_argc, a_argv, l_arg_index + 1, a_str_reply, l_hash_out_type); + + case CMD_INVALIDATE: + return s_cli_srv_stake_invalidate(a_argc, a_argv, l_arg_index + 1, a_str_reply, l_hash_out_type); + case CMD_CHECK: { const char * l_netst = NULL; @@ -1748,213 +2291,7 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, void **a_str_reply) } break; - case CMD_ORDER: - return s_cli_srv_stake_order(a_argc, a_argv, l_arg_index + 1, a_str_reply, l_hash_out_type); - case CMD_DELEGATE: { - const char *l_net_str = NULL, - *l_wallet_str = NULL, - *l_cert_str = NULL, - *l_value_str = NULL, - *l_fee_str = NULL, - *l_node_addr_str = NULL, - *l_order_hash_str = NULL, - *l_sovereign_addr_str = NULL; - l_arg_index++; - dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-net", &l_net_str); - if (!l_net_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'delegate' requires parameter -net"); - return -3; - } - dap_chain_net_t *l_net = dap_chain_net_by_name(l_net_str); - if (!l_net) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Network %s not found", l_net_str); - return -4; - } - dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-w", &l_wallet_str); - if (!l_wallet_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'delegate' requires parameter -w"); - return -17; - } - const char* l_sign_str = ""; - dap_chain_wallet_t *l_wallet = dap_chain_wallet_open(l_wallet_str, dap_chain_wallet_get_path(g_config)); - if (!l_wallet) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified wallet not found"); - return -18; - } else { - l_sign_str = dap_chain_wallet_check_sign(l_wallet); - } - dap_chain_addr_t l_signing_addr, l_sovereign_addr = {}; - uint256_t l_sovereign_tax = uint256_0; - dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-cert", &l_cert_str); - dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-order", &l_order_hash_str); - if (!l_cert_str && !l_order_hash_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'delegate' requires parameter -cert or -order"); - dap_chain_wallet_close(l_wallet); - return -13; - } - dap_chain_node_addr_t l_node_addr; - uint256_t l_value_min, l_value_max; - if (l_cert_str) { - dap_cert_t *l_signing_cert = dap_cert_find_by_name(l_cert_str); - if (!l_signing_cert) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified certificate not found"); - dap_chain_wallet_close(l_wallet); - return -19; - } - if (dap_chain_addr_fill_from_key(&l_signing_addr, l_signing_cert->enc_key, l_net->pub.id)) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified certificate is wrong"); - dap_chain_wallet_close(l_wallet); - return -20; - } - dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-node_addr", &l_node_addr_str); - if (l_node_addr_str) { - if (dap_chain_node_addr_from_str(&l_node_addr, l_node_addr_str)) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Unrecognized node addr %s", l_node_addr_str); - dap_chain_wallet_close(l_wallet); - return -14; - } - } else - l_node_addr.uint64 = dap_chain_net_get_cur_addr_int(l_net); - } else { - dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-tax_addr", &l_sovereign_addr_str); - if (l_sovereign_addr_str) { - dap_chain_addr_t *l_spec_addr = dap_chain_addr_from_str(l_sovereign_addr_str); - if (!l_spec_addr) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified address is ivalid"); - return -24; - } - l_sovereign_addr = *l_spec_addr; - DAP_DELETE(l_spec_addr); - } else - dap_chain_addr_fill_from_key(&l_sovereign_addr, dap_chain_wallet_get_key(l_wallet, 0), l_net->pub.id); - dap_chain_net_srv_order_t *l_order = dap_chain_net_srv_order_find_by_hash_str(l_net, l_order_hash_str); - if (!l_order) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified order not found"); - dap_chain_wallet_close(l_wallet); - return -25; - } - if (l_order->ext_size != sizeof(struct validator_odrer_ext)) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified order has invalid size"); - dap_chain_wallet_close(l_wallet); - DAP_DELETE(l_order); - return -26; - } - struct validator_odrer_ext *l_ext = (struct validator_odrer_ext *)l_order->ext_n_sign; - l_value_min = l_ext->value_min; - l_value_max = l_ext->value_max; - dap_sign_t *l_sign = (dap_sign_t *)(l_order->ext_n_sign + l_order->ext_size); - if (l_sign->header.type.type == SIG_TYPE_NULL) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified order is unsigned"); - dap_chain_wallet_close(l_wallet); - DAP_DELETE(l_order); - return -27; - } - if (dap_strcmp(l_order->price_ticker, l_net->pub.native_ticker)) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified order is invalid"); - dap_chain_wallet_close(l_wallet); - DAP_DELETE(l_order); - return -28; - } - dap_chain_addr_fill_from_sign(&l_signing_addr, l_sign, l_net->pub.id); - l_node_addr = l_order->node_addr; - l_sovereign_tax = l_order->price; - DAP_DELETE(l_order); - if (compare256(l_sovereign_tax, dap_chain_coins_to_balance("100.0")) == 1 || - compare256(l_sovereign_tax, GET_256_FROM_64(100)) == -1) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Tax must be lower or eqal than 100%% and higher or eqal than 1.0e-16%%"); - dap_chain_wallet_close(l_wallet); - return -29; - } - DIV_256(l_sovereign_tax, GET_256_FROM_64(100), &l_sovereign_tax); - } - if (dap_chain_net_srv_stake_key_delegated(&l_signing_addr)) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified certificate is already delegated"); - dap_chain_wallet_close(l_wallet); - return -21; - } - dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-value", &l_value_str); - if (!l_value_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'delegate' requires parameter -value"); - dap_chain_wallet_close(l_wallet); - return -9; - } - uint256_t l_value = dap_chain_balance_scan(l_value_str); - if (IS_ZERO_256(l_value)) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Unrecognized number in '-value' param"); - dap_chain_wallet_close(l_wallet); - return -10; - } - if (compare256(l_value, s_srv_stake->delegate_allowed_min) == -1) { - char *l_coin_str = dap_chain_balance_to_coins(l_value); - char *l_value_min_str = dap_chain_balance_print(s_srv_stake->delegate_allowed_min); - char *l_coin_min_str = dap_chain_balance_to_coins(s_srv_stake->delegate_allowed_min); - dap_cli_server_cmd_set_reply_text(a_str_reply, "Number in '-value' param %s(%s) is lower than minimum allowed value %s(%s)", - l_coin_str, l_value_str, l_coin_min_str, l_value_min_str); - DAP_DELETE(l_coin_str); - DAP_DELETE(l_value_min_str); - DAP_DELETE(l_coin_min_str); - dap_chain_wallet_close(l_wallet); - return -11; - } - if (l_order_hash_str && compare256(l_value, l_value_min) == -1) { - char *l_coin_str = dap_chain_balance_to_coins(l_value); - char *l_value_min_str = dap_chain_balance_print(l_value_min); - char *l_coin_min_str = dap_chain_balance_to_coins(l_value_min); - dap_cli_server_cmd_set_reply_text(a_str_reply, "Number in '-value' param %s(%s) is lower than order minimum allowed value %s(%s)", - l_coin_str, l_value_str, l_coin_min_str, l_value_min_str); - DAP_DELETE(l_coin_str); - DAP_DELETE(l_value_min_str); - DAP_DELETE(l_coin_min_str); - dap_chain_wallet_close(l_wallet); - return -13; - } - if (l_order_hash_str && compare256(l_value, l_value_max) == 1) { - char *l_coin_str = dap_chain_balance_to_coins(l_value); - char *l_value_max_str = dap_chain_balance_print(l_value_max); - char *l_coin_max_str = dap_chain_balance_to_coins(l_value_max); - dap_cli_server_cmd_set_reply_text(a_str_reply, "Number in '-value' param %s(%s) is higher than order minimum allowed value %s(%s)", - l_coin_str, l_value_str, l_coin_max_str, l_value_max_str); - DAP_DELETE(l_coin_str); - DAP_DELETE(l_value_max_str); - DAP_DELETE(l_coin_max_str); - dap_chain_wallet_close(l_wallet); - return -14; - } - dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-fee", &l_fee_str); - if (!l_fee_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'delegate' requires parameter -fee"); - dap_chain_wallet_close(l_wallet); - return -15; - } - uint256_t l_fee = dap_chain_balance_scan(l_fee_str); - if (IS_ZERO_256(l_fee)) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Unrecognized number in '-fee' param"); - dap_chain_wallet_close(l_wallet); - return -16; - } - int ret_val = 0; - if((ret_val = dap_chain_net_srv_stake_verify_key_and_node(&l_signing_addr, &l_node_addr)) != 0){ - dap_cli_server_cmd_set_reply_text(a_str_reply, "Key and node verification error"); - dap_chain_wallet_close(l_wallet); - return ret_val; - } - // Create conditional transaction - dap_chain_datum_tx_t *l_tx = s_stake_tx_create(l_net, l_wallet, l_value, l_fee, &l_signing_addr, &l_node_addr, - l_order_hash_str ? &l_sovereign_addr : NULL, l_sovereign_tax); - dap_chain_wallet_close(l_wallet); - if (!l_tx || !s_stake_tx_put(l_tx, l_net)) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Stake transaction error"); - DAP_DEL_Z(l_tx); - return -12; - } - dap_hash_fast_t l_tx_hash; - dap_hash_fast(l_tx, dap_chain_datum_tx_get_size(l_tx), &l_tx_hash); - DAP_DELETE(l_tx); - char *l_tx_hash_str = dap_hash_fast_to_str_new(&l_tx_hash); - dap_cli_server_cmd_set_reply_text(a_str_reply, "%sSAVE TO TAKE ===>>> Stake transaction %s has done", l_sign_str, l_tx_hash_str); - DAP_DELETE(l_tx_hash_str); - } break; case CMD_APPROVE: { const char *l_net_str = NULL, *l_tx_hash_str = NULL, *l_cert_str = NULL; l_arg_index++; @@ -2003,6 +2340,7 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, void **a_str_reply) l_decree_hash_str); DAP_DELETE(l_decree_hash_str); } break; + case CMD_LIST: { l_arg_index++; if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "keys", NULL)) { @@ -2160,165 +2498,7 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, void **a_str_reply) return -2; } } break; - case CMD_INVALIDATE: { - const char *l_net_str = NULL, - *l_wallet_str = NULL, - *l_fee_str = NULL, - *l_tx_hash_str = NULL, - *l_cert_str = NULL, - *l_poa_cert_str = NULL, - *l_signing_pkey_hash_str = NULL, - *l_signing_pkey_type_str = NULL; - l_arg_index++; - dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-net", &l_net_str); - if (!l_net_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'invalidate' requires parameter -net"); - return -3; - } - dap_chain_net_t *l_net = dap_chain_net_by_name(l_net_str); - if (!l_net) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Network %s not found", l_net_str); - return -4; - } - uint256_t l_fee = {}; - dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-w", &l_wallet_str); - if (!l_wallet_str) { - dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-poa_cert", &l_poa_cert_str); - if (!l_poa_cert_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'invalidate' requires parameter -w or -poa_cert"); - return -17; - } - } else { - dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-fee", &l_fee_str); - if (!l_fee_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'delegate' requires parameter -fee"); - return -5; - } - l_fee = dap_chain_balance_scan(l_fee_str); - if (IS_ZERO_256(l_fee)) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Unrecognized number in '-fee' param"); - return -6; - } - } - dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-tx", &l_tx_hash_str); - if (!l_tx_hash_str) { - dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-cert", &l_cert_str); - if (!l_cert_str) { - dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-signing_pkey_hash", &l_signing_pkey_hash_str); - if (!l_signing_pkey_hash_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'invalidate' requires parameter -tx or -cert or -signing_pkey_hash"); - return -13; - } - dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-signing_pkey_type", &l_signing_pkey_type_str); - if (!l_signing_pkey_type_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'invalidate' requires parameter -signing_pkey_type"); - return -14; - } - if (dap_sign_type_from_str(l_signing_pkey_type_str).type == SIG_TYPE_NULL) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Invalid signing_pkey_type %s", l_signing_pkey_type_str); - return -15; - } - } - } - dap_hash_fast_t l_tx_hash = {}; - if (l_tx_hash_str) { - dap_chain_hash_fast_from_str(l_tx_hash_str, &l_tx_hash); - if (!dap_ledger_tx_find_by_hash(l_net->pub.ledger, &l_tx_hash)) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Transaction %s is not found", l_tx_hash_str); - return -20; - } - dap_chain_net_srv_stake_item_t *l_stake; - HASH_FIND(hh, s_srv_stake->tx_itemlist, &l_tx_hash, sizeof(dap_hash_t), l_stake); - if (l_stake) { - char l_pkey_hash_str[DAP_HASH_FAST_STR_SIZE]; - dap_hash_fast_to_str(&l_stake->signing_addr.data.hash_fast, l_pkey_hash_str, DAP_HASH_FAST_STR_SIZE); - dap_cli_server_cmd_set_reply_text(a_str_reply, "Transaction %s has active delegated key %s, need to revoke it first", - l_tx_hash_str, l_pkey_hash_str); - return -30; - } - } else { - dap_chain_addr_t l_signing_addr; - if (l_cert_str) { - dap_cert_t *l_cert = dap_cert_find_by_name(l_cert_str); - if (!l_cert) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified certificate not found"); - return -18; - } - if (dap_chain_addr_fill_from_key(&l_signing_addr, l_cert->enc_key, l_net->pub.id)) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified certificate is wrong"); - return -22; - } - } else { - dap_hash_fast_t l_pkey_hash = {}; - if (dap_chain_hash_fast_from_str(l_tx_hash_str, &l_pkey_hash)) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Invalid pkey hash format"); - return -23; - } - dap_chain_addr_fill(&l_signing_addr, dap_sign_type_from_str(l_signing_pkey_type_str), &l_pkey_hash, l_net->pub.id); - } - dap_chain_net_srv_stake_item_t *l_stake; - HASH_FIND(hh, s_srv_stake->itemlist, &l_signing_addr, sizeof(dap_chain_addr_t), l_stake); - if (!l_stake) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified certificate/pkey hash is not delegated nor this delegating is approved." - " Try to invalidate with tx hash instead"); - return -24; - } - l_tx_hash = l_stake->tx_hash; - } - if (l_wallet_str) { - const char* l_sign_str = ""; - dap_chain_wallet_t *l_wallet = dap_chain_wallet_open(l_wallet_str, dap_chain_wallet_get_path(g_config)); - if (!l_wallet) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified wallet not found"); - return -18; - } else { - l_sign_str = dap_chain_wallet_check_sign(l_wallet); - } - dap_enc_key_t *l_enc_key = dap_chain_wallet_get_key(l_wallet, 0); - dap_chain_datum_tx_t *l_tx = s_stake_tx_invalidate(l_net, &l_tx_hash, l_fee, l_enc_key); - dap_chain_wallet_close(l_wallet); - dap_enc_key_delete(l_enc_key); - char *l_tx_hash_str = NULL; - if (l_tx && (l_tx_hash_str = s_stake_tx_put(l_tx, l_net))) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "%sAll m-tokens successfully returned to " - "owner. Returning tx hash %s.", l_sign_str, l_tx_hash_str); - DAP_DEL_Z(l_tx_hash_str); - DAP_DELETE(l_tx); - } else { - l_tx_hash_str = dap_chain_hash_fast_to_str_new(&l_tx_hash); - dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't invalidate transaction %s, examine log files for details", l_tx_hash_str); - DAP_DELETE(l_tx_hash_str); - DAP_DEL_Z(l_tx); - return -21; - } - } else { - dap_cert_t *l_poa_cert = dap_cert_find_by_name(l_poa_cert_str); - if (!l_poa_cert) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified certificate not found"); - return -25; - } - if (!s_srv_stake_is_poa_cert(l_net, l_poa_cert->enc_key)) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified certificate is not PoA root one"); - return -26; - } - dap_chain_datum_decree_t *l_decree = s_stake_decree_invalidate(l_net, &l_tx_hash, l_poa_cert); - char *l_decree_hash_str = NULL; - if (l_decree && (l_decree_hash_str = s_stake_decree_put(l_decree, l_net))) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified delageted key invalidated. " - "Created key invalidation decree %s." - "Try to execute this command with -w to return m-tokens to owner", l_decree_hash_str); - DAP_DELETE(l_decree); - DAP_DELETE(l_decree_hash_str); - } else { - char l_tx_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE]; - dap_chain_hash_fast_to_str(&l_tx_hash, l_tx_hash_str, sizeof(l_tx_hash_str)); - dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't invalidate transaction %s, examine log files for details", l_tx_hash_str); - DAP_DEL_Z(l_decree); - return -21; - } - } - } break; case CMD_MIN_VALUE: { const char *l_net_str = NULL, *l_cert_str = NULL, @@ -2373,7 +2553,8 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, void **a_str_reply) DAP_DEL_Z(l_decree); return -21; } - } break; + } break; + default: { dap_cli_server_cmd_set_reply_text(a_str_reply, "Command %s not recognized", a_argv[l_arg_index]); return -1; diff --git a/modules/service/xchange/dap_chain_net_srv_xchange.c b/modules/service/xchange/dap_chain_net_srv_xchange.c index 013ccb5d87..c1e8f25e29 100644 --- a/modules/service/xchange/dap_chain_net_srv_xchange.c +++ b/modules/service/xchange/dap_chain_net_srv_xchange.c @@ -1502,7 +1502,7 @@ static xchange_tx_type_t s_xchange_tx_get_type (dap_chain_net_t * a_net, dap_cha dap_sign_t *l_sign = dap_chain_datum_tx_item_sign_get_sig((dap_chain_tx_sig_t *)l_tx_sig); bool l_owner = false; - l_owner = dap_sign_match_pkey_signs(l_prev_sign,l_sign); + l_owner = dap_sign_compare_pkeys(l_prev_sign,l_sign); if (l_owner) l_tx_type = TX_TYPE_INVALIDATE; else diff --git a/modules/type/blocks/dap_chain_cs_blocks.c b/modules/type/blocks/dap_chain_cs_blocks.c index 38fce2f0ea..5cdb1c557b 100644 --- a/modules/type/blocks/dap_chain_cs_blocks.c +++ b/modules/type/blocks/dap_chain_cs_blocks.c @@ -450,7 +450,9 @@ static void s_cli_meta_hex_print( dap_string_t * a_str_tmp, const char * a_meta static void s_print_autocollect_table(dap_chain_net_t *a_net, dap_string_t *a_reply_str, const char *a_table_name) { - dap_string_append_printf(a_reply_str, "\n=== %s ===\n", a_table_name); + dap_string_append_printf(a_reply_str, "\nAutocollect status is %s\n", dap_chain_esbocs_get_autocollect_status(a_net->pub.id) ? + "active" : "inactive, check the network config"); + dap_string_append_printf(a_reply_str, "\nAutocollect tables content for:\n=== %s ===\n", a_table_name); size_t l_objs_count = 0; char *l_group = dap_strcmp(a_table_name, "Fees") ? dap_chain_cs_blocks_get_reward_group(a_net->pub.name) : dap_chain_cs_blocks_get_fee_group(a_net->pub.name); @@ -486,7 +488,7 @@ static void s_print_autocollect_table(dap_chain_net_t *a_net, dap_string_t *a_re char *l_profit_str = dap_chain_balance_to_coins(l_collect_value); char *l_tax_str = dap_chain_balance_to_coins(l_collect_tax); char *l_fee_str = dap_chain_balance_to_coins(l_collect_fee); - dap_string_append_printf(a_reply_str, "Total prepared value: %s %s, where\n\tprofit is %s, tax is %s, fee is %s\n", + dap_string_append_printf(a_reply_str, "\nTotal prepared value: %s %s, where\n\tprofit is %s, tax is %s, fee is %s\n", l_total_str, a_net->pub.native_ticker, l_profit_str, l_tax_str, l_fee_str); DAP_DEL_Z(l_total_str); DAP_DEL_Z(l_profit_str); @@ -1048,7 +1050,7 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply) dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'block autocollect' requires subcommand 'status'"); return -14; } - dap_string_t *l_reply_str = dap_string_new("Autocollect tables content for:\n"); + dap_string_t *l_reply_str = dap_string_new(""); s_print_autocollect_table(l_net, l_reply_str, "Fees"); s_print_autocollect_table(l_net, l_reply_str, "Rewards"); dap_cli_server_cmd_set_reply_text(a_str_reply, "%s", l_reply_str->str); -- GitLab