Electroneum
multisig.cpp
Go to the documentation of this file.
1 // Copyright (c) 2017-2019, The Monero Project
2 //
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without modification, are
6 // permitted provided that the following conditions are met:
7 //
8 // 1. Redistributions of source code must retain the above copyright notice, this list of
9 // conditions and the following disclaimer.
10 //
11 // 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 // of conditions and the following disclaimer in the documentation and/or other
13 // materials provided with the distribution.
14 //
15 // 3. Neither the name of the copyright holder nor the names of its contributors may be
16 // used to endorse or promote products derived from this software without specific
17 // prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
20 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
22 // THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
27 // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 
29 #include "gtest/gtest.h"
30 
31 #include <cstdint>
32 
33 #include "wallet/wallet2.h"
34 
35 static const struct
36 {
37  const char *address;
38  const char *spendkey;
39 } test_addresses[] =
40 {
41  {
42  "etnkQfrWyE18qgir1RPR31Vcm8ibph8a4TArBzp9hx6qG5AtWJ4cg9BYcVmDkbLsqvag2xZuBVtzATMbGENvhbEr2GpNu7NkqX",
43  "23a662c983674c3654d2f2d7c72e055523ef6bdb8bb8290d626268e73c5b4600"
44  },
45  {
46  "etnkByEHsraTqRBdDrrV2m1kDCHa1NyBpDWJ1XeB5ZGRGtdbUcteBLwN9LBpiDF6EjDj8qEUFqasKC6RNwLHuUju7PCaanugxk",
47  "77dbbfaa83fa79c9280340893dca48a868c23a1b9f8835ec421ce7281e882509"
48  },
49  {
50  "etnkQNki9u1KyZvnh4WRDsLPQbZgcRo8WFo7JfAftDU7FZhyuxmxxHQMkkxLt8y7RwTKeH1hdMZ1V7ACPDm4HwEw1tLMWjW8Lv",
51  "5f17f13c96c6fcc8ec3f9f539ea00e8087224cd9071fbecfec07441b9e64b60b"
52  },
53  {
54  "etnk3G6WfJqgTMuuAZXcKxMmv7WpVGC977okK94spzsWc3acWLjebL1MdWN2uNqLygGEHCQWtzf81Phbz952LmK35vx7iuF2zV",
55  "7083f2c357c0fc2f2fabc5d6751d989141aad8361899d427bbc0d03ca2f2850d"
56  },
57  {
58  "etnkAo9GFotYKPmgKbEXBAHhvuwcUU1vDaedMf9TLMdQ3p7tiyE6mr1BNWtyrxDoGs9dPAJ9nKJ5jLt2Gk8oGcYE4JoSB2EreS",
59  "4b754c17b2788826bf57eb028ac8af014c3a9c126a94920c1e00924a4a98cf0d"
60  }
61 };
62 
63 static const size_t KEYS_COUNT = 5;
64 
65 static void make_wallet(unsigned int idx, tools::wallet2 &wallet)
66 {
67  ASSERT_TRUE(idx < sizeof(test_addresses) / sizeof(test_addresses[0]));
68 
70  epee::string_tools::hex_to_pod(test_addresses[idx].spendkey, spendkey);
71 
72  try
73  {
74  wallet.init("", boost::none, boost::asio::ip::tcp::endpoint{}, 0, true, epee::net_utils::ssl_support_t::e_ssl_support_disabled);
75  wallet.set_subaddress_lookahead(1, 1);
76  wallet.generate("", "", spendkey, true, false);
79  }
80  catch (const std::exception &e)
81  {
82  MFATAL("Error creating test wallet: " << e.what());
83  ASSERT_TRUE(0);
84  }
85 }
86 
87 static std::vector<std::string> exchange_round(std::vector<tools::wallet2>& wallets, const std::vector<std::string>& mis)
88 {
89  std::vector<std::string> new_infos;
90  for (size_t i = 0; i < wallets.size(); ++i) {
91  new_infos.push_back(wallets[i].exchange_multisig_keys("", mis));
92  }
93 
94  return new_infos;
95 }
96 
97 static void make_wallets(std::vector<tools::wallet2>& wallets, unsigned int M)
98 {
99  ASSERT_TRUE(wallets.size() > 1 && wallets.size() <= KEYS_COUNT);
100  ASSERT_TRUE(M <= wallets.size());
101 
102  std::vector<std::string> mis(wallets.size());
103 
104  for (size_t i = 0; i < wallets.size(); ++i) {
105  make_wallet(i, wallets[i]);
106 
107  mis[i] = wallets[i].get_multisig_info();
108  }
109 
110  for (auto& wallet: wallets) {
111  ASSERT_FALSE(wallet.multisig());
112  }
113 
114  std::vector<std::string> mxis;
115  for (size_t i = 0; i < wallets.size(); ++i) {
116  // it's ok to put all of multisig keys in this function. it throws in case of error
117  mxis.push_back(wallets[i].make_multisig("", mis, M));
118  }
119 
120  while (!mxis[0].empty()) {
121  mxis = exchange_round(wallets, mxis);
122  }
123 
124  for (size_t i = 0; i < wallets.size(); ++i) {
125  ASSERT_TRUE(mxis[i].empty());
126  bool ready;
127  uint32_t threshold, total;
128  ASSERT_TRUE(wallets[i].multisig(&ready, &threshold, &total));
129  ASSERT_TRUE(ready);
130  ASSERT_TRUE(threshold == M);
131  ASSERT_TRUE(total == wallets.size());
132 
133  if (i != 0) {
134  // "equals" is transitive relation so we need only to compare first wallet's address to each others' addresses. no need to compare 0's address with itself.
135  ASSERT_TRUE(wallets[0].get_account().get_public_address_str(cryptonote::TESTNET) == wallets[i].get_account().get_public_address_str(cryptonote::TESTNET));
136  }
137  }
138 }
139 
140 TEST(multisig, make_2_2)
141 {
142  std::vector<tools::wallet2> wallets(2);
143  make_wallets(wallets, 2);
144 }
145 
146 TEST(multisig, make_3_3)
147 {
148  std::vector<tools::wallet2> wallets(3);
149  make_wallets(wallets, 3);
150 }
151 
152 TEST(multisig, make_2_3)
153 {
154  std::vector<tools::wallet2> wallets(3);
155  make_wallets(wallets, 2);
156 }
157 
158 TEST(multisig, make_2_4)
159 {
160  std::vector<tools::wallet2> wallets(4);
161  make_wallets(wallets, 2);
162 }
163 
164 TEST(multisig, make_2_5)
165 {
166  std::vector<tools::wallet2> wallets(5);
167  make_wallets(wallets, 2);
168 }
#define MFATAL(x)
Definition: misc_log_ex.h:72
std::string get_public_address_str(network_type nettype) const
Definition: account.cpp:269
#define ASSERT_FALSE(condition)
Definition: gtest.h:1868
const account_keys & get_keys() const
Definition: account.cpp:264
std::string pod_to_hex(const t_pod_type &s)
Definition: string_tools.h:317
unsigned int uint32_t
Definition: stdint.h:126
bool init(std::string daemon_address="http://localhost:8080", boost::optional< epee::net_utils::http::login > daemon_login=boost::none, boost::asio::ip::tcp::endpoint proxy={}, uint64_t upper_transaction_weight_limit=0, bool trusted_daemon=true, epee::net_utils::ssl_options_t ssl_options=epee::net_utils::ssl_support_t::e_ssl_support_autodetect, std::string blockchain_db_path="")
Definition: wallet2.cpp:1282
bool hex_to_pod(const std::string &hex_str, t_pod_type &s)
Definition: string_tools.h:324
void set_subaddress_lookahead(size_t major, size_t minor)
Definition: wallet2.cpp:1535
TEST(multisig, make_2_2)
Definition: multisig.cpp:140
#define ASSERT_TRUE(condition)
Definition: gtest.h:1865
crypto::secret_key m_spend_secret_key
Definition: account.h:44
cryptonote::account_base & get_account()
Definition: wallet2.h:734
const char * address
Definition: multisig.cpp:37
const char * spendkey
Definition: multisig.cpp:38
void generate(const std::string &wallet_, const epee::wipeable_string &password, const epee::wipeable_string &multisig_data, bool create_address_file=false)
Generates a wallet or restores one.
Definition: wallet2.cpp:4869
bool multisig(bool *ready=NULL, uint32_t *threshold=NULL, uint32_t *total=NULL) const
Definition: wallet2.cpp:5634
uint8_t threshold
Definition: blockchain.cpp:92