mirror of
https://github.com/monero-project/monero.git
synced 2024-10-01 11:49:47 -04:00
Add the possibility to export private view key for fast scan.
On client startup the device asks for authorization to export the private view key. If user agree, the client hold the private view key allowing a fast blockchain scan. If the user does not agree, the blockchain scan is fully done via the device.
This commit is contained in:
parent
da5de484f2
commit
0f3ff8ce2c
@ -78,6 +78,7 @@ namespace hw {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class device {
|
class device {
|
||||||
protected:
|
protected:
|
||||||
std::string name;
|
std::string name;
|
||||||
@ -89,10 +90,12 @@ namespace hw {
|
|||||||
virtual ~device() {}
|
virtual ~device() {}
|
||||||
|
|
||||||
explicit virtual operator bool() const = 0;
|
explicit virtual operator bool() const = 0;
|
||||||
|
enum device_mode {
|
||||||
static const int SIGNATURE_REAL = 0;
|
NONE,
|
||||||
static const int SIGNATURE_FAKE = 1;
|
TRANSACTION_CREATE_REAL,
|
||||||
|
TRANSACTION_CREATE_FAKE,
|
||||||
|
TRANSACTION_PARSE
|
||||||
|
};
|
||||||
|
|
||||||
/* ======================================================================= */
|
/* ======================================================================= */
|
||||||
/* SETUP/TEARDOWN */
|
/* SETUP/TEARDOWN */
|
||||||
@ -106,6 +109,9 @@ namespace hw {
|
|||||||
virtual bool connect(void) = 0;
|
virtual bool connect(void) = 0;
|
||||||
virtual bool disconnect(void) = 0;
|
virtual bool disconnect(void) = 0;
|
||||||
|
|
||||||
|
virtual bool set_mode(device_mode mode) = 0;
|
||||||
|
|
||||||
|
|
||||||
/* ======================================================================= */
|
/* ======================================================================= */
|
||||||
/* LOCKER */
|
/* LOCKER */
|
||||||
/* ======================================================================= */
|
/* ======================================================================= */
|
||||||
@ -166,8 +172,6 @@ namespace hw {
|
|||||||
|
|
||||||
virtual bool open_tx(crypto::secret_key &tx_key) = 0;
|
virtual bool open_tx(crypto::secret_key &tx_key) = 0;
|
||||||
|
|
||||||
virtual bool set_signature_mode(unsigned int sig_mode) = 0;
|
|
||||||
|
|
||||||
virtual bool encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key) = 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)
|
bool decrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key)
|
||||||
{
|
{
|
||||||
@ -191,6 +195,12 @@ namespace hw {
|
|||||||
virtual bool close_tx(void) = 0;
|
virtual bool close_tx(void) = 0;
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
struct reset_mode {
|
||||||
|
device& hwref;
|
||||||
|
reset_mode(hw::device& dev) : hwref(dev) { }
|
||||||
|
~reset_mode() { hwref.set_mode(hw::device::NONE);}
|
||||||
|
};
|
||||||
|
|
||||||
device& get_device(const std::string device_descriptor) ;
|
device& get_device(const std::string device_descriptor) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,6 +81,9 @@ namespace hw {
|
|||||||
dfns();
|
dfns();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool device_default::set_mode(device_mode mode) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* ======================================================================= */
|
/* ======================================================================= */
|
||||||
/* LOCKER */
|
/* LOCKER */
|
||||||
@ -273,10 +276,6 @@ namespace hw {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool device_default::set_signature_mode(unsigned int sig_mode) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool device_default::encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_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::key_derivation derivation;
|
||||||
crypto::hash hash;
|
crypto::hash hash;
|
||||||
|
@ -59,6 +59,8 @@ namespace hw {
|
|||||||
bool connect(void) override;
|
bool connect(void) override;
|
||||||
bool disconnect() override;
|
bool disconnect() override;
|
||||||
|
|
||||||
|
bool set_mode(device_mode mode) override;
|
||||||
|
|
||||||
/* ======================================================================= */
|
/* ======================================================================= */
|
||||||
/* LOCKER */
|
/* LOCKER */
|
||||||
/* ======================================================================= */
|
/* ======================================================================= */
|
||||||
@ -104,9 +106,6 @@ namespace hw {
|
|||||||
|
|
||||||
bool open_tx(crypto::secret_key &tx_key) override;
|
bool open_tx(crypto::secret_key &tx_key) override;
|
||||||
|
|
||||||
//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(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key) 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 ecdhEncode(rct::ecdhTuple & unmasked, const rct::key & sharedSec) override;
|
||||||
|
@ -58,8 +58,8 @@ namespace hw {
|
|||||||
#define ASSERT_T0(exp) CHECK_AND_ASSERT_THROW_MES(exp, "Protocol assert failure: "#exp ) ;
|
#define ASSERT_T0(exp) CHECK_AND_ASSERT_THROW_MES(exp, "Protocol assert failure: "#exp ) ;
|
||||||
|
|
||||||
#ifdef DEBUG_HWDEVICE
|
#ifdef DEBUG_HWDEVICE
|
||||||
crypto::secret_key viewkey;
|
crypto::secret_key dbg_viewkey;
|
||||||
crypto::secret_key spendkey;
|
crypto::secret_key dbg_spendkey;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ===================================================================== */
|
/* ===================================================================== */
|
||||||
@ -118,6 +118,13 @@ namespace hw {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* ===================================================================== */
|
||||||
|
/* === Internal Helpers ==== */
|
||||||
|
/* ===================================================================== */
|
||||||
|
static bool is_fake_view_key(const crypto::secret_key &sec) {
|
||||||
|
return sec == crypto::null_skey;
|
||||||
|
}
|
||||||
|
|
||||||
/* ===================================================================== */
|
/* ===================================================================== */
|
||||||
/* === Device ==== */
|
/* === Device ==== */
|
||||||
/* ===================================================================== */
|
/* ===================================================================== */
|
||||||
@ -197,6 +204,8 @@ namespace hw {
|
|||||||
this->hCard = 0;
|
this->hCard = 0;
|
||||||
this->hContext = 0;
|
this->hContext = 0;
|
||||||
this->reset_buffer();
|
this->reset_buffer();
|
||||||
|
this->mode = NONE;
|
||||||
|
this->has_view_key = false;
|
||||||
MDEBUG( "Device "<<this->id <<" Created");
|
MDEBUG( "Device "<<this->id <<" Created");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -403,10 +412,10 @@ namespace hw {
|
|||||||
#ifdef DEBUG_HWDEVICE
|
#ifdef DEBUG_HWDEVICE
|
||||||
cryptonote::account_public_address pubkey;
|
cryptonote::account_public_address pubkey;
|
||||||
this->get_public_address(pubkey);
|
this->get_public_address(pubkey);
|
||||||
|
#endif
|
||||||
crypto::secret_key vkey;
|
crypto::secret_key vkey;
|
||||||
crypto::secret_key skey;
|
crypto::secret_key skey;
|
||||||
this->get_secret_keys(vkey,skey);
|
this->get_secret_keys(vkey,skey);
|
||||||
#endif
|
|
||||||
|
|
||||||
return rv==SCARD_S_SUCCESS;
|
return rv==SCARD_S_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -420,6 +429,47 @@ namespace hw {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool device_ledger::set_mode(device_mode mode) {
|
||||||
|
AUTO_LOCK_CMD();
|
||||||
|
|
||||||
|
int offset;
|
||||||
|
|
||||||
|
reset_buffer();
|
||||||
|
|
||||||
|
switch(mode) {
|
||||||
|
case TRANSACTION_CREATE_REAL:
|
||||||
|
case TRANSACTION_CREATE_FAKE:
|
||||||
|
this->buffer_send[0] = 0x00;
|
||||||
|
this->buffer_send[1] = INS_SET_SIGNATURE_MODE;
|
||||||
|
this->buffer_send[2] = 0x01;
|
||||||
|
this->buffer_send[3] = 0x00;
|
||||||
|
this->buffer_send[4] = 0x00;
|
||||||
|
offset = 5;
|
||||||
|
//options
|
||||||
|
this->buffer_send[offset] = 0x00;
|
||||||
|
offset += 1;
|
||||||
|
//account
|
||||||
|
this->buffer_send[offset] = mode;
|
||||||
|
offset += 1;
|
||||||
|
|
||||||
|
this->buffer_send[4] = offset-5;
|
||||||
|
this->length_send = offset;
|
||||||
|
this->exchange();
|
||||||
|
|
||||||
|
this->mode = mode;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TRANSACTION_PARSE:
|
||||||
|
case NONE:
|
||||||
|
this->mode = mode;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
CHECK_AND_ASSERT_THROW_MES(false, " device_ledger::set_mode(unsigned int mode): invalid mode: "<<mode);
|
||||||
|
}
|
||||||
|
MDEBUG("Switch to mode: " <<mode);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ======================================================================= */
|
/* ======================================================================= */
|
||||||
/* WALLET & ADDRESS */
|
/* WALLET & ADDRESS */
|
||||||
@ -451,12 +501,13 @@ namespace hw {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool device_ledger::get_secret_keys(crypto::secret_key &viewkey , crypto::secret_key &spendkey) {
|
bool device_ledger::get_secret_keys(crypto::secret_key &vkey , crypto::secret_key &skey) {
|
||||||
AUTO_LOCK_CMD();
|
AUTO_LOCK_CMD();
|
||||||
memset(viewkey.data, 0x00, 32);
|
|
||||||
memset(spendkey.data, 0xFF, 32);
|
|
||||||
|
|
||||||
#ifdef DEBUG_HWDEVICE
|
//secret key are represented as fake key on the wallet side
|
||||||
|
memset(vkey.data, 0x00, 32);
|
||||||
|
memset(skey.data, 0xFF, 32);
|
||||||
|
|
||||||
//spcialkey, normal conf handled in decrypt
|
//spcialkey, normal conf handled in decrypt
|
||||||
int offset;
|
int offset;
|
||||||
reset_buffer();
|
reset_buffer();
|
||||||
@ -475,11 +526,21 @@ namespace hw {
|
|||||||
this->length_send = offset;
|
this->length_send = offset;
|
||||||
this->exchange();
|
this->exchange();
|
||||||
|
|
||||||
//clear key
|
//View key is retrievied, if allowed, to speed up blockchain parsing
|
||||||
memmove(ledger::viewkey.data, this->buffer_recv+64, 32);
|
memmove(this->viewkey.data, this->buffer_recv+0, 32);
|
||||||
memmove(ledger::spendkey.data, this->buffer_recv+96, 32);
|
if (is_fake_view_key(this->viewkey)) {
|
||||||
|
MDEBUG("Have Not view key");
|
||||||
|
this->has_view_key = false;
|
||||||
|
} else {
|
||||||
|
MDEBUG("Have view key");
|
||||||
|
this->has_view_key = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_HWDEVICE
|
||||||
|
memmove(dbg_viewkey.data, this->buffer_recv+0, 32);
|
||||||
|
memmove(dbg_spendkey.data, this->buffer_recv+32, 32);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -525,11 +586,14 @@ namespace hw {
|
|||||||
|
|
||||||
bool device_ledger::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){
|
bool device_ledger::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){
|
||||||
AUTO_LOCK_CMD();
|
AUTO_LOCK_CMD();
|
||||||
int offset;
|
|
||||||
|
|
||||||
#ifdef DEBUG_HWDEVICE
|
#ifdef DEBUG_HWDEVICE
|
||||||
const crypto::public_key pub_x = pub;
|
const crypto::public_key pub_x = pub;
|
||||||
const crypto::key_derivation derivation_x = hw::ledger::decrypt(derivation);
|
crypto::key_derivation derivation_x;
|
||||||
|
if ((this->mode == TRANSACTION_PARSE) && has_view_key) {
|
||||||
|
derivation_x = derivation;
|
||||||
|
} else {
|
||||||
|
derivation_x = hw::ledger::decrypt(derivation);
|
||||||
|
}
|
||||||
const std::size_t output_index_x = output_index;
|
const std::size_t output_index_x = output_index;
|
||||||
crypto::public_key derived_pub_x;
|
crypto::public_key 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]] pub ", pub_x.data, 32);
|
||||||
@ -539,6 +603,15 @@ namespace hw {
|
|||||||
hw::ledger::log_hexbuffer("derive_subaddress_public_key: [[OUT]] derived_pub", derived_pub_x.data, 32);
|
hw::ledger::log_hexbuffer("derive_subaddress_public_key: [[OUT]] derived_pub", derived_pub_x.data, 32);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if ((this->mode == TRANSACTION_PARSE) && has_view_key) {
|
||||||
|
//If we are in TRANSACTION_PARSE, the given derivation has been retrieved uncrypted (wihtout the help
|
||||||
|
//of the device), so continue that way.
|
||||||
|
MDEBUG( "derive_subaddress_public_key : PARSE mode with known viewkey");
|
||||||
|
crypto::derive_subaddress_public_key(pub, derivation, output_index,derived_pub);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
int offset =0;
|
||||||
|
|
||||||
reset_buffer();
|
reset_buffer();
|
||||||
|
|
||||||
this->buffer_send[0] = 0x00;
|
this->buffer_send[0] = 0x00;
|
||||||
@ -569,7 +642,7 @@ namespace hw {
|
|||||||
|
|
||||||
//pub key
|
//pub key
|
||||||
memmove(derived_pub.data, &this->buffer_recv[0], 32);
|
memmove(derived_pub.data, &this->buffer_recv[0], 32);
|
||||||
|
}
|
||||||
#ifdef DEBUG_HWDEVICE
|
#ifdef DEBUG_HWDEVICE
|
||||||
hw::ledger::check32("derive_subaddress_public_key", "derived_pub", derived_pub_x.data, derived_pub.data);
|
hw::ledger::check32("derive_subaddress_public_key", "derived_pub", derived_pub_x.data, derived_pub.data);
|
||||||
#endif
|
#endif
|
||||||
@ -959,7 +1032,7 @@ namespace hw {
|
|||||||
|
|
||||||
bool device_ledger::generate_key_derivation(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_derivation &derivation) {
|
bool device_ledger::generate_key_derivation(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_derivation &derivation) {
|
||||||
AUTO_LOCK_CMD();
|
AUTO_LOCK_CMD();
|
||||||
int offset;
|
bool r = false;
|
||||||
|
|
||||||
#ifdef DEBUG_HWDEVICE
|
#ifdef DEBUG_HWDEVICE
|
||||||
const crypto::public_key pub_x = pub;
|
const crypto::public_key pub_x = pub;
|
||||||
@ -971,6 +1044,17 @@ namespace hw {
|
|||||||
hw::ledger::log_hexbuffer("generate_key_derivation: [[OUT]] derivation", derivation_x.data, 32);
|
hw::ledger::log_hexbuffer("generate_key_derivation: [[OUT]] derivation", derivation_x.data, 32);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if ((this->mode == TRANSACTION_PARSE) && has_view_key) {
|
||||||
|
//A derivation is resquested in PASRE mode and we have the view key,
|
||||||
|
//so do that wihtout the device and return the derivation unencrypted.
|
||||||
|
MDEBUG( "generate_key_derivation : PARSE mode with known viewkey");
|
||||||
|
//Note derivation in PARSE mode can only happen with viewkey, so assert it!
|
||||||
|
assert(is_fake_view_key(sec));
|
||||||
|
r = crypto::generate_key_derivation(pub, this->viewkey, derivation);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
int offset;
|
||||||
|
|
||||||
reset_buffer();
|
reset_buffer();
|
||||||
|
|
||||||
this->buffer_send[0] = 0x00;
|
this->buffer_send[0] = 0x00;
|
||||||
@ -995,14 +1079,19 @@ namespace hw {
|
|||||||
|
|
||||||
//derivattion data
|
//derivattion data
|
||||||
memmove(derivation.data, &this->buffer_recv[0], 32);
|
memmove(derivation.data, &this->buffer_recv[0], 32);
|
||||||
|
r = true;
|
||||||
|
}
|
||||||
#ifdef DEBUG_HWDEVICE
|
#ifdef DEBUG_HWDEVICE
|
||||||
crypto::key_derivation derivation_clear = hw::ledger::decrypt(derivation);
|
crypto::key_derivation derivation_clear ;
|
||||||
|
if ((this->mode == TRANSACTION_PARSE) && has_view_key) {
|
||||||
|
derivation_clear = derivation;
|
||||||
|
}else {
|
||||||
|
derivation_clear = hw::ledger::decrypt(derivation);
|
||||||
|
}
|
||||||
hw::ledger::check32("generate_key_derivation", "derivation", derivation_x.data, derivation_clear.data);
|
hw::ledger::check32("generate_key_derivation", "derivation", derivation_x.data, derivation_clear.data);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
return r;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool device_ledger::derivation_to_scalar(const crypto::key_derivation &derivation, const size_t output_index, crypto::ec_scalar &res) {
|
bool device_ledger::derivation_to_scalar(const crypto::key_derivation &derivation, const size_t output_index, crypto::ec_scalar &res) {
|
||||||
@ -1290,32 +1379,6 @@ namespace hw {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool device_ledger::set_signature_mode(unsigned int sig_mode) {
|
|
||||||
AUTO_LOCK_CMD();
|
|
||||||
int offset ;
|
|
||||||
|
|
||||||
reset_buffer();
|
|
||||||
|
|
||||||
this->buffer_send[0] = 0x00;
|
|
||||||
this->buffer_send[1] = INS_SET_SIGNATURE_MODE;
|
|
||||||
this->buffer_send[2] = 0x01;
|
|
||||||
this->buffer_send[3] = 0x00;
|
|
||||||
this->buffer_send[4] = 0x00;
|
|
||||||
offset = 5;
|
|
||||||
//options
|
|
||||||
this->buffer_send[offset] = 0x00;
|
|
||||||
offset += 1;
|
|
||||||
//account
|
|
||||||
this->buffer_send[offset] = sig_mode;
|
|
||||||
offset += 1;
|
|
||||||
|
|
||||||
this->buffer_send[4] = offset-5;
|
|
||||||
this->length_send = offset;
|
|
||||||
this->exchange();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool device_ledger::encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key) {
|
bool device_ledger::encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key) {
|
||||||
AUTO_LOCK_CMD();
|
AUTO_LOCK_CMD();
|
||||||
int offset;
|
int offset;
|
||||||
|
@ -32,7 +32,6 @@
|
|||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <mutex>
|
|
||||||
#include "device.hpp"
|
#include "device.hpp"
|
||||||
#include <PCSC/winscard.h>
|
#include <PCSC/winscard.h>
|
||||||
#include <PCSC/wintypes.h>
|
#include <PCSC/wintypes.h>
|
||||||
@ -94,15 +93,21 @@ namespace hw {
|
|||||||
DWORD length_recv;
|
DWORD length_recv;
|
||||||
BYTE buffer_recv[BUFFER_RECV_SIZE];
|
BYTE buffer_recv[BUFFER_RECV_SIZE];
|
||||||
unsigned int id;
|
unsigned int id;
|
||||||
|
|
||||||
Keymap key_map;
|
|
||||||
|
|
||||||
|
|
||||||
void logCMD(void);
|
void logCMD(void);
|
||||||
void logRESP(void);
|
void logRESP(void);
|
||||||
unsigned int exchange(unsigned int ok=0x9000, unsigned int mask=0xFFFF);
|
unsigned int exchange(unsigned int ok=0x9000, unsigned int mask=0xFFFF);
|
||||||
void reset_buffer(void);
|
void reset_buffer(void);
|
||||||
|
|
||||||
|
// hw running mode
|
||||||
|
device_mode mode;
|
||||||
|
// map public destination key to ephemeral destination key
|
||||||
|
Keymap key_map;
|
||||||
|
|
||||||
|
// To speed up blockchain parsing the view key maybe handle here.
|
||||||
|
crypto::secret_key viewkey;
|
||||||
|
bool has_view_key;
|
||||||
|
|
||||||
|
//extra debug
|
||||||
#ifdef DEBUG_HWDEVICE
|
#ifdef DEBUG_HWDEVICE
|
||||||
device *controle_device;
|
device *controle_device;
|
||||||
#endif
|
#endif
|
||||||
@ -129,6 +134,7 @@ namespace hw {
|
|||||||
bool connect(void) override;
|
bool connect(void) override;
|
||||||
bool disconnect() override;
|
bool disconnect() override;
|
||||||
|
|
||||||
|
bool set_mode(device_mode mode) override;
|
||||||
|
|
||||||
/* ======================================================================= */
|
/* ======================================================================= */
|
||||||
/* LOCKER */
|
/* LOCKER */
|
||||||
@ -175,8 +181,6 @@ namespace hw {
|
|||||||
|
|
||||||
bool open_tx(crypto::secret_key &tx_key) override;
|
bool open_tx(crypto::secret_key &tx_key) override;
|
||||||
|
|
||||||
bool set_signature_mode(unsigned int sig_mode) override;
|
|
||||||
|
|
||||||
bool encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key) 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 ecdhEncode(rct::ecdhTuple & unmasked, const rct::key & sharedSec) override;
|
||||||
@ -197,10 +201,9 @@ namespace hw {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef DEBUG_HWDEVICE
|
#ifdef DEBUG_HWDEVICE
|
||||||
extern crypto::secret_key viewkey;
|
extern crypto::secret_key dbg_viewkey;
|
||||||
extern crypto::secret_key spendkey;
|
extern crypto::secret_key dbg_spendkey;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif //WITH_DEVICE_LEDGER
|
#endif //WITH_DEVICE_LEDGER
|
||||||
|
@ -56,8 +56,8 @@ namespace hw {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_HWDEVICE
|
#ifdef DEBUG_HWDEVICE
|
||||||
extern crypto::secret_key viewkey;
|
extern crypto::secret_key dbg_viewkey;
|
||||||
extern crypto::secret_key spendkey;
|
extern crypto::secret_key dbg_spendkey;
|
||||||
|
|
||||||
|
|
||||||
void decrypt(char* buf, size_t len) {
|
void decrypt(char* buf, size_t len) {
|
||||||
@ -69,7 +69,7 @@ namespace hw {
|
|||||||
if (buf[i] != 0) break;
|
if (buf[i] != 0) break;
|
||||||
}
|
}
|
||||||
if (i == 32) {
|
if (i == 32) {
|
||||||
memmove(buf, hw::ledger::viewkey.data, 32);
|
memmove(buf, hw::ledger::dbg_viewkey.data, 32);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//spend key?
|
//spend key?
|
||||||
@ -77,7 +77,7 @@ namespace hw {
|
|||||||
if (buf[i] != (char)0xff) break;
|
if (buf[i] != (char)0xff) break;
|
||||||
}
|
}
|
||||||
if (i == 32) {
|
if (i == 32) {
|
||||||
memmove(buf, hw::ledger::spendkey.data, 32);
|
memmove(buf, hw::ledger::dbg_spendkey.data, 32);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1007,13 +1007,16 @@ void wallet2::set_unspent(size_t idx)
|
|||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
void wallet2::check_acc_out_precomp(const tx_out &o, const crypto::key_derivation &derivation, const std::vector<crypto::key_derivation> &additional_derivations, size_t i, tx_scan_info_t &tx_scan_info) const
|
void wallet2::check_acc_out_precomp(const tx_out &o, const crypto::key_derivation &derivation, const std::vector<crypto::key_derivation> &additional_derivations, size_t i, tx_scan_info_t &tx_scan_info) const
|
||||||
{
|
{
|
||||||
|
hw::device &hwdev = m_account.get_device();
|
||||||
|
std::unique_lock<hw::device> hwdev_lock (hwdev);
|
||||||
|
hwdev.set_mode(hw::device::TRANSACTION_PARSE);
|
||||||
if (o.target.type() != typeid(txout_to_key))
|
if (o.target.type() != typeid(txout_to_key))
|
||||||
{
|
{
|
||||||
tx_scan_info.error = true;
|
tx_scan_info.error = true;
|
||||||
LOG_ERROR("wrong type id in transaction out");
|
LOG_ERROR("wrong type id in transaction out");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
tx_scan_info.received = is_out_to_acc_precomp(m_subaddresses, boost::get<txout_to_key>(o.target).key, derivation, additional_derivations, i, m_account.get_device());
|
tx_scan_info.received = is_out_to_acc_precomp(m_subaddresses, boost::get<txout_to_key>(o.target).key, derivation, additional_derivations, i, hwdev);
|
||||||
if(tx_scan_info.received)
|
if(tx_scan_info.received)
|
||||||
{
|
{
|
||||||
tx_scan_info.money_transfered = o.amount; // may be 0 for ringct outputs
|
tx_scan_info.money_transfered = o.amount; // may be 0 for ringct outputs
|
||||||
@ -1080,9 +1083,15 @@ void wallet2::scan_output(const cryptonote::transaction &tx, const crypto::publi
|
|||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote::transaction& tx, const std::vector<uint64_t> &o_indices, uint64_t height, uint64_t ts, bool miner_tx, bool pool, bool double_spend_seen)
|
void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote::transaction& tx, const std::vector<uint64_t> &o_indices, uint64_t height, uint64_t ts, bool miner_tx, bool pool, bool double_spend_seen)
|
||||||
{
|
{
|
||||||
|
//ensure device is let in NONE mode in any case
|
||||||
|
hw::device &hwdev = m_account.get_device();
|
||||||
|
|
||||||
|
std::unique_lock<hw::device> hwdev_lock (hwdev);
|
||||||
|
hw::reset_mode rst(hwdev);
|
||||||
|
hwdev_lock.unlock();
|
||||||
|
|
||||||
// In this function, tx (probably) only contains the base information
|
// In this function, tx (probably) only contains the base information
|
||||||
// (that is, the prunable stuff may or may not be included)
|
// (that is, the prunable stuff may or may not be included)
|
||||||
|
|
||||||
if (!miner_tx && !pool)
|
if (!miner_tx && !pool)
|
||||||
process_unconfirmed(txid, tx, height);
|
process_unconfirmed(txid, tx, height);
|
||||||
std::vector<size_t> outs;
|
std::vector<size_t> outs;
|
||||||
@ -1119,8 +1128,10 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
|
|||||||
tools::threadpool& tpool = tools::threadpool::getInstance();
|
tools::threadpool& tpool = tools::threadpool::getInstance();
|
||||||
tools::threadpool::waiter waiter;
|
tools::threadpool::waiter waiter;
|
||||||
const cryptonote::account_keys& keys = m_account.get_keys();
|
const cryptonote::account_keys& keys = m_account.get_keys();
|
||||||
hw::device &hwdev = m_account.get_device();
|
|
||||||
crypto::key_derivation derivation;
|
crypto::key_derivation derivation;
|
||||||
|
|
||||||
|
hwdev_lock.lock();
|
||||||
|
hwdev.set_mode(hw::device::TRANSACTION_PARSE);
|
||||||
if (!hwdev.generate_key_derivation(tx_pub_key, keys.m_view_secret_key, derivation))
|
if (!hwdev.generate_key_derivation(tx_pub_key, keys.m_view_secret_key, derivation))
|
||||||
{
|
{
|
||||||
MWARNING("Failed to generate key derivation from tx pubkey, skipping");
|
MWARNING("Failed to generate key derivation from tx pubkey, skipping");
|
||||||
@ -1140,6 +1151,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
|
|||||||
additional_derivations.pop_back();
|
additional_derivations.pop_back();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
hwdev_lock.unlock();
|
||||||
|
|
||||||
if (miner_tx && m_refresh_type == RefreshNoCoinbase)
|
if (miner_tx && m_refresh_type == RefreshNoCoinbase)
|
||||||
{
|
{
|
||||||
@ -1161,16 +1173,19 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
|
|||||||
std::ref(tx_scan_info[i])));
|
std::ref(tx_scan_info[i])));
|
||||||
}
|
}
|
||||||
waiter.wait();
|
waiter.wait();
|
||||||
|
|
||||||
// then scan all outputs from 0
|
// then scan all outputs from 0
|
||||||
|
hwdev_lock.lock();
|
||||||
|
hwdev.set_mode(hw::device::NONE);
|
||||||
for (size_t i = 0; i < tx.vout.size(); ++i)
|
for (size_t i = 0; i < tx.vout.size(); ++i)
|
||||||
{
|
{
|
||||||
THROW_WALLET_EXCEPTION_IF(tx_scan_info[i].error, error::acc_outs_lookup_error, tx, tx_pub_key, m_account.get_keys());
|
THROW_WALLET_EXCEPTION_IF(tx_scan_info[i].error, error::acc_outs_lookup_error, tx, tx_pub_key, m_account.get_keys());
|
||||||
if (tx_scan_info[i].received)
|
if (tx_scan_info[i].received)
|
||||||
{
|
{
|
||||||
|
hwdev.generate_key_derivation(tx_pub_key, keys.m_view_secret_key, tx_scan_info[i].received->derivation);
|
||||||
scan_output(tx, tx_pub_key, i, tx_scan_info[i], num_vouts_received, tx_money_got_in_outs, outs);
|
scan_output(tx, tx_pub_key, i, tx_scan_info[i], num_vouts_received, tx_money_got_in_outs, outs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
hwdev_lock.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (tx.vout.size() > 1 && tools::threadpool::getInstance().get_max_concurrency() > 1)
|
else if (tx.vout.size() > 1 && tools::threadpool::getInstance().get_max_concurrency() > 1)
|
||||||
@ -1181,14 +1196,19 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
|
|||||||
std::ref(tx_scan_info[i])));
|
std::ref(tx_scan_info[i])));
|
||||||
}
|
}
|
||||||
waiter.wait();
|
waiter.wait();
|
||||||
|
|
||||||
|
hwdev_lock.lock();
|
||||||
|
hwdev.set_mode(hw::device::NONE);
|
||||||
for (size_t i = 0; i < tx.vout.size(); ++i)
|
for (size_t i = 0; i < tx.vout.size(); ++i)
|
||||||
{
|
{
|
||||||
THROW_WALLET_EXCEPTION_IF(tx_scan_info[i].error, error::acc_outs_lookup_error, tx, tx_pub_key, m_account.get_keys());
|
THROW_WALLET_EXCEPTION_IF(tx_scan_info[i].error, error::acc_outs_lookup_error, tx, tx_pub_key, m_account.get_keys());
|
||||||
if (tx_scan_info[i].received)
|
if (tx_scan_info[i].received)
|
||||||
{
|
{
|
||||||
|
hwdev.generate_key_derivation(tx_pub_key, keys.m_view_secret_key, tx_scan_info[i].received->derivation);
|
||||||
scan_output(tx, tx_pub_key, i, tx_scan_info[i], num_vouts_received, tx_money_got_in_outs, outs);
|
scan_output(tx, tx_pub_key, i, tx_scan_info[i], num_vouts_received, tx_money_got_in_outs, outs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
hwdev_lock.unlock();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1198,7 +1218,11 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
|
|||||||
THROW_WALLET_EXCEPTION_IF(tx_scan_info[i].error, error::acc_outs_lookup_error, tx, tx_pub_key, m_account.get_keys());
|
THROW_WALLET_EXCEPTION_IF(tx_scan_info[i].error, error::acc_outs_lookup_error, tx, tx_pub_key, m_account.get_keys());
|
||||||
if (tx_scan_info[i].received)
|
if (tx_scan_info[i].received)
|
||||||
{
|
{
|
||||||
|
hwdev_lock.lock();
|
||||||
|
hwdev.set_mode(hw::device::NONE);
|
||||||
|
hwdev.generate_key_derivation(tx_pub_key, keys.m_view_secret_key, tx_scan_info[i].received->derivation);
|
||||||
scan_output(tx, tx_pub_key, i, tx_scan_info[i], num_vouts_received, tx_money_got_in_outs, outs);
|
scan_output(tx, tx_pub_key, i, tx_scan_info[i], num_vouts_received, tx_money_got_in_outs, outs);
|
||||||
|
hwdev_lock.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -7259,6 +7283,11 @@ bool wallet2::light_wallet_key_image_is_ours(const crypto::key_image& key_image,
|
|||||||
// usable balance.
|
// usable balance.
|
||||||
std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryptonote::tx_destination_entry> dsts, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices, bool trusted_daemon)
|
std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryptonote::tx_destination_entry> dsts, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices, bool trusted_daemon)
|
||||||
{
|
{
|
||||||
|
//ensure device is let in NONE mode in any case
|
||||||
|
hw::device &hwdev = m_account.get_device();
|
||||||
|
std::unique_lock<hw::device> hwdev_lock (hwdev);
|
||||||
|
hw::reset_mode rst(hwdev);
|
||||||
|
|
||||||
if(m_light_wallet) {
|
if(m_light_wallet) {
|
||||||
// Populate m_transfers
|
// Populate m_transfers
|
||||||
light_wallet_get_unspent_outs();
|
light_wallet_get_unspent_outs();
|
||||||
@ -7476,8 +7505,8 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
|||||||
unsigned int original_output_index = 0;
|
unsigned int original_output_index = 0;
|
||||||
std::vector<size_t>* unused_transfers_indices = &unused_transfers_indices_per_subaddr[0].second;
|
std::vector<size_t>* unused_transfers_indices = &unused_transfers_indices_per_subaddr[0].second;
|
||||||
std::vector<size_t>* unused_dust_indices = &unused_dust_indices_per_subaddr[0].second;
|
std::vector<size_t>* unused_dust_indices = &unused_dust_indices_per_subaddr[0].second;
|
||||||
hw::device &hwdev = m_account.get_device();
|
|
||||||
hwdev.set_signature_mode(hw::device::SIGNATURE_FAKE);
|
hwdev.set_mode(hw::device::TRANSACTION_CREATE_FAKE);
|
||||||
while ((!dsts.empty() && dsts[0].amount > 0) || adding_fee || !preferred_inputs.empty() || should_pick_a_second_output(use_rct, txes.back().selected_transfers.size(), *unused_transfers_indices, *unused_dust_indices)) {
|
while ((!dsts.empty() && dsts[0].amount > 0) || adding_fee || !preferred_inputs.empty() || should_pick_a_second_output(use_rct, txes.back().selected_transfers.size(), *unused_transfers_indices, *unused_dust_indices)) {
|
||||||
TX &tx = txes.back();
|
TX &tx = txes.back();
|
||||||
|
|
||||||
@ -7706,7 +7735,7 @@ skip_tx:
|
|||||||
LOG_PRINT_L1("Done creating " << txes.size() << " transactions, " << print_money(accumulated_fee) <<
|
LOG_PRINT_L1("Done creating " << txes.size() << " transactions, " << print_money(accumulated_fee) <<
|
||||||
" total fee, " << print_money(accumulated_change) << " total change");
|
" total fee, " << print_money(accumulated_change) << " total change");
|
||||||
|
|
||||||
hwdev.set_signature_mode(hw::device::SIGNATURE_REAL);
|
hwdev.set_mode(hw::device::TRANSACTION_CREATE_REAL);
|
||||||
for (std::vector<TX>::iterator i = txes.begin(); i != txes.end(); ++i)
|
for (std::vector<TX>::iterator i = txes.begin(); i != txes.end(); ++i)
|
||||||
{
|
{
|
||||||
TX &tx = *i;
|
TX &tx = *i;
|
||||||
@ -7837,6 +7866,11 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_single(const crypt
|
|||||||
|
|
||||||
std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const cryptonote::account_public_address &address, bool is_subaddress, std::vector<size_t> unused_transfers_indices, std::vector<size_t> unused_dust_indices, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra, bool trusted_daemon)
|
std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const cryptonote::account_public_address &address, bool is_subaddress, std::vector<size_t> unused_transfers_indices, std::vector<size_t> unused_dust_indices, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra, bool trusted_daemon)
|
||||||
{
|
{
|
||||||
|
//ensure device is let in NONE mode in any case
|
||||||
|
hw::device &hwdev = m_account.get_device();
|
||||||
|
std::unique_lock<hw::device> hwdev_lock (hwdev);
|
||||||
|
hw::reset_mode rst(hwdev);
|
||||||
|
|
||||||
uint64_t accumulated_fee, accumulated_outputs, accumulated_change;
|
uint64_t accumulated_fee, accumulated_outputs, accumulated_change;
|
||||||
struct TX {
|
struct TX {
|
||||||
std::vector<size_t> selected_transfers;
|
std::vector<size_t> selected_transfers;
|
||||||
@ -7869,8 +7903,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
|
|||||||
needed_fee = 0;
|
needed_fee = 0;
|
||||||
|
|
||||||
// while we have something to send
|
// while we have something to send
|
||||||
hw::device &hwdev = m_account.get_device();
|
hwdev.set_mode(hw::device::TRANSACTION_CREATE_FAKE);
|
||||||
hwdev.set_signature_mode(hw::device::SIGNATURE_FAKE);
|
|
||||||
while (!unused_dust_indices.empty() || !unused_transfers_indices.empty()) {
|
while (!unused_dust_indices.empty() || !unused_transfers_indices.empty()) {
|
||||||
TX &tx = txes.back();
|
TX &tx = txes.back();
|
||||||
|
|
||||||
@ -7956,7 +7989,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
|
|||||||
LOG_PRINT_L1("Done creating " << txes.size() << " transactions, " << print_money(accumulated_fee) <<
|
LOG_PRINT_L1("Done creating " << txes.size() << " transactions, " << print_money(accumulated_fee) <<
|
||||||
" total fee, " << print_money(accumulated_change) << " total change");
|
" total fee, " << print_money(accumulated_change) << " total change");
|
||||||
|
|
||||||
hwdev.set_signature_mode(hw::device::SIGNATURE_REAL);
|
hwdev.set_mode(hw::device::TRANSACTION_CREATE_REAL);
|
||||||
for (std::vector<TX>::iterator i = txes.begin(); i != txes.end(); ++i)
|
for (std::vector<TX>::iterator i = txes.begin(); i != txes.end(); ++i)
|
||||||
{
|
{
|
||||||
TX &tx = *i;
|
TX &tx = *i;
|
||||||
|
Loading…
Reference in New Issue
Block a user