forked from lthn/blockchain
Merge branch 'rpc_extension' into develop
This commit is contained in:
commit
490198feee
11 changed files with 550 additions and 38 deletions
|
|
@ -56,6 +56,9 @@ namespace currency
|
|||
const static crypto::secret_key null_skey = AUTO_VAL_INIT(null_skey);
|
||||
const static crypto::signature null_sig = AUTO_VAL_INIT(null_sig);
|
||||
const static crypto::key_derivation null_derivation = AUTO_VAL_INIT(null_derivation);
|
||||
const static crypto::eth_public_key null_eth_public_key = AUTO_VAL_INIT(null_eth_public_key);
|
||||
const static crypto::eth_signature null_eth_signature = AUTO_VAL_INIT(null_eth_signature);
|
||||
|
||||
|
||||
const static crypto::hash gdefault_genesis = epee::string_tools::hex_to_pod<crypto::hash>("CC608F59F8080E2FBFE3C8C80EB6E6A953D47CF2D6AEBD345BADA3A1CAB99852");
|
||||
|
||||
|
|
|
|||
|
|
@ -1262,4 +1262,28 @@ namespace currency
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//@#@
|
||||
//TEMPORARY CODE, TODO: talk to @val and re-do it
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
inline void schnor_old_to_schnor_new(const crypto::signature& sig, crypto::generic_schnorr_sig& sig_new)
|
||||
{
|
||||
static_assert(sizeof(sig.c) == sizeof(sig_new.c));
|
||||
static_assert(sizeof(sig.r) == sizeof(sig_new.y));
|
||||
std::memcpy(&sig_new.c, &sig.c, sizeof(sig_new.c));
|
||||
std::memcpy(&sig_new.y, &sig.r, sizeof(sig_new.y));
|
||||
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
inline void schnor_new_to_schnor_old(const crypto::generic_schnorr_sig& sig_new, crypto::signature& sig)
|
||||
{
|
||||
static_assert(sizeof(sig.c) == sizeof(sig_new.c));
|
||||
static_assert(sizeof(sig.r) == sizeof(sig_new.y));
|
||||
std::memcpy(&sig.c, &sig_new.c, sizeof(sig_new.c));
|
||||
std::memcpy(&sig.r, &sig_new.y, sizeof(sig_new.y));
|
||||
|
||||
}
|
||||
|
||||
|
||||
} // namespace currency
|
||||
|
|
|
|||
|
|
@ -559,7 +559,7 @@ namespace currency
|
|||
if(req_it == context.m_priv.m_requested_objects.end())
|
||||
{
|
||||
LOG_ERROR_CCONTEXT("sent wrong NOTIFY_RESPONSE_GET_OBJECTS: block with id=" << epst::pod_to_hex(get_blob_hash(block_entry.block))
|
||||
<< " wasn't requested, dropping connection");
|
||||
<< " wasn't requested, block_blob: " << epst::buff_to_hex_nodelimer(block_entry.block) << " dropping connection");
|
||||
m_p2p->drop_connection(context);
|
||||
m_p2p->add_ip_fail(context.m_remote_ip);
|
||||
return 1;
|
||||
|
|
|
|||
|
|
@ -4402,14 +4402,8 @@ bool wallet2::get_utxo_distribution(std::map<uint64_t, uint64_t>& distribution)
|
|||
return false;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::submit_externally_signed_asset_tx(const finalized_tx& ft, const crypto::eth_signature& eth_sig, bool unlock_transfers_on_fail, currency::transaction& result_tx, bool& transfers_unlocked)
|
||||
void wallet2::submit_externally_signed_asset_tx(const currency::finalized_tx& ft, const currency::transaction& tx, bool unlock_transfers_on_fail, currency::transaction& result_tx, bool& transfers_unlocked)
|
||||
{
|
||||
transaction tx = ft.tx;
|
||||
|
||||
currency::asset_operation_ownership_proof_eth aoop_eth{};
|
||||
aoop_eth.eth_sig = eth_sig;
|
||||
tx.proofs.push_back(std::move(aoop_eth));
|
||||
|
||||
// foolproof
|
||||
WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(ft.ftp.spend_pub_key == m_account.get_keys().account_address.spend_public_key, "The given tx was created in a different wallet, keys missmatch, tx hash: " << ft.tx_id);
|
||||
|
||||
|
|
@ -4433,8 +4427,70 @@ void wallet2::submit_externally_signed_asset_tx(const finalized_tx& ft, const cr
|
|||
add_sent_tx_detailed_info(tx, ft.ftp.attachments, ft.ftp.prepared_destinations, ft.ftp.selected_transfers);
|
||||
|
||||
print_tx_sent_message(tx, "from submit_externally_signed_asset_tx", true, get_tx_fee(tx));
|
||||
result_tx = tx;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::submit_externally_signed_asset_tx(const currency::finalized_tx& ft, const crypto::signature& sig, bool unlock_transfers_on_fail, currency::transaction& result_tx, bool& transfers_unlocked)
|
||||
{
|
||||
currency::transaction tx = ft.tx;
|
||||
|
||||
currency::asset_operation_ownership_proof aoop_eth{};
|
||||
currency::schnor_old_to_schnor_new(sig, aoop_eth.gss);
|
||||
//aoop_eth.gss = sig;
|
||||
tx.proofs.push_back(std::move(aoop_eth));
|
||||
submit_externally_signed_asset_tx(ft, tx, unlock_transfers_on_fail, result_tx, transfers_unlocked);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::submit_externally_signed_asset_tx(const currency::finalized_tx& ft, const crypto::eth_signature& eth_sig, bool unlock_transfers_on_fail, currency::transaction& result_tx, bool& transfers_unlocked)
|
||||
{
|
||||
transaction tx = ft.tx;
|
||||
|
||||
currency::asset_operation_ownership_proof_eth aoop_eth{};
|
||||
aoop_eth.eth_sig = eth_sig;
|
||||
tx.proofs.push_back(std::move(aoop_eth));
|
||||
submit_externally_signed_asset_tx(ft, tx, unlock_transfers_on_fail, result_tx, transfers_unlocked);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::attach_asset_descriptor(const wallet_public::COMMAND_ATTACH_ASSET_DESCRIPTOR::request& req, wallet_public::COMMAND_ATTACH_ASSET_DESCRIPTOR::response& resp)
|
||||
{
|
||||
if (!req.do_attach)
|
||||
{
|
||||
//detaching
|
||||
auto it = m_own_asset_descriptors.find(req.asset_id);
|
||||
if (it == m_own_asset_descriptors.end())
|
||||
{
|
||||
resp.status = API_RETURN_CODE_NOT_FOUND;
|
||||
return false;
|
||||
}
|
||||
if (!it->second.thirdparty_custody)
|
||||
{
|
||||
LOG_ERROR("Detachig assets that are not 'thirdparty_custody' are not allowed");
|
||||
resp.status = API_RETURN_CODE_ACCESS_DENIED;
|
||||
return false;
|
||||
}
|
||||
m_own_asset_descriptors.erase(it);
|
||||
resp.status = API_RETURN_CODE_OK;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
currency::COMMAND_RPC_GET_ASSET_INFO::request req_asset_info = AUTO_VAL_INIT(req_asset_info);
|
||||
currency::COMMAND_RPC_GET_ASSET_INFO::response resp_asset_info = AUTO_VAL_INIT(resp_asset_info);
|
||||
req_asset_info.asset_id = req.asset_id;
|
||||
|
||||
bool r = m_core_proxy->call_COMMAND_RPC_GET_ASSET_INFO(req_asset_info, resp_asset_info);
|
||||
if (r && resp_asset_info.status == API_RETURN_CODE_OK)
|
||||
{
|
||||
static_cast<currency::asset_descriptor_base&>(m_own_asset_descriptors[req.asset_id]) = resp_asset_info.asset_descriptor;
|
||||
m_own_asset_descriptors[req.asset_id].thirdparty_custody = true;
|
||||
resp.status = API_RETURN_CODE_OK;
|
||||
return true;
|
||||
}
|
||||
resp.status = API_RETURN_CODE_NOT_FOUND;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
void wallet2::submit_transfer(const std::string& signed_tx_blob, currency::transaction& tx)
|
||||
{
|
||||
// decrypt sources
|
||||
|
|
@ -5626,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);
|
||||
|
|
@ -5646,7 +5703,7 @@ void wallet2::update_asset(const crypto::public_key& asset_id, const currency::a
|
|||
void wallet2::transfer_asset_ownership(const crypto::public_key& asset_id, const currency::asset_owner_pub_key_v& new_owner_v, currency::finalized_tx& ft)
|
||||
{
|
||||
auto own_asset_entry_it = m_own_asset_descriptors.find(asset_id);
|
||||
CHECK_AND_ASSERT_THROW_MES(own_asset_entry_it != m_own_asset_descriptors.end(), "Failed find asset_id " << asset_id << " in own assets list");
|
||||
CHECK_AND_ASSERT_THROW_MES(own_asset_entry_it != m_own_asset_descriptors.end(), "Couldn't find asset_id " << asset_id << " in own assets list");
|
||||
currency::asset_descriptor_base last_adb{};
|
||||
bool r = this->daemon_get_asset_info(asset_id, last_adb);
|
||||
CHECK_AND_ASSERT_THROW_MES(r, "Failed to get asset info from daemon");
|
||||
|
|
@ -5659,20 +5716,29 @@ void wallet2::transfer_asset_ownership(const crypto::public_key& asset_id, const
|
|||
asset_update_info.opt_asset_id = asset_id;
|
||||
|
||||
if (new_owner_v.type() == typeid(crypto::public_key))
|
||||
asset_update_info.opt_descriptor->owner = boost::get<crypto::public_key>(new_owner_v);
|
||||
{
|
||||
const crypto::public_key new_owner_pk = boost::get<crypto::public_key>(new_owner_v);
|
||||
asset_update_info.opt_descriptor->owner = new_owner_pk;
|
||||
asset_update_info.opt_descriptor->owner_eth_pub_key = boost::none;
|
||||
}
|
||||
else
|
||||
asset_update_info.opt_descriptor->owner_eth_pub_key = boost::get<crypto::eth_public_key>(new_owner_v);
|
||||
{
|
||||
const crypto::eth_public_key new_owner_eth_pk = boost::get<crypto::eth_public_key>(new_owner_v);
|
||||
asset_update_info.opt_descriptor->owner = currency::null_pkey;
|
||||
asset_update_info.opt_descriptor->owner_eth_pub_key = new_owner_eth_pk;
|
||||
}
|
||||
|
||||
construct_tx_param ctp = get_default_construct_tx_param();
|
||||
ctp.extra.push_back(asset_update_info);
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -616,6 +616,8 @@ namespace tools
|
|||
void submit_transfer(const std::string& signed_tx_blob, currency::transaction& tx);
|
||||
void submit_transfer_files(const std::string& signed_tx_file, currency::transaction& tx);
|
||||
void submit_externally_signed_asset_tx(const currency::finalized_tx& ft, const crypto::eth_signature& eth_sig, bool unlock_transfers_on_fail, currency::transaction& result_tx, bool& transfers_unlocked);
|
||||
void submit_externally_signed_asset_tx(const currency::finalized_tx& ft, const crypto::signature& sig, bool unlock_transfers_on_fail, currency::transaction& result_tx, bool& transfers_unlocked);
|
||||
void submit_externally_signed_asset_tx(const currency::finalized_tx& ft, const currency::transaction& tx, bool unlock_transfers_on_fail, currency::transaction& result_tx, bool& transfers_unlocked);
|
||||
|
||||
void sweep_below(size_t fake_outs_count, const currency::account_public_address& destination_addr, uint64_t threshold_amount, const currency::payment_id_t& payment_id,
|
||||
uint64_t fee, size_t& outs_total, uint64_t& amount_total, size_t& outs_swept, uint64_t& amount_swept, currency::transaction* p_result_tx = nullptr, std::string* p_filename_or_unsigned_tx_blob_str = nullptr);
|
||||
|
|
@ -694,6 +696,7 @@ namespace tools
|
|||
size_t scan_for_collisions(std::unordered_map<crypto::key_image, std::list<size_t> >& key_images);
|
||||
size_t fix_collisions();
|
||||
size_t scan_for_transaction_entries(const crypto::hash& tx_id, const crypto::key_image& ki, std::list<transfer_details>& details);
|
||||
bool attach_asset_descriptor(const wallet_public::COMMAND_ATTACH_ASSET_DESCRIPTOR::request& req, wallet_public::COMMAND_ATTACH_ASSET_DESCRIPTOR::response& resp);
|
||||
|
||||
bool get_contracts(escrow_contracts_container& contracts);
|
||||
const std::list<expiration_entry_info>& get_expiration_entries() const { return m_money_expirations; };
|
||||
|
|
@ -768,6 +771,7 @@ namespace tools
|
|||
void set_concise_mode_reorg_max_reorg_blocks(uint64_t max_blocks) { m_wallet_concise_mode_max_reorg_blocks = max_blocks; }
|
||||
void set_concise_mode_truncate_history(uint64_t max_entries) { m_truncate_history_max_entries = max_entries; }
|
||||
|
||||
|
||||
construct_tx_param get_default_construct_tx_param();
|
||||
|
||||
//---------- m_rollback_events visitor ------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -2053,14 +2053,16 @@ namespace wallet_public
|
|||
{
|
||||
currency::blobdata finalized_tx;
|
||||
currency::blobdata unsigned_tx;
|
||||
crypto::eth_signature eth_sig; //TODO: add value initialization here
|
||||
crypto::eth_signature eth_sig = currency::null_eth_signature;
|
||||
crypto::signature regular_sig = currency::null_sig;
|
||||
crypto::hash expected_tx_id = currency::null_hash;
|
||||
bool unlock_transfers_on_fail = false;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE_BLOB_AS_BASE64_STRING(finalized_tx)DOC_DSCR("Base64-encoded finalized_tx data structure, which was received from emit_asset call.") DOC_EXMP("ewogICJ2ZXJzaW9uIjogMSwgC....iAgInZpbiI6IFsgewogICAgIC") DOC_END
|
||||
KV_SERIALIZE_BLOB_AS_BASE64_STRING(unsigned_tx) DOC_DSCR("Base64-encoded unsigned transaction blob, which was received from emit_asset call.") DOC_EXMP("083737bcfd826a973f74bb56a52b4fa562e6579ccaadd2697463498a66de4f1760b2cd40f11c3a00a7a80000") DOC_END
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(eth_sig) DOC_DSCR("HEX-encoded ETH signature (64 bytes)") DOC_EXMP("674bb56a5b4fa562e679ccacc4e69455e63f4a581257382191de6856c2156630b3fba0db4bdd73ffcfb36b6add697463498a66de4f1760b2cd40f11c3a00a7a8") DOC_END
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(eth_sig) DOC_DSCR("HEX-encoded ETH signature (64 bytes), used only if regular_sig is empty") DOC_EXMP("674bb56a5b4fa562e679ccacc4e69455e63f4a581257382191de6856c2156630b3fba0db4bdd73ffcfb36b6add697463498a66de4f1760b2cd40f11c3a00a7a8") DOC_END
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(regular_sig) DOC_DSCR("HEX-encoded regular signature (64 bytes)") DOC_EXMP("674bb56a5b4fa562e679ccacc4e69455e63f4a581257382191de6856c2156630b3fba0db4bdd73ffcfb36b6add697463498a66de4f1760b2cd40f11c3a00a7a8") DOC_END
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(expected_tx_id) DOC_DSCR("The expected transaction id. Tx won't be sent if the calculated one doesn't match this one. Consider using 'verified_tx_id' returned by 'decrypt_tx_details' call.") DOC_EXMP("40fa6db923728b38962718c61b4dc3af1acaa1967479c73703e260dc3609c58d") DOC_END
|
||||
KV_SERIALIZE(unlock_transfers_on_fail) DOC_DSCR("If true, all locked wallet transfers, corresponding to the transaction, will be unlocked on sending failure. False by default.") DOC_EXMP(false) DOC_END
|
||||
END_KV_SERIALIZE_MAP()
|
||||
|
|
@ -2079,5 +2081,61 @@ namespace wallet_public
|
|||
};
|
||||
|
||||
|
||||
struct COMMAND_ATTACH_ASSET_DESCRIPTOR
|
||||
{
|
||||
DOC_COMMAND("Attach asset descripto to this wallet instance, if asset descripto attached then ADO operations to this asset can be performed using API of this wallet.");
|
||||
|
||||
struct request
|
||||
{
|
||||
crypto::public_key asset_id;
|
||||
bool do_attach = true;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(asset_id) DOC_DSCR("Asset id of the ADO that need to be attached to this wallet") DOC_EXMP("40fa6db923728b38962718c61b4dc3af1acaa1967479c73703e260dc3609c58d") DOC_END
|
||||
KV_SERIALIZE(do_attach) DOC_DSCR("If true - asset descriptor attached to wallet, if false - asset detached") DOC_EXMP(true) DOC_END
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct response
|
||||
{
|
||||
std::string status;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(status) DOC_DSCR("Status of the call") DOC_EXMP("OK") DOC_END
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
||||
struct COMMAND_TRANSFER_ASSET_OWNERSHIP
|
||||
{
|
||||
DOC_COMMAND("Transfer asset ownership to new public key.");
|
||||
|
||||
struct request
|
||||
{
|
||||
crypto::public_key asset_id;
|
||||
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(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()
|
||||
};
|
||||
|
||||
struct response
|
||||
{
|
||||
std::string status;
|
||||
crypto::hash tx_id = currency::null_hash;
|
||||
std::optional<data_for_external_asset_signing_tx> data_for_external_signing;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(status) DOC_DSCR("Status of the call") DOC_EXMP("OK") DOC_END
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(tx_id) DOC_DSCR("Id of transaction that carries asset transfer ownership operation") DOC_EXMP("f74bb56a5b4fa562e679ccaadd697463498a66de4f1760b2cd40f11c3a00a7a8") DOC_END
|
||||
KV_SERIALIZE(data_for_external_signing) DOC_DSCR("[optional] Additional data for external ownership transfer tx signing(if asset is ownership is belong to third party).") DOC_EXMP_AGGR() DOC_END
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace wallet_rpc
|
||||
} // namespace tools
|
||||
|
|
|
|||
|
|
@ -1334,9 +1334,11 @@ namespace tools
|
|||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_asset_deploy(const wallet_public::COMMAND_ASSETS_DEPLOY::request& req, wallet_public::COMMAND_ASSETS_DEPLOY::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
bool wallet_rpc_server::on_asset_deploy(const wallet_public::COMMAND_ASSETS_DEPLOY::request& req_, wallet_public::COMMAND_ASSETS_DEPLOY::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
//make local req so we can modify it (if needed)
|
||||
wallet_public::COMMAND_ASSETS_DEPLOY::request req = req_;
|
||||
|
||||
if (!currency::validate_asset_ticker_and_full_name(req.asset_descriptor))
|
||||
{
|
||||
|
|
@ -1345,6 +1347,11 @@ namespace tools
|
|||
return false;
|
||||
}
|
||||
|
||||
if (req.destinations.empty() && req.asset_descriptor.current_supply != 0)
|
||||
{
|
||||
req.destinations.push_back(tools::wallet_public::transfer_destination{ req.asset_descriptor.current_supply , w.get_wallet()->get_account().get_public_address_str(), currency::null_pkey });
|
||||
}
|
||||
|
||||
std::vector<currency::tx_destination_entry> currency_destinations;
|
||||
rpc_destinations_to_currency_destinations(req.destinations, true, !req.do_not_split_destinations, currency_destinations);
|
||||
|
||||
|
|
@ -1356,6 +1363,17 @@ namespace tools
|
|||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
void finalized_tx_to_external_signing_data(const currency::finalized_tx& ft, wallet_public::data_for_external_asset_signing_tx& data)
|
||||
{
|
||||
// include additonal info into response, if it's an external signing asset operation
|
||||
data.unsigned_tx = t_serializable_object_to_blob(ft.tx);
|
||||
data.tx_secret_key = ft.one_time_key;
|
||||
std::vector<std::string>& outs_addr = data.outputs_addresses;
|
||||
for (auto d : ft.ftp.prepared_destinations)
|
||||
outs_addr.push_back(currency::get_account_address_as_str(d.addr.back()));
|
||||
data.finalized_tx = t_serializable_object_to_blob(ft);
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_asset_emit(const wallet_public::COMMAND_ASSETS_EMIT::request& req, wallet_public::COMMAND_ASSETS_EMIT::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
|
|
@ -1369,17 +1387,11 @@ namespace tools
|
|||
w.get_wallet()->emit_asset(req.asset_id, currency_destinations, ft);
|
||||
res.tx_id = ft.tx_id;
|
||||
|
||||
if (last_adb.owner_eth_pub_key.has_value())
|
||||
if (ft.ftp.ado_sign_thirdparty)
|
||||
{
|
||||
// include additonal info into response, if it's an external signing asset operation
|
||||
// include additional info into response, if it's an external signing asset operation
|
||||
wallet_public::data_for_external_asset_signing_tx data{};
|
||||
data.unsigned_tx = t_serializable_object_to_blob(ft.tx);
|
||||
data.tx_secret_key = ft.one_time_key;
|
||||
std::vector<std::string>& outs_addr = data.outputs_addresses;
|
||||
for(auto d : ft.ftp.prepared_destinations)
|
||||
outs_addr.push_back(currency::get_account_address_as_str(d.addr.back()));
|
||||
data.finalized_tx = t_serializable_object_to_blob(ft);
|
||||
|
||||
finalized_tx_to_external_signing_data(ft, data);
|
||||
res.data_for_external_signing = data;
|
||||
}
|
||||
|
||||
|
|
@ -1394,17 +1406,11 @@ namespace tools
|
|||
w.get_wallet()->update_asset(req.asset_id, req.asset_descriptor, ft);
|
||||
res.tx_id = ft.tx_id;
|
||||
|
||||
if (req.asset_descriptor.owner_eth_pub_key.has_value())
|
||||
if (ft.ftp.ado_sign_thirdparty)
|
||||
{
|
||||
// include additonal info into response, if it's an external signing asset operation
|
||||
// include additional info into response, if it's an external signing asset operation
|
||||
wallet_public::data_for_external_asset_signing_tx data{};
|
||||
data.unsigned_tx = t_serializable_object_to_blob(ft.tx);
|
||||
data.tx_secret_key = ft.one_time_key;
|
||||
std::vector<std::string>& outs_addr = data.outputs_addresses;
|
||||
for(auto d : ft.ftp.prepared_destinations)
|
||||
outs_addr.push_back(currency::get_account_address_as_str(d.addr.back()));
|
||||
data.finalized_tx = t_serializable_object_to_blob(ft);
|
||||
|
||||
finalized_tx_to_external_signing_data(ft, data);
|
||||
res.data_for_external_signing = data;
|
||||
}
|
||||
|
||||
|
|
@ -1454,7 +1460,14 @@ namespace tools
|
|||
try
|
||||
{
|
||||
currency::transaction result_tx{};
|
||||
w.get_wallet()->submit_externally_signed_asset_tx(ft, req.eth_sig, req.unlock_transfers_on_fail, result_tx, res.transfers_were_unlocked);
|
||||
if (req.regular_sig != currency::null_sig)
|
||||
{
|
||||
w.get_wallet()->submit_externally_signed_asset_tx(ft, req.regular_sig, req.unlock_transfers_on_fail, result_tx, res.transfers_were_unlocked);
|
||||
}
|
||||
else
|
||||
{
|
||||
w.get_wallet()->submit_externally_signed_asset_tx(ft, req.eth_sig, req.unlock_transfers_on_fail, result_tx, res.transfers_were_unlocked);
|
||||
}
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
|
|
@ -1467,6 +1480,57 @@ namespace tools
|
|||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_attach_asset_descriptor(const wallet_public::COMMAND_ATTACH_ASSET_DESCRIPTOR::request& req, wallet_public::COMMAND_ATTACH_ASSET_DESCRIPTOR::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
w.get_wallet()->attach_asset_descriptor(req, res);
|
||||
return true;
|
||||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_transfer_asset_ownership(const wallet_public::COMMAND_TRANSFER_ASSET_OWNERSHIP::request& req, wallet_public::COMMAND_TRANSFER_ASSET_OWNERSHIP::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
currency::asset_owner_pub_key_v new_owner_v;
|
||||
if (req.new_owner!= currency::null_pkey)
|
||||
{
|
||||
new_owner_v = req.new_owner;
|
||||
}
|
||||
else if(req.new_owner_eth_pub_key != currency::null_eth_public_key)
|
||||
{
|
||||
new_owner_v = req.new_owner_eth_pub_key;
|
||||
}else
|
||||
{
|
||||
res.status = API_RETURN_CODE_BAD_ARG_INVALID_ADDRESS;
|
||||
return true;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
currency::finalized_tx ft;
|
||||
w.get_wallet()->transfer_asset_ownership(req.asset_id, new_owner_v, ft);
|
||||
if (ft.ftp.ado_sign_thirdparty)
|
||||
{
|
||||
// include additional info into response, if it's an external signing asset operation
|
||||
wallet_public::data_for_external_asset_signing_tx data{};
|
||||
finalized_tx_to_external_signing_data(ft, data);
|
||||
res.data_for_external_signing = data;
|
||||
}
|
||||
res.tx_id = ft.tx_id;
|
||||
res.status = API_RETURN_CODE_OK;
|
||||
return true;
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
// doing this to be able to return 'transfers_were_unlocked' to the caller even in the case of exception
|
||||
res.status = e.what();
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_mw_get_wallets(const wallet_public::COMMAND_MW_GET_WALLETS::request& req, wallet_public::COMMAND_MW_GET_WALLETS::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
|
|
|
|||
|
|
@ -164,6 +164,8 @@ namespace tools
|
|||
MAP_JON_RPC_WE("update_asset", on_asset_update, wallet_public::COMMAND_ASSETS_UPDATE)
|
||||
MAP_JON_RPC_WE("burn_asset", on_asset_burn, wallet_public::COMMAND_ASSETS_BURN)
|
||||
MAP_JON_RPC_WE("send_ext_signed_asset_tx", on_asset_send_ext_signed_tx, wallet_public::COMMAND_ASSET_SEND_EXT_SIGNED_TX)
|
||||
MAP_JON_RPC_WE("attach_asset_descriptor", on_attach_asset_descriptor, wallet_public::COMMAND_ATTACH_ASSET_DESCRIPTOR)
|
||||
MAP_JON_RPC_WE("transfer_asset_ownership", on_transfer_asset_ownership, wallet_public::COMMAND_TRANSFER_ASSET_OWNERSHIP)
|
||||
|
||||
//MULTIWALLET APIs
|
||||
MAP_JON_RPC_WE("mw_get_wallets", on_mw_get_wallets, wallet_public::COMMAND_MW_GET_WALLETS)
|
||||
|
|
@ -236,6 +238,9 @@ namespace tools
|
|||
bool on_asset_update(const wallet_public::COMMAND_ASSETS_UPDATE::request& req, wallet_public::COMMAND_ASSETS_UPDATE::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
bool on_asset_burn(const wallet_public::COMMAND_ASSETS_BURN::request& req, wallet_public::COMMAND_ASSETS_BURN::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
bool on_asset_send_ext_signed_tx(const wallet_public::COMMAND_ASSET_SEND_EXT_SIGNED_TX::request& req, wallet_public::COMMAND_ASSET_SEND_EXT_SIGNED_TX::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
bool on_attach_asset_descriptor(const wallet_public::COMMAND_ATTACH_ASSET_DESCRIPTOR::request& req, wallet_public::COMMAND_ATTACH_ASSET_DESCRIPTOR::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
bool on_transfer_asset_ownership(const wallet_public::COMMAND_TRANSFER_ASSET_OWNERSHIP::request& req, wallet_public::COMMAND_TRANSFER_ASSET_OWNERSHIP::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
|
||||
|
||||
bool on_mw_get_wallets(const wallet_public::COMMAND_MW_GET_WALLETS::request& req, wallet_public::COMMAND_MW_GET_WALLETS::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
bool on_mw_select_wallet(const wallet_public::COMMAND_MW_SELECT_WALLET::request& req, wallet_public::COMMAND_MW_SELECT_WALLET::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
|
|
|
|||
|
|
@ -1314,8 +1314,7 @@ int main(int argc, char* argv[])
|
|||
|
||||
GENERATE_AND_PLAY_HF(pos_fuse_test, "4-*");
|
||||
GENERATE_AND_PLAY_HF(wallet_reorganize_and_trim_test, "4-*");
|
||||
|
||||
|
||||
GENERATE_AND_PLAY_HF(wallet_rpc_thirdparty_custody, "5-*");
|
||||
|
||||
GENERATE_AND_PLAY_HF(attachment_isolation_test, "4-*");
|
||||
|
||||
|
|
|
|||
|
|
@ -808,7 +808,7 @@ wallet_true_rpc_pos_mining::wallet_true_rpc_pos_mining()
|
|||
{
|
||||
REGISTER_CALLBACK_METHOD(wallet_true_rpc_pos_mining, c1);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool wallet_true_rpc_pos_mining::generate(std::vector<test_event_entry>& events) const
|
||||
{
|
||||
uint64_t ts = test_core_time::get_time();
|
||||
|
|
@ -924,3 +924,284 @@ bool wallet_true_rpc_pos_mining::c1(currency::core& c, size_t ev_index, const st
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
wallet_rpc_thirdparty_custody::wallet_rpc_thirdparty_custody()
|
||||
{
|
||||
REGISTER_CALLBACK_METHOD(wallet_rpc_thirdparty_custody, c1);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool wallet_rpc_thirdparty_custody::generate(std::vector<test_event_entry>& events) const
|
||||
{
|
||||
uint64_t ts = test_core_time::get_time();
|
||||
m_accounts.resize(TOTAL_ACCS_COUNT);
|
||||
account_base& miner_acc = m_accounts[MINER_ACC_IDX]; miner_acc.generate(); miner_acc.set_createtime(ts);
|
||||
account_base& alice_acc = m_accounts[ALICE_ACC_IDX]; alice_acc.generate(); alice_acc.set_createtime(ts);
|
||||
|
||||
MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, ts);
|
||||
DO_CALLBACK(events, "configure_core"); // default configure_core callback will initialize core runtime config with m_hardforks
|
||||
REWIND_BLOCKS_N_WITH_TIME(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 3);
|
||||
|
||||
DO_CALLBACK(events, "c1");
|
||||
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#define TEST_TOKEN_NAME "TEST TOKEN"
|
||||
#define TEST_TOKEN_METAINFO "Metainfo"
|
||||
#define TEST_TOKEN_TICKER "TT"
|
||||
#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)
|
||||
{
|
||||
|
||||
bool r = false;
|
||||
account_base alice_acc, bob_acc, carol_acc, custody_acc;
|
||||
alice_acc.generate();
|
||||
bob_acc.generate();
|
||||
carol_acc.generate();
|
||||
custody_acc.generate();
|
||||
|
||||
std::shared_ptr<tools::wallet2> miner_wlt = init_playtime_test_wallet(events, c, MINER_ACC_IDX);
|
||||
std::shared_ptr<tools::wallet2> alice_wlt = init_playtime_test_wallet(events, c, alice_acc);
|
||||
std::shared_ptr<tools::wallet2> bob_wlt = init_playtime_test_wallet(events, c, bob_acc);
|
||||
std::shared_ptr<tools::wallet2> carol_wlt = init_playtime_test_wallet(events, c, carol_acc);
|
||||
std::shared_ptr<tools::wallet2> custody_wlt = init_playtime_test_wallet(events, c, custody_acc);
|
||||
|
||||
r = mine_next_pow_blocks_in_playtime(alice_wlt->get_account().get_public_address(), c, 3);
|
||||
r = mine_next_pow_blocks_in_playtime(bob_wlt->get_account().get_public_address(), c, 3);
|
||||
r = mine_next_pow_blocks_in_playtime(carol_wlt->get_account().get_public_address(), c, 3);
|
||||
//r = mine_next_pow_blocks_in_playtime(custody_wlt->get_account().get_public_address(), c, 3);
|
||||
r = mine_next_pow_blocks_in_playtime(miner_wlt->get_account().get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
|
||||
|
||||
// wallet RPC server
|
||||
tools::wallet_rpc_server miner_wlt_rpc(miner_wlt);
|
||||
|
||||
miner_wlt->refresh();
|
||||
struct tools::wallet_public::COMMAND_ASSETS_DEPLOY::request req = AUTO_VAL_INIT(req);
|
||||
struct tools::wallet_public::COMMAND_ASSETS_DEPLOY::response resp = AUTO_VAL_INIT(resp);
|
||||
|
||||
req.asset_descriptor.decimal_point = 1;
|
||||
req.asset_descriptor.full_name = TEST_TOKEN_NAME;
|
||||
req.asset_descriptor.hidden_supply = false;
|
||||
req.asset_descriptor.meta_info = TEST_TOKEN_METAINFO;
|
||||
req.asset_descriptor.ticker = TEST_TOKEN_TICKER;
|
||||
req.asset_descriptor.total_max_supply = TEST_TOKEN_MAX_SUPPLY;
|
||||
req.asset_descriptor.current_supply = TEST_TOKEN_CURRENT_SUPPLY;
|
||||
|
||||
r = invoke_text_json_for_rpc(miner_wlt_rpc, "deploy_asset", req, resp);
|
||||
CHECK_AND_ASSERT_MES(r, false, "failed to call");
|
||||
|
||||
if (resp.new_asset_id == currency::null_pkey)
|
||||
{
|
||||
LOG_ERROR("Failed to deploy asset");
|
||||
return false;
|
||||
}
|
||||
|
||||
r = mine_next_pow_blocks_in_playtime(miner_wlt->get_account().get_public_address(), c, 3);
|
||||
|
||||
// core RPC server
|
||||
currency::t_currency_protocol_handler<currency::core> cprotocol(c, NULL);
|
||||
nodetool::node_server<currency::t_currency_protocol_handler<currency::core> > dummy_p2p(cprotocol);
|
||||
bc_services::bc_offers_service dummy_bc(nullptr);
|
||||
currency::core_rpc_server core_rpc(c, dummy_p2p, dummy_bc);
|
||||
currency::COMMAND_RPC_GET_ASSET_INFO::request gai_req = AUTO_VAL_INIT(gai_req);
|
||||
currency::COMMAND_RPC_GET_ASSET_INFO::response gai_resp = AUTO_VAL_INIT(gai_resp);
|
||||
gai_req.asset_id = resp.new_asset_id;
|
||||
r = invoke_text_json_for_rpc(core_rpc, "get_asset_info", gai_req, gai_resp);
|
||||
CHECK_AND_ASSERT_MES(r, false, "failed to call");
|
||||
CHECK_AND_ASSERT_MES(gai_resp.status == API_RETURN_CODE_OK, false, "failed to call");
|
||||
|
||||
CHECK_AND_ASSERT_MES(gai_resp.asset_descriptor.decimal_point == 1, false, "Wrong asset descriptor");
|
||||
CHECK_AND_ASSERT_MES(gai_resp.asset_descriptor.full_name == TEST_TOKEN_NAME, false, "Wrong asset descriptor");
|
||||
CHECK_AND_ASSERT_MES(gai_resp.asset_descriptor.hidden_supply == false, false, "Wrong asset descriptor");
|
||||
CHECK_AND_ASSERT_MES(gai_resp.asset_descriptor.meta_info == TEST_TOKEN_METAINFO, false, "Wrong asset descriptor");
|
||||
CHECK_AND_ASSERT_MES(gai_resp.asset_descriptor.ticker == TEST_TOKEN_TICKER, false, "Wrong asset descriptor");
|
||||
CHECK_AND_ASSERT_MES(gai_resp.asset_descriptor.total_max_supply == TEST_TOKEN_MAX_SUPPLY, false, "Wrong asset descriptor");
|
||||
CHECK_AND_ASSERT_MES(gai_resp.asset_descriptor.current_supply == TEST_TOKEN_CURRENT_SUPPLY, false, "Wrong asset descriptor");
|
||||
|
||||
alice_wlt->refresh();
|
||||
// wallet RPC server
|
||||
tools::wallet_rpc_server alice_wlt_rpc(alice_wlt);
|
||||
|
||||
tools::wallet_public::COMMAND_ATTACH_ASSET_DESCRIPTOR::request att_req = AUTO_VAL_INIT(att_req);
|
||||
tools::wallet_public::COMMAND_ATTACH_ASSET_DESCRIPTOR::response att_resp = AUTO_VAL_INIT(att_resp);
|
||||
att_req.asset_id = resp.new_asset_id;
|
||||
att_req.do_attach = true;
|
||||
r = invoke_text_json_for_rpc(alice_wlt_rpc, "attach_asset_descriptor", att_req, att_resp);
|
||||
CHECK_AND_ASSERT_MES(r, false, "failed to call");
|
||||
CHECK_AND_ASSERT_MES(att_resp.status == API_RETURN_CODE_OK, false, "failed to call");
|
||||
|
||||
|
||||
//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{ 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)
|
||||
{
|
||||
LOG_ERROR("Missing data_for_external_signing");
|
||||
return false;
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
r = mine_next_pow_blocks_in_playtime(miner_wlt->get_account().get_public_address(), c, 3);
|
||||
|
||||
|
||||
//check bob wallet
|
||||
tools::wallet_public::COMMAND_ASSETS_WHITELIST_ADD::request wtl_req = AUTO_VAL_INIT(wtl_req);
|
||||
tools::wallet_public::COMMAND_ASSETS_WHITELIST_ADD::response wtl_resp = AUTO_VAL_INIT(wtl_resp);
|
||||
wtl_req.asset_id = resp.new_asset_id;
|
||||
tools::wallet_rpc_server bob_wlt_rpc(bob_wlt);
|
||||
r = invoke_text_json_for_rpc(bob_wlt_rpc, "assets_whitelist_add", wtl_req, wtl_resp);
|
||||
CHECK_AND_ASSERT_MES(r, false, "RPC send_ext_signed_asset_tx failed: ");
|
||||
CHECK_AND_ASSERT_MES(wtl_resp.status == API_RETURN_CODE_OK, false, "RPC status failed");
|
||||
bob_wlt->refresh();
|
||||
|
||||
tools::wallet_public::COMMAND_RPC_GET_BALANCE::request balance_req = AUTO_VAL_INIT(balance_req);
|
||||
tools::wallet_public::COMMAND_RPC_GET_BALANCE::response balance_resp = AUTO_VAL_INIT(balance_resp);
|
||||
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: ");
|
||||
|
||||
|
||||
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);
|
||||
|
||||
bob_wlt->refresh();
|
||||
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 == 2 * COINS_TO_TRANSFER, false, "Amount is unexpected");
|
||||
}
|
||||
}
|
||||
CHECK_AND_ASSERT_MES(found_asset, false, "Asset not found ");
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -55,3 +55,11 @@ struct wallet_true_rpc_pos_mining : public wallet_test
|
|||
bool generate(std::vector<test_event_entry>& events) const;
|
||||
bool c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
|
||||
};
|
||||
|
||||
|
||||
struct wallet_rpc_thirdparty_custody : public wallet_test
|
||||
{
|
||||
wallet_rpc_thirdparty_custody();
|
||||
bool generate(std::vector<test_event_entry>& events) const;
|
||||
bool c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
|
||||
};
|
||||
Loading…
Add table
Reference in a new issue