aboutsummaryrefslogtreecommitdiff
path: root/src/wallet/wallet2.h
diff options
context:
space:
mode:
authormoneromooo-monero <moneromooo-monero@users.noreply.github.com>2017-08-13 15:29:31 +0100
committermoneromooo-monero <moneromooo-monero@users.noreply.github.com>2017-12-17 16:12:12 +0000
commitf4eda44ce35c6e1ab77566a462470deaae5376ec (patch)
treec7705926d3794b066293c4dd440701f4c91049ca /src/wallet/wallet2.h
parentmultisig address generation RPC (diff)
downloadmonero-f4eda44ce35c6e1ab77566a462470deaae5376ec.tar.xz
N-1/N multisig
Diffstat (limited to '')
-rw-r--r--src/wallet/wallet2.h110
1 files changed, 83 insertions, 27 deletions
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index 8567edc9a..5f973fef5 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -172,14 +172,25 @@ namespace tools
struct multisig_info
{
- crypto::key_image m_partial_key_image;
- rct::key m_L;
- rct::key m_R;
+ struct LR
+ {
+ rct::key m_L;
+ rct::key m_R;
+
+ BEGIN_SERIALIZE_OBJECT()
+ FIELD(m_L)
+ FIELD(m_R)
+ END_SERIALIZE()
+ };
+
+ crypto::public_key m_signer;
+ std::vector<LR> m_LR;
+ std::vector<crypto::key_image> m_partial_key_images; // one per key the participant has
BEGIN_SERIALIZE_OBJECT()
- FIELD(m_partial_key_image)
- FIELD(m_L)
- FIELD(m_R)
+ FIELD(m_signer)
+ FIELD(m_LR)
+ FIELD(m_partial_key_images)
END_SERIALIZE()
};
@@ -213,8 +224,8 @@ namespace tools
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;
+ std::vector<rct::key> m_multisig_k;
+ std::vector<multisig_info> m_multisig_info; // one per other participant
bool is_rct() const { return m_rct; }
uint64_t amount() const { return m_amount; }
@@ -327,6 +338,15 @@ namespace tools
typedef std::vector<transfer_details> transfer_container;
typedef std::unordered_multimap<crypto::hash, payment_details> payment_container;
+ struct multisig_sig
+ {
+ rct::rctSig sigs;
+ crypto::public_key ignore;
+ std::unordered_set<rct::key> used_L;
+ std::unordered_set<crypto::public_key> signing_keys;
+ rct::multisig_out msout;
+ };
+
// The convention for destinations is:
// dests does not include change
// splitted_dsts (in construction_data) does
@@ -341,7 +361,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;
+ std::vector<multisig_sig> multisig_sigs;
tx_construction_data construction_data;
@@ -357,6 +377,7 @@ namespace tools
FIELD(additional_tx_keys)
FIELD(dests)
FIELD(construction_data)
+ FIELD(multisig_sigs)
END_SERIALIZE()
};
@@ -377,7 +398,7 @@ namespace tools
struct multisig_tx_set
{
std::vector<pending_tx> m_ptx;
- std::unordered_set<crypto::hash> m_signers;
+ std::unordered_set<crypto::public_key> m_signers;
};
struct keys_file_data
@@ -446,12 +467,18 @@ namespace tools
const crypto::secret_key& viewkey = crypto::secret_key());
/*!
* \brief Creates a multisig wallet
+ * \return empty if done, non empty if we need to send another string
+ * to other participants
*/
- void make_multisig(const epee::wipeable_string &password,
+ std::string make_multisig(const epee::wipeable_string &password,
const std::vector<crypto::secret_key> &view_keys,
const std::vector<crypto::public_key> &spend_keys,
uint32_t threshold);
/*!
+ * \brief Finalizes creation of a multisig wallet
+ */
+ bool finalize_multisig(const epee::wipeable_string &password, std::unordered_set<crypto::public_key> pkeys, std::vector<crypto::public_key> signers);
+ /*!
* Get a packaged multisig information string
*/
std::string get_multisig_info() const;
@@ -460,6 +487,10 @@ namespace tools
*/
static bool verify_multisig_info(const std::string &data, crypto::secret_key &skey, crypto::public_key &pkey);
/*!
+ * Verifies and extracts keys from a packaged multisig information string
+ */
+ static bool verify_extra_multisig_info(const std::string &data, std::unordered_set<crypto::public_key> &pkeys, crypto::public_key &signer);
+ /*!
* Export multisig info
* This will generate and remember new k values
*/
@@ -610,7 +641,8 @@ namespace tools
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);
+ bool sign_multisig_tx(multisig_tx_set &exported_txs, std::vector<crypto::hash> &txids);
+ bool sign_multisig_tx_from_file(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;
@@ -890,6 +922,11 @@ namespace tools
void set_attribute(const std::string &key, const std::string &value);
std::string get_attribute(const std::string &key) const;
+ crypto::public_key get_multisig_signer_public_key(const crypto::secret_key &spend_skey) const;
+ crypto::public_key get_multisig_signer_public_key() const;
+ crypto::public_key get_multisig_signing_public_key(size_t idx) const;
+ crypto::public_key get_multisig_signing_public_key(const crypto::secret_key &skey) const;
+
private:
/*!
* \brief Stores wallet information to wallet file.
@@ -936,15 +973,17 @@ 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_export(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, size_t multisig_key_index) const;
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);
+ crypto::key_image get_multisig_composite_key_image(size_t n) const;
+ rct::multisig_kLRki get_multisig_composite_kLRki(size_t n, const crypto::public_key &ignore, std::unordered_set<rct::key> &used_L, std::unordered_set<rct::key> &new_used_L) const;
+ rct::multisig_kLRki get_multisig_kLRki(size_t n, const rct::key &k) const;
+ rct::key get_multisig_k(size_t idx, const std::unordered_set<rct::key> &used_L) const;
+ void update_multisig_rescan_info(const std::vector<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;
@@ -974,7 +1013,7 @@ namespace tools
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;
+ const std::vector<std::vector<rct::key>> *m_multisig_rescan_k;
std::atomic<bool> m_run;
@@ -988,7 +1027,7 @@ namespace tools
bool m_watch_only; /*!< no spend key */
bool m_multisig; /*!< if > 1 spend secret key will not match spend public key */
uint32_t m_multisig_threshold;
- uint32_t m_multisig_total;
+ std::vector<crypto::public_key> m_multisig_signers;
bool m_always_confirm_transfers;
bool m_print_ring_members;
bool m_store_tx_info; /*!< request txkey to be returned in RPC, and store in the wallet cache file */
@@ -1026,6 +1065,7 @@ namespace tools
BOOST_CLASS_VERSION(tools::wallet2, 22)
BOOST_CLASS_VERSION(tools::wallet2::transfer_details, 9)
BOOST_CLASS_VERSION(tools::wallet2::multisig_info, 1)
+BOOST_CLASS_VERSION(tools::wallet2::multisig_info::LR, 0)
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)
@@ -1036,6 +1076,7 @@ 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, 3)
+BOOST_CLASS_VERSION(tools::wallet2::multisig_sig, 0)
namespace boost
{
@@ -1076,8 +1117,8 @@ namespace boost
if (ver < 9)
{
x.m_key_image_partial = false;
+ x.m_multisig_k.clear();
x.m_multisig_info.clear();
- x.m_multisig_k = rct::zero();
}
}
@@ -1163,14 +1204,21 @@ namespace boost
}
template <class Archive>
- inline void serialize(Archive &a, tools::wallet2::multisig_info &x, const boost::serialization::version_type ver)
+ inline void serialize(Archive &a, tools::wallet2::multisig_info::LR &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_info &x, const boost::serialization::version_type ver)
+ {
+ a & x.m_signer;
+ a & x.m_LR;
+ a & x.m_partial_key_images;
+ }
+
+ template <class Archive>
inline void serialize(Archive &a, tools::wallet2::multisig_tx_set &x, const boost::serialization::version_type ver)
{
a & x.m_ptx;
@@ -1353,6 +1401,16 @@ namespace boost
}
template <class Archive>
+ inline void serialize(Archive &a, tools::wallet2::multisig_sig &x, const boost::serialization::version_type ver)
+ {
+ a & x.sigs;
+ a & x.ignore;
+ a & x.used_L;
+ a & x.signing_keys;
+ a & x.msout;
+ }
+
+ template <class Archive>
inline void serialize(Archive &a, tools::wallet2::pending_tx &x, const boost::serialization::version_type ver)
{
a & x.tx;
@@ -1382,7 +1440,7 @@ namespace boost
a & x.selected_transfers;
if (ver < 3)
return;
- a & x.msout;
+ a & x.multisig_sigs;
}
}
}
@@ -1458,6 +1516,8 @@ namespace tools
// throw if attempting a transaction with no destinations
THROW_WALLET_EXCEPTION_IF(dsts.empty(), error::zero_destination);
+ THROW_WALLET_EXCEPTION_IF(m_multisig, error::wallet_internal_error, "Multisig wallets cannot spend non rct outputs");
+
uint64_t upper_transaction_size_limit = get_upper_transaction_size_limit();
uint64_t needed_money = fee;
@@ -1560,10 +1620,7 @@ 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()});
+ src.multisig_kLRki = rct::multisig_kLRki({rct::zero(), rct::zero(), rct::zero(), rct::zero()});
detail::print_source_entry(src);
++i;
}
@@ -1619,7 +1676,6 @@ 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;