diff options
Diffstat (limited to 'src')
41 files changed, 710 insertions, 778 deletions
diff --git a/src/crypto/CMakeLists.txt b/src/crypto/CMakeLists.txt index 35c099697..71dcedcab 100644 --- a/src/crypto/CMakeLists.txt +++ b/src/crypto/CMakeLists.txt @@ -33,7 +33,6 @@ set(crypto_sources crypto-ops-data.c crypto-ops.c crypto.cpp - crypto_device.cpp groestl.c hash-extra-blake.c hash-extra-groestl.c @@ -78,7 +77,6 @@ monero_add_library(cncrypto target_link_libraries(cncrypto PUBLIC epee - device ${Boost_SYSTEM_LIBRARY} PRIVATE ${EXTRA_LIBRARIES}) diff --git a/src/crypto/chacha.h b/src/crypto/chacha.h index 22da53bd0..7a120931a 100644 --- a/src/crypto/chacha.h +++ b/src/crypto/chacha.h @@ -69,10 +69,17 @@ namespace crypto { chacha20(data, length, key.data(), reinterpret_cast<const uint8_t*>(&iv), cipher); } - inline void generate_chacha_key(const void *data, size_t size, chacha_key& key, int cn_variant = 0, bool prehashed=false) { + inline void generate_chacha_key(const void *data, size_t size, chacha_key& key) { static_assert(sizeof(chacha_key) <= sizeof(hash), "Size of hash must be at least that of chacha_key"); tools::scrubbed_arr<char, HASH_SIZE> pwd_hash; - crypto::cn_slow_hash_pre(data, size, pwd_hash.data(), cn_variant, prehashed); + crypto::cn_slow_hash(data, size, pwd_hash.data(), 0/*variant*/, 0/*prehashed*/); + memcpy(&key, pwd_hash.data(), sizeof(key)); + } + + inline void generate_chacha_key_prehashed(const void *data, size_t size, chacha_key& key) { + static_assert(sizeof(chacha_key) <= sizeof(hash), "Size of hash must be at least that of chacha_key"); + tools::scrubbed_arr<char, HASH_SIZE> pwd_hash; + crypto::cn_slow_hash(data, size, pwd_hash.data(), 0/*variant*/, 1/*prehashed*/); memcpy(&key, pwd_hash.data(), sizeof(key)); } diff --git a/src/crypto/crypto.cpp b/src/crypto/crypto.cpp index 0c70b9eeb..494027560 100644 --- a/src/crypto/crypto.cpp +++ b/src/crypto/crypto.cpp @@ -436,7 +436,7 @@ namespace crypto { return sc_isnonzero(&c2) == 0; } - void crypto_ops::hash_to_ec(const public_key &key, ge_p3 &res) { + static void hash_to_ec(const public_key &key, ge_p3 &res) { hash h; ge_p2 point; ge_p1p1 point2; diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h index 75b333473..81ebfb9e2 100644 --- a/src/crypto/crypto.h +++ b/src/crypto/crypto.h @@ -46,10 +46,6 @@ #include "hex.h" #include "span.h" #include "hash.h" -#include "device/device_declare.hpp" -extern "C" { - #include "crypto-ops.h" -} namespace crypto { @@ -117,9 +113,6 @@ namespace crypto { void operator=(const crypto_ops &); ~crypto_ops(); - static void hash_to_ec(const public_key &key, ge_p3 &res) ; - friend void hash_to_ec(const public_key &key, ge_p3 &res) ; - static secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key = secret_key(), bool recover = false); friend secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key, bool recover); static bool check_key(const public_key &); @@ -156,17 +149,6 @@ namespace crypto { const public_key *const *, std::size_t, const signature *); }; - secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key, bool recover, hw::device &hwdev); - secret_key generate_keys(public_key &pub, secret_key &sec, hw::device &hwdev); - bool secret_key_to_public_key(const secret_key &sec, public_key &pub, hw::device &hwdev); - bool generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation, hw::device &hwdev); - void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res, hw::device &hwdev) ; - bool derive_public_key(const key_derivation &derivation, size_t output_index, const public_key &base, public_key &derived_key, hw::device &hwdev); - void derive_secret_key(const key_derivation &derivation, size_t output_index, const secret_key &base, secret_key &derived_key, hw::device &hwdev); - bool derive_subaddress_public_key(const public_key &out_key, const key_derivation &derivation, std::size_t output_index, public_key &derived_key, hw::device &hwdev); - void generate_key_image(const public_key &pub, const secret_key &sec, key_image &image, hw::device &hwdev); - - /* Generate N random bytes */ inline void rand(size_t N, uint8_t *bytes) { @@ -184,9 +166,6 @@ namespace crypto { return res; } - inline void hash_to_ec(const public_key &key, ge_p3 &res) { - crypto_ops::hash_to_ec(key,res); - } /* Generate a new key pair */ inline secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key = secret_key(), bool recover = false) { diff --git a/src/crypto/crypto_device.cpp b/src/crypto/crypto_device.cpp deleted file mode 100644 index 5536857c8..000000000 --- a/src/crypto/crypto_device.cpp +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#include "crypto.h" -#include "device/device.hpp" -#include "device/log.hpp" - -namespace crypto { - - secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key, bool recover, hw::device &hwdev) { - secret_key rng; - hwdev.generate_keys(pub, sec, recovery_key, recover, rng); - return rng; - } - - secret_key generate_keys(public_key &pub, secret_key &sec, hw::device &hwdev) { - secret_key rng; - hwdev.generate_keys(pub, sec, secret_key(), false, rng); - return rng; - } - - - bool secret_key_to_public_key(const secret_key &sec, public_key &pub, hw::device &hwdev) { - return hwdev.secret_key_to_public_key(sec, pub); - } - - bool generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation, hw::device &hwdev) { - return hwdev.generate_key_derivation(key1, key2, derivation); - } - - void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res, hw::device &hwdev) { - hwdev.derivation_to_scalar(derivation, output_index, res); - } - - bool derive_public_key(const key_derivation &derivation, size_t output_index, - const public_key &base, public_key &derived_key, hw::device &hwdev) { - return hwdev.derive_public_key(derivation, output_index, base, derived_key); - } - - void derive_secret_key(const key_derivation &derivation, size_t output_index, - const secret_key &base, secret_key &derived_key, hw::device &hwdev) { - hwdev.derive_secret_key(derivation, output_index, base, derived_key); - } - - bool derive_subaddress_public_key(const public_key &out_key, const key_derivation &derivation, std::size_t output_index, public_key &derived_key, hw::device &hwdev) { - return hwdev.derive_subaddress_public_key(out_key, derivation, output_index, derived_key); - } - - void generate_key_image(const public_key &pub, const secret_key &sec, key_image &image, hw::device &hwdev) { - hwdev.generate_key_image(pub,sec,image); - } -}
\ No newline at end of file diff --git a/src/crypto/hash-ops.h b/src/crypto/hash-ops.h index 934d464de..d77d55cf3 100644 --- a/src/crypto/hash-ops.h +++ b/src/crypto/hash-ops.h @@ -79,8 +79,7 @@ enum { }; void cn_fast_hash(const void *data, size_t length, char *hash); -void cn_slow_hash(const void *data, size_t length, char *hash, int variant); -void cn_slow_hash_pre(const void *data, size_t length, char *hash, int variant, bool pre); +void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int prehashed); void hash_extra_blake(const void *data, size_t length, char *hash); void hash_extra_groestl(const void *data, size_t length, char *hash); diff --git a/src/crypto/hash.h b/src/crypto/hash.h index bf4f4c096..995e2294e 100644 --- a/src/crypto/hash.h +++ b/src/crypto/hash.h @@ -72,7 +72,11 @@ namespace crypto { } inline void cn_slow_hash(const void *data, std::size_t length, hash &hash, int variant = 0) { - cn_slow_hash(data, length, reinterpret_cast<char *>(&hash), variant); + cn_slow_hash(data, length, reinterpret_cast<char *>(&hash), variant, 0/*prehashed*/); + } + + inline void cn_slow_hash_prehashed(const void *data, std::size_t length, hash &hash, int variant = 0) { + cn_slow_hash(data, length, reinterpret_cast<char *>(&hash), variant, 1/*prehashed*/); } inline void tree_hash(const hash *hashes, std::size_t count, hash &root_hash) { diff --git a/src/crypto/slow-hash.c b/src/crypto/slow-hash.c index 8c7dad8e0..d7dcbd274 100644 --- a/src/crypto/slow-hash.c +++ b/src/crypto/slow-hash.c @@ -564,11 +564,7 @@ void slow_hash_free_state(void) * @param length the length in bytes of the data * @param hash a pointer to a buffer in which the final 256 bit hash will be stored */ -void cn_slow_hash(const void *data, size_t length, char *hash, int variant) { - cn_slow_hash_pre(data,length,hash,variant,false); -} - -void cn_slow_hash_pre(const void *data, size_t length, char *hash, int variant, bool prehashed) +void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int prehashed) { RDATA_ALIGN16 uint8_t expandedKey[240]; /* These buffers are aligned to use later with SSE functions */ @@ -909,7 +905,7 @@ STATIC INLINE void aes_pseudo_round_xor(const uint8_t *in, uint8_t *out, const u } } -void cn_slow_hash(const void *data, size_t length, char *hash, int variant) +void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int prehashed) { RDATA_ALIGN16 uint8_t expandedKey[240]; RDATA_ALIGN16 uint8_t hp_state[MEMORY]; @@ -932,7 +928,11 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant) /* CryptoNight Step 1: Use Keccak1600 to initialize the 'state' (and 'text') buffers from the data. */ - hash_process(&state.hs, data, length); + if (prehashed) { + memcpy(&state.hs, data, length); + } else { + hash_process(&state.hs, data, length); + } memcpy(text, state.init, INIT_SIZE_BYTE); VARIANT1_INIT64(); @@ -1105,7 +1105,7 @@ STATIC INLINE void xor_blocks(uint8_t* a, const uint8_t* b) U64(a)[1] ^= U64(b)[1]; } -void cn_slow_hash(const void *data, size_t length, char *hash, int variant) +void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int prehashed) { uint8_t text[INIT_SIZE_BYTE]; uint8_t a[AES_BLOCK_SIZE]; @@ -1131,7 +1131,11 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant) long_state = (uint8_t *)malloc(MEMORY); #endif - hash_process(&state.hs, data, length); + if (prehashed) { + memcpy(&state.hs, data, length); + } else { + hash_process(&state.hs, data, length); + } memcpy(text, state.init, INIT_SIZE_BYTE); VARIANT1_INIT64(); @@ -1289,7 +1293,7 @@ union cn_slow_hash_state { }; #pragma pack(pop) -void cn_slow_hash(const void *data, size_t length, char *hash, int variant) { +void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int prehashed) { uint8_t long_state[MEMORY]; union cn_slow_hash_state state; uint8_t text[INIT_SIZE_BYTE]; @@ -1301,7 +1305,11 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant) { uint8_t aes_key[AES_KEY_SIZE]; oaes_ctx *aes_ctx; - hash_process(&state.hs, data, length); + if (prehashed) { + memcpy(&state.hs, data, length); + } else { + hash_process(&state.hs, data, length); + } memcpy(text, state.init, INIT_SIZE_BYTE); memcpy(aes_key, state.hs.b, AES_KEY_SIZE); aes_ctx = (oaes_ctx *) oaes_alloc(); diff --git a/src/cryptonote_basic/account.cpp b/src/cryptonote_basic/account.cpp index 375b17389..bab991d19 100644 --- a/src/cryptonote_basic/account.cpp +++ b/src/cryptonote_basic/account.cpp @@ -40,7 +40,6 @@ extern "C" } #include "cryptonote_basic_impl.h" #include "cryptonote_format_utils.h" -#include "device/device.hpp" #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "account" @@ -140,9 +139,7 @@ DISABLE_VS_WARNINGS(4244 4345) hwdev.init(); hwdev.connect(); hwdev.get_public_address(m_keys.m_account_address); - #ifdef DEBUG_HWDEVICE hwdev.get_secret_keys(m_keys.m_view_secret_key, m_keys.m_spend_secret_key); - #endif struct tm timestamp = {0}; timestamp.tm_year = 2014 - 1900; // year 2014 timestamp.tm_mon = 4 - 1; // month april diff --git a/src/cryptonote_basic/account.h b/src/cryptonote_basic/account.h index b5d6ed85d..b5d119c46 100644 --- a/src/cryptonote_basic/account.h +++ b/src/cryptonote_basic/account.h @@ -33,7 +33,6 @@ #include "cryptonote_basic.h" #include "crypto/crypto.h" #include "serialization/keyvalue_serialization.h" -#include "device/device_declare.hpp" namespace cryptonote { diff --git a/src/cryptonote_basic/cryptonote_basic.h b/src/cryptonote_basic/cryptonote_basic.h index 4c5f32a09..d4558ef7b 100644 --- a/src/cryptonote_basic/cryptonote_basic.h +++ b/src/cryptonote_basic/cryptonote_basic.h @@ -49,6 +49,7 @@ #include "misc_language.h" #include "tx_extra.h" #include "ringct/rctTypes.h" +#include "device/device.hpp" namespace cryptonote { @@ -428,16 +429,10 @@ namespace cryptonote crypto::public_key pub; crypto::secret_key sec; - static inline keypair generate() - { - keypair k; - generate_keys(k.pub, k.sec); - return k; - } static inline keypair generate(hw::device &hwdev) { keypair k; - generate_keys(k.pub, k.sec, hwdev); + hwdev.generate_keys(k.pub, k.sec); return k; } }; diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp index a10772424..ae7c1c0ae 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.cpp +++ b/src/cryptonote_basic/cryptonote_format_utils.cpp @@ -41,8 +41,6 @@ using namespace epee; #include "crypto/crypto.h" #include "crypto/hash.h" #include "ringct/rctSigs.h" -#include "device/device.hpp" -#include "device/log.hpp" #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "cn" @@ -106,16 +104,6 @@ namespace cryptonote ge_p1p1_to_p3(&A2, &tmp3); ge_p3_tobytes(&AB, &A2); } - - // a copy of rct::scalarmultKey, since we can't link to libringct to avoid circular dependencies - static void secret_key_mult_public_key(crypto::public_key & aP, const crypto::public_key &P, const crypto::secret_key &a) { - ge_p3 A; - ge_p2 R; - //CHECK_AND_ASSERT_THROW_MES_L1(ge_frombytes_vartime(&A, P.bytes) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__)); - ge_frombytes_vartime(&A, (const unsigned char*)P.data); - ge_scalarmult(&R, (const unsigned char*)a.data, &A); - ge_tobytes((unsigned char*)aP.data, &R); - } } namespace cryptonote @@ -172,83 +160,17 @@ namespace cryptonote return true; } //--------------------------------------------------------------- - crypto::secret_key get_subaddress_secret_key(const crypto::secret_key& a, const subaddress_index& index) - { - const char prefix[] = "SubAddr"; - char data[sizeof(prefix) + sizeof(crypto::secret_key) + sizeof(subaddress_index)]; - memcpy(data, prefix, sizeof(prefix)); - memcpy(data + sizeof(prefix), &a, sizeof(crypto::secret_key)); - memcpy(data + sizeof(prefix) + sizeof(crypto::secret_key), &index, sizeof(subaddress_index)); - crypto::secret_key m; - crypto::hash_to_scalar(data, sizeof(data), m); - return m; - } - crypto::secret_key get_subaddress_secret_key(const crypto::secret_key& a, const subaddress_index& index, hw::device &hwdev) - { - crypto::secret_key m; - hwdev.get_subaddress_secret_key(a, index, m); - return m; - } - - //--------------------------------------------------------------- - std::vector<crypto::public_key> get_subaddress_spend_public_keys(const cryptonote::account_keys &keys, uint32_t account, uint32_t begin, uint32_t end) - { - CHECK_AND_ASSERT_THROW_MES(begin <= end, "begin > end"); - - std::vector<crypto::public_key> pkeys; - pkeys.reserve(end - begin); - cryptonote::subaddress_index index = {account, begin}; - - ge_p3 p3; - ge_cached cached; - CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&p3, (const unsigned char*)keys.m_account_address.m_spend_public_key.data) == 0, - "ge_frombytes_vartime failed to convert spend public key"); - ge_p3_to_cached(&cached, &p3); - - for (uint32_t idx = begin; idx < end; ++idx) - { - index.minor = idx; - if (index.is_zero()) - { - pkeys.push_back(keys.m_account_address.m_spend_public_key); - continue; - } - const crypto::secret_key m = cryptonote::get_subaddress_secret_key(keys.m_view_secret_key, index); - - // M = m*G - ge_scalarmult_base(&p3, (const unsigned char*)m.data); - - // D = B + M - crypto::public_key D; - ge_p1p1 p1p1; - ge_add(&p1p1, &p3, &cached); - ge_p1p1_to_p3(&p3, &p1p1); - ge_p3_tobytes((unsigned char*)D.data, &p3); - - pkeys.push_back(D); - } - return pkeys; - } - - std::vector<crypto::public_key> get_subaddress_spend_public_keys(const cryptonote::account_keys &keys, uint32_t account, uint32_t begin, uint32_t end, hw::device &hwdev) - { - std::vector<crypto::public_key> pkeys; - hwdev.get_subaddress_spend_public_keys(keys, account, begin, end, pkeys); - return pkeys; - } - - //--------------------------------------------------------------- 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) { crypto::key_derivation recv_derivation = AUTO_VAL_INIT(recv_derivation); - bool r = crypto::generate_key_derivation(tx_public_key, ack.m_view_secret_key, recv_derivation, hwdev); + bool r = hwdev.generate_key_derivation(tx_public_key, ack.m_view_secret_key, recv_derivation); CHECK_AND_ASSERT_MES(r, false, "key image helper: failed to generate_key_derivation(" << tx_public_key << ", " << ack.m_view_secret_key << ")"); std::vector<crypto::key_derivation> additional_recv_derivations; for (size_t i = 0; i < additional_tx_public_keys.size(); ++i) { crypto::key_derivation additional_recv_derivation = AUTO_VAL_INIT(additional_recv_derivation); - r = crypto::generate_key_derivation(additional_tx_public_keys[i], ack.m_view_secret_key, additional_recv_derivation, hwdev); + r = hwdev.generate_key_derivation(additional_tx_public_keys[i], ack.m_view_secret_key, additional_recv_derivation); CHECK_AND_ASSERT_MES(r, false, "key image helper: failed to generate_key_derivation(" << additional_tx_public_keys[i] << ", " << ack.m_view_secret_key << ")"); additional_recv_derivations.push_back(additional_recv_derivation); } @@ -271,7 +193,7 @@ namespace cryptonote { // derive secret key with subaddress - step 1: original CN derivation crypto::secret_key scalar_step1; - crypto::derive_secret_key(recv_derivation, real_output_index, ack.m_spend_secret_key, scalar_step1, hwdev); // computes Hs(a*R || idx) + b + hwdev.derive_secret_key(recv_derivation, real_output_index, ack.m_spend_secret_key, scalar_step1); // computes Hs(a*R || idx) + b // step 2: add Hs(a || index_major || index_minor) crypto::secret_key subaddr_sk; @@ -282,7 +204,7 @@ namespace cryptonote } else { - hwdev.get_subaddress_secret_key(ack.m_view_secret_key, received_index, subaddr_sk); + subaddr_sk = hwdev.get_subaddress_secret_key(ack.m_view_secret_key, received_index); hwdev.sc_secret_add(scalar_step2, scalar_step1,subaddr_sk); } @@ -291,17 +213,17 @@ namespace cryptonote if (ack.m_multisig_keys.empty()) { // when not in multisig, we know the full spend secret key, so the output pubkey can be obtained by scalarmultBase - CHECK_AND_ASSERT_MES(crypto::secret_key_to_public_key(in_ephemeral.sec, in_ephemeral.pub, hwdev), false, "Failed to derive public key"); + CHECK_AND_ASSERT_MES(hwdev.secret_key_to_public_key(in_ephemeral.sec, in_ephemeral.pub), false, "Failed to derive public key"); } else { // when in multisig, we only know the partial spend secret key. but we do know the full spend public key, so the output pubkey can be obtained by using the standard CN key derivation - CHECK_AND_ASSERT_MES(crypto::derive_public_key(recv_derivation, real_output_index, ack.m_account_address.m_spend_public_key, in_ephemeral.pub, hwdev), false, "Failed to derive public key"); + CHECK_AND_ASSERT_MES(hwdev.derive_public_key(recv_derivation, real_output_index, ack.m_account_address.m_spend_public_key, in_ephemeral.pub), false, "Failed to derive public key"); // and don't forget to add the contribution from the subaddress part if (!received_index.is_zero()) { crypto::public_key subaddr_pk; - CHECK_AND_ASSERT_MES(crypto::secret_key_to_public_key(subaddr_sk, subaddr_pk, hwdev), false, "Failed to derive public key"); + CHECK_AND_ASSERT_MES(hwdev.secret_key_to_public_key(subaddr_sk, subaddr_pk), false, "Failed to derive public key"); add_public_key(in_ephemeral.pub, in_ephemeral.pub, subaddr_pk); } } @@ -310,7 +232,7 @@ namespace cryptonote false, "key image helper precomp: given output pubkey doesn't match the derived one"); } - crypto::generate_key_image(in_ephemeral.pub, in_ephemeral.sec, ki, hwdev); + hwdev.generate_key_image(in_ephemeral.pub, in_ephemeral.sec, ki); return true; } //--------------------------------------------------------------- @@ -574,41 +496,6 @@ namespace cryptonote return true; } //--------------------------------------------------------------- - bool encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key) - { - crypto::key_derivation derivation; - crypto::hash hash; - char data[33]; /* A hash, and an extra byte */ - - if (!generate_key_derivation(public_key, secret_key, derivation)) - return false; - - memcpy(data, &derivation, 32); - data[32] = ENCRYPTED_PAYMENT_ID_TAIL; - cn_fast_hash(data, 33, hash); - - for (size_t b = 0; b < 8; ++b) - payment_id.data[b] ^= hash.data[b]; - - return true; - } - bool decrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key) - { - // Encryption and decryption are the same operation (xor with a key) - return encrypt_payment_id(payment_id, public_key, secret_key); - } - - //--------------------------------------------------------------- - bool encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key,hw::device &hwdev) - { - return hwdev.encrypt_payment_id(public_key, secret_key, payment_id); - } - bool decrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key, hw::device &hwdev) - { - // Encryption and decryption are the same operation (xor with a key) - return encrypt_payment_id(payment_id, public_key, secret_key, hwdev); - } - //--------------------------------------------------------------- bool get_inputs_money_amount(const transaction& tx, uint64_t& money) { money = 0; @@ -708,10 +595,10 @@ namespace cryptonote bool is_out_to_acc(const account_keys& acc, const txout_to_key& out_key, const crypto::public_key& tx_pub_key, const std::vector<crypto::public_key>& additional_tx_pub_keys, size_t output_index) { crypto::key_derivation derivation; - bool r = generate_key_derivation(tx_pub_key, acc.m_view_secret_key, derivation, acc.get_device()); + bool r = acc.get_device().generate_key_derivation(tx_pub_key, acc.m_view_secret_key, derivation); CHECK_AND_ASSERT_MES(r, false, "Failed to generate key derivation"); crypto::public_key pk; - r = derive_public_key(derivation, output_index, acc.m_account_address.m_spend_public_key, pk, acc.get_device()); + r = acc.get_device().derive_public_key(derivation, output_index, acc.m_account_address.m_spend_public_key, pk); CHECK_AND_ASSERT_MES(r, false, "Failed to derive public key"); if (pk == out_key.key) return true; @@ -719,9 +606,9 @@ namespace cryptonote if (!additional_tx_pub_keys.empty()) { CHECK_AND_ASSERT_MES(output_index < additional_tx_pub_keys.size(), false, "wrong number of additional tx pubkeys"); - r = generate_key_derivation(additional_tx_pub_keys[output_index], acc.m_view_secret_key, derivation, acc.get_device()); + r = acc.get_device().generate_key_derivation(additional_tx_pub_keys[output_index], acc.m_view_secret_key, derivation); CHECK_AND_ASSERT_MES(r, false, "Failed to generate key derivation"); - r = derive_public_key(derivation, output_index, acc.m_account_address.m_spend_public_key, pk, acc.get_device()); + r = acc.get_device().derive_public_key(derivation, output_index, acc.m_account_address.m_spend_public_key, pk); CHECK_AND_ASSERT_MES(r, false, "Failed to derive public key"); return pk == out_key.key; } @@ -732,7 +619,7 @@ namespace cryptonote { // try the shared tx pubkey crypto::public_key subaddress_spendkey; - derive_subaddress_public_key(out_key, derivation, output_index, subaddress_spendkey,hwdev); + hwdev.derive_subaddress_public_key(out_key, derivation, output_index, subaddress_spendkey); auto found = subaddresses.find(subaddress_spendkey); if (found != subaddresses.end()) return subaddress_receive_info{ found->second, derivation }; @@ -740,7 +627,7 @@ namespace cryptonote if (!additional_derivations.empty()) { CHECK_AND_ASSERT_MES(output_index < additional_derivations.size(), boost::none, "wrong number of additional derivations"); - derive_subaddress_public_key(out_key, additional_derivations[output_index], output_index, subaddress_spendkey, hwdev); + hwdev.derive_subaddress_public_key(out_key, additional_derivations[output_index], output_index, subaddress_spendkey); found = subaddresses.find(subaddress_spendkey); if (found != subaddresses.end()) return subaddress_receive_info{ found->second, additional_derivations[output_index] }; @@ -1140,64 +1027,4 @@ namespace cryptonote sc_sub((unsigned char*)key.data, (const unsigned char*)key.data, (const unsigned char*)hash.data); return key; } - - //--------------------------------------------------------------- - #define CHACHA8_KEY_TAIL 0x8c - bool generate_chacha_key_from_secret_keys(const account_keys &keys, crypto::chacha_key &key) - { - const crypto::secret_key &view_key = keys.m_view_secret_key; - const crypto::secret_key &spend_key = keys.m_spend_secret_key; - tools::scrubbed_arr<char, sizeof(view_key) + sizeof(spend_key) + 1> data; - memcpy(data.data(), &view_key, sizeof(view_key)); - memcpy(data.data() + sizeof(view_key), &spend_key, sizeof(spend_key)); - data[sizeof(data) - 1] = CHACHA8_KEY_TAIL; - crypto::generate_chacha_key(data.data(), sizeof(data), key); - return true; - } - - //--------------------------------------------------------------- - crypto::public_key get_subaddress_spend_public_key(const cryptonote::account_keys& keys, const cryptonote::subaddress_index& index) - { - if (index.is_zero()) - return keys.m_account_address.m_spend_public_key; - - // m = Hs(a || index_major || index_minor) - crypto::secret_key m = cryptonote::get_subaddress_secret_key(keys.m_view_secret_key, index); - - // M = m*G - crypto::public_key M; - crypto::secret_key_to_public_key(m, M); - - // D = B + M - crypto::public_key D; - add_public_key(D, keys.m_account_address.m_spend_public_key, M); // could have defined add_public_key() under src/crypto - return D; - } - - //--------------------------------------------------------------- - cryptonote::account_public_address get_subaddress(const cryptonote::account_keys& keys, const cryptonote::subaddress_index& index) - { - if (index.is_zero()) - return keys.m_account_address; - - crypto::public_key D = get_subaddress_spend_public_key(keys, index); - - // C = a*D - crypto::public_key C; - secret_key_mult_public_key(C, D, keys.m_view_secret_key); // could have defined secret_key_mult_public_key() under src/crypto - - // result: (C, D) - cryptonote::account_public_address address; - address.m_view_public_key = C; - address.m_spend_public_key = D; - return address; - } - - //--------------------------------------------------------------- - bool verify_keys(const crypto::secret_key& sec, const crypto::public_key& expected_pub) - { - crypto::public_key pub; - bool r = crypto::secret_key_to_public_key(sec, pub); - return r && expected_pub == pub; - } } diff --git a/src/cryptonote_basic/cryptonote_format_utils.h b/src/cryptonote_basic/cryptonote_format_utils.h index 7bd34ea87..79466e9c4 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.h +++ b/src/cryptonote_basic/cryptonote_format_utils.h @@ -37,7 +37,6 @@ #include "crypto/crypto.h" #include "crypto/hash.h" #include <unordered_map> -#include "device/device_declare.hpp" namespace epee { @@ -52,10 +51,6 @@ namespace cryptonote bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash, crypto::hash& tx_prefix_hash); bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx); bool parse_and_validate_tx_base_from_blob(const blobdata& tx_blob, transaction& tx); - bool encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key); - bool encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key, hw::device &hwdev); - bool decrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key); - bool decrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key, hw::device &hwdev); template<typename T> bool find_tx_extra_field_by_type(const std::vector<tx_extra_field>& tx_extra_fields, T& field, size_t index = 0) @@ -95,10 +90,6 @@ namespace cryptonote bool lookup_acc_outs(const account_keys& acc, const transaction& tx, std::vector<size_t>& outs, uint64_t& money_transfered); bool get_tx_fee(const transaction& tx, uint64_t & fee); uint64_t get_tx_fee(const transaction& tx); - crypto::secret_key get_subaddress_secret_key(const crypto::secret_key& a, const subaddress_index& index); - crypto::secret_key get_subaddress_secret_key(const crypto::secret_key& a, const subaddress_index& index, hw::device &hwdev); - std::vector<crypto::public_key> get_subaddress_spend_public_keys(const cryptonote::account_keys &keys, uint32_t account, uint32_t begin, uint32_t end); - std::vector<crypto::public_key> get_subaddress_spend_public_keys(const cryptonote::account_keys &keys, uint32_t account, uint32_t begin, uint32_t end, hw::device &hwdev); 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); bool generate_key_image_helper_precomp(const account_keys& ack, const crypto::public_key& out_key, const crypto::key_derivation& recv_derivation, size_t real_output_index, const subaddress_index& received_index, keypair& in_ephemeral, crypto::key_image& ki, hw::device &hwdev); void get_blob_hash(const blobdata& blob, crypto::hash& res); @@ -242,10 +233,4 @@ namespace cryptonote #define CHECKED_GET_SPECIFIC_VARIANT(variant_var, specific_type, variable_name, fail_return_val) \ CHECK_AND_ASSERT_MES(variant_var.type() == typeid(specific_type), fail_return_val, "wrong variant type: " << variant_var.type().name() << ", expected " << typeid(specific_type).name()); \ specific_type& variable_name = boost::get<specific_type>(variant_var); - - cryptonote::account_public_address get_subaddress(const cryptonote::account_keys &keys, const cryptonote::subaddress_index& index); - crypto::public_key get_subaddress_spend_public_key(const cryptonote::account_keys &keys, const cryptonote::subaddress_index& index); - bool generate_chacha_key_from_secret_keys(const cryptonote::account_keys &keys, crypto::chacha_key &key); - bool verify_keys(const crypto::secret_key& sec, const crypto::public_key& expected_pub); - } diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index c97b75f98..d2d43490e 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -106,6 +106,9 @@ static const struct { // version 6 starts from block 1400000, which is on or around the 16th of September, 2017. Fork time finalised on 2017-08-18. { 6, 1400000, 0, 1503046577 }, + + // version 7 starts from block 1539500, which is on or around the 28th of March, 2018. Fork time finalised on 2018-03-07. + { 7, 1539500, 0, 1520436050 }, }; static const uint64_t mainnet_hard_fork_version_1_till = 1009826; @@ -140,6 +143,14 @@ static const struct { } stagenet_hard_forks[] = { // version 1 from the start of the blockchain { 1, 1, 0, 1341378000 }, + + // versions 2-7 in rapid succession from March 13th, 2018 + { 2, 32000, 0, 1521000000 }, + { 3, 33000, 0, 1521120000 }, + { 4, 34000, 0, 1521240000 }, + { 5, 35000, 0, 1521360000 }, + { 6, 36000, 0, 1521480000 }, + { 7, 37000, 0, 1521600000 }, }; //------------------------------------------------------------------ diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp index d0a958e1e..db4ab9e11 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.cpp +++ b/src/cryptonote_core/cryptonote_tx_utils.cpp @@ -41,7 +41,6 @@ using namespace epee; #include "crypto/hash.h" #include "ringct/rctSigs.h" #include "multisig/multisig.h" -#include "device/device.hpp" using namespace crypto; @@ -79,7 +78,7 @@ namespace cryptonote tx.vout.clear(); tx.extra.clear(); - keypair txkey = keypair::generate(); + keypair txkey = keypair::generate(hw::get_device("default")); add_tx_pub_key_to_extra(tx, txkey.pub); if(!extra_nonce.empty()) if(!add_extra_nonce_to_tx_extra(tx.extra, extra_nonce)) @@ -237,7 +236,7 @@ namespace cryptonote return false; } - if (!encrypt_payment_id(payment_id, view_key_pub, tx_key, hwdev)) + if (!hwdev.encrypt_payment_id(payment_id, view_key_pub, tx_key)) { LOG_ERROR("Failed to encrypt payment id"); return false; @@ -343,11 +342,11 @@ namespace cryptonote // if this is a single-destination transfer to a subaddress, we set the tx pubkey to R=s*D if (num_stdaddresses == 0 && num_subaddresses == 1) { - txkey_pub = rct::rct2pk(rct::scalarmultKey(rct::pk2rct(single_dest_subaddress.m_spend_public_key), rct::sk2rct(tx_key), hwdev)); + txkey_pub = rct::rct2pk(hwdev.scalarmultKey(rct::pk2rct(single_dest_subaddress.m_spend_public_key), rct::sk2rct(tx_key))); } else { - txkey_pub = rct::rct2pk(rct::scalarmultBase(rct::sk2rct(tx_key), hwdev)); + txkey_pub = rct::rct2pk(hwdev.scalarmultBase(rct::sk2rct(tx_key))); } remove_field_from_tx_extra(tx.extra, typeid(tx_extra_pub_key)); add_tx_pub_key_to_extra(tx, txkey_pub); @@ -376,22 +375,22 @@ namespace cryptonote { additional_txkey.sec = additional_tx_keys[output_index]; if (dst_entr.is_subaddress) - additional_txkey.pub = rct::rct2pk(rct::scalarmultKey(rct::pk2rct(dst_entr.addr.m_spend_public_key), rct::sk2rct(additional_txkey.sec),hwdev)); + additional_txkey.pub = rct::rct2pk(hwdev.scalarmultKey(rct::pk2rct(dst_entr.addr.m_spend_public_key), rct::sk2rct(additional_txkey.sec))); else - additional_txkey.pub = rct::rct2pk(rct::scalarmultBase(rct::sk2rct(additional_txkey.sec), hwdev)); + additional_txkey.pub = rct::rct2pk(hwdev.scalarmultBase(rct::sk2rct(additional_txkey.sec))); } bool r; if (change_addr && dst_entr.addr == *change_addr) { // sending change to yourself; derivation = a*R - r = crypto::generate_key_derivation(txkey_pub, sender_account_keys.m_view_secret_key, derivation, hwdev); + r = hwdev.generate_key_derivation(txkey_pub, sender_account_keys.m_view_secret_key, derivation); CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to generate_key_derivation(" << txkey_pub << ", " << sender_account_keys.m_view_secret_key << ")"); } else { // sending to the recipient; derivation = r*A (or s*C in the subaddress scheme) - r = crypto::generate_key_derivation(dst_entr.addr.m_view_public_key, dst_entr.is_subaddress && need_additional_txkeys ? additional_txkey.sec : tx_key, derivation, hwdev); + r = hwdev.generate_key_derivation(dst_entr.addr.m_view_public_key, dst_entr.is_subaddress && need_additional_txkeys ? additional_txkey.sec : tx_key, derivation); CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to generate_key_derivation(" << dst_entr.addr.m_view_public_key << ", " << (dst_entr.is_subaddress && need_additional_txkeys ? additional_txkey.sec : tx_key) << ")"); } @@ -403,13 +402,13 @@ namespace cryptonote if (tx.version > 1) { crypto::secret_key scalar1; - crypto::derivation_to_scalar(derivation, output_index, scalar1, hwdev); + hwdev.derivation_to_scalar(derivation, output_index, scalar1); amount_keys.push_back(rct::sk2rct(scalar1)); } - r = crypto::derive_public_key(derivation, output_index, dst_entr.addr.m_spend_public_key, out_eph_public_key, hwdev); + r = hwdev.derive_public_key(derivation, output_index, dst_entr.addr.m_spend_public_key, out_eph_public_key); CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to derive_public_key(" << derivation << ", " << output_index << ", "<< dst_entr.addr.m_spend_public_key << ")"); - hwdev.add_output_key_mapping(dst_entr.addr.m_view_public_key, dst_entr.addr.m_spend_public_key, output_index, amount_keys.back(), out_eph_public_key); + hwdev.add_output_key_mapping(dst_entr.addr.m_view_public_key, dst_entr.addr.m_spend_public_key, dst_entr.is_subaddress, output_index, amount_keys.back(), out_eph_public_key); tx_out out; out.amount = dst_entr.amount; diff --git a/src/device/CMakeLists.txt b/src/device/CMakeLists.txt index 7eccc1cc2..cc2d20a54 100644 --- a/src/device/CMakeLists.txt +++ b/src/device/CMakeLists.txt @@ -37,7 +37,6 @@ if(PCSC_FOUND) endif() set(device_headers - device_declare.hpp device.hpp device_default.hpp log.hpp @@ -68,7 +67,7 @@ target_link_libraries(device PUBLIC ${PCSC_LIBRARIES} cncrypto - ringct + ringct_basic ${OPENSSL_CRYPTO_LIBRARIES} PRIVATE ${Blocks} diff --git a/src/device/device.cpp b/src/device/device.cpp index 068529388..983f59b60 100644 --- a/src/device/device.cpp +++ b/src/device/device.cpp @@ -67,4 +67,4 @@ namespace hw { return *device->second; } -}
\ No newline at end of file +} diff --git a/src/device/device.hpp b/src/device/device.hpp index bdea7b8f6..b47460472 100644 --- a/src/device/device.hpp +++ b/src/device/device.hpp @@ -28,11 +28,25 @@ // +/* Note about debug: + * To debug Device you can def the following : + * #define DEBUG_HWDEVICE + * Activate debug mechanism: + * - Add more trace + * - All computation done by device are checked by default device. + * Required IODUMMYCRYPT_HWDEVICE or IONOCRYPT_HWDEVICE for fully working + * #define IODUMMYCRYPT_HWDEVICE 1 + * - It assumes sensitive data encryption is is off on device side. a XOR with 0x55. This allow Ledger Class to make check on clear value + * #define IONOCRYPT_HWDEVICE 1 + * - It assumes sensitive data encryption is off on device side. + */ + + #pragma once -#include "cryptonote_basic/cryptonote_basic.h" -#include "cryptonote_basic/account.h" -#include "cryptonote_basic/subaddress_index.h" +#include "crypto/crypto.h" +#include "crypto/chacha.h" +#include "ringct/rctTypes.h" #ifndef USE_DEVICE_LEDGER #define USE_DEVICE_LEDGER 1 @@ -47,6 +61,14 @@ #define WITH_DEVICE_LEDGER #endif +// forward declaration needed because this header is included by headers in libcryptonote_basic which depends on libdevice +namespace cryptonote +{ + struct account_public_address; + struct account_keys; + struct subaddress_index; +} + namespace hw { namespace { //device funcion not supported @@ -95,10 +117,10 @@ namespace hw { /* SUB ADDRESS */ /* ======================================================================= */ virtual bool derive_subaddress_public_key(const crypto::public_key &pub, const crypto::key_derivation &derivation, const std::size_t output_index, crypto::public_key &derived_pub) = 0; - virtual bool get_subaddress_spend_public_key(const cryptonote::account_keys& keys, const cryptonote::subaddress_index& index, crypto::public_key &D) = 0; - virtual bool get_subaddress_spend_public_keys(const cryptonote::account_keys &keys, uint32_t account, uint32_t begin, uint32_t end, std::vector<crypto::public_key> &pkeys) = 0; - virtual bool get_subaddress(const cryptonote::account_keys& keys, const cryptonote::subaddress_index &index, cryptonote::account_public_address &address) = 0; - virtual bool get_subaddress_secret_key(const crypto::secret_key &sec, const cryptonote::subaddress_index &index, crypto::secret_key &sub_sec) = 0; + virtual crypto::public_key get_subaddress_spend_public_key(const cryptonote::account_keys& keys, const cryptonote::subaddress_index& index) = 0; + virtual std::vector<crypto::public_key> get_subaddress_spend_public_keys(const cryptonote::account_keys &keys, uint32_t account, uint32_t begin, uint32_t end) = 0; + virtual cryptonote::account_public_address get_subaddress(const cryptonote::account_keys& keys, const cryptonote::subaddress_index &index) = 0; + virtual crypto::secret_key get_subaddress_secret_key(const crypto::secret_key &sec, const cryptonote::subaddress_index &index) = 0; /* ======================================================================= */ /* DERIVATION & KEY */ @@ -107,7 +129,7 @@ namespace hw { virtual bool scalarmultKey(rct::key & aP, const rct::key &P, const rct::key &a) = 0; virtual bool scalarmultBase(rct::key &aG, const rct::key &a) = 0; virtual bool sc_secret_add( crypto::secret_key &r, const crypto::secret_key &a, const crypto::secret_key &b) = 0; - virtual bool generate_keys(crypto::public_key &pub, crypto::secret_key &sec, const crypto::secret_key& recovery_key, bool recover, crypto::secret_key &rng) = 0; + virtual crypto::secret_key generate_keys(crypto::public_key &pub, crypto::secret_key &sec, const crypto::secret_key& recovery_key = crypto::secret_key(), bool recover = false) = 0; virtual bool generate_key_derivation(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_derivation &derivation) = 0; virtual bool derivation_to_scalar(const crypto::key_derivation &derivation, const size_t output_index, crypto::ec_scalar &res) = 0; virtual bool derive_secret_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::secret_key &sec, crypto::secret_key &derived_sec) = 0; @@ -115,6 +137,21 @@ namespace hw { virtual bool secret_key_to_public_key(const crypto::secret_key &sec, crypto::public_key &pub) = 0; virtual bool generate_key_image(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_image &image) = 0; + // alternative prototypes available in libringct + rct::key scalarmultKey(const rct::key &P, const rct::key &a) + { + rct::key aP; + scalarmultKey(aP, P, a); + return aP; + } + + rct::key scalarmultBase(const rct::key &a) + { + rct::key aG; + scalarmultBase(aG, a); + return aG; + } + /* ======================================================================= */ /* TRANSACTION */ /* ======================================================================= */ @@ -123,13 +160,18 @@ namespace hw { virtual bool set_signature_mode(unsigned int sig_mode) = 0; - virtual bool encrypt_payment_id(const crypto::public_key &public_key, const crypto::secret_key &secret_key, crypto::hash8 &payment_id ) = 0; + virtual bool encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key) = 0; + bool decrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key) + { + // Encryption and decryption are the same operation (xor with a key) + return encrypt_payment_id(payment_id, public_key, secret_key); + } virtual bool ecdhEncode(rct::ecdhTuple & unmasked, const rct::key & sharedSec) = 0; virtual bool ecdhDecode(rct::ecdhTuple & masked, const rct::key & sharedSec) = 0; - virtual bool add_output_key_mapping(const crypto::public_key &Aout, const crypto::public_key &Bout, size_t real_output_index, - const rct::key &amount_key, const crypto::public_key &out_eph_public_key) = 0; + virtual bool add_output_key_mapping(const crypto::public_key &Aout, const crypto::public_key &Bout, const bool is_subaddress, const size_t real_output_index, + const rct::key &amount_key, const crypto::public_key &out_eph_public_key) = 0; virtual bool mlsag_prehash(const std::string &blob, size_t inputs_size, size_t outputs_size, const rct::keyV &hashes, const rct::ctkeyV &outPk, rct::key &prehash) = 0; diff --git a/src/device/device_declare.hpp b/src/device/device_declare.hpp deleted file mode 100644 index 799052ad2..000000000 --- a/src/device/device_declare.hpp +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) 2017-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once - - -//#define DEBUG_HWDEVICE -//#define IODUMMYCRYPT 1 -//#define IONOCRYPT 1 - -namespace hw { - class device; - - device& get_device(std::string device_descriptor); -} - diff --git a/src/device/device_default.cpp b/src/device/device_default.cpp index c3ba42000..d63dafe9e 100644 --- a/src/device/device_default.cpp +++ b/src/device/device_default.cpp @@ -31,10 +31,13 @@ #include "device_default.hpp" - -#include "cryptonote_basic/cryptonote_format_utils.h" +#include "cryptonote_basic/account.h" +#include "cryptonote_basic/subaddress_index.h" #include "ringct/rctOps.h" +#define ENCRYPTED_PAYMENT_ID_TAIL 0x8d +#define CHACHA8_KEY_TAIL 0x8c + namespace hw { namespace core { @@ -83,7 +86,14 @@ namespace hw { /* ======================================================================= */ bool device_default::generate_chacha_key(const cryptonote::account_keys &keys, crypto::chacha_key &key) { - return cryptonote::generate_chacha_key_from_secret_keys(keys, key); + const crypto::secret_key &view_key = keys.m_view_secret_key; + const crypto::secret_key &spend_key = keys.m_spend_secret_key; + tools::scrubbed_arr<char, sizeof(view_key) + sizeof(spend_key) + 1> data; + memcpy(data.data(), &view_key, sizeof(view_key)); + memcpy(data.data() + sizeof(view_key), &spend_key, sizeof(spend_key)); + data[sizeof(data) - 1] = CHACHA8_KEY_TAIL; + crypto::generate_chacha_key(data.data(), sizeof(data), key); + return true; } bool device_default::get_public_address(cryptonote::account_public_address &pubkey) { dfns(); @@ -99,24 +109,85 @@ namespace hw { return crypto::derive_subaddress_public_key(out_key, derivation, output_index,derived_key); } - bool device_default::get_subaddress_spend_public_key(const cryptonote::account_keys& keys, const cryptonote::subaddress_index &index, crypto::public_key &D) { - D = cryptonote::get_subaddress_spend_public_key(keys,index); - return true; + crypto::public_key device_default::get_subaddress_spend_public_key(const cryptonote::account_keys& keys, const cryptonote::subaddress_index &index) { + if (index.is_zero()) + return keys.m_account_address.m_spend_public_key; + + // m = Hs(a || index_major || index_minor) + crypto::secret_key m = get_subaddress_secret_key(keys.m_view_secret_key, index); + + // M = m*G + crypto::public_key M; + crypto::secret_key_to_public_key(m, M); + + // D = B + M + crypto::public_key D = rct::rct2pk(rct::addKeys(rct::pk2rct(keys.m_account_address.m_spend_public_key), rct::pk2rct(M))); + return D; } - bool device_default::get_subaddress_spend_public_keys(const cryptonote::account_keys &keys, uint32_t account, uint32_t begin, uint32_t end, std::vector<crypto::public_key> &pkeys) { - pkeys = cryptonote::get_subaddress_spend_public_keys(keys, account, begin, end); - return true; + std::vector<crypto::public_key> device_default::get_subaddress_spend_public_keys(const cryptonote::account_keys &keys, uint32_t account, uint32_t begin, uint32_t end) { + CHECK_AND_ASSERT_THROW_MES(begin <= end, "begin > end"); + + std::vector<crypto::public_key> pkeys; + pkeys.reserve(end - begin); + cryptonote::subaddress_index index = {account, begin}; + + ge_p3 p3; + ge_cached cached; + CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&p3, (const unsigned char*)keys.m_account_address.m_spend_public_key.data) == 0, + "ge_frombytes_vartime failed to convert spend public key"); + ge_p3_to_cached(&cached, &p3); + + for (uint32_t idx = begin; idx < end; ++idx) + { + index.minor = idx; + if (index.is_zero()) + { + pkeys.push_back(keys.m_account_address.m_spend_public_key); + continue; + } + crypto::secret_key m = get_subaddress_secret_key(keys.m_view_secret_key, index); + + // M = m*G + ge_scalarmult_base(&p3, (const unsigned char*)m.data); + + // D = B + M + crypto::public_key D; + ge_p1p1 p1p1; + ge_add(&p1p1, &p3, &cached); + ge_p1p1_to_p3(&p3, &p1p1); + ge_p3_tobytes((unsigned char*)D.data, &p3); + + pkeys.push_back(D); + } + return pkeys; } - bool device_default::get_subaddress(const cryptonote::account_keys& keys, const cryptonote::subaddress_index &index, cryptonote::account_public_address &address) { - address = cryptonote::get_subaddress(keys,index); - return true; + cryptonote::account_public_address device_default::get_subaddress(const cryptonote::account_keys& keys, const cryptonote::subaddress_index &index) { + if (index.is_zero()) + return keys.m_account_address; + + crypto::public_key D = get_subaddress_spend_public_key(keys, index); + + // C = a*D + crypto::public_key C = rct::rct2pk(rct::scalarmultKey(rct::pk2rct(D), rct::sk2rct(keys.m_view_secret_key))); + + // result: (C, D) + cryptonote::account_public_address address; + address.m_view_public_key = C; + address.m_spend_public_key = D; + return address; } - bool device_default::get_subaddress_secret_key(const crypto::secret_key &a, const cryptonote::subaddress_index &index, crypto::secret_key &m) { - m = cryptonote::get_subaddress_secret_key(a,index); - return true; + crypto::secret_key device_default::get_subaddress_secret_key(const crypto::secret_key &a, const cryptonote::subaddress_index &index) { + const char prefix[] = "SubAddr"; + char data[sizeof(prefix) + sizeof(crypto::secret_key) + sizeof(cryptonote::subaddress_index)]; + memcpy(data, prefix, sizeof(prefix)); + memcpy(data + sizeof(prefix), &a, sizeof(crypto::secret_key)); + memcpy(data + sizeof(prefix) + sizeof(crypto::secret_key), &index, sizeof(cryptonote::subaddress_index)); + crypto::secret_key m; + crypto::hash_to_scalar(data, sizeof(data), m); + return m; } /* ======================================================================= */ @@ -124,7 +195,9 @@ namespace hw { /* ======================================================================= */ bool device_default::verify_keys(const crypto::secret_key &secret_key, const crypto::public_key &public_key) { - return cryptonote::verify_keys(secret_key, public_key); + crypto::public_key calculated_pub; + bool r = crypto::secret_key_to_public_key(secret_key, calculated_pub); + return r && public_key == calculated_pub; } bool device_default::scalarmultKey(rct::key & aP, const rct::key &P, const rct::key &a) { @@ -142,9 +215,8 @@ namespace hw { return true; } - bool device_default::generate_keys(crypto::public_key &pub, crypto::secret_key &sec, const crypto::secret_key& recovery_key, bool recover, crypto::secret_key &rng) { - rng = crypto::generate_keys(pub, sec, recovery_key, recover); - return true; + crypto::secret_key device_default::generate_keys(crypto::public_key &pub, crypto::secret_key &sec, const crypto::secret_key& recovery_key, bool recover) { + return crypto::generate_keys(pub, sec, recovery_key, recover); } bool device_default::generate_key_derivation(const crypto::public_key &key1, const crypto::secret_key &key2, crypto::key_derivation &derivation) { @@ -179,13 +251,13 @@ namespace hw { /* ======================================================================= */ bool device_default::open_tx(crypto::secret_key &tx_key) { - cryptonote::keypair txkey = cryptonote::keypair::generate(); + cryptonote::keypair txkey = cryptonote::keypair::generate(*this); tx_key = txkey.sec; return true; } - bool device_default::add_output_key_mapping(const crypto::public_key &Aout, const crypto::public_key &Bout, size_t real_output_index, + bool device_default::add_output_key_mapping(const crypto::public_key &Aout, const crypto::public_key &Bout, const bool is_subaddress, const size_t real_output_index, const rct::key &amount_key, const crypto::public_key &out_eph_public_key) { return true; } @@ -194,8 +266,22 @@ namespace hw { return true; } - bool device_default::encrypt_payment_id(const crypto::public_key &public_key, const crypto::secret_key &secret_key, crypto::hash8 &payment_id ) { - return cryptonote::encrypt_payment_id(payment_id, public_key, secret_key); + bool device_default::encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key) { + crypto::key_derivation derivation; + crypto::hash hash; + char data[33]; /* A hash, and an extra byte */ + + if (!generate_key_derivation(public_key, secret_key, derivation)) + return false; + + memcpy(data, &derivation, 32); + data[32] = ENCRYPTED_PAYMENT_ID_TAIL; + cn_fast_hash(data, 33, hash); + + for (size_t b = 0; b < 8; ++b) + payment_id.data[b] ^= hash.data[b]; + + return true; } bool device_default::ecdhEncode(rct::ecdhTuple & unmasked, const rct::key & sharedSec) { diff --git a/src/device/device_default.hpp b/src/device/device_default.hpp index f5b158a3b..02faeba0c 100644 --- a/src/device/device_default.hpp +++ b/src/device/device_default.hpp @@ -70,10 +70,10 @@ namespace hw { /* SUB ADDRESS */ /* ======================================================================= */ bool derive_subaddress_public_key(const crypto::public_key &pub, const crypto::key_derivation &derivation, const std::size_t output_index, crypto::public_key &derived_pub) override; - bool get_subaddress_spend_public_key(const cryptonote::account_keys& keys, const cryptonote::subaddress_index& index, crypto::public_key &D) override; - bool get_subaddress_spend_public_keys(const cryptonote::account_keys &keys, uint32_t account, uint32_t begin, uint32_t end, std::vector<crypto::public_key> &pkeys) override; - bool get_subaddress(const cryptonote::account_keys& keys, const cryptonote::subaddress_index &index, cryptonote::account_public_address &address) override; - bool get_subaddress_secret_key(const crypto::secret_key &sec, const cryptonote::subaddress_index &index, crypto::secret_key &sub_sec) override; + crypto::public_key get_subaddress_spend_public_key(const cryptonote::account_keys& keys, const cryptonote::subaddress_index& index) override; + std::vector<crypto::public_key> get_subaddress_spend_public_keys(const cryptonote::account_keys &keys, uint32_t account, uint32_t begin, uint32_t end) override; + cryptonote::account_public_address get_subaddress(const cryptonote::account_keys& keys, const cryptonote::subaddress_index &index) override; + crypto::secret_key get_subaddress_secret_key(const crypto::secret_key &sec, const cryptonote::subaddress_index &index) override; /* ======================================================================= */ /* DERIVATION & KEY */ @@ -82,7 +82,7 @@ namespace hw { bool scalarmultKey(rct::key & aP, const rct::key &P, const rct::key &a) override; bool scalarmultBase(rct::key &aG, const rct::key &a) override; bool sc_secret_add(crypto::secret_key &r, const crypto::secret_key &a, const crypto::secret_key &b) override; - bool generate_keys(crypto::public_key &pub, crypto::secret_key &sec, const crypto::secret_key& recovery_key, bool recover, crypto::secret_key &rng) override; + crypto::secret_key generate_keys(crypto::public_key &pub, crypto::secret_key &sec, const crypto::secret_key& recovery_key = crypto::secret_key(), bool recover = false) override; bool generate_key_derivation(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_derivation &derivation) override; bool derivation_to_scalar(const crypto::key_derivation &derivation, const size_t output_index, crypto::ec_scalar &res) override; bool derive_secret_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::secret_key &sec, crypto::secret_key &derived_sec) override; @@ -100,13 +100,13 @@ namespace hw { //bool get_additional_key(const bool subaddr, cryptonote::keypair &additional_txkey) override; bool set_signature_mode(unsigned int sig_mode) override; - bool encrypt_payment_id(const crypto::public_key &public_key, const crypto::secret_key &secret_key, crypto::hash8 &payment_id ) override; + bool encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key) override; bool ecdhEncode(rct::ecdhTuple & unmasked, const rct::key & sharedSec) override; bool ecdhDecode(rct::ecdhTuple & masked, const rct::key & sharedSec) override; - bool add_output_key_mapping(const crypto::public_key &Aout, const crypto::public_key &Bout, size_t real_output_index, - const rct::key &amount_key, const crypto::public_key &out_eph_public_key) override; + bool add_output_key_mapping(const crypto::public_key &Aout, const crypto::public_key &Bout, const bool is_subaddress, const size_t real_output_index, + const rct::key &amount_key, const crypto::public_key &out_eph_public_key) override; bool mlsag_prehash(const std::string &blob, size_t inputs_size, size_t outputs_size, const rct::keyV &hashes, const rct::ctkeyV &outPk, rct::key &prehash) override; diff --git a/src/device/device_ledger.cpp b/src/device/device_ledger.cpp index 571d42724..b3c0035a1 100644 --- a/src/device/device_ledger.cpp +++ b/src/device/device_ledger.cpp @@ -30,6 +30,8 @@ #include "device_ledger.hpp" #include "log.hpp" #include "ringct/rctOps.h" +#include "cryptonote_basic/account.h" +#include "cryptonote_basic/subaddress_index.h" @@ -55,30 +57,29 @@ namespace hw { #define ASSERT_T0(exp) CHECK_AND_ASSERT_THROW_MES(exp, "Protocol assert failure: "#exp ) ; #ifdef DEBUG_HWDEVICE - #define DEVICE_CONTROLE :controle_device(hw::get_device("default")) crypto::secret_key viewkey; crypto::secret_key spendkey; - #else - #define DEVICE_CONTROLE #endif /* ===================================================================== */ /* === Keymap ==== */ /* ===================================================================== */ - ABPkeys::ABPkeys(const rct::key& A, const rct::key& B, size_t real_output_index, const rct::key& P, const rct::key& AK) { + ABPkeys::ABPkeys(const rct::key& A, const rct::key& B, const bool is_subaddr, const size_t real_output_index, const rct::key& P, const rct::key& AK) { Aout = A; Bout = B; + is_subaddress = is_subaddr; index = real_output_index; Pout = P; AKout = AK; } ABPkeys::ABPkeys(const ABPkeys& keys) { - Aout = keys.Aout; - Bout = keys.Bout; + Aout = keys.Aout; + Bout = keys.Bout; + is_subaddress = keys.is_subaddress; index = keys.index; - Pout = keys.Pout; + Pout = keys.Pout; AKout = keys.AKout; } @@ -109,6 +110,7 @@ namespace hw { log_message(" keymap", std::to_string(i)); log_hexbuffer(" Aout", (char*)ABP[i].Aout.bytes, 32); log_hexbuffer(" Bout", (char*)ABP[i].Bout.bytes, 32); + log_message (" is_sub", std::to_string(ABP[i].is_subaddress)); log_message (" index", std::to_string(ABP[i].index)); log_hexbuffer(" Pout", (char*)ABP[i].Pout.bytes, 32); } @@ -189,7 +191,7 @@ namespace hw { } /* -------------------------------------------------------------- */ - device_ledger::device_ledger() DEVICE_CONTROLE { + device_ledger::device_ledger() { this->id = device_id++; this->hCard = 0; this->hContext = 0; @@ -300,6 +302,9 @@ namespace hw { } bool device_ledger::init(void) { + #ifdef DEBUG_HWDEVICE + this->controle_device = &hw::get_device("default"); + #endif LONG rv; this->release(); rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM,0,0, &this->hContext); @@ -411,12 +416,6 @@ namespace hw { /* WALLET & ADDRESS */ /* ======================================================================= */ - bool device_ledger::get_secret_keys(crypto::secret_key &viewkey , crypto::secret_key &spendkey) { - memset(viewkey.data, 0x00, 32); - memset(spendkey.data, 0xFF, 32); - return true; - } - /* Application API */ bool device_ledger::get_public_address(cryptonote::account_public_address &pubkey){ @@ -449,8 +448,11 @@ namespace hw { return true; } - #ifdef DEBUG_HWDEVICE bool device_ledger::get_secret_keys(crypto::secret_key &viewkey , crypto::secret_key &spendkey) { + memset(viewkey.data, 0x00, 32); + memset(spendkey.data, 0xFF, 32); + + #ifdef DEBUG_HWDEVICE lock_device(); try { //spcialkey, normal conf handled in decrypt @@ -479,9 +481,9 @@ namespace hw { unlock_device(); throw; } + #endif return true; } - #endif bool device_ledger::generate_chacha_key(const cryptonote::account_keys &keys, crypto::chacha_key &key) { lock_device(); @@ -489,9 +491,9 @@ namespace hw { int offset; #ifdef DEBUG_HWDEVICE - const cryptonote::account_keys keys_x = decrypt(keys); crypto::chacha_key key_x; - this->controle_device.generate_chacha_key(keys_x, key_x); + cryptonote::account_keys keys_x = hw::ledger::decrypt(keys); + this->controle_device->generate_chacha_key(keys_x, key_x); #endif reset_buffer(); @@ -511,10 +513,10 @@ namespace hw { char prekey[200]; memmove(prekey, &this->buffer_recv[0], 200); - crypto::generate_chacha_key(&prekey[0], sizeof(prekey), key, 0, true); + crypto::generate_chacha_key_prehashed(&prekey[0], sizeof(prekey), key); #ifdef DEBUG_HWDEVICE - hw::ledger::check32("generate_chacha_key", "key", (char*)key_x.data(), (char*)key.data()); + hw::ledger::check32("generate_chacha_key_prehashed", "key", (char*)key_x.data(), (char*)key.data()); #endif unlock_device(); @@ -541,7 +543,11 @@ namespace hw { const crypto::key_derivation derivation_x = hw::ledger::decrypt(derivation); const std::size_t output_index_x = output_index; crypto::public_key derived_pub_x; - this->controle_device.derive_subaddress_public_key(pub_x, derivation_x,output_index_x,derived_pub_x); + hw::ledger::log_hexbuffer("derive_subaddress_public_key: [[IN]] pub ", pub_x.data, 32); + hw::ledger::log_hexbuffer("derive_subaddress_public_key: [[IN]] derivation", derivation_x.data, 32); + hw::ledger::log_message ("derive_subaddress_public_key: [[IN]] index ", std::to_string((int)output_index_x)); + this->controle_device->derive_subaddress_public_key(pub_x, derivation_x,output_index_x,derived_pub_x); + hw::ledger::log_hexbuffer("derive_subaddress_public_key: [[OUT]] derived_pub", derived_pub_x.data, 32); #endif reset_buffer(); @@ -589,7 +595,8 @@ namespace hw { return true; } - bool device_ledger::get_subaddress_spend_public_key(const cryptonote::account_keys& keys, const cryptonote::subaddress_index &index, crypto::public_key &D) { + crypto::public_key device_ledger::get_subaddress_spend_public_key(const cryptonote::account_keys& keys, const cryptonote::subaddress_index &index) { + crypto::public_key D; lock_device(); try { int offset =0; @@ -599,7 +606,11 @@ namespace hw { const cryptonote::account_keys keys_x = hw::ledger::decrypt(keys); const cryptonote::subaddress_index index_x = index; crypto::public_key D_x; - this->controle_device.get_subaddress_spend_public_key(keys_x, index_x, D_x); + hw::ledger::log_hexbuffer("derive_subaddress_public_key: [[IN]] keys.m_view_secret_key ", keys_x.m_view_secret_key.data,32); + hw::ledger::log_hexbuffer("derive_subaddress_public_key: [[IN]] keys.m_spend_secret_key", keys_x.m_spend_secret_key.data,32); + hw::ledger::log_message ("get_subaddress_spend_public_key: [[IN]] index ", std::to_string(index_x.major)+"."+std::to_string(index_x.minor)); + this->controle_device->get_subaddress_spend_public_key(keys_x, index_x, D_x); + hw::ledger::log_hexbuffer("get_subaddress_spend_public_key: [[OUT]] derivation ", D_x.data, 32); #endif if (index.is_zero()) { @@ -638,21 +649,23 @@ namespace hw { unlock_device(); throw; } - return true; + return D; } - bool device_ledger::get_subaddress_spend_public_keys(const cryptonote::account_keys &keys, uint32_t account, uint32_t begin, uint32_t end, std::vector<crypto::public_key> &pkeys) { + std::vector<crypto::public_key> device_ledger::get_subaddress_spend_public_keys(const cryptonote::account_keys &keys, uint32_t account, uint32_t begin, uint32_t end) { + std::vector<crypto::public_key> pkeys; cryptonote::subaddress_index index = {account, begin}; crypto::public_key D; for (uint32_t idx = begin; idx < end; ++idx) { index.minor = idx; - this->get_subaddress_spend_public_key(keys, index, D); + D = this->get_subaddress_spend_public_key(keys, index); pkeys.push_back(D); } - return true; + return pkeys; } - bool device_ledger::get_subaddress(const cryptonote::account_keys& keys, const cryptonote::subaddress_index &index, cryptonote::account_public_address &address) { + cryptonote::account_public_address device_ledger::get_subaddress(const cryptonote::account_keys& keys, const cryptonote::subaddress_index &index) { + cryptonote::account_public_address address; lock_device(); try { int offset =0; @@ -662,7 +675,14 @@ namespace hw { const cryptonote::account_keys keys_x = hw::ledger::decrypt(keys); const cryptonote::subaddress_index index_x = index; cryptonote::account_public_address address_x; - this->controle_device.get_subaddress(keys_x, index_x, address_x); + hw::ledger::log_hexbuffer("derive_subaddress_public_key: [[IN]] keys.m_view_secret_key ", keys_x.m_view_secret_key.data, 32); + hw::ledger::log_hexbuffer("derive_subaddress_public_key: [[IN]] keys.m_view_public_key", keys_x.m_account_address.m_view_public_key.data, 32); + hw::ledger::log_hexbuffer("derive_subaddress_public_key: [[IN]] keys.m_view_secret_key ", keys_x.m_view_secret_key.data, 32); + hw::ledger::log_hexbuffer("derive_subaddress_public_key: [[IN]] keys.m_spend_public_key", keys_x.m_account_address.m_spend_public_key.data, 32); + hw::ledger::log_message ("get_subaddress: [[IN]] index ", std::to_string(index_x.major)+"."+std::to_string(index_x.minor)); + this->controle_device->get_subaddress(keys_x, index_x, address_x); + hw::ledger::log_hexbuffer("derive_subaddress_public_key: [[IN]] keys.m_view_public_key ", address_x.m_view_public_key.data, 32); + hw::ledger::log_hexbuffer("derive_subaddress_public_key: [[IN]] keys.m_spend_public_key", address_x.m_spend_public_key.data, 32); #endif if (index.is_zero()) { @@ -702,10 +722,11 @@ namespace hw { unlock_device(); throw; } - return true; + return address; } - bool device_ledger::get_subaddress_secret_key(const crypto::secret_key &sec, const cryptonote::subaddress_index &index, crypto::secret_key &sub_sec) { + crypto::secret_key device_ledger::get_subaddress_secret_key(const crypto::secret_key &sec, const cryptonote::subaddress_index &index) { + crypto::secret_key sub_sec; lock_device(); try { int offset =0; @@ -715,7 +736,10 @@ namespace hw { const crypto::secret_key sec_x = hw::ledger::decrypt(sec); const cryptonote::subaddress_index index_x = index; crypto::secret_key sub_sec_x; - this->controle_device.get_subaddress_secret_key(sec_x, index_x, sub_sec_x); + hw::ledger::log_message ("get_subaddress_secret_key: [[IN]] index ", std::to_string(index.major)+"."+std::to_string(index.minor)); + hw::ledger::log_hexbuffer("get_subaddress_secret_key: [[IN]] sec ", sec_x.data, 32); + this->controle_device->get_subaddress_secret_key(sec_x, index_x, sub_sec_x); + hw::ledger::log_hexbuffer("get_subaddress_secret_key: [[OUT]] sub_sec", sub_sec_x.data, 32); #endif reset_buffer(); @@ -753,7 +777,7 @@ namespace hw { unlock_device(); throw; } - return true; + return sub_sec; } /* ======================================================================= */ @@ -808,10 +832,13 @@ namespace hw { unsigned char options = 0; #ifdef DEBUG_HWDEVICE - const rct::key pub_x = pub; - const rct::key sec_x = hw::ledger::decrypt(sec); - rct::key mulkey_x; - this->controle_device.scalarmultKey(pub_x, sec_x, mulkey_x); + const rct::key P_x = P; + const rct::key a_x = hw::ledger::decrypt(a); + rct::key aP_x; + hw::ledger::log_hexbuffer("scalarmultKey: [[IN]] P ", (char*)P_x.bytes, 32); + hw::ledger::log_hexbuffer("scalarmultKey: [[IN]] a ", (char*)a_x.bytes, 32); + this->controle_device->scalarmultKey(aP_x, P_x, a_x); + hw::ledger::log_hexbuffer("scalarmultKey: [[OUT]] aP", (char*)aP_x.bytes, 32); #endif reset_buffer(); @@ -843,7 +870,7 @@ namespace hw { memmove(aP.bytes, &this->buffer_recv[0], 32); #ifdef DEBUG_HWDEVICE - hw::ledger::check32("scalarmultKey", "mulkey", (char*)mulkey_x.bytes, (char*)mulkey.bytes); + hw::ledger::check32("scalarmultKey", "mulkey", (char*)aP_x.bytes, (char*)aP.bytes); #endif unlock_device(); @@ -861,9 +888,11 @@ namespace hw { unsigned char options = 0; #ifdef DEBUG_HWDEVICE - const rct::key sec_x = hw::ledger::decrypt(sec); - rct::key mulkey_x; - this->controle_device.scalarmultBase(sec_x, mulkey_x); + const rct::key a_x = hw::ledger::decrypt(a); + rct::key aG_x; + hw::ledger::log_hexbuffer("scalarmultKey: [[IN]] a ", (char*)a_x.bytes, 32); + this->controle_device->scalarmultBase(aG_x, a_x); + hw::ledger::log_hexbuffer("scalarmultKey: [[OUT]] aG", (char*)aG_x.bytes, 32); #endif reset_buffer(); @@ -891,7 +920,7 @@ namespace hw { memmove(aG.bytes, &this->buffer_recv[0], 32); #ifdef DEBUG_HWDEVICE - hw::ledger::check32("scalarmultBase", "mulkey", (char*)mulkey_x.bytes, (char*)mulkey.bytes); + hw::ledger::check32("scalarmultBase", "mulkey", (char*)aG_x.bytes, (char*)aG.bytes); #endif unlock_device(); @@ -913,7 +942,7 @@ namespace hw { const crypto::secret_key a_x = hw::ledger::decrypt(a); const crypto::secret_key b_x = hw::ledger::decrypt(b); crypto::secret_key r_x; - this->controle_device.sc_secret_add(r_x, a_x, b_x); + this->controle_device->sc_secret_add(r_x, a_x, b_x); #endif reset_buffer(); @@ -956,7 +985,7 @@ namespace hw { return true; } - bool device_ledger::generate_keys(crypto::public_key &pub, crypto::secret_key &sec, const crypto::secret_key& recovery_key, bool recover, crypto::secret_key &rng) { + crypto::secret_key device_ledger::generate_keys(crypto::public_key &pub, crypto::secret_key &sec, const crypto::secret_key& recovery_key, bool recover) { if (recover) { throw std::runtime_error("device generate key does not support recover"); } @@ -1007,7 +1036,7 @@ namespace hw { unlock_device(); throw; } - return true; + return sec; } @@ -1021,10 +1050,10 @@ namespace hw { const crypto::public_key pub_x = pub; const crypto::secret_key sec_x = hw::ledger::decrypt(sec); crypto::key_derivation derivation_x; - this->controle_device.generate_key_derivation(pub_x, sec_x, derivation_x); - hw::ledger::log_hexbuffer("generate_key_derivation: sec_x.data", sec_x.data, 32); - hw::ledger::log_hexbuffer("generate_key_derivation: pub_x.data", pub_x.data, 32); - hw::ledger::log_hexbuffer("generate_key_derivation: derivation_x.data", derivation_x.data, 32); + hw::ledger::log_hexbuffer("generate_key_derivation: [[IN]] pub ", pub_x.data, 32); + hw::ledger::log_hexbuffer("generate_key_derivation: [[IN]] sec ", sec_x.data, 32); + this->controle_device->generate_key_derivation(pub_x, sec_x, derivation_x); + hw::ledger::log_hexbuffer("generate_key_derivation: [[OUT]] derivation", derivation_x.data, 32); #endif reset_buffer(); @@ -1075,7 +1104,10 @@ namespace hw { const crypto::key_derivation derivation_x = hw::ledger::decrypt(derivation); const size_t output_index_x = output_index; crypto::ec_scalar res_x; - this->controle_device.derivation_to_scalar(derivation_x, output_index_x, res_x); + hw::ledger::log_hexbuffer("derivation_to_scalar: [[IN]] derivation ", derivation_x.data, 32); + hw::ledger::log_message ("derivation_to_scalar: [[IN]] output_index ", std::to_string(output_index_x)); + this->controle_device->derivation_to_scalar(derivation_x, output_index_x, res_x); + hw::ledger::log_hexbuffer("derivation_to_scalar: [[OUT]] res ", res_x.data, 32); #endif reset_buffer(); @@ -1132,7 +1164,11 @@ namespace hw { const std::size_t output_index_x = output_index; const crypto::secret_key sec_x = hw::ledger::decrypt(sec); crypto::secret_key derived_sec_x; - this->controle_device.derive_secret_key(derivation_x, output_index_x, sec_x, derived_sec_x); + hw::ledger::log_hexbuffer("derive_secret_key: [[IN]] derivation ", derivation_x.data, 32); + hw::ledger::log_message ("derive_secret_key: [[IN]] index ", std::to_string(output_index_x)); + hw::ledger::log_hexbuffer("derive_secret_key: [[IN]] sec ", sec_x.data, 32); + this->controle_device->derive_secret_key(derivation_x, output_index_x, sec_x, derived_sec_x); + hw::ledger::log_hexbuffer("derive_secret_key: [[OUT]] derived_sec", derived_sec_x.data, 32); #endif reset_buffer(); @@ -1192,7 +1228,11 @@ namespace hw { const std::size_t output_index_x = output_index; const crypto::public_key pub_x = pub; crypto::public_key derived_pub_x; - this->controle_device.derive_public_key(derivation_x, output_index_x, pub_x, derived_pub_x); + hw::ledger::log_hexbuffer("derive_public_key: [[IN]] derivation ", derivation_x.data, 32); + hw::ledger::log_message ("derive_public_key: [[IN]] output_index", std::to_string(output_index_x)); + hw::ledger::log_hexbuffer("derive_public_key: [[IN]] pub ", pub_x.data, 32); + this->controle_device->derive_public_key(derivation_x, output_index_x, pub_x, derived_pub_x); + hw::ledger::log_hexbuffer("derive_public_key: [[OUT]] derived_pub ", derived_pub_x.data, 32); #endif reset_buffer(); @@ -1249,7 +1289,12 @@ namespace hw { #ifdef DEBUG_HWDEVICE const crypto::secret_key sec_x = hw::ledger::decrypt(sec); crypto::public_key pub_x; - this->controle_device.secret_key_to_public_key(sec_x, pub_x); + hw::ledger::log_hexbuffer("secret_key_to_public_key: [[IN]] sec ", sec_x.data, 32); + bool rc = this->controle_device->secret_key_to_public_key(sec_x, pub_x); + hw::ledger::log_hexbuffer("secret_key_to_public_key: [[OUT]] pub", pub_x.data, 32); + if (!rc){ + hw::ledger::log_message("secret_key_to_public_key", "secret_key rejected"); + } #endif reset_buffer(); @@ -1298,7 +1343,10 @@ namespace hw { const crypto::public_key pub_x = pub; const crypto::secret_key sec_x = hw::ledger::decrypt(sec); crypto::key_image image_x; - this->controle_device.generate_key_image(pub_x, sec_x, image_x); + hw::ledger::log_hexbuffer("generate_key_image: [[IN]] pub ", pub_x.data, 32); + hw::ledger::log_hexbuffer("generate_key_image: [[IN]] sec ", sec_x.data, 32); + this->controle_device->generate_key_image(pub_x, sec_x, image_x); + hw::ledger::log_hexbuffer("generate_key_image: [[OUT]] image ", image_x.data, 32); #endif reset_buffer(); @@ -1415,7 +1463,7 @@ namespace hw { return true; } - bool device_ledger::encrypt_payment_id(const crypto::public_key &public_key, const crypto::secret_key &secret_key, crypto::hash8 &payment_id) { + bool device_ledger::encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key) { lock_device(); try { int offset =0; @@ -1425,7 +1473,7 @@ namespace hw { const crypto::public_key public_key_x = public_key; const crypto::secret_key secret_key_x = hw::ledger::decrypt(secret_key); crypto::hash8 payment_id_x = payment_id; - this->controle_device.encrypt_payment_id(public_key_x, secret_key_x, payment_id_x); + this->controle_device->encrypt_payment_id(public_key_x, secret_key_x, payment_id_x); #endif reset_buffer(); @@ -1466,11 +1514,11 @@ namespace hw { return true; } - bool device_ledger::add_output_key_mapping(const crypto::public_key &Aout, const crypto::public_key &Bout, size_t real_output_index, - const rct::key &amount_key, const crypto::public_key &out_eph_public_key) { + bool device_ledger::add_output_key_mapping(const crypto::public_key &Aout, const crypto::public_key &Bout, const bool is_subaddress, const size_t real_output_index, + const rct::key &amount_key, const crypto::public_key &out_eph_public_key) { lock_device(); try { - key_map.add(ABPkeys(rct::pk2rct(Aout),rct::pk2rct(Bout), real_output_index, rct::pk2rct(out_eph_public_key), amount_key)); + key_map.add(ABPkeys(rct::pk2rct(Aout),rct::pk2rct(Bout), is_subaddress, real_output_index, rct::pk2rct(out_eph_public_key), amount_key)); unlock_device(); }catch (...) { unlock_device(); @@ -1488,7 +1536,7 @@ namespace hw { #ifdef DEBUG_HWDEVICE const rct::key AKout_x = hw::ledger::decrypt(AKout); rct::ecdhTuple unmasked_x = unmasked; - this->controle_device.ecdhEncode(AKout_x, unmasked_x); + this->controle_device->ecdhEncode(unmasked_x, AKout_x); #endif reset_buffer(); @@ -1543,7 +1591,7 @@ namespace hw { #ifdef DEBUG_HWDEVICE const rct::key AKout_x = hw::ledger::decrypt(AKout); rct::ecdhTuple masked_x = masked; - this->controle_device.ecdhDecode(AKout_x, masked_x); + this->controle_device->ecdhDecode(masked_x, AKout_x); #endif reset_buffer(); @@ -1604,7 +1652,7 @@ namespace hw { const rct::keyV hashes_x = hashes; const rct::ctkeyV outPk_x = outPk; rct::key prehash_x; - this->controle_device.mlsag_prehash(blob_x, inputs_size_x, outputs_size_x, hashes_x, outPk_x, prehash_x); + this->controle_device->mlsag_prehash(blob_x, inputs_size_x, outputs_size_x, hashes_x, outPk_x, prehash_x); if (inputs_size) { log_message("mlsag_prehash", (std::string("inputs_size not null: ") + std::to_string(inputs_size)).c_str()); } @@ -1629,6 +1677,7 @@ namespace hw { offset += 1; //type + uint8_t type = data[0]; this->buffer_send[offset] = data[0]; offset += 1; @@ -1648,25 +1697,27 @@ namespace hw { this->exchange(); //pseudoOuts - for ( i = 0; i < inputs_size; i++) { - reset_buffer(); - this->buffer_send[0] = 0x00; - this->buffer_send[1] = INS_VALIDATE; - this->buffer_send[2] = 0x01; - this->buffer_send[3] = i+2; - this->buffer_send[4] = 0x00; - offset = 5; - //options - this->buffer_send[offset] = (i==inputs_size-1)? 0x00:0x80; - offset += 1; - //pseudoOut - memmove(this->buffer_send+offset, data+data_offset,32); - offset += 32; - data_offset += 32; - - this->buffer_send[4] = offset-5; - this->length_send = offset; - this->exchange(); + if ((type == rct::RCTTypeSimple) || (type == rct::RCTTypeSimpleBulletproof)) { + for ( i = 0; i < inputs_size; i++) { + reset_buffer(); + this->buffer_send[0] = 0x00; + this->buffer_send[1] = INS_VALIDATE; + this->buffer_send[2] = 0x01; + this->buffer_send[3] = i+2; + this->buffer_send[4] = 0x00; + offset = 5; + //options + this->buffer_send[offset] = (i==inputs_size-1)? 0x00:0x80; + offset += 1; + //pseudoOut + memmove(this->buffer_send+offset, data+data_offset,32); + offset += 32; + data_offset += 32; + + this->buffer_send[4] = offset-5; + this->length_send = offset; + this->exchange(); + } } // ====== Aout, Bout, AKout, C, v, k ====== @@ -1693,6 +1744,9 @@ namespace hw { this->buffer_send[offset] = (i==outputs_size-1)? 0x00:0x80 ; offset += 1; if (found) { + //is_subaddress + this->buffer_send[offset] = outKeys.is_subaddress; + offset++; //Aout memmove(this->buffer_send+offset, outKeys.Aout.bytes, 32); offset+=32; @@ -1703,8 +1757,8 @@ namespace hw { memmove(this->buffer_send+offset, outKeys.AKout.bytes, 32); offset+=32; } else { - // dummy: Aout Bout AKout - offset += 32*3; + // dummy: is_subaddress Aout Bout AKout + offset += 1+32*3; } //C memmove(this->buffer_send+offset, data+C_offset,32); @@ -1905,7 +1959,7 @@ namespace hw { #ifdef DEBUG_HWDEVICE const rct::keyV long_message_x = long_message; rct::key c_x; - this->controle_device.mlsag_hash(long_message_x, c_x); + this->controle_device->mlsag_hash(long_message_x, c_x); #endif cnt = long_message.size(); @@ -1964,7 +2018,7 @@ namespace hw { const int rows_x = rows; const int dsRows_x = dsRows; rct::keyV ss_x(ss.size()); - this->controle_device.mlsag_sign(c_x, xx_x, alpha_x, rows_x, dsRows_x, ss_x); + this->controle_device->mlsag_sign(c_x, xx_x, alpha_x, rows_x, dsRows_x, ss_x); #endif for (size_t j = 0; j < dsRows; j++) { diff --git a/src/device/device_ledger.hpp b/src/device/device_ledger.hpp index ab8e0c553..e06c5f72c 100644 --- a/src/device/device_ledger.hpp +++ b/src/device/device_ledger.hpp @@ -56,12 +56,13 @@ namespace hw { public: rct::key Aout; rct::key Bout; + bool is_subaddress; size_t index; rct::key Pout; rct::key AKout; - ABPkeys(const rct::key& A, const rct::key& B, size_t index, const rct::key& P,const rct::key& AK); + ABPkeys(const rct::key& A, const rct::key& B, const bool is_subaddr, size_t index, const rct::key& P,const rct::key& AK); ABPkeys(const ABPkeys& keys) ; - ABPkeys() {index=0;} + ABPkeys() {index=0;is_subaddress=false;} }; class Keymap { @@ -103,8 +104,8 @@ namespace hw { unsigned int exchange(unsigned int ok=0x9000, unsigned int mask=0xFFFF); void reset_buffer(void); - #ifdef DEBUGLEDGER - Device &controle_device; + #ifdef DEBUG_HWDEVICE + device *controle_device; #endif public: @@ -141,10 +142,10 @@ namespace hw { /* SUB ADDRESS */ /* ======================================================================= */ bool derive_subaddress_public_key(const crypto::public_key &pub, const crypto::key_derivation &derivation, const std::size_t output_index, crypto::public_key &derived_pub) override; - bool get_subaddress_spend_public_key(const cryptonote::account_keys& keys, const cryptonote::subaddress_index& index, crypto::public_key &D) override; - bool get_subaddress_spend_public_keys(const cryptonote::account_keys &keys, uint32_t account, uint32_t begin, uint32_t end, std::vector<crypto::public_key> &pkeys) override; - bool get_subaddress(const cryptonote::account_keys& keys, const cryptonote::subaddress_index &index, cryptonote::account_public_address &address) override; - bool get_subaddress_secret_key(const crypto::secret_key &sec, const cryptonote::subaddress_index &index, crypto::secret_key &sub_sec) override; + crypto::public_key get_subaddress_spend_public_key(const cryptonote::account_keys& keys, const cryptonote::subaddress_index& index) override; + std::vector<crypto::public_key> get_subaddress_spend_public_keys(const cryptonote::account_keys &keys, uint32_t account, uint32_t begin, uint32_t end) override; + cryptonote::account_public_address get_subaddress(const cryptonote::account_keys& keys, const cryptonote::subaddress_index &index) override; + crypto::secret_key get_subaddress_secret_key(const crypto::secret_key &sec, const cryptonote::subaddress_index &index) override; /* ======================================================================= */ /* DERIVATION & KEY */ @@ -153,7 +154,7 @@ namespace hw { bool scalarmultKey(rct::key & aP, const rct::key &P, const rct::key &a) override; bool scalarmultBase(rct::key &aG, const rct::key &a) override; bool sc_secret_add(crypto::secret_key &r, const crypto::secret_key &a, const crypto::secret_key &b) override; - bool generate_keys(crypto::public_key &pub, crypto::secret_key &sec, const crypto::secret_key& recovery_key, bool recover, crypto::secret_key &rng) override; + crypto::secret_key generate_keys(crypto::public_key &pub, crypto::secret_key &sec, const crypto::secret_key& recovery_key = crypto::secret_key(), bool recover = false) override; bool generate_key_derivation(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_derivation &derivation) override; bool derivation_to_scalar(const crypto::key_derivation &derivation, const size_t output_index, crypto::ec_scalar &res) override; bool derive_secret_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::secret_key &sec, crypto::secret_key &derived_sec) override; @@ -169,13 +170,13 @@ namespace hw { bool set_signature_mode(unsigned int sig_mode) override; - bool encrypt_payment_id(const crypto::public_key &public_key, const crypto::secret_key &secret_key, crypto::hash8 &payment_id ) override; + bool encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key) override; bool ecdhEncode(rct::ecdhTuple & unmasked, const rct::key & sharedSec) override; bool ecdhDecode(rct::ecdhTuple & masked, const rct::key & sharedSec) override; - bool add_output_key_mapping(const crypto::public_key &Aout, const crypto::public_key &Bout, size_t real_output_index, - const rct::key &amount_key, const crypto::public_key &out_eph_public_key) override; + bool add_output_key_mapping(const crypto::public_key &Aout, const crypto::public_key &Bout, const bool is_subaddress, const size_t real_output_index, + const rct::key &amount_key, const crypto::public_key &out_eph_public_key) override; bool mlsag_prehash(const std::string &blob, size_t inputs_size, size_t outputs_size, const rct::keyV &hashes, const rct::ctkeyV &outPk, rct::key &prehash) override; @@ -190,7 +191,7 @@ namespace hw { - #ifdef DEBUGLEDGER + #ifdef DEBUG_HWDEVICE extern crypto::secret_key viewkey; extern crypto::secret_key spendkey; #endif diff --git a/src/device/log.cpp b/src/device/log.cpp index 103b2b3ba..a2ad0f4f4 100644 --- a/src/device/log.cpp +++ b/src/device/log.cpp @@ -55,14 +55,14 @@ namespace hw { MDEBUG(msg << ": " << info); } - #ifdef DEBUGLEDGER + #ifdef DEBUG_HWDEVICE extern crypto::secret_key viewkey; extern crypto::secret_key spendkey; void decrypt(char* buf, size_t len) { - #ifdef IODUMMYCRYPT - int i; + #ifdef IODUMMYCRYPT_HWDEVICE + size_t i; if (len == 32) { //view key? for (i = 0; i<32; i++) { @@ -144,7 +144,7 @@ namespace hw { log_hexbuffer(" device", dd, len); } else { - buffer_to_str(logstr, dd, len); + buffer_to_str(logstr, 128, dd, len); log_message("ASSERT EQ OK", msg + ": "+ info + ": "+ std::string(logstr) ); } } diff --git a/src/gen_multisig/gen_multisig.cpp b/src/gen_multisig/gen_multisig.cpp index 9bcf4495c..e165b8053 100644 --- a/src/gen_multisig/gen_multisig.cpp +++ b/src/gen_multisig/gen_multisig.cpp @@ -73,11 +73,12 @@ namespace const command_line::arg_descriptor<uint32_t> arg_threshold = {"threshold", genms::tr("How many signers are required to sign a valid transaction"), 0}; const command_line::arg_descriptor<bool, false> arg_testnet = {"testnet", genms::tr("Create testnet multisig wallets"), false}; const command_line::arg_descriptor<bool, false> arg_stagenet = {"stagenet", genms::tr("Create stagenet multisig wallets"), false}; + const command_line::arg_descriptor<bool, false> arg_create_address_file = {"create-address-file", genms::tr("Create an address file for new wallets"), false}; const command_line::arg_descriptor< std::vector<std::string> > arg_command = {"command", ""}; } -static bool generate_multisig(uint32_t threshold, uint32_t total, const std::string &basename, network_type nettype) +static bool generate_multisig(uint32_t threshold, uint32_t total, const std::string &basename, network_type nettype, bool create_address_file) { tools::msg_writer() << (boost::format(genms::tr("Generating %u %u/%u multisig wallets")) % total % threshold % total).str(); @@ -92,7 +93,7 @@ static bool generate_multisig(uint32_t threshold, uint32_t total, const std::str std::string name = basename + "-" + std::to_string(n + 1); wallets[n].reset(new tools::wallet2(nettype)); wallets[n]->init(""); - wallets[n]->generate(name, pwd_container->password(), rct::rct2sk(rct::skGen()), false, false); + wallets[n]->generate(name, pwd_container->password(), rct::rct2sk(rct::skGen()), false, false, create_address_file); } // gather the keys @@ -171,6 +172,7 @@ int main(int argc, char* argv[]) command_line::add_arg(desc_params, arg_participants); command_line::add_arg(desc_params, arg_testnet); command_line::add_arg(desc_params, arg_stagenet); + command_line::add_arg(desc_params, arg_create_address_file); const auto vm = wallet_args::main( argc, argv, @@ -241,7 +243,8 @@ int main(int argc, char* argv[]) tools::fail_msg_writer() << genms::tr("Error: unsupported scheme: only N/N and N-1/N are supported"); return 1; } - if (!generate_multisig(threshold, total, basename, testnet ? TESTNET : stagenet ? STAGENET : MAINNET)) + bool create_address_file = command_line::get_arg(*vm, arg_create_address_file); + if (!generate_multisig(threshold, total, basename, testnet ? TESTNET : stagenet ? STAGENET : MAINNET, create_address_file)) return 1; return 0; diff --git a/src/multisig/multisig.cpp b/src/multisig/multisig.cpp index 91042d58a..d85c47772 100644 --- a/src/multisig/multisig.cpp +++ b/src/multisig/multisig.cpp @@ -33,7 +33,6 @@ #include "cryptonote_basic/account.h" #include "cryptonote_basic/cryptonote_format_utils.h" #include "multisig.h" -#include "device/device_default.hpp" #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "multisig" diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index 8ef240326..54875e619 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -422,9 +422,11 @@ namespace nodetool memcpy(&m_network_id, &::config::stagenet::NETWORK_ID, 16); full_addrs = get_seed_nodes(cryptonote::STAGENET); } - else if (m_exclusive_peers.empty()) + else { memcpy(&m_network_id, &::config::NETWORK_ID, 16); + if (m_exclusive_peers.empty()) + { // for each hostname in the seed nodes list, attempt to DNS resolve and // add the result addresses as seed nodes // TODO: at some point add IPv6 support, but that won't be relevant @@ -505,6 +507,7 @@ namespace nodetool full_addrs.insert(peer); } } + } for (const auto& full_addr : full_addrs) { diff --git a/src/ringct/CMakeLists.txt b/src/ringct/CMakeLists.txt index 2d3ea5cf4..c8dcdca26 100644 --- a/src/ringct/CMakeLists.txt +++ b/src/ringct/CMakeLists.txt @@ -26,21 +26,39 @@ # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF # THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -set(ringct_sources +set(ringct_basic_sources rctOps.cpp - rctOps_device.cpp - rctSigs.cpp rctTypes.cpp rctCryptoOps.c bulletproofs.cc) +set(ringct_basic_private_headers + rctOps.h + rctTypes.h + bulletproofs.h) + +monero_private_headers(ringct_basic + ${crypto_private_headers}) +monero_add_library(ringct_basic + ${ringct_basic_sources} + ${ringct_basic_private_headers}) +target_link_libraries(ringct_basic + PUBLIC + common + cncrypto + PRIVATE + ${OPENSSL_LIBRARIES} + ${EXTRA_LIBRARIES}) + +set(ringct_sources + rctSigs.cpp +) + set(ringct_headers) set(ringct_private_headers - rctOps.h rctSigs.h - rctTypes.h - bulletproofs.h) +) monero_private_headers(ringct ${crypto_private_headers}) diff --git a/src/ringct/rctOps.h b/src/ringct/rctOps.h index c9f2e7a43..3f8f6955c 100644 --- a/src/ringct/rctOps.h +++ b/src/ringct/rctOps.h @@ -112,14 +112,10 @@ namespace rct { //does a * G where a is a scalar and G is the curve basepoint void scalarmultBase(key & aG, const key &a); - void scalarmultBase(key & aG, const key &a, hw::device &hwdev); key scalarmultBase(const key & a); - key scalarmultBase(const key & a, hw::device &hwdev); //does a * P where a is a scalar and P is an arbitrary point void scalarmultKey(key &aP, const key &P, const key &a); - void scalarmultKey(key &aP, const key &P, const key &a, hw::device &hwdev); key scalarmultKey(const key &P, const key &a); - key scalarmultKey(const key &P, const key &a, hw::device &hwdev); //Computes aH where H= toPoint(cn_fast_hash(G)), G the basepoint key scalarmultH(const key & a); @@ -178,8 +174,6 @@ namespace rct { //Elliptic Curve Diffie Helman: encodes and decodes the amount b and mask a // where C= aG + bH void ecdhEncode(ecdhTuple & unmasked, const key & sharedSec); - void ecdhEncode(ecdhTuple & unmasked, const key & sharedSec, hw::device &hwdev); void ecdhDecode(ecdhTuple & masked, const key & sharedSec); - void ecdhDecode(ecdhTuple & masked, const key & sharedSec, hw::device &hwdev); } #endif /* RCTOPS_H */ diff --git a/src/ringct/rctOps_device.cpp b/src/ringct/rctOps_device.cpp deleted file mode 100644 index fbfe8e9cf..000000000 --- a/src/ringct/rctOps_device.cpp +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) 2017-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#include "misc_log_ex.h" -#include "rctOps.h" -#include "device/device.hpp" -using namespace crypto; -using namespace std; - - -namespace rct -{ - void scalarmultKey(key & aP, const key &P, const key &a, hw::device &hwdev) { - hwdev.scalarmultKey(aP, P, a); - } - - key scalarmultKey(const key & P, const key & a, hw::device &hwdev) { - key aP; - hwdev.scalarmultKey(aP, P, a); - return aP; - } - - void scalarmultBase(key &aG, const key &a, hw::device &hwdev) { - hwdev.scalarmultBase(aG, a); - } - - key scalarmultBase(const key & a, hw::device &hwdev) { - key aG; - hwdev.scalarmultBase(aG, a); - return aG; - } - - void ecdhDecode(ecdhTuple & masked, const key & sharedSec, hw::device &hwdev) { - hwdev.ecdhDecode(masked, sharedSec); - } - - void ecdhEncode(ecdhTuple & unmasked, const key & sharedSec, hw::device &hwdev) { - hwdev.ecdhEncode(unmasked, sharedSec); - } -}
\ No newline at end of file diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp index ae0ee21c8..4ecf62cec 100644 --- a/src/ringct/rctSigs.cpp +++ b/src/ringct/rctSigs.cpp @@ -35,9 +35,6 @@ #include "rctSigs.h" #include "bulletproofs.h" #include "cryptonote_basic/cryptonote_format_utils.h" -#include "cryptonote_basic/cryptonote_basic.h" -#include "cryptonote_basic/subaddress_index.h" -#include "device/device.hpp" using namespace crypto; using namespace std; @@ -118,19 +115,32 @@ namespace rct { } //see above. - bool verifyBorromean(const boroSig &bb, const key64 P1, const key64 P2) { + bool verifyBorromean(const boroSig &bb, const ge_p3 P1[64], const ge_p3 P2[64]) { key64 Lv1; key chash, LL; int ii = 0; + ge_p2 p2; for (ii = 0 ; ii < 64 ; ii++) { - addKeys2(LL, bb.s0[ii], bb.ee, P1[ii]); + // equivalent of: addKeys2(LL, bb.s0[ii], bb.ee, P1[ii]); + ge_double_scalarmult_base_vartime(&p2, bb.ee.bytes, &P1[ii], bb.s0[ii].bytes); + ge_tobytes(LL.bytes, &p2); chash = hash_to_scalar(LL); - addKeys2(Lv1[ii], bb.s1[ii], chash, P2[ii]); + // equivalent of: addKeys2(Lv1[ii], bb.s1[ii], chash, P2[ii]); + ge_double_scalarmult_base_vartime(&p2, chash.bytes, &P2[ii], bb.s1[ii].bytes); + ge_tobytes(Lv1[ii].bytes, &p2); } key eeComputed = hash_to_scalar(Lv1); //hash function fine return equalKeys(eeComputed, bb.ee); } - + bool verifyBorromean(const boroSig &bb, const key64 P1, const key64 P2) { + ge_p3 P1_p3[64], P2_p3[64]; + for (size_t i = 0 ; i < 64 ; ++i) { + CHECK_AND_ASSERT_MES(ge_frombytes_vartime(&P1_p3[i], P1[i].bytes) == 0, false, "point conv failed"); + CHECK_AND_ASSERT_MES(ge_frombytes_vartime(&P2_p3[i], P2[i].bytes) == 0, false, "point conv failed"); + } + return verifyBorromean(bb, P1_p3, P2_p3); + } + //Multilayered Spontaneous Anonymous Group Signatures (MLSAG signatures) //This is a just slghtly more efficient version than the ones described below //(will be explained in more detail in Ring Multisig paper @@ -336,16 +346,30 @@ namespace rct { try { PERF_TIMER(verRange); - key64 CiH; + ge_p3 CiH[64], asCi[64]; int i = 0; - key Ctmp = identity(); + ge_p3 Ctmp_p3 = ge_p3_identity; for (i = 0; i < 64; i++) { - subKeys(CiH[i], as.Ci[i], H2[i]); - addKeys(Ctmp, Ctmp, as.Ci[i]); + // faster equivalent of: + // subKeys(CiH[i], as.Ci[i], H2[i]); + // addKeys(Ctmp, Ctmp, as.Ci[i]); + ge_cached cached; + ge_p3 p3; + ge_p1p1 p1; + CHECK_AND_ASSERT_MES(ge_frombytes_vartime(&p3, H2[i].bytes) == 0, false, "point conv failed"); + ge_p3_to_cached(&cached, &p3); + CHECK_AND_ASSERT_MES(ge_frombytes_vartime(&asCi[i], as.Ci[i].bytes) == 0, false, "point conv failed"); + ge_sub(&p1, &asCi[i], &cached); + ge_p3_to_cached(&cached, &asCi[i]); + ge_p1p1_to_p3(&CiH[i], &p1); + ge_add(&p1, &Ctmp_p3, &cached); + ge_p1p1_to_p3(&Ctmp_p3, &p1); } + key Ctmp; + ge_p3_tobytes(Ctmp.bytes, &Ctmp_p3); if (!equalKeys(C, Ctmp)) return false; - if (!verifyBorromean(as.asig, as.Ci, CiH)) + if (!verifyBorromean(as.asig, asCi, CiH)) return false; return true; } @@ -669,7 +693,7 @@ namespace rct { //mask amount and mask rv.ecdhInfo[i].mask = copy(outSk[i].mask); rv.ecdhInfo[i].amount = d2h(amounts[i]); - ecdhEncode(rv.ecdhInfo[i], amount_keys[i], hwdev); + hwdev.ecdhEncode(rv.ecdhInfo[i], amount_keys[i]); } //set txn fee @@ -750,7 +774,7 @@ namespace rct { //mask amount and mask rv.ecdhInfo[i].mask = copy(outSk[i].mask); rv.ecdhInfo[i].amount = d2h(outamounts[i]); - ecdhEncode(rv.ecdhInfo[i], amount_keys[i],hwdev); + hwdev.ecdhEncode(rv.ecdhInfo[i], amount_keys[i]); } //set txn fee @@ -1007,7 +1031,7 @@ namespace rct { //mask amount and mask ecdhTuple ecdh_info = rv.ecdhInfo[i]; - ecdhDecode(ecdh_info, sk, hwdev); + hwdev.ecdhDecode(ecdh_info, sk); mask = ecdh_info.mask; key amount = ecdh_info.amount; key C = rv.outPk[i].mask; @@ -1035,7 +1059,7 @@ namespace rct { //mask amount and mask ecdhTuple ecdh_info = rv.ecdhInfo[i]; - ecdhDecode(ecdh_info, sk, hwdev); + hwdev.ecdhDecode(ecdh_info, sk); mask = ecdh_info.mask; key amount = ecdh_info.amount; key C = rv.outPk[i].mask; diff --git a/src/ringct/rctSigs.h b/src/ringct/rctSigs.h index 7485938ee..b8aab0f11 100644 --- a/src/ringct/rctSigs.h +++ b/src/ringct/rctSigs.h @@ -50,8 +50,6 @@ extern "C" { #include "rctTypes.h" #include "rctOps.h" -#include "cryptonote_basic/cryptonote_basic.h" -#include "device/device_declare.hpp" //Define this flag when debugging to get additional info on the console #ifdef DBG @@ -60,6 +58,9 @@ extern "C" { #define DP(x) #endif +namespace hw { + class device; +} namespace rct { diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index cbb174e1a..3668df7b9 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -62,7 +62,6 @@ #include "ringct/rctSigs.h" #include "multisig/multisig.h" #include "wallet/wallet_args.h" -#include "device/device.hpp" #include <stdexcept> #ifdef WIN32 @@ -134,6 +133,7 @@ namespace const command_line::arg_descriptor<bool> arg_allow_mismatched_daemon_version = {"allow-mismatched-daemon-version", sw::tr("Allow communicating with a daemon that uses a different RPC version"), false}; const command_line::arg_descriptor<uint64_t> arg_restore_height = {"restore-height", sw::tr("Restore from specific blockchain height"), 0}; const command_line::arg_descriptor<bool> arg_do_not_relay = {"do-not-relay", sw::tr("The newly created transaction will not be relayed to the monero network"), false}; + const command_line::arg_descriptor<bool> arg_create_address_file = {"create-address-file", sw::tr("Create an address file for new wallets"), false}; const command_line::arg_descriptor< std::vector<std::string> > arg_command = {"command", ""}; @@ -2848,10 +2848,12 @@ bool simple_wallet::new_wallet(const boost::program_options::variables_map& vm, m_wallet->set_seed_language(mnemonic_language); + bool create_address_file = command_line::get_arg(vm, arg_create_address_file); + crypto::secret_key recovery_val; try { - recovery_val = m_wallet->generate(m_wallet_file, std::move(rc.second).password(), recovery_key, recover, two_random); + recovery_val = m_wallet->generate(m_wallet_file, std::move(rc.second).password(), recovery_key, recover, two_random, create_address_file); message_writer(console_color_white, true) << tr("Generated new wallet: ") << m_wallet->get_account().get_public_address_str(m_wallet->nettype()); std::cout << tr("View key: ") << string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_view_secret_key) << ENDL; @@ -2900,15 +2902,17 @@ bool simple_wallet::new_wallet(const boost::program_options::variables_map& vm, if (m_restore_height) m_wallet->set_refresh_from_block_height(m_restore_height); + bool create_address_file = command_line::get_arg(vm, arg_create_address_file); + try { if (spendkey) { - m_wallet->generate(m_wallet_file, std::move(rc.second).password(), address, *spendkey, viewkey); + m_wallet->generate(m_wallet_file, std::move(rc.second).password(), address, *spendkey, viewkey, create_address_file); } else { - m_wallet->generate(m_wallet_file, std::move(rc.second).password(), address, viewkey); + m_wallet->generate(m_wallet_file, std::move(rc.second).password(), address, viewkey, create_address_file); } message_writer(console_color_white, true) << tr("Generated new wallet: ") << m_wallet->get_account().get_public_address_str(m_wallet->nettype()); @@ -2971,9 +2975,11 @@ bool simple_wallet::new_wallet(const boost::program_options::variables_map& vm, m_wallet->set_seed_language(mnemonic_language); + bool create_address_file = command_line::get_arg(vm, arg_create_address_file); + try { - m_wallet->generate(m_wallet_file, std::move(rc.second).password(), multisig_keys); + m_wallet->generate(m_wallet_file, std::move(rc.second).password(), multisig_keys, create_address_file); bool ready; uint32_t threshold, total; if (!m_wallet->multisig(&ready, &threshold, &total) || !ready) @@ -3143,7 +3149,17 @@ bool simple_wallet::save_watch_only(const std::vector<std::string> &args/* = std return true; } - m_wallet->write_watch_only_wallet(m_wallet_file, pwd_container->password()); + try + { + std::string new_keys_filename; + m_wallet->write_watch_only_wallet(m_wallet_file, pwd_container->password(), new_keys_filename); + success_msg_writer() << tr("Watch only wallet saved as: ") << new_keys_filename; + } + catch (const std::exception &e) + { + fail_msg_writer() << tr("Failed to save watch only wallet: ") << e.what(); + return true; + } return true; } @@ -5862,8 +5878,7 @@ std::string simple_wallet::get_prompt() const { std::string addr_start = m_wallet->get_subaddress_as_str({m_current_subaddress_account, 0}).substr(0, 6); std::string prompt = std::string("[") + tr("wallet") + " " + addr_start; - uint32_t version; - if (!m_wallet->check_connection(&version)) + if (!m_wallet->check_connection(NULL)) prompt += tr(" (no daemon)"); else if (!m_wallet->is_synced()) prompt += tr(" (out of sync)"); @@ -6979,6 +6994,7 @@ int main(int argc, char* argv[]) command_line::add_arg(desc_params, arg_allow_mismatched_daemon_version); command_line::add_arg(desc_params, arg_restore_height); command_line::add_arg(desc_params, arg_do_not_relay); + command_line::add_arg(desc_params, arg_create_address_file); po::positional_options_description positional_options; positional_options.add(arg_command.name, -1); diff --git a/src/wallet/CMakeLists.txt b/src/wallet/CMakeLists.txt index c6d0bd9da..d82e1dace 100644 --- a/src/wallet/CMakeLists.txt +++ b/src/wallet/CMakeLists.txt @@ -111,7 +111,9 @@ if (BUILD_GUI_DEPS) mnemonics common cncrypto + device ringct + ringct_basic checkpoints version) diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index ff0d2fdbd..fb9e8b28b 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -306,8 +306,20 @@ void Wallet::init(const char *argv0, const char *default_log_base_name) { mlog_configure(mlog_get_default_log_path(default_log_base_name), true); } -void Wallet::debug(const std::string &str) { - MDEBUG(str); +void Wallet::debug(const std::string &category, const std::string &str) { + MCDEBUG(category.empty() ? MONERO_DEFAULT_LOG_CATEGORY : category.c_str(), str); +} + +void Wallet::info(const std::string &category, const std::string &str) { + MCINFO(category.empty() ? MONERO_DEFAULT_LOG_CATEGORY : category.c_str(), str); +} + +void Wallet::warning(const std::string &category, const std::string &str) { + MCWARNING(category.empty() ? MONERO_DEFAULT_LOG_CATEGORY : category.c_str(), str); +} + +void Wallet::error(const std::string &category, const std::string &str) { + MCERROR(category.empty() ? MONERO_DEFAULT_LOG_CATEGORY : category.c_str(), str); } ///////////////////////// WalletImpl implementation //////////////////////// diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h index 36b3b9c9b..87c1cccfa 100644 --- a/src/wallet/api/wallet2_api.h +++ b/src/wallet/api/wallet2_api.h @@ -556,7 +556,10 @@ struct Wallet static uint64_t maximumAllowedAmount(); // Easylogger wrapper static void init(const char *argv0, const char *default_log_base_name); - static void debug(const std::string &str); + static void debug(const std::string &category, const std::string &str); + static void info(const std::string &category, const std::string &str); + static void warning(const std::string &category, const std::string &str); + static void error(const std::string &category, const std::string &str); /** * @brief StartRefresh - Start/resume refresh thread (refresh every 10 seconds) @@ -774,7 +777,7 @@ struct WalletManager * \param nettype Network type * \return Wallet instance (Wallet::status() needs to be called to check if created successfully) */ - virtual Wallet * createWallet(const std::string &path, const std::string &password, const std::string &language, NetworkType nettype = MAINNET) = 0; + virtual Wallet * createWallet(const std::string &path, const std::string &password, const std::string &language, NetworkType nettype) = 0; Wallet * createWallet(const std::string &path, const std::string &password, const std::string &language, bool testnet = false) // deprecated { return createWallet(path, password, language, testnet ? TESTNET : MAINNET); @@ -787,7 +790,7 @@ struct WalletManager * \param nettype Network type * \return Wallet instance (Wallet::status() needs to be called to check if opened successfully) */ - virtual Wallet * openWallet(const std::string &path, const std::string &password, NetworkType nettype = MAINNET) = 0; + virtual Wallet * openWallet(const std::string &path, const std::string &password, NetworkType nettype) = 0; Wallet * openWallet(const std::string &path, const std::string &password, bool testnet = false) // deprecated { return openWallet(path, password, testnet ? TESTNET : MAINNET); @@ -819,7 +822,7 @@ struct WalletManager * \param restoreHeight restore from start height * \return Wallet instance (Wallet::status() needs to be called to check if recovered successfully) */ - virtual Wallet * recoveryWallet(const std::string &path, const std::string &mnemonic, NetworkType nettype = MAINNET, uint64_t restoreHeight = 0) = 0; + virtual Wallet * recoveryWallet(const std::string &path, const std::string &mnemonic, NetworkType nettype, uint64_t restoreHeight = 0) = 0; Wallet * recoveryWallet(const std::string &path, const std::string &mnemonic, bool testnet = false, uint64_t restoreHeight = 0) // deprecated { return recoveryWallet(path, mnemonic, testnet ? TESTNET : MAINNET, restoreHeight); diff --git a/src/wallet/api/wallet_manager.cpp b/src/wallet/api/wallet_manager.cpp index b03332f40..80f5780b5 100644 --- a/src/wallet/api/wallet_manager.cpp +++ b/src/wallet/api/wallet_manager.cpp @@ -37,7 +37,6 @@ #include "common/updates.h" #include "version.h" #include "net/http_client.h" -#include "device/device.hpp" #include <boost/filesystem.hpp> #include <boost/regex.hpp> diff --git a/src/wallet/node_rpc_proxy.cpp b/src/wallet/node_rpc_proxy.cpp index a9562291e..f11ff9295 100644 --- a/src/wallet/node_rpc_proxy.cpp +++ b/src/wallet/node_rpc_proxy.cpp @@ -116,7 +116,7 @@ void NodeRPCProxy::set_height(uint64_t h) boost::optional<std::string> NodeRPCProxy::get_target_height(uint64_t &height) const { const time_t now = time(NULL); - if (m_height == 0 || now >= m_height_time + 30) // re-cache every 30 seconds + if (m_target_height == 0 || now >= m_target_height_time + 30) // re-cache every 30 seconds { epee::json_rpc::request<cryptonote::COMMAND_RPC_GET_INFO::request> req_t = AUTO_VAL_INIT(req_t); epee::json_rpc::response<cryptonote::COMMAND_RPC_GET_INFO::response, std::string> resp_t = AUTO_VAL_INIT(resp_t); diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 96224e81b..fcc7a73d0 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -66,7 +66,6 @@ using namespace epee; #include "memwipe.h" #include "common/base58.h" #include "ringct/rctSigs.h" -#include "device/device.hpp" extern "C" { @@ -318,10 +317,13 @@ std::unique_ptr<tools::wallet2> generate_from_json(const std::string& json_file, GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, address, std::string, String, false, std::string()); + GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, create_address_file, int, Int, false, false); + bool create_address_file = field_create_address_file; + // compatibility checks if (!field_seed_found && !field_viewkey_found && !field_spendkey_found) { - THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("At least one of Electrum-style word list and private view key and private spend key must be specified")); + THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("At least one of either an Electrum-style word list, private view key, or private spend key must be specified")); } if (field_seed_found && (field_viewkey_found || field_spendkey_found)) { @@ -372,11 +374,11 @@ std::unique_ptr<tools::wallet2> generate_from_json(const std::string& json_file, { if (!field_seed.empty()) { - wallet->generate(field_filename, field_password, recovery_key, recover, false); + wallet->generate(field_filename, field_password, recovery_key, recover, false, create_address_file); } else if (field_viewkey.empty() && !field_spendkey.empty()) { - wallet->generate(field_filename, field_password, spendkey, recover, false); + wallet->generate(field_filename, field_password, spendkey, recover, false, create_address_file); } else { @@ -402,14 +404,14 @@ std::unique_ptr<tools::wallet2> generate_from_json(const std::string& json_file, { THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("Address must be specified in order to create watch-only wallet")); } - wallet->generate(field_filename, field_password, address, viewkey); + wallet->generate(field_filename, field_password, address, viewkey, create_address_file); } else { if (!crypto::secret_key_to_public_key(spendkey, address.m_spend_public_key)) { THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("failed to verify spend key secret key")); } - wallet->generate(field_filename, field_password, address, spendkey, viewkey); + wallet->generate(field_filename, field_password, address, spendkey, viewkey, create_address_file); } } } @@ -558,7 +560,7 @@ crypto::hash8 get_short_payment_id(const tools::wallet2::pending_tx &ptx, hw::de MWARNING("Encrypted payment id found, but no destinations public key, cannot decrypt"); return crypto::null_hash8; } - decrypt_payment_id(payment_id8, ptx.dests[0].addr.m_view_public_key, ptx.tx_key, hwdev); + hwdev.decrypt_payment_id(payment_id8, ptx.dests[0].addr.m_view_public_key, ptx.tx_key); } } return payment_id8; @@ -582,6 +584,14 @@ tools::wallet2::tx_construction_data get_construction_data_with_decrypted_short_ return construction_data; } +uint32_t get_subaddress_clamped_sum(uint32_t idx, uint32_t extra) +{ + static constexpr uint32_t uint32_max = std::numeric_limits<uint32_t>::max(); + if (idx > uint32_max - extra) + return uint32_max; + return idx + extra; +} + //----------------------------------------------------------------- } //namespace @@ -829,18 +839,14 @@ void wallet2::set_seed_language(const std::string &language) //---------------------------------------------------------------------------------------------------- cryptonote::account_public_address wallet2::get_subaddress(const cryptonote::subaddress_index& index) const { - cryptonote::account_public_address address; hw::device &hwdev = m_account.get_device(); - hwdev.get_subaddress(m_account.get_keys(), index,address); - return address; + return hwdev.get_subaddress(m_account.get_keys(), index); } //---------------------------------------------------------------------------------------------------- crypto::public_key wallet2::get_subaddress_spend_public_key(const cryptonote::subaddress_index& index) const { - crypto::public_key D ; hw::device &hwdev = m_account.get_device(); - hwdev.get_subaddress_spend_public_key(m_account.get_keys(), index, D); - return D; + return hwdev.get_subaddress_spend_public_key(m_account.get_keys(), index); } //---------------------------------------------------------------------------------------------------- std::string wallet2::get_subaddress_as_str(const cryptonote::subaddress_index& index) const @@ -876,10 +882,11 @@ void wallet2::expand_subaddresses(const cryptonote::subaddress_index& index) { // add new accounts cryptonote::subaddress_index index2; - for (index2.major = m_subaddress_labels.size(); index2.major < index.major + m_subaddress_lookahead_major; ++index2.major) + const uint32_t major_end = get_subaddress_clamped_sum(index.major, m_subaddress_lookahead_major); + for (index2.major = m_subaddress_labels.size(); index2.major < major_end; ++index2.major) { - const uint32_t end = (index2.major == index.major ? index.minor : 0) + m_subaddress_lookahead_minor; - const std::vector<crypto::public_key> pkeys = cryptonote::get_subaddress_spend_public_keys(m_account.get_keys(), index2.major, 0, end, hwdev); + const uint32_t end = get_subaddress_clamped_sum((index2.major == index.major ? index.minor : 0), m_subaddress_lookahead_minor); + const std::vector<crypto::public_key> pkeys = hwdev.get_subaddress_spend_public_keys(m_account.get_keys(), index2.major, 0, end); for (index2.minor = 0; index2.minor < end; ++index2.minor) { const crypto::public_key &D = pkeys[index2.minor]; @@ -892,10 +899,10 @@ void wallet2::expand_subaddresses(const cryptonote::subaddress_index& index) else if (m_subaddress_labels[index.major].size() <= index.minor) { // add new subaddresses - const uint32_t end = index.minor + m_subaddress_lookahead_minor; + const uint32_t end = get_subaddress_clamped_sum(index.minor, m_subaddress_lookahead_minor); const uint32_t begin = m_subaddress_labels[index.major].size(); cryptonote::subaddress_index index2 = {index.major, begin}; - const std::vector<crypto::public_key> pkeys = cryptonote::get_subaddress_spend_public_keys(m_account.get_keys(), index2.major, index2.minor, end, hwdev); + const std::vector<crypto::public_key> pkeys = hwdev.get_subaddress_spend_public_keys(m_account.get_keys(), index2.major, index2.minor, end); for (; index2.minor < end; ++index2.minor) { const crypto::public_key &D = pkeys[index2.minor - begin]; @@ -924,6 +931,8 @@ void wallet2::set_subaddress_label(const cryptonote::subaddress_index& index, co //---------------------------------------------------------------------------------------------------- void wallet2::set_subaddress_lookahead(size_t major, size_t minor) { + THROW_WALLET_EXCEPTION_IF(major > 0xffffffff, error::wallet_internal_error, "Subaddress major lookahead is too large"); + THROW_WALLET_EXCEPTION_IF(minor > 0xffffffff, error::wallet_internal_error, "Subaddress minor lookahead is too large"); m_subaddress_lookahead_major = major; m_subaddress_lookahead_minor = minor; } @@ -975,7 +984,7 @@ void wallet2::check_acc_out_precomp(const tx_out &o, const crypto::key_derivatio static uint64_t decodeRct(const rct::rctSig & rv, const crypto::key_derivation &derivation, unsigned int i, rct::key & mask, hw::device &hwdev) { crypto::secret_key scalar1; - crypto::derivation_to_scalar(derivation, i, scalar1, hwdev); + hwdev.derivation_to_scalar(derivation, i, scalar1); try { switch (rv.type) @@ -1068,7 +1077,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote const cryptonote::account_keys& keys = m_account.get_keys(); hw::device &hwdev = m_account.get_device(); crypto::key_derivation derivation; - if (!generate_key_derivation(tx_pub_key, keys.m_view_secret_key, derivation, hwdev)) + if (!hwdev.generate_key_derivation(tx_pub_key, keys.m_view_secret_key, derivation)) { MWARNING("Failed to generate key derivation from tx pubkey, skipping"); static_assert(sizeof(derivation) == sizeof(rct::key), "Mismatched sizes of key_derivation and rct::key"); @@ -1081,7 +1090,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote for (size_t i = 0; i < additional_tx_pub_keys.size(); ++i) { additional_derivations.push_back({}); - if (!generate_key_derivation(additional_tx_pub_keys[i], keys.m_view_secret_key, additional_derivations.back(),hwdev)) + if (!hwdev.generate_key_derivation(additional_tx_pub_keys[i], keys.m_view_secret_key, additional_derivations.back())) { MWARNING("Failed to generate key derivation from tx pubkey, skipping"); additional_derivations.pop_back(); @@ -1373,7 +1382,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote LOG_PRINT_L2("Found encrypted payment ID: " << payment_id8); if (tx_pub_key != null_pkey) { - if (!decrypt_payment_id(payment_id8, tx_pub_key, m_account.get_keys().m_view_secret_key, m_account.get_device())) + if (!m_account.get_device().decrypt_payment_id(payment_id8, tx_pub_key, m_account.get_keys().m_view_secret_key)) { LOG_PRINT_L0("Failed to decrypt payment ID: " << payment_id8); } @@ -2182,6 +2191,11 @@ void wallet2::refresh(uint64_t start_height, uint64_t & blocks_fetched, bool& re std::list<cryptonote::block_complete_entry> next_blocks; std::vector<cryptonote::COMMAND_RPC_GET_BLOCKS_FAST::block_output_indices> next_o_indices; bool error = false; + if (blocks.empty()) + { + refreshed = false; + break; + } tpool.submit(&waiter, [&]{pull_next_blocks(start_height, next_blocks_start_height, short_chain_history, blocks, next_blocks, next_o_indices, error);}); process_blocks(blocks_start_height, blocks, o_indices, added_blocks); @@ -2740,7 +2754,7 @@ bool wallet2::verify_password(const std::string& keys_file_name, const epee::wip * \param multisig_data The multisig restore info and keys */ void wallet2::generate(const std::string& wallet_, const epee::wipeable_string& password, - const std::string& multisig_data) + const std::string& multisig_data, bool create_address_file) { clear(); prepare_file_names(wallet_); @@ -2812,8 +2826,11 @@ void wallet2::generate(const std::string& wallet_, const epee::wipeable_string& bool r = store_keys(m_keys_file, password, false); THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file); - r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype)); - if(!r) MERROR("String with address text not saved"); + if (m_nettype != MAINNET || create_address_file) + { + r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype)); + if(!r) MERROR("String with address text not saved"); + } } cryptonote::block b; @@ -2835,7 +2852,7 @@ void wallet2::generate(const std::string& wallet_, const epee::wipeable_string& * \return The secret key of the generated wallet */ crypto::secret_key wallet2::generate(const std::string& wallet_, const epee::wipeable_string& password, - const crypto::secret_key& recovery_param, bool recover, bool two_random) + const crypto::secret_key& recovery_param, bool recover, bool two_random, bool create_address_file) { clear(); prepare_file_names(wallet_); @@ -2866,8 +2883,11 @@ crypto::secret_key wallet2::generate(const std::string& wallet_, const epee::wip bool r = store_keys(m_keys_file, password, false); THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file); - r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype)); - if(!r) MERROR("String with address text not saved"); + if (m_nettype != MAINNET || create_address_file) + { + r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype)); + if(!r) MERROR("String with address text not saved"); + } } cryptonote::block b; @@ -2931,7 +2951,7 @@ crypto::secret_key wallet2::generate(const std::string& wallet_, const epee::wip */ void wallet2::generate(const std::string& wallet_, const epee::wipeable_string& password, const cryptonote::account_public_address &account_public_address, - const crypto::secret_key& viewkey) + const crypto::secret_key& viewkey, bool create_address_file) { clear(); prepare_file_names(wallet_); @@ -2956,8 +2976,11 @@ void wallet2::generate(const std::string& wallet_, const epee::wipeable_string& bool r = store_keys(m_keys_file, password, true); THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file); - r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype)); - if(!r) MERROR("String with address text not saved"); + if (m_nettype != MAINNET || create_address_file) + { + r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype)); + if(!r) MERROR("String with address text not saved"); + } } cryptonote::block b; @@ -2978,7 +3001,7 @@ void wallet2::generate(const std::string& wallet_, const epee::wipeable_string& */ void wallet2::generate(const std::string& wallet_, const epee::wipeable_string& password, const cryptonote::account_public_address &account_public_address, - const crypto::secret_key& spendkey, const crypto::secret_key& viewkey) + const crypto::secret_key& spendkey, const crypto::secret_key& viewkey, bool create_address_file) { clear(); prepare_file_names(wallet_); @@ -3003,8 +3026,11 @@ void wallet2::generate(const std::string& wallet_, const epee::wipeable_string& bool r = store_keys(m_keys_file, password, false); THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file); - r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype)); - if(!r) MERROR("String with address text not saved"); + if (m_nettype != MAINNET || create_address_file) + { + r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype)); + if(!r) MERROR("String with address text not saved"); + } } cryptonote::block b; @@ -3136,8 +3162,11 @@ std::string wallet2::make_multisig(const epee::wipeable_string &password, bool r = store_keys(m_keys_file, password, false); THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file); - r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype)); - if(!r) MERROR("String with address text not saved"); + if (boost::filesystem::exists(m_wallet_file + ".address.txt")) + { + r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype)); + if(!r) MERROR("String with address text not saved"); + } } cryptonote::block b; @@ -3236,8 +3265,11 @@ bool wallet2::finalize_multisig(const epee::wipeable_string &password, std::unor bool r = store_keys(m_keys_file, password, false); THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file); - r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype)); - if(!r) MERROR("String with address text not saved"); + if (boost::filesystem::exists(m_wallet_file + ".address.txt")) + { + r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype)); + if(!r) MERROR("String with address text not saved"); + } } m_subaddresses.clear(); @@ -3415,15 +3447,15 @@ void wallet2::rewrite(const std::string& wallet_name, const epee::wipeable_strin * \param wallet_name Base name of wallet file * \param password Password for wallet file */ -void wallet2::write_watch_only_wallet(const std::string& wallet_name, const epee::wipeable_string& password) +void wallet2::write_watch_only_wallet(const std::string& wallet_name, const epee::wipeable_string& password, std::string &new_keys_filename) { prepare_file_names(wallet_name); boost::system::error_code ignored_ec; - std::string filename = m_keys_file + "-watchonly"; - bool watch_only_keys_file_exists = boost::filesystem::exists(filename, ignored_ec); - THROW_WALLET_EXCEPTION_IF(watch_only_keys_file_exists, error::file_save_error, filename); - bool r = store_keys(filename, password, true); - THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, filename); + new_keys_filename = m_wallet_file + "-watchonly.keys"; + bool watch_only_keys_file_exists = boost::filesystem::exists(new_keys_filename, ignored_ec); + THROW_WALLET_EXCEPTION_IF(watch_only_keys_file_exists, error::file_save_error, new_keys_filename); + bool r = store_keys(new_keys_filename, password, true); + THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, new_keys_filename); } //---------------------------------------------------------------------------------------------------- void wallet2::wallet_exists(const std::string& file_path, bool& keys_file_exists, bool& wallet_file_exists) @@ -3760,10 +3792,13 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas prepare_file_names(path); bool r = store_keys(m_keys_file, password, false); THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file); - // save address to the new file - const std::string address_file = m_wallet_file + ".address.txt"; - r = file_io_utils::save_string_to_file(address_file, m_account.get_public_address_str(m_nettype)); - THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_wallet_file); + if (boost::filesystem::exists(old_address_file)) + { + // save address to the new file + const std::string address_file = m_wallet_file + ".address.txt"; + r = file_io_utils::save_string_to_file(address_file, m_account.get_public_address_str(m_nettype)); + THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_wallet_file); + } // remove old wallet file r = boost::filesystem::remove(old_file); if (!r) { @@ -4316,7 +4351,7 @@ crypto::hash wallet2::get_payment_id(const pending_tx &ptx) const MWARNING("Encrypted payment id found, but no destinations public key, cannot decrypt"); return crypto::null_hash; } - if (decrypt_payment_id(payment_id8, ptx.dests[0].addr.m_view_public_key, ptx.tx_key, m_account.get_device())) + if (m_account.get_device().decrypt_payment_id(payment_id8, ptx.dests[0].addr.m_view_public_key, ptx.tx_key)) { memcpy(payment_id.data, payment_id8.data, 8); } @@ -6677,6 +6712,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp cryptonote::transaction tx; pending_tx ptx; size_t bytes; + std::vector<std::vector<tools::wallet2::get_outs_entry>> outs; void add(const account_public_address &addr, bool is_subaddress, uint64_t amount, unsigned int original_output_index, bool merge_destinations) { if (merge_destinations) @@ -7066,40 +7102,10 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp LOG_PRINT_L2("Made a final " << get_size_string(txBlob) << " tx, with " << print_money(test_ptx.fee) << " fee and " << print_money(test_ptx.change_dts.amount) << " change"); - if ((!dsts.empty()) || - (dsts.empty() && !(adding_fee || !preferred_inputs.empty() || should_pick_a_second_output(use_rct, txes.back().selected_transfers.size(), *unused_transfers_indices, *unused_dust_indices)) ) - ) { - hwdev.set_signature_mode(hw::device::SIGNATURE_REAL); - if (use_rct) { - transfer_selected_rct(tx.dsts, /* NOMOD std::vector<cryptonote::tx_destination_entry> dsts,*/ - tx.selected_transfers, /* const std::list<size_t> selected_transfers */ - fake_outs_count, /* CONST size_t fake_outputs_count, */ - outs, /* MOD std::vector<std::vector<tools::wallet2::get_outs_entry>> &outs, */ - unlock_time, /* CONST uint64_t unlock_time, */ - needed_fee, /* CONST uint64_t fee, */ - extra, /* const std::vector<uint8_t>& extra, */ - test_tx, /* OUT cryptonote::transaction& tx, */ - test_ptx, /* OUT cryptonote::transaction& tx, */ - bulletproof); - } else { - transfer_selected(tx.dsts, - tx.selected_transfers, - fake_outs_count, - outs, - unlock_time, - needed_fee, - extra, - detail::digit_split_strategy, - tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), - test_tx, - test_ptx); - } - hwdev.set_signature_mode(hw::device::SIGNATURE_FAKE); - } - tx.tx = test_tx; tx.ptx = test_ptx; tx.bytes = txBlob.size(); + tx.outs = outs; accumulated_fee += test_ptx.fee; accumulated_change += test_ptx.change_dts.amount; adding_fee = false; @@ -7139,6 +7145,42 @@ skip_tx: LOG_PRINT_L1("Done creating " << txes.size() << " transactions, " << print_money(accumulated_fee) << " total fee, " << print_money(accumulated_change) << " total change"); + hwdev.set_signature_mode(hw::device::SIGNATURE_REAL); + for (std::vector<TX>::iterator i = txes.begin(); i != txes.end(); ++i) + { + TX &tx = *i; + cryptonote::transaction test_tx; + pending_tx test_ptx; + if (use_rct) { + transfer_selected_rct(tx.dsts, /* NOMOD std::vector<cryptonote::tx_destination_entry> dsts,*/ + tx.selected_transfers, /* const std::list<size_t> selected_transfers */ + fake_outs_count, /* CONST size_t fake_outputs_count, */ + tx.outs, /* MOD std::vector<std::vector<tools::wallet2::get_outs_entry>> &outs, */ + unlock_time, /* CONST uint64_t unlock_time, */ + needed_fee, /* CONST uint64_t fee, */ + extra, /* const std::vector<uint8_t>& extra, */ + test_tx, /* OUT cryptonote::transaction& tx, */ + test_ptx, /* OUT cryptonote::transaction& tx, */ + bulletproof); + } else { + transfer_selected(tx.dsts, + tx.selected_transfers, + fake_outs_count, + tx.outs, + unlock_time, + needed_fee, + extra, + detail::digit_split_strategy, + tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), + test_tx, + test_ptx); + } + auto txBlob = t_serializable_object_to_blob(test_ptx.tx); + tx.tx = test_tx; + tx.ptx = test_ptx; + tx.bytes = txBlob.size(); + } + std::vector<wallet2::pending_tx> ptx_vector; for (std::vector<TX>::iterator i = txes.begin(); i != txes.end(); ++i) { @@ -7241,6 +7283,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton cryptonote::transaction tx; pending_tx ptx; size_t bytes; + std::vector<std::vector<get_outs_entry>> outs; }; std::vector<TX> txes; uint64_t needed_fee, available_for_fee = 0; @@ -7332,24 +7375,13 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton " fee and " << print_money(test_ptx.change_dts.amount) << " change"); } while (needed_fee > test_ptx.fee); - if (!unused_transfers_indices.empty() || !unused_dust_indices.empty()) { - hwdev.set_signature_mode(hw::device::SIGNATURE_REAL); - if (use_rct) { - transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra, - test_tx, test_ptx, bulletproof); - } else { - transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra, - detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx); - } - hwdev.set_signature_mode(hw::device::SIGNATURE_FAKE); - } - LOG_PRINT_L2("Made a final " << get_size_string(txBlob) << " tx, with " << print_money(test_ptx.fee) << " fee and " << print_money(test_ptx.change_dts.amount) << " change"); tx.tx = test_tx; tx.ptx = test_ptx; tx.bytes = txBlob.size(); + tx.outs = outs; accumulated_fee += test_ptx.fee; accumulated_change += test_ptx.change_dts.amount; if (!unused_transfers_indices.empty() || !unused_dust_indices.empty()) @@ -7362,6 +7394,25 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton LOG_PRINT_L1("Done creating " << txes.size() << " transactions, " << print_money(accumulated_fee) << " total fee, " << print_money(accumulated_change) << " total change"); + + hwdev.set_signature_mode(hw::device::SIGNATURE_REAL); + for (std::vector<TX>::iterator i = txes.begin(); i != txes.end(); ++i) + { + TX &tx = *i; + cryptonote::transaction test_tx; + pending_tx test_ptx; + if (use_rct) { + transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, tx.outs, unlock_time, needed_fee, extra, + test_tx, test_ptx, bulletproof); + } else { + transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, tx.outs, unlock_time, needed_fee, extra, + detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx); + } + auto txBlob = t_serializable_object_to_blob(test_ptx.tx); + tx.tx = test_tx; + tx.ptx = test_ptx; + tx.bytes = txBlob.size(); + } std::vector<wallet2::pending_tx> ptx_vector; for (std::vector<TX>::iterator i = txes.begin(); i != txes.end(); ++i) @@ -7808,13 +7859,13 @@ bool wallet2::check_spend_proof(const crypto::hash &txid, const std::string &mes void wallet2::check_tx_key(const crypto::hash &txid, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys, const cryptonote::account_public_address &address, uint64_t &received, bool &in_pool, uint64_t &confirmations) { crypto::key_derivation derivation; - THROW_WALLET_EXCEPTION_IF(!crypto::generate_key_derivation(address.m_view_public_key, tx_key, derivation, m_account.get_device()), error::wallet_internal_error, + THROW_WALLET_EXCEPTION_IF(!crypto::generate_key_derivation(address.m_view_public_key, tx_key, derivation), error::wallet_internal_error, "Failed to generate key derivation from supplied parameters"); std::vector<crypto::key_derivation> additional_derivations; additional_derivations.resize(additional_tx_keys.size()); for (size_t i = 0; i < additional_tx_keys.size(); ++i) - THROW_WALLET_EXCEPTION_IF(!crypto::generate_key_derivation(address.m_view_public_key, additional_tx_keys[i], additional_derivations[i], m_account.get_device()), error::wallet_internal_error, + THROW_WALLET_EXCEPTION_IF(!crypto::generate_key_derivation(address.m_view_public_key, additional_tx_keys[i], additional_derivations[i]), error::wallet_internal_error, "Failed to generate key derivation from supplied parameters"); check_tx_key_helper(txid, derivation, additional_derivations, address, received, in_pool, confirmations); @@ -7856,13 +7907,13 @@ void wallet2::check_tx_key_helper(const crypto::hash &txid, const crypto::key_de continue; crypto::public_key derived_out_key; - bool r = derive_public_key(derivation, n, address.m_spend_public_key, derived_out_key, hwdev); + bool r = hwdev.derive_public_key(derivation, n, address.m_spend_public_key, derived_out_key); THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to derive public key"); bool found = out_key->key == derived_out_key; crypto::key_derivation found_derivation = derivation; if (!found && !additional_derivations.empty()) { - r = derive_public_key(additional_derivations[n], n, address.m_spend_public_key, derived_out_key,hwdev); + r = hwdev.derive_public_key(additional_derivations[n], n, address.m_spend_public_key, derived_out_key); THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to derive public key"); found = out_key->key == derived_out_key; found_derivation = additional_derivations[n]; @@ -7878,9 +7929,9 @@ void wallet2::check_tx_key_helper(const crypto::hash &txid, const crypto::key_de else { crypto::secret_key scalar1; - crypto::derivation_to_scalar(found_derivation, n, scalar1, hwdev); + hwdev.derivation_to_scalar(found_derivation, n, scalar1); rct::ecdhTuple ecdh_info = tx.rct_signatures.ecdhInfo[n]; - rct::ecdhDecode(ecdh_info, rct::sk2rct(scalar1), hwdev); + hwdev.ecdhDecode(ecdh_info, rct::sk2rct(scalar1)); const rct::key C = tx.rct_signatures.outPk[n].mask; rct::key Ctmp; rct::addKeys2(Ctmp, ecdh_info.mask, ecdh_info.amount, rct::H); @@ -8250,7 +8301,7 @@ std::string wallet2::get_reserve_proof(const boost::optional<std::pair<uint32_t, crypto::secret_key subaddr_spend_skey = m_account.get_keys().m_spend_secret_key; if (!index.is_zero()) { - crypto::secret_key m = cryptonote::get_subaddress_secret_key(m_account.get_keys().m_view_secret_key, index); + crypto::secret_key m = m_account.get_device().get_subaddress_secret_key(m_account.get_keys().m_view_secret_key, index); crypto::secret_key tmp = subaddr_spend_skey; sc_add((unsigned char*)&subaddr_spend_skey, (unsigned char*)&m, (unsigned char*)&tmp); } @@ -8615,14 +8666,14 @@ crypto::public_key wallet2::get_tx_pub_key_from_received_outs(const tools::walle for (size_t i = 0; i < additional_tx_pub_keys.size(); ++i) { additional_derivations.push_back({}); - bool r = generate_key_derivation(additional_tx_pub_keys[i], keys.m_view_secret_key, additional_derivations.back(), hwdev); + bool r = hwdev.generate_key_derivation(additional_tx_pub_keys[i], keys.m_view_secret_key, additional_derivations.back()); THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key derivation"); } while (find_tx_extra_field_by_type(tx_extra_fields, pub_key_field, pk_index++)) { const crypto::public_key tx_pub_key = pub_key_field.pub_key; crypto::key_derivation derivation; - bool r = generate_key_derivation(tx_pub_key, keys.m_view_secret_key, derivation, hwdev); + bool r = hwdev.generate_key_derivation(tx_pub_key, keys.m_view_secret_key, derivation); THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key derivation"); for (size_t i = 0; i < td.m_tx.vout.size(); ++i) @@ -8911,14 +8962,14 @@ uint64_t wallet2::import_key_images(const std::vector<std::pair<crypto::key_imag const cryptonote::account_keys& keys = m_account.get_keys(); const crypto::public_key tx_pub_key = get_tx_pub_key_from_extra(spent_tx); crypto::key_derivation derivation; - bool r = generate_key_derivation(tx_pub_key, keys.m_view_secret_key, derivation, hwdev); + bool r = hwdev.generate_key_derivation(tx_pub_key, keys.m_view_secret_key, derivation); THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key derivation"); const std::vector<crypto::public_key> additional_tx_pub_keys = get_additional_tx_pub_keys_from_extra(spent_tx); std::vector<crypto::key_derivation> additional_derivations; for (size_t i = 0; i < additional_tx_pub_keys.size(); ++i) { additional_derivations.push_back({}); - r = generate_key_derivation(additional_tx_pub_keys[i], keys.m_view_secret_key, additional_derivations.back(), hwdev); + r = hwdev.generate_key_derivation(additional_tx_pub_keys[i], keys.m_view_secret_key, additional_derivations.back()); THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key derivation"); } size_t output_index = 0; diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 57a61cb9d..9accc65ca 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -449,44 +449,48 @@ namespace tools /*! * \brief Generates a wallet or restores one. - * \param wallet_ Name of wallet file - * \param password Password of wallet file - * \param multisig_data The multisig restore info and keys + * \param wallet_ Name of wallet file + * \param password Password of wallet file + * \param multisig_data The multisig restore info and keys + * \param create_address_file Whether to create an address file */ void generate(const std::string& wallet_, const epee::wipeable_string& password, - const std::string& multisig_data); + const std::string& multisig_data, bool create_address_file = false); /*! * \brief Generates a wallet or restores one. - * \param wallet_ Name of wallet file - * \param password Password of wallet file - * \param recovery_param If it is a restore, the recovery key - * \param recover Whether it is a restore - * \param two_random Whether it is a non-deterministic wallet - * \return The secret key of the generated wallet + * \param wallet_ Name of wallet file + * \param password Password of wallet file + * \param recovery_param If it is a restore, the recovery key + * \param recover Whether it is a restore + * \param two_random Whether it is a non-deterministic wallet + * \param create_address_file Whether to create an address file + * \return The secret key of the generated wallet */ crypto::secret_key generate(const std::string& wallet, const epee::wipeable_string& password, const crypto::secret_key& recovery_param = crypto::secret_key(), bool recover = false, - bool two_random = false); + bool two_random = false, bool create_address_file = false); /*! * \brief Creates a wallet from a public address and a spend/view secret key pair. - * \param wallet_ Name of wallet file - * \param password Password of wallet file - * \param viewkey view secret key - * \param spendkey spend secret key + * \param wallet_ Name of wallet file + * \param password Password of wallet file + * \param viewkey view secret key + * \param spendkey spend secret key + * \param create_address_file Whether to create an address file */ void generate(const std::string& wallet, const epee::wipeable_string& password, const cryptonote::account_public_address &account_public_address, - const crypto::secret_key& spendkey, const crypto::secret_key& viewkey); + const crypto::secret_key& spendkey, const crypto::secret_key& viewkey, bool create_address_file = false); /*! * \brief Creates a watch only wallet from a public address and a view secret key. - * \param wallet_ Name of wallet file - * \param password Password of wallet file - * \param viewkey view secret key + * \param wallet_ Name of wallet file + * \param password Password of wallet file + * \param viewkey view secret key + * \param create_address_file Whether to create an address file */ void generate(const std::string& wallet, const epee::wipeable_string& password, const cryptonote::account_public_address &account_public_address, - const crypto::secret_key& viewkey = crypto::secret_key()); + const crypto::secret_key& viewkey = crypto::secret_key(), bool create_address_file = false); /*! * \brief Restore a wallet hold by an HW. * \param wallet_ Name of wallet file @@ -548,7 +552,7 @@ namespace tools * \param password Password for wallet file */ void rewrite(const std::string& wallet_name, const epee::wipeable_string& password); - void write_watch_only_wallet(const std::string& wallet_name, const epee::wipeable_string& password); + void write_watch_only_wallet(const std::string& wallet_name, const epee::wipeable_string& password, std::string &new_keys_filename); void load(const std::string& wallet, const epee::wipeable_string& password); void store(); /*! diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h index 370fea858..a0f43c9b9 100644 --- a/src/wallet/wallet_rpc_server_commands_defs.h +++ b/src/wallet/wallet_rpc_server_commands_defs.h @@ -398,7 +398,7 @@ namespace wallet_rpc KV_SERIALIZE(account_index) KV_SERIALIZE(subaddr_indices) KV_SERIALIZE(priority) - KV_SERIALIZE(mixin) + KV_SERIALIZE_OPT(mixin, (uint64_t)0) KV_SERIALIZE_OPT(ring_size, (uint64_t)0) KV_SERIALIZE(unlock_time) KV_SERIALIZE(payment_id) @@ -455,7 +455,7 @@ namespace wallet_rpc KV_SERIALIZE(account_index) KV_SERIALIZE(subaddr_indices) KV_SERIALIZE(priority) - KV_SERIALIZE(mixin) + KV_SERIALIZE_OPT(mixin, (uint64_t)0) KV_SERIALIZE_OPT(ring_size, (uint64_t)0) KV_SERIALIZE(unlock_time) KV_SERIALIZE(payment_id) @@ -568,7 +568,7 @@ namespace wallet_rpc KV_SERIALIZE(account_index) KV_SERIALIZE(subaddr_indices) KV_SERIALIZE(priority) - KV_SERIALIZE(mixin) + KV_SERIALIZE_OPT(mixin, (uint64_t)0) KV_SERIALIZE_OPT(ring_size, (uint64_t)0) KV_SERIALIZE(unlock_time) KV_SERIALIZE(payment_id) @@ -630,7 +630,7 @@ namespace wallet_rpc BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(address) KV_SERIALIZE(priority) - KV_SERIALIZE(mixin) + KV_SERIALIZE_OPT(mixin, (uint64_t)0) KV_SERIALIZE_OPT(ring_size, (uint64_t)0) KV_SERIALIZE(unlock_time) KV_SERIALIZE(payment_id) |