1
0
Fork 0
forked from lthn/blockchain

multiple fixes for wallet rpc api on_asset_send_ext_signed_tx on_attach_asset_descriptor and on_transfer_asset_ownership

This commit is contained in:
cryptozoidberg 2025-03-29 00:14:47 +04:00
parent 0662f9bbed
commit 938050df0f
No known key found for this signature in database
GPG key ID: 2E10CC61CAC8F36D
4 changed files with 143 additions and 37 deletions

View file

@ -5682,11 +5682,12 @@ void wallet2::update_asset(const crypto::public_key& asset_id, const currency::a
ctp.tx_meaning_for_logs = "asset update";
bool send_to_network = true;
if (last_adb.owner_eth_pub_key.has_value())
if (own_asset_entry_it->second.thirdparty_custody || last_adb.owner_eth_pub_key.has_value())
{
send_to_network = false;
ctp.additional_transfer_flags_to_mark = WALLET_TRANSFER_DETAIL_FLAG_ASSET_OP_RESERVATION;
ctp.tx_meaning_for_logs = "asset eth update";
ctp.ado_sign_thirdparty = true;
}
this->transfer(ctp, ft, send_to_network, nullptr);
@ -5724,11 +5725,12 @@ void wallet2::transfer_asset_ownership(const crypto::public_key& asset_id, const
ctp.tx_meaning_for_logs = "transfer asset ownership";
bool send_to_network = true;
if (last_adb.owner_eth_pub_key.has_value())
if (own_asset_entry_it->second.thirdparty_custody || last_adb.owner_eth_pub_key.has_value())
{
send_to_network = false;
ctp.additional_transfer_flags_to_mark = WALLET_TRANSFER_DETAIL_FLAG_ASSET_OP_RESERVATION;
ctp.tx_meaning_for_logs = "transfer asset eth ownership";
ctp.ado_sign_thirdparty = true;
}
this->transfer(ctp, ft, send_to_network, nullptr);

View file

@ -2113,13 +2113,13 @@ namespace wallet_public
struct request
{
crypto::public_key asset_id;
crypto::eth_public_key owner_eth_pub_key = currency::null_eth_public_key; // note: the size is 33 bytes (if present)
crypto::public_key owner = currency::null_pkey; // regular Zano Ed25519 public key
crypto::eth_public_key new_owner_eth_pub_key = currency::null_eth_public_key; // note: the size is 33 bytes (if present)
crypto::public_key new_owner = currency::null_pkey; // regular Zano Ed25519 public key
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE_POD_AS_HEX_STRING(asset_id) DOC_DSCR("Own asset id, that would be transfered to someone else") DOC_EXMP("40fa6db923728b38962718c61b4dc3af1acaa1967479c73703e260dc3609c58d") DOC_END
KV_SERIALIZE_POD_AS_HEX_STRING(owner) DOC_DSCR("Public key of the new owner(default Ed25519 public key, 32 bytes)") DOC_EXMP("f74bb56a5b4fa562e679ccaadd697463498a66de4f1760b2cd40f11c3a00a7a8") DOC_END
KV_SERIALIZE_POD_AS_HEX_STRING(owner_eth_pub_key) DOC_DSCR("Public key of the new owner(ECDSA public key, 33 bytes) Used only if 'owner' field is empty") DOC_EXMP("f74bb56a5b4fa562e679ccaadd697463498a66de4f1760b2cd40f11c3a00a7a84d") DOC_END
KV_SERIALIZE_POD_AS_HEX_STRING(new_owner) DOC_DSCR("Public key of the new owner(default Ed25519 public key, 32 bytes)") DOC_EXMP("f74bb56a5b4fa562e679ccaadd697463498a66de4f1760b2cd40f11c3a00a7a8") DOC_END
KV_SERIALIZE_POD_AS_HEX_STRING(new_owner_eth_pub_key) DOC_DSCR("Public key of the new owner(ECDSA public key, 33 bytes) Used only if 'owner' field is empty") DOC_EXMP("f74bb56a5b4fa562e679ccaadd697463498a66de4f1760b2cd40f11c3a00a7a84d") DOC_END
END_KV_SERIALIZE_MAP()
};

View file

@ -1470,13 +1470,13 @@ namespace tools
{
WALLET_RPC_BEGIN_TRY_ENTRY();
currency::asset_owner_pub_key_v new_owner_v;
if (req.owner != currency::null_pkey)
if (req.new_owner!= currency::null_pkey)
{
new_owner_v = req.owner;
new_owner_v = req.new_owner;
}
else if(req.owner_eth_pub_key != currency::null_eth_public_key)
else if(req.new_owner_eth_pub_key != currency::null_eth_public_key)
{
new_owner_v = req.owner_eth_pub_key;
new_owner_v = req.new_owner_eth_pub_key;
}else
{
res.status = API_RETURN_CODE_BAD_ARG_INVALID_ADDRESS;

View file

@ -955,6 +955,64 @@ bool wallet_rpc_thirdparty_custody::generate(std::vector<test_event_entry>& even
#define TEST_TOKEN_MAX_SUPPLY 2000
#define TEST_TOKEN_CURRENT_SUPPLY 1000
typedef boost::variant<crypto::secret_key, crypto::eth_secret_key> secret_key_v;
typedef boost::variant<crypto::public_key, crypto::eth_public_key> public_key_v;
template<typename t_response>
bool sign_signature_with_keys(const t_response& rsp_with_data, tools::wallet_rpc_server& attached_wallet_rpc, const secret_key_v& signer_v, const public_key_v& verifier)
{
bool r = false;
tools::wallet_public::COMMAND_ASSET_SEND_EXT_SIGNED_TX::request send_signed_req = AUTO_VAL_INIT(send_signed_req);
if (signer_v.type() == typeid(crypto::secret_key))
{
//schnor sig
const crypto::secret_key& signer = boost::get<crypto::secret_key>(signer_v);
crypto::signature sig = AUTO_VAL_INIT(sig);
crypto::generic_schnorr_sig sig_sch = AUTO_VAL_INIT(sig_sch);
r = crypto::generate_schnorr_sig(rsp_with_data.tx_id, signer, sig_sch);
CHECK_AND_ASSERT_MES(r, false, "gailed to generate schnorr signature");
//crypto::generate_signature(emm_resp.tx_id, miner_wlt->get_account().get_keys().account_address.spend_public_key, miner_wlt->get_account().get_keys().spend_secret_key, sig);
// instant verification, just in case
r = crypto::verify_schnorr_sig(rsp_with_data.tx_id, boost::get<crypto::public_key>(verifier), sig_sch);
CHECK_AND_ASSERT_MES(r, false, "verify_schnorr_sig failed");
currency::schnor_new_to_schnor_old(sig_sch, sig);
send_signed_req.regular_sig = sig;
}
else if (signer_v.type() == typeid(crypto::eth_secret_key))
{
////ecdsa sig
const crypto::eth_secret_key& signer = boost::get<crypto::eth_secret_key>(signer_v);
r = crypto::generate_eth_signature(rsp_with_data.tx_id, signer, send_signed_req.eth_sig);
CHECK_AND_ASSERT_MES(r, false, "gailed to generate schnorr signature");
r = crypto::verify_eth_signature(rsp_with_data.tx_id, boost::get<crypto::eth_public_key>(verifier), send_signed_req.eth_sig);
CHECK_AND_ASSERT_MES(r, false, "verify_eth_signature failed");
}
else
{
return false;
}
send_signed_req.unsigned_tx = rsp_with_data.data_for_external_signing->unsigned_tx;
send_signed_req.expected_tx_id = rsp_with_data.tx_id;
send_signed_req.finalized_tx = rsp_with_data.data_for_external_signing->finalized_tx;
send_signed_req.unlock_transfers_on_fail = true;
tools::wallet_public::COMMAND_ASSET_SEND_EXT_SIGNED_TX::response send_signed_resp{};
r = invoke_text_json_for_rpc(attached_wallet_rpc, "send_ext_signed_asset_tx", send_signed_req, send_signed_resp);
CHECK_AND_ASSERT_MES(r, false, "RPC send_ext_signed_asset_tx failed: ");
CHECK_AND_ASSERT_MES(send_signed_resp.status == API_RETURN_CODE_OK, false, "RPC send_ext_signed_asset_tx failed: ");
return true;
}
bool wallet_rpc_thirdparty_custody::c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
{
@ -1040,9 +1098,10 @@ bool wallet_rpc_thirdparty_custody::c1(currency::core& c, size_t ev_index, const
//let's emit it, but transfer actually to Bob, by using Alice wallet as attache
tools::wallet_public::COMMAND_ASSETS_EMIT::request emm_req = AUTO_VAL_INIT(emm_req);
tools::wallet_public::COMMAND_ASSETS_EMIT::response emm_resp = AUTO_VAL_INIT(emm_resp);
#define COINS_TO_TRANSFER 10
emm_req.asset_id = resp.new_asset_id;
emm_req.destinations.push_back(tools::wallet_public::transfer_destination{10, bob_wlt->get_account().get_public_address_str(), emm_req.asset_id });
emm_req.destinations.push_back(tools::wallet_public::transfer_destination{ COINS_TO_TRANSFER, bob_wlt->get_account().get_public_address_str(), emm_req.asset_id });
r = invoke_text_json_for_rpc(alice_wlt_rpc, "emit_asset", emm_req, emm_resp);
CHECK_AND_ASSERT_MES(r, false, "failed to call");
if (!emm_resp.data_for_external_signing)
@ -1051,33 +1110,9 @@ bool wallet_rpc_thirdparty_custody::c1(currency::core& c, size_t ev_index, const
return false;
}
crypto::signature sig = AUTO_VAL_INIT(sig);
crypto::generic_schnorr_sig sig_sch = AUTO_VAL_INIT(sig_sch);
r = crypto::generate_schnorr_sig(emm_resp.tx_id, miner_wlt->get_account().get_keys().spend_secret_key, sig_sch);
CHECK_AND_ASSERT_MES(r, false, "gailed to generate schnorr signature");
r = sign_signature_with_keys(emm_resp, alice_wlt_rpc, miner_wlt->get_account().get_keys().spend_secret_key, miner_wlt->get_account().get_keys().account_address.spend_public_key);
CHECK_AND_ASSERT_MES(r, false, "failed to call sign_signature_with_keys");
//crypto::generate_signature(emm_resp.tx_id, miner_wlt->get_account().get_keys().account_address.spend_public_key, miner_wlt->get_account().get_keys().spend_secret_key, sig);
// instant verification, just in case
r = crypto::verify_schnorr_sig(emm_resp.tx_id, miner_wlt->get_account().get_keys().account_address.spend_public_key, sig_sch);
CHECK_AND_ASSERT_MES(r, false, "verify_schnorr_sig failed");
currency::schnor_new_to_schnor_old(sig_sch, sig);
//
// send ETH signature alogn with all previous data to a wallet RPC call for final tx assembling and broadcasting
//
tools::wallet_public::COMMAND_ASSET_SEND_EXT_SIGNED_TX::request send_signed_req = AUTO_VAL_INIT(send_signed_req);
send_signed_req.unsigned_tx = emm_resp.data_for_external_signing->unsigned_tx;
send_signed_req.regular_sig = sig;
send_signed_req.expected_tx_id = emm_resp.tx_id;
send_signed_req.finalized_tx = emm_resp.data_for_external_signing->finalized_tx;
send_signed_req.unlock_transfers_on_fail = true;
tools::wallet_public::COMMAND_ASSET_SEND_EXT_SIGNED_TX::response send_signed_resp{};
r = invoke_text_json_for_rpc(alice_wlt_rpc, "send_ext_signed_asset_tx", send_signed_req, send_signed_resp);
CHECK_AND_ASSERT_MES(r, false, "RPC send_ext_signed_asset_tx failed: ");
CHECK_AND_ASSERT_MES(send_signed_resp.status == API_RETURN_CODE_OK, false, "RPC send_ext_signed_asset_tx failed: ");
r = mine_next_pow_blocks_in_playtime(miner_wlt->get_account().get_public_address(), c, 3);
@ -1097,6 +1132,75 @@ bool wallet_rpc_thirdparty_custody::c1(currency::core& c, size_t ev_index, const
CHECK_AND_ASSERT_MES(r, false, "RPC send_ext_signed_asset_tx failed: ");
bool found_asset = false;
for (auto& bal : balance_resp.balances)
{
if (bal.asset_info.asset_id == resp.new_asset_id)
{
found_asset = true;
CHECK_AND_ASSERT_MES(bal.total == COINS_TO_TRANSFER, false, "Amount is unexpected");
}
}
CHECK_AND_ASSERT_MES(found_asset, false, "Asset not found ");
//transfer ownership of the asset to new address
//let's change the owner to ecdsa
crypto::eth_secret_key eth_sk_2{};
crypto::eth_public_key eth_pk_2{};
r = crypto::generate_eth_key_pair(eth_sk_2, eth_pk_2);
CHECK_AND_ASSERT_MES(r, false, "generate_eth_key_pair failed");
tools::wallet_public::COMMAND_TRANSFER_ASSET_OWNERSHIP::request req_own = AUTO_VAL_INIT(req_own);
tools::wallet_public::COMMAND_TRANSFER_ASSET_OWNERSHIP::response res_own = AUTO_VAL_INIT(res_own);
req_own.asset_id = resp.new_asset_id;
req_own.new_owner_eth_pub_key = eth_pk_2;
r = invoke_text_json_for_rpc(alice_wlt_rpc, "transfer_asset_ownership", req_own, res_own);
CHECK_AND_ASSERT_MES(r, false, "failed to call");
if (!res_own.data_for_external_signing)
{
LOG_ERROR("Missing data_for_external_signing");
return false;
}
r = sign_signature_with_keys(res_own, alice_wlt_rpc, miner_wlt->get_account().get_keys().spend_secret_key, miner_wlt->get_account().get_keys().account_address.spend_public_key);
CHECK_AND_ASSERT_MES(r, false, "failed to call sign_signature_with_keys");
r = mine_next_pow_blocks_in_playtime(miner_wlt->get_account().get_public_address(), c, 3);
//now make another tx and see of ownership got changed
emm_resp = AUTO_VAL_INIT(emm_resp);
r = invoke_text_json_for_rpc(alice_wlt_rpc, "emit_asset", emm_req, emm_resp);
CHECK_AND_ASSERT_MES(r, false, "failed to call");
if (!emm_resp.data_for_external_signing)
{
LOG_ERROR("Missing data_for_external_signing");
return false;
}
r = sign_signature_with_keys(emm_resp, alice_wlt_rpc, eth_sk_2, eth_pk_2);
CHECK_AND_ASSERT_MES(r, false, "failed to call sign_signature_with_keys");
r = mine_next_pow_blocks_in_playtime(miner_wlt->get_account().get_public_address(), c, 3);
r = invoke_text_json_for_rpc(bob_wlt_rpc, "getbalance", balance_req, balance_resp);
CHECK_AND_ASSERT_MES(r, false, "RPC send_ext_signed_asset_tx failed: ");
found_asset = false;
for (auto& bal : balance_resp.balances)
{
if (bal.asset_info.asset_id == resp.new_asset_id)
{
found_asset = true;
CHECK_AND_ASSERT_MES(bal.total == COINS_TO_TRANSFER, false, "Amount is unexpected");
}
}
CHECK_AND_ASSERT_MES(found_asset, false, "Asset not found ");
return true;
}