Merge pull request #5203
8b514645
add multisig tx sets to describe_transfer rpc endpoint (spoke0)
This commit is contained in:
commit
695d51a481
|
@ -6349,17 +6349,17 @@ bool wallet2::save_multisig_tx(const std::vector<pending_tx>& ptx_vector, const
|
||||||
return epee::file_io_utils::save_string_to_file(filename, ciphertext);
|
return epee::file_io_utils::save_string_to_file(filename, ciphertext);
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
bool wallet2::load_multisig_tx(cryptonote::blobdata s, multisig_tx_set &exported_txs, std::function<bool(const multisig_tx_set&)> accept_func)
|
bool wallet2::parse_multisig_tx_from_str(std::string multisig_tx_st, multisig_tx_set &exported_txs) const
|
||||||
{
|
{
|
||||||
const size_t magiclen = strlen(MULTISIG_UNSIGNED_TX_PREFIX);
|
const size_t magiclen = strlen(MULTISIG_UNSIGNED_TX_PREFIX);
|
||||||
if (strncmp(s.c_str(), MULTISIG_UNSIGNED_TX_PREFIX, magiclen))
|
if (strncmp(multisig_tx_st.c_str(), MULTISIG_UNSIGNED_TX_PREFIX, magiclen))
|
||||||
{
|
{
|
||||||
LOG_PRINT_L0("Bad magic from multisig tx data");
|
LOG_PRINT_L0("Bad magic from multisig tx data");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
s = decrypt_with_view_secret_key(std::string(s, magiclen));
|
multisig_tx_st = decrypt_with_view_secret_key(std::string(multisig_tx_st, magiclen));
|
||||||
}
|
}
|
||||||
catch (const std::exception &e)
|
catch (const std::exception &e)
|
||||||
{
|
{
|
||||||
|
@ -6368,7 +6368,7 @@ bool wallet2::load_multisig_tx(cryptonote::blobdata s, multisig_tx_set &exported
|
||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
std::istringstream iss(s);
|
std::istringstream iss(multisig_tx_st);
|
||||||
boost::archive::portable_binary_iarchive ar(iss);
|
boost::archive::portable_binary_iarchive ar(iss);
|
||||||
ar >> exported_txs;
|
ar >> exported_txs;
|
||||||
}
|
}
|
||||||
|
@ -6390,6 +6390,17 @@ bool wallet2::load_multisig_tx(cryptonote::blobdata s, multisig_tx_set &exported
|
||||||
CHECK_AND_ASSERT_MES(ptx.construction_data.sources.size() == ptx.tx.vin.size(), false, "Mismatched sources/vin sizes");
|
CHECK_AND_ASSERT_MES(ptx.construction_data.sources.size() == ptx.tx.vin.size(), false, "Mismatched sources/vin sizes");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
bool wallet2::load_multisig_tx(cryptonote::blobdata s, multisig_tx_set &exported_txs, std::function<bool(const multisig_tx_set&)> accept_func)
|
||||||
|
{
|
||||||
|
if(!parse_multisig_tx_from_str(s, exported_txs))
|
||||||
|
{
|
||||||
|
LOG_PRINT_L0("Failed to parse multisig transaction from string");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
LOG_PRINT_L1("Loaded multisig tx unsigned data from binary: " << exported_txs.m_ptx.size() << " transactions");
|
LOG_PRINT_L1("Loaded multisig tx unsigned data from binary: " << exported_txs.m_ptx.size() << " transactions");
|
||||||
for (auto &ptx: exported_txs.m_ptx) LOG_PRINT_L0(cryptonote::obj_to_json_str(ptx.tx));
|
for (auto &ptx: exported_txs.m_ptx) LOG_PRINT_L0(cryptonote::obj_to_json_str(ptx.tx));
|
||||||
|
|
||||||
|
|
|
@ -800,6 +800,7 @@ namespace tools
|
||||||
void cold_tx_aux_import(const std::vector<pending_tx>& ptx, const std::vector<std::string>& tx_device_aux);
|
void cold_tx_aux_import(const std::vector<pending_tx>& ptx, const std::vector<std::string>& tx_device_aux);
|
||||||
void cold_sign_tx(const std::vector<pending_tx>& ptx_vector, signed_tx_set &exported_txs, std::vector<cryptonote::address_parse_info> &dsts_info, std::vector<std::string> & tx_device_aux);
|
void cold_sign_tx(const std::vector<pending_tx>& ptx_vector, signed_tx_set &exported_txs, std::vector<cryptonote::address_parse_info> &dsts_info, std::vector<std::string> & tx_device_aux);
|
||||||
uint64_t cold_key_image_sync(uint64_t &spent, uint64_t &unspent);
|
uint64_t cold_key_image_sync(uint64_t &spent, uint64_t &unspent);
|
||||||
|
bool parse_multisig_tx_from_str(std::string multisig_tx_st, multisig_tx_set &exported_txs) const;
|
||||||
bool load_multisig_tx(cryptonote::blobdata blob, multisig_tx_set &exported_txs, std::function<bool(const multisig_tx_set&)> accept_func = NULL);
|
bool load_multisig_tx(cryptonote::blobdata blob, multisig_tx_set &exported_txs, std::function<bool(const multisig_tx_set&)> accept_func = NULL);
|
||||||
bool load_multisig_tx_from_file(const std::string &filename, multisig_tx_set &exported_txs, std::function<bool(const multisig_tx_set&)> accept_func = NULL);
|
bool load_multisig_tx_from_file(const std::string &filename, multisig_tx_set &exported_txs, std::function<bool(const multisig_tx_set&)> accept_func = NULL);
|
||||||
bool sign_multisig_tx_from_file(const std::string &filename, std::vector<crypto::hash> &txids, std::function<bool(const multisig_tx_set&)> accept_func);
|
bool sign_multisig_tx_from_file(const std::string &filename, std::vector<crypto::hash> &txids, std::function<bool(const multisig_tx_set&)> accept_func);
|
||||||
|
|
|
@ -1074,40 +1074,70 @@ namespace tools
|
||||||
er.message = "command not supported by watch-only wallet";
|
er.message = "command not supported by watch-only wallet";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if(req.unsigned_txset.empty() && req.multisig_txset.empty())
|
||||||
tools::wallet2::unsigned_tx_set exported_txs;
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
cryptonote::blobdata blob;
|
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
||||||
if (!epee::string_tools::parse_hexstr_to_binbuff(req.unsigned_txset, blob))
|
er.message = "no txset provided";
|
||||||
{
|
|
||||||
er.code = WALLET_RPC_ERROR_CODE_BAD_HEX;
|
|
||||||
er.message = "Failed to parse hex.";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(!m_wallet->parse_unsigned_tx_from_str(blob, exported_txs))
|
|
||||||
{
|
|
||||||
er.code = WALLET_RPC_ERROR_CODE_BAD_UNSIGNED_TX_DATA;
|
|
||||||
er.message = "cannot load unsigned_txset";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (const std::exception &e)
|
|
||||||
{
|
|
||||||
er.code = WALLET_RPC_ERROR_CODE_BAD_UNSIGNED_TX_DATA;
|
|
||||||
er.message = "failed to parse unsigned transfers: " + std::string(e.what());
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector <wallet2::tx_construction_data> tx_constructions;
|
||||||
|
if (!req.unsigned_txset.empty()) {
|
||||||
|
try {
|
||||||
|
tools::wallet2::unsigned_tx_set exported_txs;
|
||||||
|
cryptonote::blobdata blob;
|
||||||
|
if (!epee::string_tools::parse_hexstr_to_binbuff(req.unsigned_txset, blob)) {
|
||||||
|
er.code = WALLET_RPC_ERROR_CODE_BAD_HEX;
|
||||||
|
er.message = "Failed to parse hex.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!m_wallet->parse_unsigned_tx_from_str(blob, exported_txs)) {
|
||||||
|
er.code = WALLET_RPC_ERROR_CODE_BAD_UNSIGNED_TX_DATA;
|
||||||
|
er.message = "cannot load unsigned_txset";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
tx_constructions = exported_txs.txes;
|
||||||
|
}
|
||||||
|
catch (const std::exception &e) {
|
||||||
|
er.code = WALLET_RPC_ERROR_CODE_BAD_UNSIGNED_TX_DATA;
|
||||||
|
er.message = "failed to parse unsigned transfers: " + std::string(e.what());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (!req.multisig_txset.empty()) {
|
||||||
|
try {
|
||||||
|
tools::wallet2::multisig_tx_set exported_txs;
|
||||||
|
cryptonote::blobdata blob;
|
||||||
|
if (!epee::string_tools::parse_hexstr_to_binbuff(req.multisig_txset, blob)) {
|
||||||
|
er.code = WALLET_RPC_ERROR_CODE_BAD_HEX;
|
||||||
|
er.message = "Failed to parse hex.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!m_wallet->parse_multisig_tx_from_str(blob, exported_txs)) {
|
||||||
|
er.code = WALLET_RPC_ERROR_CODE_BAD_MULTISIG_TX_DATA;
|
||||||
|
er.message = "cannot load multisig_txset";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t n = 0; n < exported_txs.m_ptx.size(); ++n) {
|
||||||
|
tx_constructions.push_back(exported_txs.m_ptx[n].construction_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (const std::exception &e) {
|
||||||
|
er.code = WALLET_RPC_ERROR_CODE_BAD_MULTISIG_TX_DATA;
|
||||||
|
er.message = "failed to parse multisig transfers: " + std::string(e.what());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<tools::wallet2::pending_tx> ptx;
|
std::vector<tools::wallet2::pending_tx> ptx;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// gather info to ask the user
|
// gather info to ask the user
|
||||||
std::unordered_map<cryptonote::account_public_address, std::pair<std::string, uint64_t>> dests;
|
std::unordered_map<cryptonote::account_public_address, std::pair<std::string, uint64_t>> dests;
|
||||||
int first_known_non_zero_change_index = -1;
|
int first_known_non_zero_change_index = -1;
|
||||||
for (size_t n = 0; n < exported_txs.txes.size(); ++n)
|
for (size_t n = 0; n < tx_constructions.size(); ++n)
|
||||||
{
|
{
|
||||||
const tools::wallet2::tx_construction_data &cd = exported_txs.txes[n];
|
const tools::wallet2::tx_construction_data &cd = tx_constructions[n];
|
||||||
res.desc.push_back({0, 0, std::numeric_limits<uint32_t>::max(), 0, {}, "", 0, "", 0, 0, ""});
|
res.desc.push_back({0, 0, std::numeric_limits<uint32_t>::max(), 0, {}, "", 0, "", 0, 0, ""});
|
||||||
wallet_rpc::COMMAND_RPC_DESCRIBE_TRANSFER::transfer_description &desc = res.desc.back();
|
wallet_rpc::COMMAND_RPC_DESCRIBE_TRANSFER::transfer_description &desc = res.desc.back();
|
||||||
|
|
||||||
|
@ -1171,7 +1201,7 @@ namespace tools
|
||||||
{
|
{
|
||||||
if (first_known_non_zero_change_index == -1)
|
if (first_known_non_zero_change_index == -1)
|
||||||
first_known_non_zero_change_index = n;
|
first_known_non_zero_change_index = n;
|
||||||
const tools::wallet2::tx_construction_data &cdn = exported_txs.txes[first_known_non_zero_change_index];
|
const tools::wallet2::tx_construction_data &cdn = tx_constructions[first_known_non_zero_change_index];
|
||||||
if (memcmp(&cd.change_dts.addr, &cdn.change_dts.addr, sizeof(cd.change_dts.addr)))
|
if (memcmp(&cd.change_dts.addr, &cdn.change_dts.addr, sizeof(cd.change_dts.addr)))
|
||||||
{
|
{
|
||||||
er.code = WALLET_RPC_ERROR_CODE_BAD_UNSIGNED_TX_DATA;
|
er.code = WALLET_RPC_ERROR_CODE_BAD_UNSIGNED_TX_DATA;
|
||||||
|
@ -1199,7 +1229,7 @@ namespace tools
|
||||||
|
|
||||||
if (desc.change_amount > 0)
|
if (desc.change_amount > 0)
|
||||||
{
|
{
|
||||||
const tools::wallet2::tx_construction_data &cd0 = exported_txs.txes[0];
|
const tools::wallet2::tx_construction_data &cd0 = tx_constructions[0];
|
||||||
desc.change_address = get_account_address_as_str(m_wallet->nettype(), cd0.subaddr_account > 0, cd0.change_dts.addr);
|
desc.change_address = get_account_address_as_str(m_wallet->nettype(), cd0.subaddr_account > 0, cd0.change_dts.addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -610,9 +610,11 @@ namespace wallet_rpc
|
||||||
struct request_t
|
struct request_t
|
||||||
{
|
{
|
||||||
std::string unsigned_txset;
|
std::string unsigned_txset;
|
||||||
|
std::string multisig_txset;
|
||||||
|
|
||||||
BEGIN_KV_SERIALIZE_MAP()
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
KV_SERIALIZE(unsigned_txset)
|
KV_SERIALIZE(unsigned_txset)
|
||||||
|
KV_SERIALIZE(multisig_txset)
|
||||||
END_KV_SERIALIZE_MAP()
|
END_KV_SERIALIZE_MAP()
|
||||||
};
|
};
|
||||||
typedef epee::misc_utils::struct_init<request_t> request;
|
typedef epee::misc_utils::struct_init<request_t> request;
|
||||||
|
|
Loading…
Reference in New Issue