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 <unordered_set>
30 #include "include_base_utils.h"
31 #include "crypto/crypto.h"
32 #include "ringct/rctOps.h"
35 #include "multisig.h"
36 
37 #undef ELECTRONEUM_DEFAULT_LOG_CATEGORY
38 #define ELECTRONEUM_DEFAULT_LOG_CATEGORY "multisig"
39 
40 using namespace std;
41 
42 static const rct::key multisig_salt = { {'M', 'u', 'l', 't' , 'i', 's', 'i', 'g', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } };
43 
44 namespace cryptonote
45 {
46  //-----------------------------------------------------------------
48  {
49  rct::keyV data;
50  data.reserve(2);
51  data.push_back(rct::sk2rct(key));
52  data.push_back(multisig_salt);
53  crypto::secret_key result = rct::rct2sk(rct::hash_to_scalar(data));
54  memwipe(&data[0], sizeof(rct::key));
55  return result;
56  }
57  //-----------------------------------------------------------------
58  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)
59  {
60  // the multisig spend public key is the sum of all spend public keys
61  multisig_keys.clear();
63  CHECK_AND_ASSERT_THROW_MES(crypto::secret_key_to_public_key(spend_secret_key, (crypto::public_key&)spend_pkey), "Failed to derive public key");
64  for (const auto &k: spend_keys)
65  rct::addKeys(spend_pkey, spend_pkey, rct::pk2rct(k));
66  multisig_keys.push_back(spend_secret_key);
67  spend_skey = rct::sk2rct(spend_secret_key);
68  }
69  //-----------------------------------------------------------------
70  void generate_multisig_N1_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)
71  {
72  multisig_keys.clear();
73  spend_pkey = rct::identity();
74  spend_skey = rct::zero();
75 
76  // create all our composite private keys
78  for (const auto &k: spend_keys)
79  {
80  rct::key sk = rct::scalarmultKey(rct::pk2rct(k), rct::sk2rct(blinded_skey));
82  multisig_keys.push_back(msk);
83  sc_add(spend_skey.bytes, spend_skey.bytes, (const unsigned char*)msk.data);
84  }
85  }
86  //-----------------------------------------------------------------
87  std::vector<crypto::public_key> generate_multisig_derivations(const account_keys &keys, const std::vector<crypto::public_key> &derivations)
88  {
89  std::vector<crypto::public_key> multisig_keys;
91  for (const auto &k: derivations)
92  {
93  rct::key d = rct::scalarmultKey(rct::pk2rct(k), rct::sk2rct(blinded_skey));
94  multisig_keys.push_back(rct::rct2pk(d));
95  }
96 
97  return multisig_keys;
98  }
99  //-----------------------------------------------------------------
100  crypto::secret_key calculate_multisig_signer_key(const std::vector<crypto::secret_key>& multisig_keys)
101  {
103  for (const auto &k: multisig_keys)
104  {
105  sc_add(secret_key.bytes, secret_key.bytes, (const unsigned char*)k.data);
106  }
107 
108  return rct::rct2sk(secret_key);
109  }
110  //-----------------------------------------------------------------
111  std::vector<crypto::secret_key> calculate_multisig_keys(const std::vector<crypto::public_key>& derivations)
112  {
113  std::vector<crypto::secret_key> multisig_keys;
114  multisig_keys.reserve(derivations.size());
115 
116  for (const auto &k: derivations)
117  {
118  multisig_keys.emplace_back(get_multisig_blinded_secret_key(rct::rct2sk(rct::pk2rct(k))));
119  }
120 
121  return multisig_keys;
122  }
123  //-----------------------------------------------------------------
124  crypto::secret_key generate_multisig_view_secret_key(const crypto::secret_key &skey, const std::vector<crypto::secret_key> &skeys)
125  {
126  rct::key view_skey = rct::sk2rct(get_multisig_blinded_secret_key(skey));
127  for (const auto &k: skeys)
128  sc_add(view_skey.bytes, view_skey.bytes, rct::sk2rct(k).bytes);
129  return rct::rct2sk(view_skey);
130  }
131  //-----------------------------------------------------------------
132  crypto::public_key generate_multisig_M_N_spend_public_key(const std::vector<crypto::public_key> &pkeys)
133  {
134  rct::key spend_public_key = rct::identity();
135  for (const auto &pk: pkeys)
136  {
137  rct::addKeys(spend_public_key, spend_public_key, rct::pk2rct(pk));
138  }
139  return rct::rct2pk(spend_public_key);
140  }
141  //-----------------------------------------------------------------
142  bool generate_multisig_key_image(const account_keys &keys, size_t multisig_key_index, const crypto::public_key& out_key, crypto::key_image& ki)
143  {
144  if (multisig_key_index >= keys.m_multisig_keys.size())
145  return false;
146  crypto::generate_key_image(out_key, keys.m_multisig_keys[multisig_key_index], ki);
147  return true;
148  }
149  //-----------------------------------------------------------------
151  {
152  rct::scalarmultBase((rct::key&)L, rct::sk2rct(k));
154  }
155  //-----------------------------------------------------------------
156  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)
157  {
158  cryptonote::keypair in_ephemeral;
159  if (!cryptonote::generate_key_image_helper(keys, subaddresses, out_key, tx_public_key, additional_tx_public_keys, real_output_index, in_ephemeral, ki, keys.get_device()))
160  return false;
161  std::unordered_set<crypto::key_image> used;
162  for (size_t m = 0; m < keys.m_multisig_keys.size(); ++m)
163  {
164  crypto::key_image pki;
165  bool r = cryptonote::generate_multisig_key_image(keys, m, out_key, pki);
166  if (!r)
167  return false;
168  used.insert(pki);
169  }
170  for (const auto &pki: pkis)
171  {
172  if (used.find(pki) == used.end())
173  {
174  used.insert(pki);
175  rct::addKeys((rct::key&)ki, rct::ki2rct(ki), rct::ki2rct(pki));
176  }
177  }
178  return true;
179  }
180  //-----------------------------------------------------------------
182  {
183  CHECK_AND_ASSERT_THROW_MES(participants >= threshold, "participants must be greater or equal than threshold");
184  return participants - threshold + 1;
185  }
186 }
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
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
Definition: misc_log_ex.h:173
void generate_multisig_N1_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:70
void scalarmultKey(key &aP, const key &P, const key &a)
Definition: rctOps.cpp:368
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
epee::mlocked< tools::scrubbed< ec_scalar > > secret_key
Definition: crypto.h:82
STL namespace.
std::vector< key > keyV
Definition: rctTypes.h:88
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
uint32_t multisig_rounds_required(uint32_t participants, uint32_t threshold)
Definition: multisig.cpp:181
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
void generate_key_image(const public_key &pub, const secret_key &sec, key_image &image)
Definition: crypto.h:324
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_key_image_helper(const account_keys &ack, 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, keypair &in_ephemeral, crypto::key_image &ki, hw::device &hwdev, const uint32_t account_major_offset)
crypto::secret_key get_multisig_blinded_secret_key(const crypto::secret_key &key)
Definition: multisig.cpp:47
void hash_to_scalar(key &hash, const void *data, const std::size_t l)
Definition: rctOps.cpp:536
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
POD_CLASS public_key
Definition: crypto.h:76
void scalarmultBase(key &aG, const key &a)
Definition: rctOps.cpp:350
unsigned char bytes[32]
Definition: rctTypes.h:86
key identity()
Definition: rctOps.h:73
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
crypto::secret_key m_spend_secret_key
Definition: account.h:44
std::vector< crypto::secret_key > m_multisig_keys
Definition: account.h:46
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
void * memwipe(void *src, size_t n)
void sc_add(unsigned char *, const unsigned char *, const unsigned char *)
key zero()
Definition: rctOps.h:70
hw::device & get_device() const
Definition: account.cpp:59
crypto::secret_key calculate_multisig_signer_key(const std::vector< crypto::secret_key > &multisig_keys)
Definition: multisig.cpp:100
uint8_t threshold
Definition: blockchain.cpp:92