aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cryptonote_basic/account.cpp2
-rw-r--r--src/cryptonote_core/blockchain.cpp11
-rw-r--r--src/cryptonote_core/cryptonote_tx_utils.cpp2
-rw-r--r--src/device/device.cpp2
-rw-r--r--src/device/device.hpp18
-rw-r--r--src/device/device_declare.hpp5
-rw-r--r--src/device/device_default.cpp2
-rw-r--r--src/device/device_default.hpp4
-rw-r--r--src/device/device_ledger.cpp190
-rw-r--r--src/device/device_ledger.hpp15
-rw-r--r--src/device/log.cpp8
-rw-r--r--src/gen_multisig/gen_multisig.cpp9
-rw-r--r--src/simplewallet/simplewallet.cpp28
-rw-r--r--src/wallet/CMakeLists.txt1
-rw-r--r--src/wallet/api/wallet.cpp16
-rw-r--r--src/wallet/api/wallet2_api.h11
-rw-r--r--src/wallet/wallet2.cpp203
-rw-r--r--src/wallet/wallet2.h46
-rw-r--r--src/wallet/wallet_rpc_server_commands_defs.h8
19 files changed, 370 insertions, 211 deletions
diff --git a/src/cryptonote_basic/account.cpp b/src/cryptonote_basic/account.cpp
index 375b17389..70f7533ea 100644
--- a/src/cryptonote_basic/account.cpp
+++ b/src/cryptonote_basic/account.cpp
@@ -140,9 +140,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_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..df98feb5a 100644
--- a/src/cryptonote_core/cryptonote_tx_utils.cpp
+++ b/src/cryptonote_core/cryptonote_tx_utils.cpp
@@ -409,7 +409,7 @@ namespace cryptonote
r = crypto::derive_public_key(derivation, output_index, dst_entr.addr.m_spend_public_key, out_eph_public_key, hwdev);
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/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..614d2c243 100644
--- a/src/device/device.hpp
+++ b/src/device/device.hpp
@@ -28,6 +28,20 @@
//
+/* 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"
@@ -128,8 +142,8 @@ namespace hw {
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
index 799052ad2..fcf5762af 100644
--- a/src/device/device_declare.hpp
+++ b/src/device/device_declare.hpp
@@ -29,11 +29,6 @@
#pragma once
-
-//#define DEBUG_HWDEVICE
-//#define IODUMMYCRYPT 1
-//#define IONOCRYPT 1
-
namespace hw {
class device;
diff --git a/src/device/device_default.cpp b/src/device/device_default.cpp
index c3ba42000..7ae72af44 100644
--- a/src/device/device_default.cpp
+++ b/src/device/device_default.cpp
@@ -185,7 +185,7 @@ namespace hw {
}
- 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;
}
diff --git a/src/device/device_default.hpp b/src/device/device_default.hpp
index f5b158a3b..d7fc2b914 100644
--- a/src/device/device_default.hpp
+++ b/src/device/device_default.hpp
@@ -105,8 +105,8 @@ namespace hw {
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..51837b8a2 100644
--- a/src/device/device_ledger.cpp
+++ b/src/device/device_ledger.cpp
@@ -55,30 +55,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 +108,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 +189,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 +300,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 +414,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 +446,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 +479,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 +489,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();
@@ -541,7 +541,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();
@@ -599,7 +603,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()) {
@@ -662,7 +670,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()) {
@@ -715,7 +730,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();
@@ -808,10 +826,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 +864,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 +882,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 +914,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 +936,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();
@@ -1021,10 +1044,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 +1098,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 +1158,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 +1222,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 +1283,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 +1337,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();
@@ -1425,7 +1467,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 +1508,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 +1530,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 +1585,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 +1646,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 +1671,7 @@ namespace hw {
offset += 1;
//type
+ uint8_t type = data[0];
this->buffer_send[offset] = data[0];
offset += 1;
@@ -1648,25 +1691,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 +1738,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 +1751,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 +1953,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 +2012,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..37e35167c 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:
@@ -174,8 +175,8 @@ namespace hw {
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/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index cbb174e1a..71ce1574f 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -134,6 +134,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 +2849,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 +2903,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 +2976,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 +3150,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;
}
@@ -6979,6 +6996,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..36b661004 100644
--- a/src/wallet/CMakeLists.txt
+++ b/src/wallet/CMakeLists.txt
@@ -111,6 +111,7 @@ if (BUILD_GUI_DEPS)
mnemonics
common
cncrypto
+ device
ringct
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/wallet2.cpp b/src/wallet/wallet2.cpp
index d845dd896..b0488fc03 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -318,6 +318,9 @@ 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)
{
@@ -372,11 +375,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 +405,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);
}
}
}
@@ -582,6 +585,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
@@ -876,9 +887,10 @@ 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 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 = cryptonote::get_subaddress_spend_public_keys(m_account.get_keys(), index2.major, 0, end, hwdev);
for (index2.minor = 0; index2.minor < end; ++index2.minor)
{
@@ -892,7 +904,7 @@ 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);
@@ -924,6 +936,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;
}
@@ -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) {
@@ -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)
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)