From 7b97f45b47a1a4938c4f00c6f2f4a3ec7002cec6 Mon Sep 17 00:00:00 2001 From: woodser Date: Tue, 20 Aug 2019 06:35:26 -0400 Subject: [PATCH] switch wallet sends to use monero_tx_set compiling --- src/wallet/monero_wallet.cpp | 73 ++++++++++++++++++------------ src/wallet/monero_wallet.h | 42 ++++++++--------- src/wallet/monero_wallet_model.cpp | 11 +++++ src/wallet/monero_wallet_model.h | 28 ++++++++++-- test/sample_code.cpp | 4 +- 5 files changed, 103 insertions(+), 55 deletions(-) diff --git a/src/wallet/monero_wallet.cpp b/src/wallet/monero_wallet.cpp index 018b48a..3727cf9 100644 --- a/src/wallet/monero_wallet.cpp +++ b/src/wallet/monero_wallet.cpp @@ -1753,17 +1753,17 @@ namespace monero { return result; } - shared_ptr monero_wallet::create_tx(monero_send_request& request) { + monero_tx_set monero_wallet::create_tx(monero_send_request& request) { if (request.m_can_split != boost::none && request.m_can_split.get()) throw runtime_error("Cannot request split transactions with create_tx() which prevents splitting; use create_txs() instead"); request.m_can_split = false; - return create_txs(request)[0]; + return create_txs(request); } - shared_ptr monero_wallet::create_tx(uint32_t account_index, string address, uint64_t amount) { + monero_tx_set monero_wallet::create_tx(uint32_t account_index, string address, uint64_t amount) { return create_tx(account_index, address, amount, monero_send_priority::NORMAL); } - shared_ptr monero_wallet::create_tx(int account_index, string address, uint64_t amount, monero_send_priority priority) { + monero_tx_set monero_wallet::create_tx(int account_index, string address, uint64_t amount, monero_send_priority priority) { monero_send_request req; req.m_account_index = account_index; req.m_destinations.push_back(make_shared(address, amount)); @@ -1771,21 +1771,21 @@ namespace monero { return create_tx(req); } - vector> monero_wallet::create_txs(monero_send_request& request) { + monero_tx_set monero_wallet::create_txs(monero_send_request& request) { // modify request to not relay boost::optional requested_do_not_relay = request.m_do_not_relay; request.m_do_not_relay = true; // invoke common method which doesn't relay - vector> created_txs = send_split(request); + monero_tx_set tx_set = send_split(request); // restore doNotRelay of request and txs request.m_do_not_relay = requested_do_not_relay; - for (const shared_ptr& tx : created_txs) tx->m_do_not_relay = requested_do_not_relay; + for (const shared_ptr& tx : tx_set.m_txs) tx->m_do_not_relay = requested_do_not_relay; // return results - return created_txs; + return tx_set; } string monero_wallet::relay_tx(const string& tx_metadata) { @@ -1842,17 +1842,17 @@ namespace monero { return relay_txs(tx_hexes); } - shared_ptr monero_wallet::send(monero_send_request& request) { + monero_tx_set monero_wallet::send(monero_send_request& request) { if (request.m_can_split != boost::none && request.m_can_split.get()) throw runtime_error("Cannot request split transactions with send() which prevents splitting; use sendSplit() instead"); request.m_can_split = false; - return send_split(request)[0]; + return send_split(request); } - shared_ptr monero_wallet::send(uint32_t account_index, string address, uint64_t amount) { + monero_tx_set monero_wallet::send(uint32_t account_index, string address, uint64_t amount) { return send(account_index, address, amount, monero_send_priority::NORMAL); } - shared_ptr monero_wallet::send(uint32_t account_index, string address, uint64_t amount, monero_send_priority priority) { + monero_tx_set monero_wallet::send(uint32_t account_index, string address, uint64_t amount, monero_send_priority priority) { monero_send_request req; req.m_account_index = account_index; req.m_destinations.push_back(make_shared(address, amount)); @@ -1860,7 +1860,7 @@ namespace monero { return send(req); } - vector> monero_wallet::send_split(const monero_send_request& request) { + monero_tx_set monero_wallet::send_split(const monero_send_request& request) { MTRACE("monero_wallet::send_split(request)"); MTRACE("monero_send_request: " << request.serialize()); @@ -1913,12 +1913,12 @@ namespace monero { list tx_keys; list tx_amounts; list tx_fees; - string multisig_tx_set; - string unsigned_tx_set; + string multisig_tx_hex; + string unsigned_tx_hex; list m_tx_ids; list tx_blobs; list tx_metadatas; - if (!fill_response(m_w2.get(), ptx_vector, get_tx_keys, tx_keys, tx_amounts, tx_fees, multisig_tx_set, unsigned_tx_set, m_do_not_relay, m_tx_ids, get_tx_hex, tx_blobs, get_tx_metadata, tx_metadatas, err)) { + if (!fill_response(m_w2.get(), ptx_vector, get_tx_keys, tx_keys, tx_amounts, tx_fees, multisig_tx_hex, unsigned_tx_hex, m_do_not_relay, m_tx_ids, get_tx_hex, tx_blobs, get_tx_metadata, tx_metadatas, err)) { throw runtime_error("need to handle error filling response!"); // TODO } @@ -1969,10 +1969,16 @@ namespace monero { tx_blobs_iter++; tx_metadatas_iter++; } - return txs; + + // build and return tx set + monero_tx_set tx_set; + tx_set.m_txs = txs; + tx_set.m_multisig_tx_hex = multisig_tx_hex; + tx_set.m_unsigned_tx_hex = unsigned_tx_hex; + return tx_set; } - shared_ptr monero_wallet::sweep_output(const monero_send_request& request) const { + monero_tx_set monero_wallet::sweep_output(const monero_send_request& request) { MTRACE("sweep_output()"); MTRACE("monero_send_request: " << request.serialize()); @@ -2022,12 +2028,12 @@ namespace monero { list tx_keys; list tx_amounts; list tx_fees; - string multisig_tx_set; - string unsigned_tx_set; + string multisig_tx_hex; + string unsigned_tx_hex; list m_tx_ids; list tx_blobs; list tx_metadatas; - if (!fill_response(m_w2.get(), ptx_vector, get_tx_keys, tx_keys, tx_amounts, tx_fees, multisig_tx_set, unsigned_tx_set, m_do_not_relay, m_tx_ids, get_tx_hex, tx_blobs, get_tx_metadata, tx_metadatas, er)) { + if (!fill_response(m_w2.get(), ptx_vector, get_tx_keys, tx_keys, tx_amounts, tx_fees, multisig_tx_hex, unsigned_tx_hex, m_do_not_relay, m_tx_ids, get_tx_hex, tx_blobs, get_tx_metadata, tx_metadatas, er)) { throw runtime_error("need to handle error filling response!"); // TODO: return err message } @@ -2080,12 +2086,18 @@ namespace monero { tx_metadatas_iter++; } - // return tx + // validate one transaction if (txs.size() != 1) throw runtime_error("Expected 1 transaction but was " + boost::lexical_cast(txs.size())); - return txs[0]; + + // build and return tx set + monero_tx_set tx_set; + tx_set.m_txs = txs; + tx_set.m_multisig_tx_hex = multisig_tx_hex; + tx_set.m_unsigned_tx_hex = unsigned_tx_hex; + return tx_set; } - vector> monero_wallet::sweep_dust(bool do_not_relay) { + monero_tx_set monero_wallet::sweep_dust(bool do_not_relay) { MTRACE("monero_wallet::sweep_dust()"); // create transaction to fill @@ -2100,13 +2112,13 @@ namespace monero { list tx_keys; list tx_amounts; list tx_fees; - string multisig_tx_set; - string unsigned_tx_set; + string multisig_tx_hex; + string unsigned_tx_hex; list m_tx_ids; list tx_blobs; list tx_metadatas; epee::json_rpc::error er; - if (!fill_response(m_w2.get(), ptx_vector, get_tx_keys, tx_keys, tx_amounts, tx_fees, multisig_tx_set, unsigned_tx_set, do_not_relay, m_tx_ids, get_tx_hex, tx_blobs, get_tx_metadata, tx_metadatas, er)) { + if (!fill_response(m_w2.get(), ptx_vector, get_tx_keys, tx_keys, tx_amounts, tx_fees, multisig_tx_hex, unsigned_tx_hex, do_not_relay, m_tx_ids, get_tx_hex, tx_blobs, get_tx_metadata, tx_metadatas, er)) { throw runtime_error("need to handle error filling response!"); // TODO: return err message } @@ -2155,7 +2167,12 @@ namespace monero { tx_metadatas_iter++; } - return txs; + // build and return tx set + monero_tx_set tx_set; + tx_set.m_txs = txs; + tx_set.m_multisig_tx_hex = multisig_tx_hex; + tx_set.m_unsigned_tx_hex = unsigned_tx_hex; + return tx_set; } string monero_wallet::sign(const string& msg) const { diff --git a/src/wallet/monero_wallet.h b/src/wallet/monero_wallet.h index 9713f71..aa625c3 100644 --- a/src/wallet/monero_wallet.h +++ b/src/wallet/monero_wallet.h @@ -780,9 +780,9 @@ namespace monero { * given request. The transaction may be relayed later. * * @param request configures the transaction to create - * @return the created transaction + * @return a tx set for the requested transaction if possible */ - shared_ptr create_tx(monero_send_request& request); + monero_tx_set create_tx(monero_send_request& request); /** * Create a transaction to transfers funds from this wallet to a destination address. @@ -791,9 +791,9 @@ namespace monero { * @param accountIndex is the index of the account to withdraw funds from * @param address is the destination address to send funds to * @param amount is the amount being sent - * @return the resulting transaction + * @return a tx set for the requested transaction if possible */ - shared_ptr create_tx(uint32_t account_index, string address, uint64_t amount); + monero_tx_set create_tx(uint32_t account_index, string address, uint64_t amount); /** * Create a transaction to transfers funds from this wallet to a destination address. @@ -803,18 +803,18 @@ namespace monero { * @param address is the destination address to send funds to * @param amount is the amount being sent * @param priority is the send priority (default normal) - * @return the resulting transaction + * @return a tx set for the requested transaction if possible */ - shared_ptr create_tx(int account_index, string address, uint64_t amount, monero_send_priority priority); + monero_tx_set create_tx(int account_index, string address, uint64_t amount, monero_send_priority priority); /** * Create one or more transactions to transfer funds from this wallet * according to the given request. The transactions may later be relayed. * * @param request configures the transactions to create - * @return the created transactions + * @return a tx set for the requested transactions if possible */ - vector> create_txs(monero_send_request& request); + monero_tx_set create_txs(monero_send_request& request); /** * Relay a transaction previously created without relaying. @@ -853,9 +853,9 @@ namespace monero { * according to the given request. * * @param request configures the transaction - * @return the resulting transaction + * @return a tx set with the requested transaction if possible */ - shared_ptr send(monero_send_request& request); + monero_tx_set send(monero_send_request& request); /** * Create and relay a transaction to transfers funds from this wallet to @@ -864,9 +864,9 @@ namespace monero { * @param account_index is the index of the account to withdraw funds from * @param address is the destination address to send funds to * @param amount is the amount being sent - * @return the resulting transaction + * @return a tx set with the requested transaction if possible */ - shared_ptr send(uint32_t account_index, string address, uint64_t amount); + monero_tx_set send(uint32_t account_index, string address, uint64_t amount); /** * Create and relay a transaction to transfers funds from this wallet to @@ -876,19 +876,19 @@ namespace monero { * @param address is the destination address to send funds to * @param amount is the amount being sent * @param priority is the send priority (default normal) - * @return the resulting transaction + * @return a tx set with the requested transaction if possible */ - shared_ptr send(uint32_t account_index, string address, uint64_t amount, monero_send_priority priority); + monero_tx_set send(uint32_t account_index, string address, uint64_t amount, monero_send_priority priority); /** * Create one or more transactions which transfer funds from this wallet to * one or more destinations depending on the given configuration. * * @param request configures the transaction - * @return the resulting transaction + * @return a tx set with the requested transactions if possible */ - vector> send_split(const monero_send_request& request); -// + monero_tx_set send_split(const monero_send_request& request); + // /** // * Create and relay one or more transactions which transfer funds from this // * wallet to one or more destination. @@ -916,9 +916,9 @@ namespace monero { * Sweep an output with a given key image. * * @param request configures the sweep transaction - * @return the resulting transaction from sweeping an output + * @return a tx set with the requested transaction if possible */ - shared_ptr sweep_output(const monero_send_request& request) const; + monero_tx_set sweep_output(const monero_send_request& request); // /** // * Sweep an output with a given key image. @@ -987,9 +987,9 @@ namespace monero { * Sweep all unmixable dust outputs back to the wallet to make them easier to spend and mix. * * @param do_not_relay specifies if the resulting transaction should not be relayed (defaults to false i.e. relayed) - * @return the resulting transactions from sweeping dust + * @return a tx set with the requested transactions if possible */ - vector> sweep_dust(bool do_not_relay = false); + monero_tx_set sweep_dust(bool do_not_relay = false); /** * Sign a message. diff --git a/src/wallet/monero_wallet_model.cpp b/src/wallet/monero_wallet_model.cpp index 95e22d7..b2beaac 100644 --- a/src/wallet/monero_wallet_model.cpp +++ b/src/wallet/monero_wallet_model.cpp @@ -297,6 +297,17 @@ namespace monero { return node; } + // ----------------------------- MONERO TX SET ------------------------------ + + boost::property_tree::ptree monero_tx_set::to_property_tree() const { + boost::property_tree::ptree node; + if (!m_txs.empty()) node.add_child("txs", monero_utils::to_property_tree(m_txs)); + if (m_multisig_tx_hex != boost::none) node.put("multisigTxHex", *m_multisig_tx_hex); + if (m_unsigned_tx_hex != boost::none) node.put("unsignedTxHex", *m_unsigned_tx_hex); + if (m_signed_tx_hex != boost::none) node.put("signedTxHex", *m_signed_tx_hex); + return node; + } + // ---------------------------- MONERO TRANSFER ----------------------------- shared_ptr monero_transfer::copy(const shared_ptr& src, const shared_ptr& tgt) const { diff --git a/src/wallet/monero_wallet_model.h b/src/wallet/monero_wallet_model.h index c59c037..79a5221 100644 --- a/src/wallet/monero_wallet_model.h +++ b/src/wallet/monero_wallet_model.h @@ -124,10 +124,6 @@ namespace monero { boost::property_tree::ptree to_property_tree() const; }; - // forward declarations - struct monero_tx_wallet; - struct monero_tx_query; - /** * Models an outgoing transfer destination. */ @@ -141,6 +137,11 @@ namespace monero { boost::property_tree::ptree to_property_tree() const; }; + // forward declarations + struct monero_tx_wallet; + struct monero_tx_query; + struct monero_tx_set; + /** * Models a base transfer of funds to or from the wallet. */ @@ -248,10 +249,12 @@ namespace monero { bool meets_criteria(monero_output_wallet* output) const; }; + /** * Models a Monero transaction in the context of a wallet. */ struct monero_tx_wallet : public monero_tx { + boost::optional> m_tx_set; vector> m_incoming_transfers; boost::optional> m_outgoing_transfer; boost::optional m_note; @@ -291,6 +294,23 @@ namespace monero { bool meets_criteria(monero_tx_wallet* tx) const; }; + /** + * Groups transactions who share common hex data which is needed in order to + * sign and submit the transactions. + * + * For example, multisig transactions created from send_split() share a common + * hex string which is needed in order to sign and submit the multisig + * transactions. + */ + struct monero_tx_set : serializable_struct { + vector> m_txs; + boost::optional m_signed_tx_hex; + boost::optional m_unsigned_tx_hex; + boost::optional m_multisig_tx_hex; + + boost::property_tree::ptree to_property_tree() const; + }; + /** * Monero integrated address model. */ diff --git a/test/sample_code.cpp b/test/sample_code.cpp index 19e5e2c..8a3ef98 100644 --- a/test/sample_code.cpp +++ b/test/sample_code.cpp @@ -99,7 +99,7 @@ int main(int argc, const char* argv[]) { wallet_random->add_listener(my_listener); // send funds from the restored wallet to the random wallet - shared_ptr sent_tx = wallet_restored->send(0, wallet_random->get_address(1, 0), 50000); + shared_ptr sent_tx = wallet_restored->send(0, wallet_random->get_address(1, 0), 50000).m_txs[0]; bool in_pool = sent_tx->m_in_tx_pool.get(); // true // mine with 7 threads to push the network along @@ -127,7 +127,7 @@ int main(int argc, const char* argv[]) { send_request.m_destinations = destinations; // create the transaction, confirm with the user, and relay to the network - shared_ptr created_tx = wallet_restored->create_tx(send_request); + shared_ptr created_tx = wallet_restored->create_tx(send_request).m_txs[0]; uint64_t fee = created_tx->m_fee.get(); // "Are you sure you want to send ...?" wallet_restored->relay_tx(*created_tx); // submit the transaction to the Monero network which will notify the recipient wallet