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 // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
30 
31 #include "ringct/rctSigs.h"
33 #include "multisig/multisig.h"
35 #include "chaingen.h"
36 #include "multisig.h"
37 #include "device/device.hpp"
38 using namespace epee;
39 using namespace crypto;
40 using namespace cryptonote;
41 
42 //#define NO_MULTISIG
43 
44 void make_multisig_accounts(std::vector<cryptonote::account_base>& account, uint32_t threshold)
45 {
46  std::vector<crypto::secret_key> all_view_keys;
47  std::vector<std::vector<crypto::public_key>> derivations(account.size());
48  //storage for all set of multisig derivations and spend public key (in first round)
49  std::unordered_set<crypto::public_key> exchanging_keys;
50 
51  for (size_t msidx = 0; msidx < account.size(); ++msidx)
52  {
53  crypto::secret_key vkh = cryptonote::get_multisig_blinded_secret_key(account[msidx].get_keys().m_view_secret_key);
54  all_view_keys.push_back(vkh);
55 
56  crypto::secret_key skh = cryptonote::get_multisig_blinded_secret_key(account[msidx].get_keys().m_spend_secret_key);
57  crypto::public_key pskh;
59 
60  derivations[msidx].push_back(pskh);
61  exchanging_keys.insert(pskh);
62  }
63 
64  uint32_t roundsTotal = 1;
65  if (threshold < account.size())
66  roundsTotal = account.size() - threshold;
67 
68  //secret multisig keys of every account
69  std::vector<std::vector<crypto::secret_key>> multisig_keys(account.size());
70  std::vector<crypto::secret_key> spend_skey(account.size());
71  std::vector<crypto::public_key> spend_pkey(account.size());
72  for (uint32_t round = 0; round < roundsTotal; ++round)
73  {
74  std::unordered_set<crypto::public_key> roundKeys;
75  for (size_t msidx = 0; msidx < account.size(); ++msidx)
76  {
77  // subtracting one's keys from set of all unique keys is the same as key exchange
78  auto myKeys = exchanging_keys;
79  for (const auto& d: derivations[msidx])
80  myKeys.erase(d);
81 
82  if (threshold == account.size())
83  {
84  cryptonote::generate_multisig_N_N(account[msidx].get_keys(), std::vector<crypto::public_key>(myKeys.begin(), myKeys.end()), multisig_keys[msidx], (rct::key&)spend_skey[msidx], (rct::key&)spend_pkey[msidx]);
85  }
86  else
87  {
88  derivations[msidx] = cryptonote::generate_multisig_derivations(account[msidx].get_keys(), std::vector<crypto::public_key>(myKeys.begin(), myKeys.end()));
89  roundKeys.insert(derivations[msidx].begin(), derivations[msidx].end());
90  }
91  }
92 
93  exchanging_keys = roundKeys;
94  roundKeys.clear();
95  }
96 
97  std::unordered_set<crypto::public_key> all_multisig_keys;
98  for (size_t msidx = 0; msidx < account.size(); ++msidx)
99  {
100  std::unordered_set<crypto::secret_key> view_keys(all_view_keys.begin(), all_view_keys.end());
101  view_keys.erase(all_view_keys[msidx]);
102 
103  crypto::secret_key view_skey = cryptonote::generate_multisig_view_secret_key(account[msidx].get_keys().m_view_secret_key, std::vector<secret_key>(view_keys.begin(), view_keys.end()));
104  if (threshold < account.size())
105  {
106  multisig_keys[msidx] = cryptonote::calculate_multisig_keys(derivations[msidx]);
107  spend_skey[msidx] = cryptonote::calculate_multisig_signer_key(multisig_keys[msidx]);
108  }
109  account[msidx].make_multisig(view_skey, spend_skey[msidx], spend_pkey[msidx], multisig_keys[msidx]);
110  for (const auto &k: multisig_keys[msidx]) {
111  all_multisig_keys.insert(rct::rct2pk(rct::scalarmultBase(rct::sk2rct(k))));
112  }
113  }
114 
115  if (threshold < account.size())
116  {
117  std::vector<crypto::public_key> public_keys(std::vector<crypto::public_key>(all_multisig_keys.begin(), all_multisig_keys.end()));
119 
120  for (size_t msidx = 0; msidx < account.size(); ++msidx)
121  account[msidx].finalize_multisig(spend_pkey);
122  }
123 }
124 
125 //----------------------------------------------------------------------------------------------------------------------
126 // Tests
127 
128 bool gen_multisig_tx_validation_base::generate_with(std::vector<test_event_entry>& events,
129  size_t inputs, size_t mixin, uint64_t amount_paid, bool valid,
130  size_t threshold, size_t total, size_t creator, std::vector<size_t> signers,
131  const std::function<void(std::vector<tx_source_entry> &sources, std::vector<tx_destination_entry> &destinations)> &pre_tx,
132  const std::function<void(transaction &tx)> &post_tx) const
133 {
134  uint64_t ts_start = 1338224400;
135  bool r;
136 
137  CHECK_AND_ASSERT_MES(total >= 2, false, "Bad scheme");
138  CHECK_AND_ASSERT_MES(threshold <= total, false, "Bad scheme");
139 #ifdef NO_MULTISIG
140  CHECK_AND_ASSERT_MES(total <= 5, false, "Unsupported scheme");
141 #endif
142  CHECK_AND_ASSERT_MES(inputs >= 1 && inputs <= 8, false, "Inputs should between 1 and 8");
143 
144  // given as 1 based for clarity
145  --creator;
146  for (size_t &signer: signers)
147  --signer;
148 
149  CHECK_AND_ASSERT_MES(creator < total, false, "invalid creator");
150  for (size_t signer: signers)
151  CHECK_AND_ASSERT_MES(signer < total, false, "invalid signer");
152 
153 #ifdef NO_MULTISIG
154  GENERATE_ACCOUNT(acc0);
155  GENERATE_ACCOUNT(acc1);
156  GENERATE_ACCOUNT(acc2);
157  GENERATE_ACCOUNT(acc3);
158  GENERATE_ACCOUNT(acc4);
159  account_base miner_account[5] = {acc0, acc1, acc2, acc3, acc4};
160 #else
161  GENERATE_MULTISIG_ACCOUNT(miner_account, threshold, total);
162 #endif
163 
164  MAKE_GENESIS_BLOCK(events, blk_0, miner_account[creator], ts_start);
165 
166  // create 8 miner accounts, and have them mine the next 8 blocks
167  // they will have a coinbase with a single out that's pseudo rct
168  constexpr size_t n_coinbases = 8;
169  cryptonote::account_base miner_accounts[n_coinbases];
170  const cryptonote::block *prev_block = &blk_0;
171  cryptonote::block blocks[n_coinbases];
172  for (size_t n = 0; n < n_coinbases; ++n) {
173  // the first block goes to the multisig account
174  miner_accounts[n].generate();
175  account_base &account = n < inputs ? miner_account[creator] : miner_accounts[n];
176  CHECK_AND_ASSERT_MES(generator.construct_block_manually(blocks[n], *prev_block, account,
178  4, 4, prev_block->timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN * 2, // v2 has blocks twice as long
179  crypto::hash(), 0, transaction(), std::vector<crypto::hash>(), 0, 1, 4),
180  false, "Failed to generate block");
181  events.push_back(blocks[n]);
182  prev_block = blocks + n;
183  LOG_PRINT_L0("Initial miner tx " << n << ": " << obj_to_json_str(blocks[n].miner_tx));
184  LOG_PRINT_L0("in block: " << obj_to_json_str(blocks[n]));
185  }
186 
187  // rewind
188  cryptonote::block blk_r, blk_last;
189  {
190  blk_last = blocks[n_coinbases - 1];
191  for (size_t i = 0; i < CRYPTONOTE_MINED_ETN_UNLOCK_WINDOW; ++i)
192  {
193  cryptonote::block blk;
194  CHECK_AND_ASSERT_MES(generator.construct_block_manually(blk, blk_last, miner_accounts[0],
196  4, 4, blk_last.timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN * 2, // v2 has blocks twice as long
197  crypto::hash(), 0, transaction(), std::vector<crypto::hash>(), 0, 1, 4),
198  false, "Failed to generate block");
199  events.push_back(blk);
200  blk_last = blk;
201  }
202  blk_r = blk_last;
203  }
204 
205  cryptonote::keypair in_ephemeral;
206  crypto::public_key tx_pub_key[n_coinbases];
207  crypto::public_key output_pub_key[n_coinbases];
208  for (size_t n = 0; n < n_coinbases; ++n)
209  {
210  tx_pub_key[n] = get_tx_pub_key_from_extra(blocks[n].miner_tx);
211  MDEBUG("tx_pub_key: " << tx_pub_key);
212  output_pub_key[n] = boost::get<txout_to_key>(blocks[n].miner_tx.vout[0].target).key;
213  MDEBUG("output_pub_key: " << output_pub_key);
214  }
215 
216  std::unordered_map<crypto::public_key, cryptonote::subaddress_index> subaddresses;
217  subaddresses[miner_account[0].get_keys().m_account_address.m_spend_public_key] = {0,0};
218 
219 #ifndef NO_MULTISIG
220  // create k/L/R/ki for that output we're going to spend
221  std::vector<std::vector<std::vector<crypto::secret_key>>> account_k(total);
222  std::vector<std::vector<std::vector<crypto::public_key>>> account_L(total);
223  std::vector<std::vector<std::vector<crypto::public_key>>> account_R(total);
224  std::vector<std::vector<std::vector<crypto::key_image>>> account_ki(total);
225  std::vector<crypto::public_key> additional_tx_keys;
226  for (size_t msidx = 0; msidx < total; ++msidx)
227  {
228  CHECK_AND_ASSERT_MES(miner_account[msidx].get_keys().m_account_address.m_spend_public_key == miner_account[0].get_keys().m_account_address.m_spend_public_key,
229  false, "Mismatched spend public keys");
230 
231  size_t nlr = threshold < total ? threshold - 1 : 1;
232  account_k[msidx].resize(inputs);
233  account_L[msidx].resize(inputs);
234  account_R[msidx].resize(inputs);
235  account_ki[msidx].resize(inputs);
236  for (size_t tdidx = 0; tdidx < inputs; ++tdidx)
237  {
238  account_L[msidx][tdidx].resize(nlr);
239  account_R[msidx][tdidx].resize(nlr);
240  for (size_t n = 0; n < nlr; ++n)
241  {
242  account_k[msidx][tdidx].push_back(rct::rct2sk(rct::skGen()));
243  cryptonote::generate_multisig_LR(output_pub_key[tdidx], account_k[msidx][tdidx][n], account_L[msidx][tdidx][n], account_R[msidx][tdidx][n]);
244  }
245  size_t numki = miner_account[msidx].get_multisig_keys().size();
246  account_ki[msidx][tdidx].resize(numki);
247  for (size_t kiidx = 0; kiidx < numki; ++kiidx)
248  {
249  r = cryptonote::generate_multisig_key_image(miner_account[msidx].get_keys(), kiidx, output_pub_key[tdidx], account_ki[msidx][tdidx][kiidx]);
250  CHECK_AND_ASSERT_MES(r, false, "Failed to generate multisig export key image");
251  }
252  MDEBUG("Party " << msidx << ":");
253  MDEBUG("spend: sec " << miner_account[msidx].get_keys().m_spend_secret_key << ", pub " << miner_account[msidx].get_keys().m_account_address.m_spend_public_key);
254  MDEBUG("view: sec " << miner_account[msidx].get_keys().m_view_secret_key << ", pub " << miner_account[msidx].get_keys().m_account_address.m_view_public_key);
255  for (const auto &k: miner_account[msidx].get_multisig_keys())
256  MDEBUG("msk: " << k);
257  for (size_t n = 0; n < account_k[msidx][tdidx].size(); ++n)
258  {
259  MDEBUG("k: " << account_k[msidx][tdidx][n]);
260  MDEBUG("L: " << account_L[msidx][tdidx][n]);
261  MDEBUG("R: " << account_R[msidx][tdidx][n]);
262  }
263  for (const auto &ki: account_ki[msidx][tdidx])
264  MDEBUG("ki: " << ki);
265  }
266  }
267 #endif
268 
269  // create kLRki
270  std::vector<rct::multisig_kLRki> kLRkis;
271  std::unordered_set<crypto::public_key> used_L;
272  for (size_t tdidx = 0; tdidx < inputs; ++tdidx)
273  {
274  kLRkis.push_back(rct::multisig_kLRki());
275  rct::multisig_kLRki &kLRki = kLRkis.back();
276 #ifdef NO_MULTISIG
277  kLRki = {rct::zero(), rct::zero(), rct::zero(), rct::zero()};
278 #else
279  kLRki.k = rct::sk2rct(account_k[creator][tdidx][0]);
280  kLRki.L = rct::pk2rct(account_L[creator][tdidx][0]);
281  kLRki.R = rct::pk2rct(account_R[creator][tdidx][0]);
282  MDEBUG("Starting with k " << kLRki.k);
283  MDEBUG("Starting with L " << kLRki.L);
284  MDEBUG("Starting with R " << kLRki.R);
285  for (size_t msidx = 0; msidx < total; ++msidx)
286  {
287  if (msidx == creator)
288  continue;
289  if (std::find(signers.begin(), signers.end(), msidx) == signers.end())
290  continue;
291  for (size_t lr = 0; lr < account_L[msidx][tdidx].size(); ++lr)
292  {
293  if (used_L.find(account_L[msidx][tdidx][lr]) == used_L.end())
294  {
295  used_L.insert(account_L[msidx][tdidx][lr]);
296  MDEBUG("Adding L " << account_L[msidx][tdidx][lr] << " (for k " << account_k[msidx][tdidx][lr] << ")");
297  MDEBUG("Adding R " << account_R[msidx][tdidx][lr]);
298  rct::addKeys((rct::key&)kLRki.L, kLRki.L, rct::pk2rct(account_L[msidx][tdidx][lr]));
299  rct::addKeys((rct::key&)kLRki.R, kLRki.R, rct::pk2rct(account_R[msidx][tdidx][lr]));
300  break;
301  }
302  }
303  }
304  std::vector<crypto::key_image> pkis;
305  for (size_t msidx = 0; msidx < total; ++msidx)
306  for (size_t n = 0; n < account_ki[msidx][tdidx].size(); ++n)
307  pkis.push_back(account_ki[msidx][tdidx][n]);
308  r = cryptonote::generate_multisig_composite_key_image(miner_account[0].get_keys(), subaddresses, output_pub_key[tdidx], tx_pub_key[tdidx], additional_tx_keys, 0, pkis, (crypto::key_image&)kLRki.ki);
309  CHECK_AND_ASSERT_MES(r, false, "Failed to generate composite key image");
310  MDEBUG("composite ki: " << kLRki.ki);
311  MDEBUG("L: " << kLRki.L);
312  MDEBUG("R: " << kLRki.R);
313  for (size_t n = 1; n < total; ++n)
314  {
315  rct::key ki;
316  r = cryptonote::generate_multisig_composite_key_image(miner_account[n].get_keys(), subaddresses, output_pub_key[tdidx], tx_pub_key[tdidx], additional_tx_keys, 0, pkis, (crypto::key_image&)ki);
317  CHECK_AND_ASSERT_MES(r, false, "Failed to generate composite key image");
318  CHECK_AND_ASSERT_MES(kLRki.ki == ki, false, "Composite key images do not match");
319  }
320  }
321 #endif
322 
323  // create a tx: we have 8 outputs, all from coinbase, so "fake" rct - use 2
324  std::vector<tx_source_entry> sources;
325  for (size_t n = 0; n < inputs; ++n)
326  {
327  sources.resize(sources.size() + 1);
328  tx_source_entry& src = sources.back();
329 
330  src.real_output = n;
331  src.amount = blocks[n].miner_tx.vout[0].amount;
332  src.real_out_tx_key = tx_pub_key[n];
333  src.real_output_in_tx_index = 0;
334  src.mask = rct::identity();
335  src.rct = true;
336  src.multisig_kLRki = kLRkis[n];
337 
338  for (size_t m = 0; m <= mixin; ++m)
339  {
340  rct::ctkey ctkey;
341  ctkey.dest = rct::pk2rct(boost::get<txout_to_key>(blocks[m].miner_tx.vout[0].target).key);
342  MDEBUG("using " << (m == n ? "real" : "fake") << " input " << ctkey.dest);
343  ctkey.mask = rct::commit(blocks[m].miner_tx.vout[0].amount, rct::identity()); // since those are coinbases, the masks are known
344  src.outputs.push_back(std::make_pair(m, ctkey));
345  }
346  }
347 
348  //fill outputs entry
350  td.addr = miner_account[creator].get_keys().m_account_address;
351  td.amount = amount_paid;
352  std::vector<tx_destination_entry> destinations;
353  destinations.push_back(td);
354 
355  if (pre_tx)
356  pre_tx(sources, destinations);
357 
358  transaction tx;
359  crypto::secret_key tx_key;
360 #ifdef NO_MULTISIG
361  rct::multisig_out *msoutp = NULL;
362 #else
363  rct::multisig_out msout;
364  rct::multisig_out *msoutp = &msout;
365 #endif
366  std::vector<crypto::secret_key> additional_tx_secret_keys;
367  auto sources_copy = sources;
368  r = construct_tx_and_get_tx_key(miner_account[creator].get_keys(), subaddresses, sources, destinations, boost::none, std::vector<uint8_t>(), tx, 0, tx_key, additional_tx_secret_keys, true, { rct::RangeProofBorromean, 0 }, msoutp);
369  CHECK_AND_ASSERT_MES(r, false, "failed to construct transaction");
370 
371 #ifndef NO_MULTISIG
372  // work out the permutation done on sources
373  std::vector<size_t> ins_order;
374  for (size_t n = 0; n < sources.size(); ++n)
375  {
376  for (size_t idx = 0; idx < sources_copy.size(); ++idx)
377  {
378  CHECK_AND_ASSERT_MES((size_t)sources_copy[idx].real_output < sources_copy[idx].outputs.size(),
379  false, "Invalid real_output");
380  if (sources_copy[idx].outputs[sources_copy[idx].real_output].second.dest == sources[n].outputs[sources[n].real_output].second.dest)
381  ins_order.push_back(idx);
382  }
383  }
384  CHECK_AND_ASSERT_MES(ins_order.size() == sources.size(), false, "Failed to work out sources permutation");
385 #endif
386 
387 #ifndef NO_MULTISIG
388  // sign
389  std::unordered_set<crypto::secret_key> used_keys;
390  const std::vector<crypto::secret_key> &msk0 = miner_account[creator].get_multisig_keys();
391  for (const auto &sk: msk0)
392  used_keys.insert(sk);
393  for (size_t signer: signers)
394  {
395  rct::key skey = rct::zero();
396  const std::vector<crypto::secret_key> &msk1 = miner_account[signer].get_multisig_keys();
397  for (size_t n = 0; n < msk1.size(); ++n)
398  {
399  const crypto::secret_key &sk1 = msk1[n];
400  if (used_keys.find(sk1) == used_keys.end())
401  {
402  used_keys.insert(sk1);
403  sc_add(skey.bytes, skey.bytes, rct::sk2rct(sk1).bytes);
404  }
405  }
406  CHECK_AND_ASSERT_MES(!(skey == rct::zero()), false, "failed to find secret multisig key to sign transaction");
407  std::vector<unsigned int> indices;
408  for (const auto &src: sources_copy)
409  indices.push_back(src.real_output);
410  rct::keyV k;
411  for (size_t tdidx = 0; tdidx < inputs; ++tdidx)
412  {
413  k.push_back(rct::zero());
414  for (size_t n = 0; n < account_k[signer][tdidx].size(); ++n)
415  {
417  rct::scalarmultBase((rct::key&)L, rct::sk2rct(account_k[signer][tdidx][n]));
418  if (used_L.find(L) != used_L.end())
419  {
420  sc_add(k.back().bytes, k.back().bytes, rct::sk2rct(account_k[signer][tdidx][n]).bytes);
421  }
422  }
423  CHECK_AND_ASSERT_MES(!(k.back() == rct::zero()), false, "failed to find k to sign transaction");
424  }
425  tools::apply_permutation(ins_order, indices);
426  tools::apply_permutation(ins_order, k);
427 
428  MDEBUG("signing with k size " << k.size());
429  MDEBUG("signing with k " << k.back());
430  MDEBUG("signing with sk " << skey);
431  for (const auto &sk: used_keys)
432  MDEBUG(" created with sk " << sk);
433  MDEBUG("signing with c size " << msout.c.size());
434  MDEBUG("signing with c " << msout.c.back());
435  r = rct::signMultisig(tx.rct_signatures, indices, k, msout, skey);
436  CHECK_AND_ASSERT_MES(r, false, "failed to sign transaction");
437  }
438 #endif
439 
440  // verify this tx is really to the expected address
441  const crypto::public_key tx_pub_key2 = get_tx_pub_key_from_extra(tx, 0);
442  crypto::key_derivation derivation;
443  r = crypto::generate_key_derivation(tx_pub_key2, miner_account[creator].get_keys().m_view_secret_key, derivation);
444  CHECK_AND_ASSERT_MES(r, false, "Failed to generate derivation");
445  uint64_t n_outs = 0, amount = 0;
446  std::vector<crypto::key_derivation> additional_derivations;
447  for (size_t n = 0; n < tx.vout.size(); ++n)
448  {
449  CHECK_AND_ASSERT_MES(typeid(txout_to_key) == tx.vout[n].target.type(), false, "Unexpected tx out type");
450  if (is_out_to_acc_precomp(subaddresses, boost::get<txout_to_key>(tx.vout[n].target).key, derivation, additional_derivations, n, hw::get_device(("default"))))
451  {
452  ++n_outs;
453  CHECK_AND_ASSERT_MES(tx.vout[n].amount == 0, false, "Destination amount is not zero");
454  rct::key Ctmp;
455  crypto::secret_key scalar1;
456  crypto::derivation_to_scalar(derivation, n, scalar1);
457  rct::ecdhTuple ecdh_info = tx.rct_signatures.ecdhInfo[n];
458  rct::ecdhDecode(ecdh_info, rct::sk2rct(scalar1), tx.rct_signatures.type == rct::RCTTypeBulletproof2);
459  rct::key C = tx.rct_signatures.outPk[n].mask;
460  rct::addKeys2(Ctmp, ecdh_info.mask, ecdh_info.amount, rct::H);
461  CHECK_AND_ASSERT_MES(rct::equalKeys(C, Ctmp), false, "Failed to decode amount");
462  amount += rct::h2d(ecdh_info.amount);
463  }
464  }
465  CHECK_AND_ASSERT_MES(n_outs == 1, false, "Not exactly 1 output was received");
466  CHECK_AND_ASSERT_MES(amount == amount_paid, false, "Amount paid was not the expected amount");
467 
468  if (post_tx)
469  post_tx(tx);
470 
471  if (!valid)
472  DO_CALLBACK(events, "mark_invalid_tx");
473  events.push_back(tx);
474  LOG_PRINT_L0("Test tx: " << obj_to_json_str(tx));
475 
476  return true;
477 }
478 
479 bool gen_multisig_tx_valid_22_1_2::generate(std::vector<test_event_entry>& events) const
480 {
481  const size_t mixin = 4;
482  const uint64_t amount_paid = 10000;
483  return generate_with(events, 2, mixin, amount_paid, true, 2, 2, 1, {2}, NULL, NULL);
484 }
485 
486 bool gen_multisig_tx_valid_22_1_2_many_inputs::generate(std::vector<test_event_entry>& events) const
487 {
488  const size_t mixin = 4;
489  const uint64_t amount_paid = 10000;
490  return generate_with(events, 4, mixin, amount_paid, true, 2, 2, 1, {2}, NULL, NULL);
491 }
492 
493 bool gen_multisig_tx_valid_22_2_1::generate(std::vector<test_event_entry>& events) const
494 {
495  const size_t mixin = 4;
496  const uint64_t amount_paid = 10000;
497  return generate_with(events, 2, mixin, amount_paid, true, 2, 2, 2, {1}, NULL, NULL);
498 }
499 
500 bool gen_multisig_tx_valid_33_1_23::generate(std::vector<test_event_entry>& events) const
501 {
502  const size_t mixin = 4;
503  const uint64_t amount_paid = 10000;
504  return generate_with(events, 2, mixin, amount_paid, true, 3, 3, 1, {2, 3}, NULL, NULL);
505 }
506 
507 bool gen_multisig_tx_valid_33_3_21::generate(std::vector<test_event_entry>& events) const
508 {
509  const size_t mixin = 4;
510  const uint64_t amount_paid = 10000;
511  return generate_with(events, 2, mixin, amount_paid, true, 3, 3, 3, {2, 1}, NULL, NULL);
512 }
513 
514 bool gen_multisig_tx_valid_23_1_2::generate(std::vector<test_event_entry>& events) const
515 {
516  const size_t mixin = 4;
517  const uint64_t amount_paid = 10000;
518  return generate_with(events, 2, mixin, amount_paid, true, 2, 3, 1, {2}, NULL, NULL);
519 }
520 
521 bool gen_multisig_tx_valid_23_1_3::generate(std::vector<test_event_entry>& events) const
522 {
523  const size_t mixin = 4;
524  const uint64_t amount_paid = 10000;
525  return generate_with(events, 2, mixin, amount_paid, true, 2, 3, 1, {3}, NULL, NULL);
526 }
527 
528 bool gen_multisig_tx_valid_23_2_1::generate(std::vector<test_event_entry>& events) const
529 {
530  const size_t mixin = 4;
531  const uint64_t amount_paid = 10000;
532  return generate_with(events, 2, mixin, amount_paid, true, 2, 3, 2, {1}, NULL, NULL);
533 }
534 
535 bool gen_multisig_tx_valid_23_2_3::generate(std::vector<test_event_entry>& events) const
536 {
537  const size_t mixin = 4;
538  const uint64_t amount_paid = 10000;
539  return generate_with(events, 2, mixin, amount_paid, true, 2, 3, 2, {3}, NULL, NULL);
540 }
541 
542 bool gen_multisig_tx_valid_45_1_234::generate(std::vector<test_event_entry>& events) const
543 {
544  const size_t mixin = 4;
545  const uint64_t amount_paid = 10000;
546  return generate_with(events, 2, mixin, amount_paid, true, 4, 5, 1, {2, 3, 4}, NULL, NULL);
547 }
548 
549 bool gen_multisig_tx_valid_45_4_135_many_inputs::generate(std::vector<test_event_entry>& events) const
550 {
551  const size_t mixin = 4;
552  const uint64_t amount_paid = 10000;
553  return generate_with(events, 4, mixin, amount_paid, true, 4, 5, 4, {1, 3, 5}, NULL, NULL);
554 }
555 
556 bool gen_multisig_tx_valid_89_3_1245789::generate(std::vector<test_event_entry>& events) const
557 {
558  const size_t mixin = 4;
559  const uint64_t amount_paid = 10000;
560  return generate_with(events, 2, mixin, amount_paid, true, 8, 9, 3, {1, 2, 4, 5, 7, 8, 9}, NULL, NULL);
561 }
562 
563 bool gen_multisig_tx_valid_24_1_2::generate(std::vector<test_event_entry>& events) const
564 {
565  const size_t mixin = 4;
566  const uint64_t amount_paid = 10000;
567  return generate_with(events, 2, mixin, amount_paid, true, 2, 4, 1, {2}, NULL, NULL);
568 }
569 
570 bool gen_multisig_tx_valid_24_1_2_many_inputs::generate(std::vector<test_event_entry>& events) const
571 {
572  const size_t mixin = 4;
573  const uint64_t amount_paid = 10000;
574  return generate_with(events, 4, mixin, amount_paid, true, 2, 4, 1, {2}, NULL, NULL);
575 }
576 
577 bool gen_multisig_tx_valid_25_1_2::generate(std::vector<test_event_entry>& events) const
578 {
579  const size_t mixin = 4;
580  const uint64_t amount_paid = 10000;
581  return generate_with(events, 2, mixin, amount_paid, true, 2, 5, 1, {2}, NULL, NULL);
582 }
583 
584 bool gen_multisig_tx_valid_25_1_2_many_inputs::generate(std::vector<test_event_entry>& events) const
585 {
586  const size_t mixin = 4;
587  const uint64_t amount_paid = 10000;
588  return generate_with(events, 4, mixin, amount_paid, true, 2, 5, 1, {2}, NULL, NULL);
589 }
590 
591 bool gen_multisig_tx_valid_48_1_234::generate(std::vector<test_event_entry>& events) const
592 {
593  const size_t mixin = 4;
594  const uint64_t amount_paid = 10000;
595  return generate_with(events, 2, mixin, amount_paid, true, 4, 8, 1, {2, 3, 4}, NULL, NULL);
596 }
597 
598 bool gen_multisig_tx_valid_48_1_234_many_inputs::generate(std::vector<test_event_entry>& events) const
599 {
600  const size_t mixin = 4;
601  const uint64_t amount_paid = 10000;
602  return generate_with(events, 4, mixin, amount_paid, true, 4, 8, 1, {2, 3, 4}, NULL, NULL);
603 }
604 
605 bool gen_multisig_tx_invalid_22_1__no_threshold::generate(std::vector<test_event_entry>& events) const
606 {
607  const size_t mixin = 4;
608  const uint64_t amount_paid = 10000;
609  return generate_with(events, 2, mixin, amount_paid, false, 2, 2, 1, {}, NULL, NULL);
610 }
611 
612 bool gen_multisig_tx_invalid_33_1__no_threshold::generate(std::vector<test_event_entry>& events) const
613 {
614  const size_t mixin = 4;
615  const uint64_t amount_paid = 10000;
616  return generate_with(events, 2, mixin, amount_paid, false, 3, 3, 1, {}, NULL, NULL);
617 }
618 
619 bool gen_multisig_tx_invalid_33_1_2_no_threshold::generate(std::vector<test_event_entry>& events) const
620 {
621  const size_t mixin = 4;
622  const uint64_t amount_paid = 10000;
623  return generate_with(events, 2, mixin, amount_paid, false, 3, 3, 1, {2}, NULL, NULL);
624 }
625 
626 bool gen_multisig_tx_invalid_33_1_3_no_threshold::generate(std::vector<test_event_entry>& events) const
627 {
628  const size_t mixin = 4;
629  const uint64_t amount_paid = 10000;
630  return generate_with(events, 2, mixin, amount_paid, false, 3, 3, 1, {3}, NULL, NULL);
631 }
632 
633 bool gen_multisig_tx_invalid_23_1__no_threshold::generate(std::vector<test_event_entry>& events) const
634 {
635  const size_t mixin = 4;
636  const uint64_t amount_paid = 10000;
637  return generate_with(events, 2, mixin, amount_paid, false, 2, 3, 1, {}, NULL, NULL);
638 }
639 
640 bool gen_multisig_tx_invalid_45_5_23_no_threshold::generate(std::vector<test_event_entry>& events) const
641 {
642  const size_t mixin = 4;
643  const uint64_t amount_paid = 10000;
644  return generate_with(events, 2, mixin, amount_paid, false, 4, 5, 5, {2, 3}, NULL, NULL);
645 }
646 
647 bool gen_multisig_tx_invalid_24_1_no_signers::generate(std::vector<test_event_entry>& events) const
648 {
649  const size_t mixin = 4;
650  const uint64_t amount_paid = 10000;
651  return generate_with(events, 2, mixin, amount_paid, false, 2, 4, 1, {}, NULL, NULL);
652 }
653 
654 bool gen_multisig_tx_invalid_25_1_no_signers::generate(std::vector<test_event_entry>& events) const
655 {
656  const size_t mixin = 4;
657  const uint64_t amount_paid = 10000;
658  return generate_with(events, 2, mixin, amount_paid, false, 2, 5, 1, {}, NULL, NULL);
659 }
660 
661 bool gen_multisig_tx_invalid_48_1_no_signers::generate(std::vector<test_event_entry>& events) const
662 {
663  const size_t mixin = 4;
664  const uint64_t amount_paid = 10000;
665  return generate_with(events, 2, mixin, amount_paid, false, 4, 8, 1, {}, NULL, NULL);
666 }
667 
668 bool gen_multisig_tx_invalid_48_1_23_no_threshold::generate(std::vector<test_event_entry>& events) const
669 {
670  const size_t mixin = 4;
671  const uint64_t amount_paid = 10000;
672  return generate_with(events, 2, mixin, amount_paid, false, 4, 8, 1, {2, 3}, NULL, NULL);
673 }
void generate_multisig_LR(const crypto::public_key pkey, const crypto::secret_key &k, crypto::public_key &L, crypto::public_key &R)
Definition: multisig.cpp:150
bool generate(std::vector< test_event_entry > &events) const
Definition: multisig.cpp:521
#define CRYPTONOTE_MINED_ETN_UNLOCK_WINDOW
bool generate(std::vector< test_event_entry > &events) const
Definition: multisig.cpp:605
void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res)
Definition: crypto.h:279
bool generate(std::vector< test_event_entry > &events) const
Definition: multisig.cpp:626
bool generate(std::vector< test_event_entry > &events) const
Definition: multisig.cpp:542
bool generate(std::vector< test_event_entry > &events) const
Definition: multisig.cpp:493
crypto::public_key real_out_tx_key
etn_amount h2d(const key &test)
Definition: rctTypes.cpp:161
bool generate(std::vector< test_event_entry > &events) const
Definition: multisig.cpp:668
void apply_permutation(std::vector< size_t > permutation, const F &swap)
bool generate(std::vector< test_event_entry > &events) const
Definition: multisig.cpp:612
POD_CLASS key_derivation
Definition: crypto.h:98
bool generate(std::vector< test_event_entry > &events) const
Definition: multisig.cpp:563
key commit(etn_amount amount, const key &mask)
Definition: rctOps.cpp:336
bool generate(std::vector< test_event_entry > &events) const
Definition: multisig.cpp:556
#define CHECK_AND_ASSERT_MES(expr, fail_ret_val, message)
Definition: misc_log_ex.h:181
bool generate(std::vector< test_event_entry > &events) const
Definition: multisig.cpp:577
bool generate(std::vector< test_event_entry > &events) const
Definition: multisig.cpp:528
bool generate(std::vector< test_event_entry > &events) const
Definition: multisig.cpp:619
bool generate(std::vector< test_event_entry > &events) const
Definition: multisig.cpp:500
bool generate(std::vector< test_event_entry > &events) const
Definition: multisig.cpp:570
bool generate(std::vector< test_event_entry > &events) const
Definition: multisig.cpp:640
std::vector< crypto::public_key > generate_multisig_derivations(const account_keys &keys, const std::vector< crypto::public_key > &derivations)
generate_multisig_derivations performs common DH key derivation. Each middle round in M/N scheme is D...
Definition: multisig.cpp:87
const char * key
Definition: hmac_keccak.cpp:39
#define LOG_PRINT_L0(x)
Definition: misc_log_ex.h:99
crypto namespace.
Definition: crypto.cpp:58
bool generate(std::vector< test_event_entry > &events) const
Definition: multisig.cpp:584
bool rct
bool generate_with(std::vector< test_event_entry > &events, size_t inputs, size_t mixin, uint64_t amount_paid, bool valid, size_t threshold, size_t total, size_t creator, std::vector< size_t > signers, const std::function< void(std::vector< cryptonote::tx_source_entry > &sources, std::vector< cryptonote::tx_destination_entry > &destinations)> &pre_tx, const std::function< void(cryptonote::transaction &tx)> &post_tx) const
Definition: multisig.cpp:128
crypto::secret_key generate(const crypto::secret_key &recovery_key=crypto::secret_key(), bool recover=false, bool two_random=false)
Definition: account.cpp:158
bool generate(std::vector< test_event_entry > &events) const
Definition: multisig.cpp:661
uint64_t amount
key dest
Definition: rctTypes.h:97
uint8_t type
Definition: rctTypes.h:241
bool generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation)
Definition: crypto.h:272
size_t real_output
std::vector< key > keyV
Definition: rctTypes.h:88
#define MDEBUG(x)
Definition: misc_log_ex.h:76
const account_keys & get_keys() const
Definition: account.cpp:264
std::vector< ecdhTuple > ecdhInfo
Definition: rctTypes.h:246
void generate_multisig_N_N(const account_keys &keys, const std::vector< crypto::public_key > &spend_keys, std::vector< crypto::secret_key > &multisig_keys, rct::key &spend_skey, rct::key &spend_pkey)
Definition: multisig.cpp:58
Holds cryptonote related classes and helpers.
Definition: ban.cpp:40
crypto::public_key generate_multisig_M_N_spend_public_key(const std::vector< crypto::public_key > &pkeys)
generate_multisig_M_N_spend_public_key calculates multisig wallet&#39;s spend public key by summing all o...
Definition: multisig.cpp:132
boost::optional< subaddress_receive_info > is_out_to_acc_precomp(const std::unordered_map< crypto::public_key, subaddress_index > &subaddresses, const crypto::public_key &out_key, const crypto::key_derivation &derivation, const std::vector< crypto::key_derivation > &additional_derivations, size_t output_index, hw::device &hwdev)
bool generate(std::vector< test_event_entry > &events) const
Definition: multisig.cpp:647
std::vector< crypto::secret_key > calculate_multisig_keys(const std::vector< crypto::public_key > &derivations)
calculate_multisig_keys. Calculates secret multisig keys from others&#39; participants ones as follows: m...
Definition: multisig.cpp:111
#define GENERATE_MULTISIG_ACCOUNT(account, threshold, total)
Definition: chaingen.h:805
bool generate_multisig_key_image(const account_keys &keys, size_t multisig_key_index, const crypto::public_key &out_key, crypto::key_image &ki)
Definition: multisig.cpp:142
unsigned int uint32_t
Definition: stdint.h:126
bool generate(std::vector< test_event_entry > &events) const
Definition: multisig.cpp:654
bool generate(std::vector< test_event_entry > &events) const
Definition: multisig.cpp:549
device & get_device(const std::string &device_descriptor)
Definition: device.cpp:95
#define MAKE_GENESIS_BLOCK(VEC_EVENTS, BLK_NAME, MINER_ACC, TS)
Definition: chaingen.h:833
std::string obj_to_json_str(T &obj)
unsigned __int64 uint64_t
Definition: stdint.h:136
bool generate(std::vector< test_event_entry > &events) const
Definition: multisig.cpp:514
crypto::public_key get_tx_pub_key_from_extra(const std::vector< uint8_t > &tx_extra, size_t pk_index)
uint64_t amount
crypto::secret_key get_multisig_blinded_secret_key(const crypto::secret_key &key)
Definition: multisig.cpp:47
bool generate_multisig_composite_key_image(const account_keys &keys, const std::unordered_map< crypto::public_key, subaddress_index > &subaddresses, const crypto::public_key &out_key, const crypto::public_key &tx_public_key, const std::vector< crypto::public_key > &additional_tx_public_keys, size_t real_output_index, const std::vector< crypto::key_image > &pkis, crypto::key_image &ki)
Definition: multisig.cpp:156
bool signMultisig(rctSig &rv, const std::vector< unsigned int > &indices, const keyV &k, const multisig_out &msout, const key &secret_key)
Definition: rctSigs.cpp:1210
bool generate(std::vector< test_event_entry > &events) const
Definition: multisig.cpp:479
POD_CLASS public_key
Definition: crypto.h:76
void skGen(key &sk)
Definition: rctOps.cpp:253
rct::multisig_kLRki multisig_kLRki
void ecdhDecode(ecdhTuple &masked, const key &sharedSec, bool v2)
Definition: rctOps.cpp:712
account_public_address addr
std::vector< key > c
Definition: rctTypes.h:112
void scalarmultBase(key &aG, const key &a)
Definition: rctOps.cpp:350
bool generate(std::vector< test_event_entry > &events) const
Definition: multisig.cpp:591
account_public_address m_account_address
Definition: account.h:43
bool generate(std::vector< test_event_entry > &events) const
Definition: multisig.cpp:535
unsigned char bytes[32]
Definition: rctTypes.h:86
key identity()
Definition: rctOps.h:73
bool generate(std::vector< test_event_entry > &events) const
Definition: multisig.cpp:633
void make_multisig_accounts(std::vector< cryptonote::account_base > &account, uint32_t threshold)
Definition: multisig.cpp:44
POD_CLASS key_image
Definition: crypto.h:102
crypto::secret_key generate_multisig_view_secret_key(const crypto::secret_key &skey, const std::vector< crypto::secret_key > &skeys)
Definition: multisig.cpp:124
size_t real_output_in_tx_index
ctkeyV outPk
Definition: rctTypes.h:247
void addKeys2(key &aGbB, const key &a, const key &b, const key &B)
Definition: rctOps.cpp:466
bool generate(std::vector< test_event_entry > &events) const
Definition: multisig.cpp:598
key mask
Definition: rctTypes.h:98
bool generate(std::vector< test_event_entry > &events) const
Definition: multisig.cpp:486
std::vector< output_entry > outputs
POD_CLASS hash
Definition: hash.h:50
void addKeys(key &AB, const key &A, const key &B)
Definition: rctOps.cpp:420
bool secret_key_to_public_key(const secret_key &sec, public_key &pub)
Definition: crypto.h:262
#define DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN
#define GENERATE_ACCOUNT(account)
Definition: chaingen.h:801
void sc_add(unsigned char *, const unsigned char *, const unsigned char *)
bool construct_tx_and_get_tx_key(const account_keys &sender_account_keys, const std::unordered_map< crypto::public_key, subaddress_index > &subaddresses, std::vector< tx_source_entry > &sources, std::vector< tx_destination_entry > &destinations, const boost::optional< cryptonote::account_public_address > &change_addr, const std::vector< uint8_t > &extra, transaction &tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector< crypto::secret_key > &additional_tx_keys, bool rct, const rct::RCTConfig &rct_config, rct::multisig_out *msout, const uint32_t account_major_offset, const cryptonote::network_type nettype)
bool equalKeys(const key &a, const key &b)
Definition: rctOps.cpp:519
bool generate(std::vector< test_event_entry > &events) const
Definition: multisig.cpp:507
key zero()
Definition: rctOps.h:70
#define DO_CALLBACK(VEC_EVENTS, CB_NAME)
Definition: chaingen.h:820
crypto::secret_key calculate_multisig_signer_key(const std::vector< crypto::secret_key > &multisig_keys)
Definition: multisig.cpp:100
rct::key mask
uint8_t threshold
Definition: blockchain.cpp:92