Electroneum
Loading...
Searching...
No Matches
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
40using namespace std;
41
42static 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
44namespace 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 {
102 rct::key secret_key = rct::zero();
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 //-----------------------------------------------------------------
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 {
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}
uint8_t threshold
void sc_add(unsigned char *, const unsigned char *, const unsigned char *)
const char * key
void * memwipe(void *src, size_t n)
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
epee::mlocked< tools::scrubbed< ec_scalar > > secret_key
Definition crypto.h:82
POD_CLASS public_key
Definition crypto.h:79
POD_CLASS key_image
Definition crypto.h:105
bool secret_key_to_public_key(const secret_key &sec, public_key &pub)
Definition crypto.h:262
void generate_key_image(const public_key &pub, const secret_key &sec, key_image &image)
Definition crypto.h:324
Holds cryptonote related classes and helpers.
Definition ban.cpp:40
crypto::secret_key calculate_multisig_signer_key(const std::vector< crypto::secret_key > &multisig_keys)
Definition multisig.cpp:100
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's spend public key by summing all o...
Definition multisig.cpp:132
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)
uint32_t multisig_rounds_required(uint32_t participants, uint32_t threshold)
Definition multisig.cpp:181
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 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
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 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
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
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
std::vector< crypto::secret_key > calculate_multisig_keys(const std::vector< crypto::public_key > &derivations)
calculate_multisig_keys. Calculates secret multisig keys from others' participants ones as follows: m...
Definition multisig.cpp:111
crypto::secret_key generate_multisig_view_secret_key(const crypto::secret_key &skey, const std::vector< crypto::secret_key > &skeys)
Definition multisig.cpp:124
void scalarmultBase(key &aG, const key &a)
Definition rctOps.cpp:350
void hash_to_scalar(key &hash, const void *data, const std::size_t l)
Definition rctOps.cpp:536
std::vector< key > keyV
Definition rctTypes.h:88
void scalarmultKey(key &aP, const key &P, const key &a)
Definition rctOps.cpp:368
void addKeys(key &AB, const key &A, const key &B)
Definition rctOps.cpp:420
key zero()
Definition rctOps.h:70
key identity()
Definition rctOps.h:73
STL namespace.
unsigned int uint32_t
Definition stdint.h:126
hw::device & get_device() const
Definition account.cpp:59
crypto::secret_key m_spend_secret_key
Definition account.h:44
std::vector< crypto::secret_key > m_multisig_keys
Definition account.h:46
unsigned char bytes[32]
Definition rctTypes.h:86