aboutsummaryrefslogtreecommitdiff
path: root/src/wallet/wallet2.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/wallet/wallet2.h')
-rw-r--r--src/wallet/wallet2.h100
1 files changed, 93 insertions, 7 deletions
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index 9b068df3c..97abb1476 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -145,7 +145,7 @@ namespace tools
};
private:
- wallet2(const wallet2&) : m_run(true), m_callback(0), m_testnet(false), m_always_confirm_transfers(true), m_print_ring_members(false), m_store_tx_info(true), m_default_mixin(0), m_default_priority(0), m_refresh_type(RefreshDefault), m_auto_refresh(true), m_refresh_from_block_height(0), m_confirm_missing_payment_id(true), m_ask_password(true), m_min_output_count(0), m_min_output_value(0), m_merge_destinations(false), m_confirm_backlog(true), m_is_initialized(false),m_node_rpc_proxy(m_http_client, m_daemon_rpc_mutex) {}
+ wallet2(const wallet2&) : m_multisig_rescan_info(NULL), m_multisig_rescan_k(NULL), m_run(true), m_callback(0), m_testnet(false), m_always_confirm_transfers(true), m_print_ring_members(false), m_store_tx_info(true), m_default_mixin(0), m_default_priority(0), m_refresh_type(RefreshDefault), m_auto_refresh(true), m_refresh_from_block_height(0), m_confirm_missing_payment_id(true), m_ask_password(true), m_min_output_count(0), m_min_output_value(0), m_merge_destinations(false), m_confirm_backlog(true), m_is_initialized(false),m_node_rpc_proxy(m_http_client, m_daemon_rpc_mutex) {}
public:
static const char* tr(const char* str);
@@ -168,7 +168,20 @@ namespace tools
static bool verify_password(const std::string& keys_file_name, const epee::wipeable_string& password, bool no_spend_key);
- wallet2(bool testnet = false, bool restricted = false) : m_run(true), m_callback(0), m_testnet(testnet), m_always_confirm_transfers(true), m_print_ring_members(false), m_store_tx_info(true), m_default_mixin(0), m_default_priority(0), m_refresh_type(RefreshDefault), m_auto_refresh(true), m_refresh_from_block_height(0), m_confirm_missing_payment_id(true), m_ask_password(true), m_min_output_count(0), m_min_output_value(0), m_merge_destinations(false), m_confirm_backlog(true), m_is_initialized(false), m_restricted(restricted), is_old_file_format(false), m_node_rpc_proxy(m_http_client, m_daemon_rpc_mutex), m_light_wallet(false), m_light_wallet_scanned_block_height(0), m_light_wallet_blockchain_height(0), m_light_wallet_connected(false), m_light_wallet_balance(0), m_light_wallet_unlocked_balance(0) {}
+ wallet2(bool testnet = false, bool restricted = false) : m_multisig_rescan_info(NULL), m_multisig_rescan_k(NULL), m_run(true), m_callback(0), m_testnet(testnet), m_always_confirm_transfers(true), m_print_ring_members(false), m_store_tx_info(true), m_default_mixin(0), m_default_priority(0), m_refresh_type(RefreshDefault), m_auto_refresh(true), m_refresh_from_block_height(0), m_confirm_missing_payment_id(true), m_ask_password(true), m_min_output_count(0), m_min_output_value(0), m_merge_destinations(false), m_confirm_backlog(true), m_is_initialized(false), m_restricted(restricted), is_old_file_format(false), m_node_rpc_proxy(m_http_client, m_daemon_rpc_mutex), m_light_wallet(false), m_light_wallet_scanned_block_height(0), m_light_wallet_blockchain_height(0), m_light_wallet_connected(false), m_light_wallet_balance(0), m_light_wallet_unlocked_balance(0) {}
+
+ struct multisig_info
+ {
+ crypto::key_image m_partial_key_image;
+ rct::key m_L;
+ rct::key m_R;
+
+ BEGIN_SERIALIZE_OBJECT()
+ FIELD(m_partial_key_image)
+ FIELD(m_L)
+ FIELD(m_R)
+ END_SERIALIZE()
+ };
struct tx_scan_info_t
{
@@ -199,6 +212,9 @@ namespace tools
bool m_key_image_known;
size_t m_pk_index;
cryptonote::subaddress_index m_subaddr_index;
+ bool m_key_image_partial;
+ rct::key m_multisig_k;
+ std::vector<multisig_info> m_multisig_info;
bool is_rct() const { return m_rct; }
uint64_t amount() const { return m_amount; }
@@ -219,6 +235,9 @@ namespace tools
FIELD(m_key_image_known)
FIELD(m_pk_index)
FIELD(m_subaddr_index)
+ FIELD(m_key_image_partial)
+ FIELD(m_multisig_k)
+ FIELD(m_multisig_info)
END_SERIALIZE()
};
@@ -322,6 +341,7 @@ namespace tools
crypto::secret_key tx_key;
std::vector<crypto::secret_key> additional_tx_keys;
std::vector<cryptonote::tx_destination_entry> dests;
+ rct::multisig_out msout;
tx_construction_data construction_data;
@@ -354,6 +374,12 @@ namespace tools
std::vector<crypto::key_image> key_images;
};
+ struct multisig_tx_set
+ {
+ std::vector<pending_tx> m_ptx;
+ std::unordered_set<crypto::hash> m_signers;
+ };
+
struct keys_file_data
{
crypto::chacha8_iv iv;
@@ -434,6 +460,16 @@ namespace tools
*/
static bool verify_multisig_info(const std::string &data, crypto::secret_key &skey, crypto::public_key &pkey);
/*!
+ * Export multisig info
+ * This will generate and remember new k values
+ */
+ std::vector<tools::wallet2::multisig_info> export_multisig();
+ /*!
+ * Import a set of multisig info from multisig partners
+ * \return the number of inputs which were imported
+ */
+ size_t import_multisig(std::vector<std::vector<tools::wallet2::multisig_info>> info);
+ /*!
* \brief Rewrites to the wallet file for wallet upgrade (doesn't generate key, assumes it's already there)
* \param wallet_name Name of wallet file (should exist)
* \param password Password for wallet file
@@ -528,6 +564,7 @@ namespace tools
bool restricted() const { return m_restricted; }
bool watch_only() const { return m_watch_only; }
bool multisig(uint32_t *threshold = NULL, uint32_t *total = NULL) const;
+ bool has_multisig_partial_key_images() const;
// locked & unlocked balance of given or current subaddress account
uint64_t balance(uint32_t subaddr_index_major) const;
@@ -555,6 +592,8 @@ namespace tools
void commit_tx(pending_tx& ptx_vector);
void commit_tx(std::vector<pending_tx>& ptx_vector);
bool save_tx(const std::vector<pending_tx>& ptx_vector, const std::string &filename);
+ bool save_multisig_tx(multisig_tx_set txs, const std::string &filename);
+ bool save_multisig_tx(const std::vector<pending_tx>& ptx_vector, const std::string &filename);
// load unsigned tx from file and sign it. Takes confirmation callback as argument. Used by the cli wallet
bool sign_tx(const std::string &unsigned_filename, const std::string &signed_filename, std::vector<wallet2::pending_tx> &ptx, std::function<bool(const unsigned_tx_set&)> accept_func = NULL, bool export_raw = false);
// sign unsigned tx. Takes unsigned_tx_set as argument. Used by GUI
@@ -567,6 +606,9 @@ namespace tools
std::vector<wallet2::pending_tx> create_transactions_all(uint64_t below, const cryptonote::account_public_address &address, bool is_subaddress, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices, bool trusted_daemon);
std::vector<wallet2::pending_tx> create_transactions_single(const crypto::key_image &ki, const cryptonote::account_public_address &address, bool is_subaddress, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra, bool trusted_daemon);
std::vector<wallet2::pending_tx> create_transactions_from(const cryptonote::account_public_address &address, bool is_subaddress, std::vector<size_t> unused_transfers_indices, std::vector<size_t> unused_dust_indices, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra, bool trusted_daemon);
+ 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(multisig_tx_set &exported_txs, const std::string &filename, std::vector<crypto::hash> &txids);
std::vector<pending_tx> create_unmixable_sweep_transactions(bool trusted_daemon);
bool check_connection(uint32_t *version = NULL, uint32_t timeout = 200000);
void get_transfers(wallet2::transfer_container& incoming_transfers) const;
@@ -881,7 +923,6 @@ namespace tools
void check_genesis(const crypto::hash& genesis_hash) const; //throws
bool generate_chacha8_key_from_secret_keys(crypto::chacha8_key &key) const;
crypto::hash get_payment_id(const pending_tx &ptx) const;
- crypto::hash8 get_short_payment_id(const pending_tx &ptx) const;
void check_acc_out_precomp(const cryptonote::tx_out &o, const crypto::key_derivation &derivation, const std::vector<crypto::key_derivation> &additional_derivations, size_t i, tx_scan_info_t &tx_scan_info) const;
void parse_block_round(const cryptonote::blobdata &blob, cryptonote::block &bl, crypto::hash &bl_id, bool &error) const;
uint64_t get_upper_transaction_size_limit();
@@ -893,12 +934,15 @@ namespace tools
void set_unspent(size_t idx);
void get_outs(std::vector<std::vector<get_outs_entry>> &outs, const std::vector<size_t> &selected_transfers, size_t fake_outputs_count);
bool tx_add_fake_output(std::vector<std::vector<tools::wallet2::get_outs_entry>> &outs, uint64_t global_index, const crypto::public_key& tx_public_key, const rct::key& mask, uint64_t real_index, bool unlocked) const;
- bool wallet_generate_key_image_helper(const cryptonote::account_keys& ack, const crypto::public_key& tx_public_key, size_t real_output_index, cryptonote::keypair& in_ephemeral, crypto::key_image& ki);
crypto::public_key get_tx_pub_key_from_received_outs(const tools::wallet2::transfer_details &td) const;
bool should_pick_a_second_output(bool use_rct, size_t n_transfers, const std::vector<size_t> &unused_transfers_indices, const std::vector<size_t> &unused_dust_indices) const;
std::vector<size_t> get_only_rct(const std::vector<size_t> &unused_dust_indices, const std::vector<size_t> &unused_transfers_indices) const;
void scan_output(const cryptonote::account_keys &keys, const cryptonote::transaction &tx, const crypto::public_key &tx_pub_key, size_t i, tx_scan_info_t &tx_scan_info, int &num_vouts_received, std::unordered_map<cryptonote::subaddress_index, uint64_t> &tx_money_got_in_outs, std::vector<size_t> &outs);
void trim_hashchain();
+ rct::multisig_kLRki get_multisig_composite_LRki(size_t n, const rct::key &k) const;
+ rct::multisig_kLRki get_multisig_LRki(size_t n, const rct::key &k) const;
+ rct::key get_multisig_k(size_t idx) const;
+ void update_multisig_rescan_info(const std::vector<rct::key> &multisig_k, const std::vector<std::vector<tools::wallet2::multisig_info>> &info, size_t n);
cryptonote::account_base m_account;
boost::optional<epee::net_utils::http::login> m_daemon_login;
@@ -927,6 +971,8 @@ namespace tools
std::unordered_map<std::string, std::string> m_attributes;
std::vector<tools::wallet2::address_book_row> m_address_book;
uint64_t m_upper_transaction_size_limit; //TODO: auto-calc this value or request from daemon, now use some fixed value
+ const std::vector<std::vector<tools::wallet2::multisig_info>> *m_multisig_rescan_info;
+ const std::vector<rct::key> *m_multisig_rescan_k;
std::atomic<bool> m_run;
@@ -976,7 +1022,9 @@ namespace tools
};
}
BOOST_CLASS_VERSION(tools::wallet2, 22)
-BOOST_CLASS_VERSION(tools::wallet2::transfer_details, 8)
+BOOST_CLASS_VERSION(tools::wallet2::transfer_details, 9)
+BOOST_CLASS_VERSION(tools::wallet2::multisig_info, 1)
+BOOST_CLASS_VERSION(tools::wallet2::multisig_tx_set, 1)
BOOST_CLASS_VERSION(tools::wallet2::payment_details, 2)
BOOST_CLASS_VERSION(tools::wallet2::pool_payment_details, 1)
BOOST_CLASS_VERSION(tools::wallet2::unconfirmed_transfer_details, 7)
@@ -985,7 +1033,7 @@ BOOST_CLASS_VERSION(tools::wallet2::address_book_row, 17)
BOOST_CLASS_VERSION(tools::wallet2::unsigned_tx_set, 0)
BOOST_CLASS_VERSION(tools::wallet2::signed_tx_set, 0)
BOOST_CLASS_VERSION(tools::wallet2::tx_construction_data, 2)
-BOOST_CLASS_VERSION(tools::wallet2::pending_tx, 2)
+BOOST_CLASS_VERSION(tools::wallet2::pending_tx, 3)
namespace boost
{
@@ -1023,6 +1071,12 @@ namespace boost
{
x.m_subaddr_index = {};
}
+ if (ver < 9)
+ {
+ x.m_key_image_partial = false;
+ x.m_multisig_info.clear();
+ x.m_multisig_k = rct::zero();
+ }
}
template <class Archive>
@@ -1096,6 +1150,29 @@ namespace boost
return;
}
a & x.m_subaddr_index;
+ if (ver < 9)
+ {
+ initialize_transfer_details(a, x, ver);
+ return;
+ }
+ a & x.m_multisig_info;
+ a & x.m_multisig_k;
+ a & x.m_key_image_partial;
+ }
+
+ template <class Archive>
+ inline void serialize(Archive &a, tools::wallet2::multisig_info &x, const boost::serialization::version_type ver)
+ {
+ a & x.m_partial_key_image;
+ a & x.m_L;
+ a & x.m_R;
+ }
+
+ template <class Archive>
+ inline void serialize(Archive &a, tools::wallet2::multisig_tx_set &x, const boost::serialization::version_type ver)
+ {
+ a & x.m_ptx;
+ a & x.m_signers;
}
template <class Archive>
@@ -1301,6 +1378,9 @@ namespace boost
if (ver < 2)
return;
a & x.selected_transfers;
+ if (ver < 3)
+ return;
+ a & x.msout;
}
}
}
@@ -1478,6 +1558,10 @@ namespace tools
src.real_out_tx_key = get_tx_pub_key_from_extra(td.m_tx);
src.real_output = interted_it - src.outputs.begin();
src.real_output_in_tx_index = td.m_internal_output_index;
+ if (m_multisig)
+ src.multisig_kLRki = get_multisig_composite_LRki(idx, get_multisig_k(idx));
+ else
+ src.multisig_kLRki = rct::multisig_kLRki({rct::zero(), rct::zero(), rct::zero(), rct::zero()});
detail::print_source_entry(src);
++i;
}
@@ -1504,7 +1588,8 @@ namespace tools
crypto::secret_key tx_key;
std::vector<crypto::secret_key> additional_tx_keys;
- bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), m_subaddresses, sources, splitted_dsts, change_dts.addr, extra, tx, unlock_time, tx_key, additional_tx_keys);
+ rct::multisig_out msout;
+ bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), m_subaddresses, sources, splitted_dsts, change_dts.addr, extra, tx, unlock_time, tx_key, additional_tx_keys, false, false, m_multisig ? &msout : NULL);
THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_testnet);
THROW_WALLET_EXCEPTION_IF(upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, upper_transaction_size_limit);
@@ -1532,6 +1617,7 @@ namespace tools
ptx.tx_key = tx_key;
ptx.additional_tx_keys = additional_tx_keys;
ptx.dests = dsts;
+ ptx.msout = msout;
ptx.construction_data.sources = sources;
ptx.construction_data.change_dts = change_dts;
ptx.construction_data.splitted_dsts = splitted_dsts;