Merge pull request #5332
7c440915
Add get_tx_proof support, needed for new sanity check (cslashm)98fdcb2a
Add support for V11 protocol with BulletProofV2 and short amount. New scheme key destination contrfol Fix dummy decryption in debug mode (cslashm)3a981a33
Add application version compatibility check. (cslashm)
This commit is contained in:
commit
b8ab510f23
|
@ -104,6 +104,13 @@ namespace cryptonote
|
|||
std::vector<rct::key> &amount_keys,
|
||||
crypto::public_key &out_eph_public_key) ;
|
||||
|
||||
bool generate_output_ephemeral_keys(const size_t tx_version, const cryptonote::account_keys &sender_account_keys, const crypto::public_key &txkey_pub, const crypto::secret_key &tx_key,
|
||||
const cryptonote::tx_destination_entry &dst_entr, const boost::optional<cryptonote::account_public_address> &change_addr, const size_t output_index,
|
||||
const bool &need_additional_txkeys, const std::vector<crypto::secret_key> &additional_tx_keys,
|
||||
std::vector<crypto::public_key> &additional_tx_public_keys,
|
||||
std::vector<rct::key> &amount_keys,
|
||||
crypto::public_key &out_eph_public_key) ;
|
||||
|
||||
bool generate_genesis_block(
|
||||
block& bl
|
||||
, std::string const & genesis_tx
|
||||
|
|
|
@ -75,4 +75,6 @@ target_link_libraries(device
|
|||
${OPENSSL_CRYPTO_LIBRARIES}
|
||||
${Boost_SERIALIZATION_LIBRARY}
|
||||
PRIVATE
|
||||
version
|
||||
${Blocks}
|
||||
${EXTRA_LIBRARIES})
|
||||
|
|
|
@ -27,21 +27,6 @@
|
|||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
|
||||
/* 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 "crypto/crypto.h"
|
||||
|
@ -211,6 +196,10 @@ namespace hw {
|
|||
/* TRANSACTION */
|
||||
/* ======================================================================= */
|
||||
|
||||
virtual void generate_tx_proof(const crypto::hash &prefix_hash,
|
||||
const crypto::public_key &R, const crypto::public_key &A, const boost::optional<crypto::public_key> &B, const crypto::public_key &D, const crypto::secret_key &r,
|
||||
crypto::signature &sig) = 0;
|
||||
|
||||
virtual bool open_tx(crypto::secret_key &tx_key) = 0;
|
||||
|
||||
virtual bool encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key) = 0;
|
||||
|
@ -220,6 +209,8 @@ namespace hw {
|
|||
return encrypt_payment_id(payment_id, public_key, secret_key);
|
||||
}
|
||||
|
||||
virtual rct::key genCommitmentMask(const rct::key &amount_key) = 0;
|
||||
|
||||
virtual bool ecdhEncode(rct::ecdhTuple & unmasked, const rct::key & sharedSec, bool short_amount) = 0;
|
||||
virtual bool ecdhDecode(rct::ecdhTuple & masked, const rct::key & sharedSec, bool short_amount) = 0;
|
||||
|
||||
|
|
|
@ -37,7 +37,6 @@
|
|||
#include "cryptonote_core/cryptonote_tx_utils.h"
|
||||
#include "ringct/rctOps.h"
|
||||
|
||||
#include "log.hpp"
|
||||
#define ENCRYPTED_PAYMENT_ID_TAIL 0x8d
|
||||
#define CHACHA8_KEY_TAIL 0x8c
|
||||
|
||||
|
@ -273,6 +272,11 @@ namespace hw {
|
|||
/* ======================================================================= */
|
||||
/* TRANSACTION */
|
||||
/* ======================================================================= */
|
||||
void device_default::generate_tx_proof(const crypto::hash &prefix_hash,
|
||||
const crypto::public_key &R, const crypto::public_key &A, const boost::optional<crypto::public_key> &B, const crypto::public_key &D, const crypto::secret_key &r,
|
||||
crypto::signature &sig) {
|
||||
crypto::generate_tx_proof(prefix_hash, R, A, B, D, r, sig);
|
||||
}
|
||||
|
||||
bool device_default::open_tx(crypto::secret_key &tx_key) {
|
||||
cryptonote::keypair txkey = cryptonote::keypair::generate(*this);
|
||||
|
@ -349,6 +353,10 @@ namespace hw {
|
|||
return true;
|
||||
}
|
||||
|
||||
rct::key device_default::genCommitmentMask(const rct::key &amount_key) {
|
||||
return rct::genCommitmentMask(amount_key);
|
||||
}
|
||||
|
||||
bool device_default::ecdhEncode(rct::ecdhTuple & unmasked, const rct::key & sharedSec, bool short_amount) {
|
||||
rct::ecdhEncode(unmasked, sharedSec, short_amount);
|
||||
return true;
|
||||
|
|
|
@ -107,10 +107,16 @@ namespace hw {
|
|||
/* TRANSACTION */
|
||||
/* ======================================================================= */
|
||||
|
||||
void generate_tx_proof(const crypto::hash &prefix_hash,
|
||||
const crypto::public_key &R, const crypto::public_key &A, const boost::optional<crypto::public_key> &B, const crypto::public_key &D, const crypto::secret_key &r,
|
||||
crypto::signature &sig) override;
|
||||
|
||||
bool open_tx(crypto::secret_key &tx_key) override;
|
||||
|
||||
bool encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key) override;
|
||||
|
||||
rct::key genCommitmentMask(const rct::key &amount_key) override;
|
||||
|
||||
bool ecdhEncode(rct::ecdhTuple & unmasked, const rct::key & sharedSec, bool short_amount) override;
|
||||
bool ecdhDecode(rct::ecdhTuple & masked, const rct::key & sharedSec, bool short_amount) override;
|
||||
|
||||
|
|
|
@ -27,8 +27,8 @@
|
|||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#include "version.h"
|
||||
#include "device_ledger.hpp"
|
||||
#include "log.hpp"
|
||||
#include "ringct/rctOps.h"
|
||||
#include "cryptonote_basic/account.h"
|
||||
#include "cryptonote_basic/subaddress_index.h"
|
||||
|
@ -173,6 +173,7 @@ namespace hw {
|
|||
#define INS_SET_SIGNATURE_MODE 0x72
|
||||
#define INS_GET_ADDITIONAL_KEY 0x74
|
||||
#define INS_STEALTH 0x76
|
||||
#define INS_GEN_COMMITMENT_MASK 0x77
|
||||
#define INS_BLIND 0x78
|
||||
#define INS_UNBLIND 0x7A
|
||||
#define INS_GEN_TXOUT_KEYS 0x7B
|
||||
|
@ -180,6 +181,7 @@ namespace hw {
|
|||
#define INS_MLSAG 0x7E
|
||||
#define INS_CLOSE_TX 0x80
|
||||
|
||||
#define INS_GET_TX_PROOF 0xA0
|
||||
|
||||
#define INS_GET_RESPONSE 0xc0
|
||||
|
||||
|
@ -302,7 +304,23 @@ namespace hw {
|
|||
}
|
||||
|
||||
bool device_ledger::reset() {
|
||||
send_simple(INS_RESET);
|
||||
reset_buffer();
|
||||
int offset = set_command_header_noopt(INS_RESET);
|
||||
memmove(this->buffer_send+offset, MONERO_VERSION, strlen(MONERO_VERSION));
|
||||
offset += strlen(MONERO_VERSION);
|
||||
this->buffer_send[4] = offset-5;
|
||||
this->length_send = offset;
|
||||
this->exchange();
|
||||
|
||||
ASSERT_X(this->length_recv>=3, "Communication error, less than three bytes received. Check your application version.");
|
||||
|
||||
unsigned int device_version = 0;
|
||||
device_version = VERSION(this->buffer_recv[0], this->buffer_recv[1], this->buffer_recv[2]);
|
||||
|
||||
ASSERT_X (device_version >= MINIMAL_APP_VERSION,
|
||||
"Unsupported device application version: " << VERSION_MAJOR(device_version)<<"."<<VERSION_MINOR(device_version)<<"."<<VERSION_MICRO(device_version) <<
|
||||
" At least " << MINIMAL_APP_VERSION_MAJOR<<"."<<MINIMAL_APP_VERSION_MINOR<<"."<<MINIMAL_APP_VERSION_MICRO<<" is required.");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -314,9 +332,9 @@ namespace hw {
|
|||
|
||||
this->length_recv -= 2;
|
||||
this->sw = (this->buffer_recv[length_recv]<<8) | this->buffer_recv[length_recv+1];
|
||||
logRESP();
|
||||
ASSERT_SW(this->sw,ok,msk);
|
||||
|
||||
logRESP();
|
||||
return this->sw;
|
||||
}
|
||||
|
||||
|
@ -790,7 +808,11 @@ 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;
|
||||
rct::key aG_x;
|
||||
log_hexbuffer("sc_secret_add: [[IN]] a ", (char*)a_x.data, 32);
|
||||
log_hexbuffer("sc_secret_add: [[IN]] b ", (char*)b_x.data, 32);
|
||||
this->controle_device->sc_secret_add(r_x, a_x, b_x);
|
||||
log_hexbuffer("sc_secret_add: [[OUT]] aG", (char*)r_x.data, 32);
|
||||
#endif
|
||||
|
||||
int offset = set_command_header_noopt(INS_SECRET_KEY_ADD);
|
||||
|
@ -825,6 +847,11 @@ namespace hw {
|
|||
#ifdef DEBUG_HWDEVICE
|
||||
crypto::public_key pub_x;
|
||||
crypto::secret_key sec_x;
|
||||
crypto::secret_key recovery_key_x;
|
||||
if (recover) {
|
||||
recovery_key_x = hw::ledger::decrypt(recovery_key);
|
||||
log_hexbuffer("generate_keys: [[IN]] pub", (char*)recovery_key_x.data, 32);
|
||||
}
|
||||
#endif
|
||||
|
||||
send_simple(INS_GENERATE_KEYPAIR);
|
||||
|
@ -836,6 +863,9 @@ namespace hw {
|
|||
#ifdef DEBUG_HWDEVICE
|
||||
crypto::secret_key sec_clear = hw::ledger::decrypt(sec);
|
||||
sec_x = sec_clear;
|
||||
log_hexbuffer("generate_keys: [[OUT]] pub", (char*)pub.data, 32);
|
||||
log_hexbuffer("generate_keys: [[OUT]] sec", (char*)sec_clear.data, 32);
|
||||
|
||||
crypto::secret_key_to_public_key(sec_x,pub_x);
|
||||
hw::ledger::check32("generate_keys", "pub", pub_x.data, pub.data);
|
||||
#endif
|
||||
|
@ -850,7 +880,7 @@ namespace hw {
|
|||
|
||||
#ifdef DEBUG_HWDEVICE
|
||||
const crypto::public_key pub_x = pub;
|
||||
const crypto::secret_key sec_x = hw::ledger::decrypt(sec);
|
||||
const crypto::secret_key sec_x = (sec == rct::rct2sk(rct::I)) ? sec: hw::ledger::decrypt(sec);
|
||||
crypto::key_derivation derivation_x;
|
||||
log_hexbuffer("generate_key_derivation: [[IN]] pub ", pub_x.data, 32);
|
||||
log_hexbuffer("generate_key_derivation: [[IN]] sec ", sec_x.data, 32);
|
||||
|
@ -866,7 +896,6 @@ namespace hw {
|
|||
assert(is_fake_view_key(sec));
|
||||
r = crypto::generate_key_derivation(pub, this->viewkey, derivation);
|
||||
} else {
|
||||
|
||||
int offset = set_command_header_noopt(INS_GEN_KEY_DERIVATION);
|
||||
//pub
|
||||
memmove(this->buffer_send+offset, pub.data, 32);
|
||||
|
@ -887,7 +916,7 @@ namespace hw {
|
|||
crypto::key_derivation derivation_clear ;
|
||||
if ((this->mode == TRANSACTION_PARSE) && has_view_key) {
|
||||
derivation_clear = derivation;
|
||||
}else {
|
||||
} else {
|
||||
derivation_clear = hw::ledger::decrypt(derivation);
|
||||
}
|
||||
hw::ledger::check32("generate_key_derivation", "derivation", derivation_x.data, derivation_clear.data);
|
||||
|
@ -1050,7 +1079,7 @@ namespace hw {
|
|||
bool rc = this->controle_device->secret_key_to_public_key(sec_x, pub_x);
|
||||
log_hexbuffer("secret_key_to_public_key: [[OUT]] pub", pub_x.data, 32);
|
||||
if (!rc){
|
||||
log_message("secret_key_to_public_key", "secret_key rejected");
|
||||
log_message("FAIL secret_key_to_public_key", "secret_key rejected");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1112,6 +1141,75 @@ namespace hw {
|
|||
/* TRANSACTION */
|
||||
/* ======================================================================= */
|
||||
|
||||
void device_ledger::generate_tx_proof(const crypto::hash &prefix_hash,
|
||||
const crypto::public_key &R, const crypto::public_key &A, const boost::optional<crypto::public_key> &B, const crypto::public_key &D, const crypto::secret_key &r,
|
||||
crypto::signature &sig) {
|
||||
|
||||
AUTO_LOCK_CMD();
|
||||
|
||||
#ifdef DEBUG_HWDEVICE
|
||||
const crypto::hash prefix_hash_x = prefix_hash;
|
||||
const crypto::public_key R_x = R;
|
||||
const crypto::public_key A_x = A;
|
||||
const boost::optional<crypto::public_key> B_x = B;
|
||||
const crypto::public_key D_x = D;
|
||||
const crypto::secret_key r_x = hw::ledger::decrypt(r);
|
||||
crypto::signature sig_x;
|
||||
log_hexbuffer("generate_tx_proof: [[IN]] prefix_hash ", prefix_hash_x.data, 32);
|
||||
log_hexbuffer("generate_tx_proof: [[IN]] R ", R_x.data, 32);
|
||||
log_hexbuffer("generate_tx_proof: [[IN]] A ", A_x.data, 32);
|
||||
if (B_x) {
|
||||
log_hexbuffer("generate_tx_proof: [[IN]] B ", (*B_x).data, 32);
|
||||
}
|
||||
log_hexbuffer("generate_tx_proof: [[IN]] D ", D_x.data, 32);
|
||||
log_hexbuffer("generate_tx_proof: [[IN]] r ", r_x.data, 32);
|
||||
#endif
|
||||
|
||||
|
||||
int offset = set_command_header(INS_GET_TX_PROOF);
|
||||
//options
|
||||
this->buffer_send[offset] = B?0x01:0x00;
|
||||
offset += 1;
|
||||
//prefix_hash
|
||||
memmove(&this->buffer_send[offset], prefix_hash.data, 32);
|
||||
offset += 32;
|
||||
// R
|
||||
memmove(&this->buffer_send[offset], R.data, 32);
|
||||
offset += 32;
|
||||
// A
|
||||
memmove(&this->buffer_send[offset], A.data, 32);
|
||||
offset += 32;
|
||||
// B
|
||||
if (B) {
|
||||
memmove(&this->buffer_send[offset], (*B).data, 32);
|
||||
} else {
|
||||
memset(&this->buffer_send[offset], 0, 32);
|
||||
}
|
||||
offset += 32;
|
||||
// D
|
||||
memmove(&this->buffer_send[offset], D.data, 32);
|
||||
offset += 32;
|
||||
// r
|
||||
memmove(&this->buffer_send[offset], r.data, 32);
|
||||
offset += 32;
|
||||
|
||||
this->buffer_send[4] = offset-5;
|
||||
this->length_send = offset;
|
||||
this->exchange();
|
||||
|
||||
memmove(sig.c.data, &this->buffer_recv[0], 32);
|
||||
memmove(sig.r.data, &this->buffer_recv[32], 32);
|
||||
#ifdef DEBUG_HWDEVICE
|
||||
log_hexbuffer("GENERATE_TX_PROOF: **c** ", sig.c.data, sizeof( sig.c.data));
|
||||
log_hexbuffer("GENERATE_TX_PROOF: **r** ", sig.r.data, sizeof( sig.r.data));
|
||||
|
||||
this->controle_device->generate_tx_proof(prefix_hash_x, R_x, A_x, B_x, D_x, r_x, sig_x);
|
||||
hw::ledger::check32("generate_tx_proof", "c", sig_x.c.data, sig.c.data);
|
||||
hw::ledger::check32("generate_tx_proof", "r", sig_x.r.data, sig.r.data);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
bool device_ledger::open_tx(crypto::secret_key &tx_key) {
|
||||
AUTO_LOCK_CMD();
|
||||
|
||||
|
@ -1130,7 +1228,11 @@ namespace hw {
|
|||
this->exchange();
|
||||
|
||||
memmove(tx_key.data, &this->buffer_recv[32], 32);
|
||||
|
||||
#ifdef DEBUG_HWDEVICE
|
||||
const crypto::secret_key r_x = hw::ledger::decrypt(tx_key);
|
||||
log_hexbuffer("open_tx: [[OUT]] R ", (char*)&this->buffer_recv[0], 32);
|
||||
log_hexbuffer("open_tx: [[OUT]] r ", r_x.data, 32);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1141,7 +1243,11 @@ 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;
|
||||
log_hexbuffer("encrypt_payment_id: [[IN]] payment_id ", payment_id_x.data, 32);
|
||||
log_hexbuffer("encrypt_payment_id: [[IN]] public_key ", public_key_x.data, 32);
|
||||
log_hexbuffer("encrypt_payment_id: [[IN]] secret_key ", secret_key_x.data, 32);
|
||||
this->controle_device->encrypt_payment_id(payment_id_x, public_key_x, secret_key_x);
|
||||
log_hexbuffer("encrypt_payment_id: [[OUT]] payment_id ", payment_id_x.data, 32);
|
||||
#endif
|
||||
|
||||
int offset = set_command_header_noopt(INS_STEALTH);
|
||||
|
@ -1178,49 +1284,58 @@ namespace hw {
|
|||
|
||||
#ifdef DEBUG_HWDEVICE
|
||||
const size_t &tx_version_x = tx_version;
|
||||
const cryptonote::account_keys sender_account_keys_x = sender_account_keys;
|
||||
const cryptonote::account_keys sender_account_keys_x = hw::ledger::decrypt(sender_account_keys);
|
||||
memmove((void*)sender_account_keys_x.m_view_secret_key.data, dbg_viewkey.data, 32);
|
||||
|
||||
const crypto::public_key &txkey_pub_x = txkey_pub;
|
||||
const crypto::secret_key &tx_key_x = tx_key;
|
||||
const cryptonote::tx_destination_entry &dst_entr_x = dst_entr;
|
||||
const boost::optional<cryptonote::account_public_address> &change_addr_x = change_addr;
|
||||
const size_t &output_index_x = output_index;
|
||||
const bool &need_additional_txkeys_x = need_additional_txkeys;
|
||||
const std::vector<crypto::secret_key> &additional_tx_keys_x = additional_tx_keys;
|
||||
const crypto::public_key txkey_pub_x = txkey_pub;
|
||||
const crypto::secret_key tx_key_x = hw::ledger::decrypt(tx_key);
|
||||
const cryptonote::tx_destination_entry dst_entr_x = dst_entr;
|
||||
const boost::optional<cryptonote::account_public_address> change_addr_x = change_addr;
|
||||
const size_t output_index_x = output_index;
|
||||
const bool need_additional_txkeys_x = need_additional_txkeys;
|
||||
|
||||
std::vector<crypto::secret_key> additional_tx_keys_x;
|
||||
for (const auto k: additional_tx_keys) {
|
||||
additional_tx_keys_x.push_back(hw::ledger::decrypt(k));
|
||||
}
|
||||
|
||||
std::vector<crypto::public_key> additional_tx_public_keys_x;
|
||||
std::vector<rct::key> amount_keys_x;
|
||||
crypto::public_key out_eph_public_key_x;
|
||||
|
||||
log_message ("generate_output_ephemeral_keys: [[IN]] tx_version", std::to_string(tx_version_x));
|
||||
//log_hexbuffer("generate_output_ephemeral_keys: [[IN]] sender_account_keys.view", sender_account_keys.m_sview_secret_key.data, 32);
|
||||
//log_hexbuffer("generate_output_ephemeral_keys: [[IN]] sender_account_keys.spend", sender_account_keys.m_spend_secret_key.data, 32);
|
||||
log_hexbuffer("generate_output_ephemeral_keys: [[IN]] txkey_pub", txkey_pub_x.data, 32);
|
||||
log_hexbuffer("generate_output_ephemeral_keys: [[IN]] tx_key", tx_key_x.data, 32);
|
||||
log_hexbuffer("generate_output_ephemeral_keys: [[IN]] dst_entr.view", dst_entr_x.addr.m_view_public_key.data, 32);
|
||||
log_hexbuffer("generate_output_ephemeral_keys: [[IN]] dst_entr.spend", dst_entr_x.addr.m_spend_public_key.data, 32);
|
||||
if (change_addr) {
|
||||
log_hexbuffer("generate_output_ephemeral_keys: [[IN]] change_addr.view", (*change_addr_x).m_view_public_key.data, 32);
|
||||
log_hexbuffer("generate_output_ephemeral_keys: [[IN]] change_addr.spend", (*change_addr_x).m_spend_public_key.data, 32);
|
||||
}
|
||||
log_message ("generate_output_ephemeral_keys: [[IN]] output_index", std::to_string(output_index_x));
|
||||
log_message ("generate_output_ephemeral_keys: [[IN]] need_additional_txkeys", std::to_string(need_additional_txkeys_x));
|
||||
if(need_additional_txkeys_x) {
|
||||
log_hexbuffer("generate_output_ephemeral_keys: [[IN]] additional_tx_keys[oi]", additional_tx_keys_x[output_index].data, 32);
|
||||
}
|
||||
this->controle_device->generate_output_ephemeral_keys(tx_version_x, sender_account_keys_x, txkey_pub_x, tx_key_x, dst_entr_x, change_addr_x, output_index_x, need_additional_txkeys_x, additional_tx_keys_x,
|
||||
additional_tx_public_keys_x, amount_keys_x, out_eph_public_key_x);
|
||||
if(need_additional_txkeys_x) {
|
||||
log_hexbuffer("additional_tx_public_keys_x: [[OUT]] additional_tx_public_keys_x", additional_tx_public_keys_x.back().data, 32);
|
||||
}
|
||||
log_hexbuffer("generate_output_ephemeral_keys: [[OUT]] amount_keys ", (char*)amount_keys_x.back().bytes, 32);
|
||||
log_hexbuffer("generate_output_ephemeral_keys: [[OUT]] out_eph_public_key ", out_eph_public_key_x.data, 32);
|
||||
#endif
|
||||
|
||||
ASSERT_X(tx_version > 1, "TX version not supported"<<tx_version);
|
||||
|
||||
// make additional tx pubkey if necessary
|
||||
cryptonote::keypair additional_txkey;
|
||||
if (need_additional_txkeys) {
|
||||
additional_txkey.sec = additional_tx_keys[output_index];
|
||||
}
|
||||
|
||||
//compute derivation, out_eph_public_key, and amount key in one shot on device, to ensure checkable link
|
||||
const crypto::secret_key *sec;
|
||||
bool is_change;
|
||||
|
||||
if (change_addr && dst_entr.addr == *change_addr)
|
||||
{
|
||||
// sending change to yourself; derivation = a*R
|
||||
is_change = true;
|
||||
sec = &sender_account_keys.m_view_secret_key;
|
||||
}
|
||||
else
|
||||
{
|
||||
is_change = false;
|
||||
if (dst_entr.is_subaddress && need_additional_txkeys) {
|
||||
sec = &additional_txkey.sec;
|
||||
} else {
|
||||
sec = &tx_key;
|
||||
}
|
||||
}
|
||||
|
||||
int offset = set_command_header_noopt(INS_GEN_TXOUT_KEYS);
|
||||
//tx_version
|
||||
this->buffer_send[offset+0] = tx_version>>24;
|
||||
|
@ -1228,8 +1343,11 @@ namespace hw {
|
|||
this->buffer_send[offset+2] = tx_version>>8;
|
||||
this->buffer_send[offset+3] = tx_version>>0;
|
||||
offset += 4;
|
||||
//tx_sec
|
||||
memmove(&this->buffer_send[offset], sec->data, 32);
|
||||
//tx_key
|
||||
memmove(&this->buffer_send[offset], tx_key.data, 32);
|
||||
offset += 32;
|
||||
//txkey_pub
|
||||
memmove(&this->buffer_send[offset], txkey_pub.data, 32);
|
||||
offset += 32;
|
||||
//Aout
|
||||
memmove(&this->buffer_send[offset], dst_entr.addr.m_view_public_key.data, 32);
|
||||
|
@ -1244,6 +1362,7 @@ namespace hw {
|
|||
this->buffer_send[offset+3] = output_index>>0;
|
||||
offset += 4;
|
||||
//is_change,
|
||||
bool is_change = (change_addr && dst_entr.addr == *change_addr);
|
||||
this->buffer_send[offset] = is_change;
|
||||
offset++;
|
||||
//is_subaddress
|
||||
|
@ -1252,6 +1371,13 @@ namespace hw {
|
|||
//need_additional_key
|
||||
this->buffer_send[offset] = need_additional_txkeys;
|
||||
offset++;
|
||||
//additional_tx_key
|
||||
if (need_additional_txkeys) {
|
||||
memmove(&this->buffer_send[offset], additional_txkey.sec.data, 32);
|
||||
} else {
|
||||
memset(&this->buffer_send[offset], 0, 32);
|
||||
}
|
||||
offset += 32;
|
||||
|
||||
this->buffer_send[4] = offset-5;
|
||||
this->length_send = offset;
|
||||
|
@ -1259,15 +1385,8 @@ namespace hw {
|
|||
|
||||
offset = 0;
|
||||
unsigned int recv_len = this->length_recv;
|
||||
if (need_additional_txkeys)
|
||||
{
|
||||
ASSERT_X(recv_len>=32, "Not enought data from device");
|
||||
memmove(additional_txkey.pub.data, &this->buffer_recv[offset], 32);
|
||||
additional_tx_public_keys.push_back(additional_txkey.pub);
|
||||
offset += 32;
|
||||
recv_len -= 32;
|
||||
}
|
||||
if (tx_version > 1)
|
||||
|
||||
//if (tx_version > 1)
|
||||
{
|
||||
ASSERT_X(recv_len>=32, "Not enought data from device");
|
||||
crypto::secret_key scalar1;
|
||||
|
@ -1279,6 +1398,16 @@ namespace hw {
|
|||
ASSERT_X(recv_len>=32, "Not enought data from device");
|
||||
memmove(out_eph_public_key.data, &this->buffer_recv[offset], 32);
|
||||
recv_len -= 32;
|
||||
offset += 32;
|
||||
|
||||
if (need_additional_txkeys)
|
||||
{
|
||||
ASSERT_X(recv_len>=32, "Not enought data from device");
|
||||
memmove(additional_txkey.pub.data, &this->buffer_recv[offset], 32);
|
||||
additional_tx_public_keys.push_back(additional_txkey.pub);
|
||||
offset += 32;
|
||||
recv_len -= 32;
|
||||
}
|
||||
|
||||
// add ABPkeys
|
||||
this->add_output_key_mapping(dst_entr.addr.m_view_public_key, dst_entr.addr.m_spend_public_key, dst_entr.is_subaddress, is_change,
|
||||
|
@ -1286,9 +1415,10 @@ namespace hw {
|
|||
amount_keys.back(), out_eph_public_key);
|
||||
|
||||
#ifdef DEBUG_HWDEVICE
|
||||
log_hexbuffer("generate_output_ephemeral_keys: clear amount_key", (const char*)hw::ledger::decrypt(amount_keys.back()).bytes, 32);
|
||||
hw::ledger::check32("generate_output_ephemeral_keys", "amount_key", (const char*)amount_keys_x.back().bytes, (const char*)hw::ledger::decrypt(amount_keys.back()).bytes);
|
||||
if (need_additional_txkeys) {
|
||||
hw::ledger::check32("generate_output_ephemeral_keys", "additional_tx_key", additional_tx_keys_x.back().data, additional_tx_keys.back().data);
|
||||
hw::ledger::check32("generate_output_ephemeral_keys", "additional_tx_key", additional_tx_public_keys_x.back().data, additional_tx_public_keys.back().data);
|
||||
}
|
||||
hw::ledger::check32("generate_output_ephemeral_keys", "out_eph_public_key", out_eph_public_key_x.data, out_eph_public_key.data);
|
||||
#endif
|
||||
|
@ -1303,6 +1433,32 @@ namespace hw {
|
|||
return true;
|
||||
}
|
||||
|
||||
rct::key device_ledger::genCommitmentMask(const rct::key &AKout) {
|
||||
#ifdef DEBUG_HWDEVICE
|
||||
const rct::key AKout_x = hw::ledger::decrypt(AKout);
|
||||
rct::key mask_x;
|
||||
mask_x = this->controle_device->genCommitmentMask(AKout_x);
|
||||
#endif
|
||||
|
||||
rct::key mask;
|
||||
int offset = set_command_header_noopt(INS_GEN_COMMITMENT_MASK);
|
||||
// AKout
|
||||
memmove(this->buffer_send+offset, AKout.bytes, 32);
|
||||
offset += 32;
|
||||
|
||||
this->buffer_send[4] = offset-5;
|
||||
this->length_send = offset;
|
||||
this->exchange();
|
||||
|
||||
memmove(mask.bytes, &this->buffer_recv[0], 32);
|
||||
|
||||
#ifdef DEBUG_HWDEVICE
|
||||
hw::ledger::check32("genCommitmentMask", "mask", (const char*)mask_x.bytes, (const char*)mask.bytes);
|
||||
#endif
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
bool device_ledger::ecdhEncode(rct::ecdhTuple & unmasked, const rct::key & AKout, bool short_amount) {
|
||||
AUTO_LOCK_CMD();
|
||||
|
||||
|
@ -1334,6 +1490,7 @@ namespace hw {
|
|||
memmove(unmasked.mask.bytes, &this->buffer_recv[32], 32);
|
||||
|
||||
#ifdef DEBUG_HWDEVICE
|
||||
MDEBUG("ecdhEncode: Akout: "<<AKout_x);
|
||||
hw::ledger::check32("ecdhEncode", "amount", (char*)unmasked_x.amount.bytes, (char*)unmasked.amount.bytes);
|
||||
hw::ledger::check32("ecdhEncode", "mask", (char*)unmasked_x.mask.bytes, (char*)unmasked.mask.bytes);
|
||||
|
||||
|
@ -1374,6 +1531,7 @@ namespace hw {
|
|||
memmove(masked.mask.bytes, &this->buffer_recv[32], 32);
|
||||
|
||||
#ifdef DEBUG_HWDEVICE
|
||||
MDEBUG("ecdhEncode: Akout: "<<AKout_x);
|
||||
hw::ledger::check32("ecdhDecode", "amount", (char*)masked_x.amount.bytes, (char*)masked.amount.bytes);
|
||||
hw::ledger::check32("ecdhDecode", "mask", (char*)masked_x.mask.bytes,(char*) masked.mask.bytes);
|
||||
#endif
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <cstddef>
|
||||
#include <string>
|
||||
#include "device.hpp"
|
||||
#include "log.hpp"
|
||||
#include "device_io_hid.hpp"
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/recursive_mutex.hpp>
|
||||
|
@ -41,6 +42,18 @@ namespace hw {
|
|||
|
||||
namespace ledger {
|
||||
|
||||
/* Minimal supported version */
|
||||
#define MINIMAL_APP_VERSION_MAJOR 1
|
||||
#define MINIMAL_APP_VERSION_MINOR 3
|
||||
#define MINIMAL_APP_VERSION_MICRO 1
|
||||
|
||||
#define VERSION(M,m,u) ((M)<<16|(m)<<8|(u))
|
||||
#define VERSION_MAJOR(v) (((v)>>16)&0xFF)
|
||||
#define VERSION_MINOR(v) (((v)>>8)&0xFF)
|
||||
#define VERSION_MICRO(v) (((v)>>0)&0xFF)
|
||||
|
||||
#define MINIMAL_APP_VERSION VERSION(MINIMAL_APP_VERSION_MAJOR, MINIMAL_APP_VERSION_MINOR, MINIMAL_APP_VERSION_MICRO)
|
||||
|
||||
void register_all(std::map<std::string, std::unique_ptr<device>> ®istry);
|
||||
|
||||
#ifdef WITH_DEVICE_LEDGER
|
||||
|
@ -190,11 +203,16 @@ namespace hw {
|
|||
/* ======================================================================= */
|
||||
/* TRANSACTION */
|
||||
/* ======================================================================= */
|
||||
void generate_tx_proof(const crypto::hash &prefix_hash,
|
||||
const crypto::public_key &R, const crypto::public_key &A, const boost::optional<crypto::public_key> &B, const crypto::public_key &D, const crypto::secret_key &r,
|
||||
crypto::signature &sig) override;
|
||||
|
||||
bool open_tx(crypto::secret_key &tx_key) override;
|
||||
|
||||
bool encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key) override;
|
||||
|
||||
rct::key genCommitmentMask(const rct::key &amount_key) override;
|
||||
|
||||
bool ecdhEncode(rct::ecdhTuple & unmasked, const rct::key & sharedSec, bool short_format) override;
|
||||
bool ecdhDecode(rct::ecdhTuple & masked, const rct::key & sharedSec, bool short_format) override;
|
||||
|
||||
|
|
|
@ -40,6 +40,19 @@
|
|||
|
||||
namespace hw {
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
void buffer_to_str(char *to_buff, size_t to_len, const char *buff, size_t len) ;
|
||||
void log_hexbuffer(const std::string &msg, const char* buff, size_t len);
|
||||
void log_message(const std::string &msg, const std::string &info );
|
||||
|
|
|
@ -79,12 +79,12 @@ namespace
|
|||
}
|
||||
|
||||
namespace rct {
|
||||
Bulletproof proveRangeBulletproof(keyV &C, keyV &masks, const std::vector<uint64_t> &amounts, epee::span<const key> sk)
|
||||
Bulletproof proveRangeBulletproof(keyV &C, keyV &masks, const std::vector<uint64_t> &amounts, epee::span<const key> sk, hw::device &hwdev)
|
||||
{
|
||||
CHECK_AND_ASSERT_THROW_MES(amounts.size() == sk.size(), "Invalid amounts/sk sizes");
|
||||
masks.resize(amounts.size());
|
||||
for (size_t i = 0; i < masks.size(); ++i)
|
||||
masks[i] = genCommitmentMask(sk[i]);
|
||||
masks[i] = hwdev.genCommitmentMask(sk[i]);
|
||||
Bulletproof proof = bulletproof_PROVE(amounts, masks);
|
||||
CHECK_AND_ASSERT_THROW_MES(proof.V.size() == amounts.size(), "V does not have the expected size");
|
||||
C = proof.V;
|
||||
|
@ -804,7 +804,7 @@ namespace rct {
|
|||
else
|
||||
{
|
||||
const epee::span<const key> keys{&amount_keys[0], amount_keys.size()};
|
||||
rv.p.bulletproofs.push_back(proveRangeBulletproof(C, masks, outamounts, keys));
|
||||
rv.p.bulletproofs.push_back(proveRangeBulletproof(C, masks, outamounts, keys, hwdev));
|
||||
#ifdef DBG
|
||||
CHECK_AND_ASSERT_THROW_MES(verBulletproof(rv.p.bulletproofs.back()), "verBulletproof failed on newly created proof");
|
||||
#endif
|
||||
|
@ -833,7 +833,7 @@ namespace rct {
|
|||
else
|
||||
{
|
||||
const epee::span<const key> keys{&amount_keys[amounts_proved], batch_size};
|
||||
rv.p.bulletproofs.push_back(proveRangeBulletproof(C, masks, batch_amounts, keys));
|
||||
rv.p.bulletproofs.push_back(proveRangeBulletproof(C, masks, batch_amounts, keys, hwdev));
|
||||
#ifdef DBG
|
||||
CHECK_AND_ASSERT_THROW_MES(verBulletproof(rv.p.bulletproofs.back()), "verBulletproof failed on newly created proof");
|
||||
#endif
|
||||
|
|
|
@ -6873,11 +6873,6 @@ bool simple_wallet::set_tx_key(const std::vector<std::string> &args_)
|
|||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::get_tx_proof(const std::vector<std::string> &args)
|
||||
{
|
||||
if (m_wallet->key_on_device() && m_wallet->get_account().get_device().get_type() != hw::device::TREZOR)
|
||||
{
|
||||
fail_msg_writer() << tr("command not supported by HW wallet");
|
||||
return true;
|
||||
}
|
||||
if (args.size() != 2 && args.size() != 3)
|
||||
{
|
||||
PRINT_USAGE(USAGE_GET_TX_PROOF);
|
||||
|
|
|
@ -10430,7 +10430,7 @@ void wallet2::check_tx_key(const crypto::hash &txid, const crypto::secret_key &t
|
|||
void wallet2::check_tx_key_helper(const cryptonote::transaction &tx, const crypto::key_derivation &derivation, const std::vector<crypto::key_derivation> &additional_derivations, const cryptonote::account_public_address &address, uint64_t &received) const
|
||||
{
|
||||
received = 0;
|
||||
hw::device &hwdev = m_account.get_device();
|
||||
|
||||
for (size_t n = 0; n < tx.vout.size(); ++n)
|
||||
{
|
||||
const cryptonote::txout_to_key* const out_key = boost::get<cryptonote::txout_to_key>(std::addressof(tx.vout[n].target));
|
||||
|
@ -10438,13 +10438,13 @@ void wallet2::check_tx_key_helper(const cryptonote::transaction &tx, const crypt
|
|||
continue;
|
||||
|
||||
crypto::public_key derived_out_key;
|
||||
bool r = hwdev.derive_public_key(derivation, n, address.m_spend_public_key, derived_out_key);
|
||||
bool r = crypto::derive_public_key(derivation, n, address.m_spend_public_key, derived_out_key);
|
||||
THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to derive public key");
|
||||
bool found = out_key->key == derived_out_key;
|
||||
crypto::key_derivation found_derivation = derivation;
|
||||
if (!found && !additional_derivations.empty())
|
||||
{
|
||||
r = hwdev.derive_public_key(additional_derivations[n], n, address.m_spend_public_key, derived_out_key);
|
||||
r = crypto::derive_public_key(additional_derivations[n], n, address.m_spend_public_key, derived_out_key);
|
||||
THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to derive public key");
|
||||
found = out_key->key == derived_out_key;
|
||||
found_derivation = additional_derivations[n];
|
||||
|
@ -10460,9 +10460,9 @@ void wallet2::check_tx_key_helper(const cryptonote::transaction &tx, const crypt
|
|||
else
|
||||
{
|
||||
crypto::secret_key scalar1;
|
||||
hwdev.derivation_to_scalar(found_derivation, n, scalar1);
|
||||
crypto::derivation_to_scalar(found_derivation, n, scalar1);
|
||||
rct::ecdhTuple ecdh_info = tx.rct_signatures.ecdhInfo[n];
|
||||
hwdev.ecdhDecode(ecdh_info, rct::sk2rct(scalar1), tx.rct_signatures.type == rct::RCTTypeBulletproof2);
|
||||
rct::ecdhDecode(ecdh_info, rct::sk2rct(scalar1), tx.rct_signatures.type == rct::RCTTypeBulletproof2);
|
||||
const rct::key C = tx.rct_signatures.outPk[n].mask;
|
||||
rct::key Ctmp;
|
||||
THROW_WALLET_EXCEPTION_IF(sc_check(ecdh_info.mask.bytes) != 0, error::wallet_internal_error, "Bad ECDH input mask");
|
||||
|
@ -10573,6 +10573,8 @@ std::string wallet2::get_tx_proof(const crypto::hash &txid, const cryptonote::ac
|
|||
|
||||
std::string wallet2::get_tx_proof(const cryptonote::transaction &tx, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys, const cryptonote::account_public_address &address, bool is_subaddress, const std::string &message) const
|
||||
{
|
||||
hw::device &hwdev = m_account.get_device();
|
||||
rct::key aP;
|
||||
// determine if the address is found in the subaddress hash table (i.e. whether the proof is outbound or inbound)
|
||||
const bool is_out = m_subaddresses.count(address.m_spend_public_key) == 0;
|
||||
|
||||
|
@ -10591,30 +10593,34 @@ std::string wallet2::get_tx_proof(const cryptonote::transaction &tx, const crypt
|
|||
shared_secret.resize(num_sigs);
|
||||
sig.resize(num_sigs);
|
||||
|
||||
shared_secret[0] = rct::rct2pk(rct::scalarmultKey(rct::pk2rct(address.m_view_public_key), rct::sk2rct(tx_key)));
|
||||
hwdev.scalarmultKey(aP, rct::pk2rct(address.m_view_public_key), rct::sk2rct(tx_key));
|
||||
shared_secret[0] = rct::rct2pk(aP);
|
||||
crypto::public_key tx_pub_key;
|
||||
if (is_subaddress)
|
||||
{
|
||||
tx_pub_key = rct2pk(rct::scalarmultKey(rct::pk2rct(address.m_spend_public_key), rct::sk2rct(tx_key)));
|
||||
crypto::generate_tx_proof(prefix_hash, tx_pub_key, address.m_view_public_key, address.m_spend_public_key, shared_secret[0], tx_key, sig[0]);
|
||||
hwdev.scalarmultKey(aP, rct::pk2rct(address.m_spend_public_key), rct::sk2rct(tx_key));
|
||||
tx_pub_key = rct2pk(aP);
|
||||
hwdev.generate_tx_proof(prefix_hash, tx_pub_key, address.m_view_public_key, address.m_spend_public_key, shared_secret[0], tx_key, sig[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
crypto::secret_key_to_public_key(tx_key, tx_pub_key);
|
||||
crypto::generate_tx_proof(prefix_hash, tx_pub_key, address.m_view_public_key, boost::none, shared_secret[0], tx_key, sig[0]);
|
||||
hwdev.secret_key_to_public_key(tx_key, tx_pub_key);
|
||||
hwdev.generate_tx_proof(prefix_hash, tx_pub_key, address.m_view_public_key, boost::none, shared_secret[0], tx_key, sig[0]);
|
||||
}
|
||||
for (size_t i = 1; i < num_sigs; ++i)
|
||||
{
|
||||
shared_secret[i] = rct::rct2pk(rct::scalarmultKey(rct::pk2rct(address.m_view_public_key), rct::sk2rct(additional_tx_keys[i - 1])));
|
||||
hwdev.scalarmultKey(aP, rct::pk2rct(address.m_view_public_key), rct::sk2rct(additional_tx_keys[i - 1]));
|
||||
shared_secret[i] = rct::rct2pk(aP);
|
||||
if (is_subaddress)
|
||||
{
|
||||
tx_pub_key = rct2pk(rct::scalarmultKey(rct::pk2rct(address.m_spend_public_key), rct::sk2rct(additional_tx_keys[i - 1])));
|
||||
crypto::generate_tx_proof(prefix_hash, tx_pub_key, address.m_view_public_key, address.m_spend_public_key, shared_secret[i], additional_tx_keys[i - 1], sig[i]);
|
||||
hwdev.scalarmultKey(aP, rct::pk2rct(address.m_spend_public_key), rct::sk2rct(additional_tx_keys[i - 1]));
|
||||
tx_pub_key = rct2pk(aP);
|
||||
hwdev.generate_tx_proof(prefix_hash, tx_pub_key, address.m_view_public_key, address.m_spend_public_key, shared_secret[i], additional_tx_keys[i - 1], sig[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
crypto::secret_key_to_public_key(additional_tx_keys[i - 1], tx_pub_key);
|
||||
crypto::generate_tx_proof(prefix_hash, tx_pub_key, address.m_view_public_key, boost::none, shared_secret[i], additional_tx_keys[i - 1], sig[i]);
|
||||
hwdev.secret_key_to_public_key(additional_tx_keys[i - 1], tx_pub_key);
|
||||
hwdev.generate_tx_proof(prefix_hash, tx_pub_key, address.m_view_public_key, boost::none, shared_secret[i], additional_tx_keys[i - 1], sig[i]);
|
||||
}
|
||||
}
|
||||
sig_str = std::string("OutProofV1");
|
||||
|
@ -10630,25 +10636,27 @@ std::string wallet2::get_tx_proof(const cryptonote::transaction &tx, const crypt
|
|||
sig.resize(num_sigs);
|
||||
|
||||
const crypto::secret_key& a = m_account.get_keys().m_view_secret_key;
|
||||
shared_secret[0] = rct::rct2pk(rct::scalarmultKey(rct::pk2rct(tx_pub_key), rct::sk2rct(a)));
|
||||
hwdev.scalarmultKey(aP, rct::pk2rct(tx_pub_key), rct::sk2rct(a));
|
||||
shared_secret[0] = rct2pk(aP);
|
||||
if (is_subaddress)
|
||||
{
|
||||
crypto::generate_tx_proof(prefix_hash, address.m_view_public_key, tx_pub_key, address.m_spend_public_key, shared_secret[0], a, sig[0]);
|
||||
hwdev.generate_tx_proof(prefix_hash, address.m_view_public_key, tx_pub_key, address.m_spend_public_key, shared_secret[0], a, sig[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
crypto::generate_tx_proof(prefix_hash, address.m_view_public_key, tx_pub_key, boost::none, shared_secret[0], a, sig[0]);
|
||||
hwdev.generate_tx_proof(prefix_hash, address.m_view_public_key, tx_pub_key, boost::none, shared_secret[0], a, sig[0]);
|
||||
}
|
||||
for (size_t i = 1; i < num_sigs; ++i)
|
||||
{
|
||||
shared_secret[i] = rct::rct2pk(rct::scalarmultKey(rct::pk2rct(additional_tx_pub_keys[i - 1]), rct::sk2rct(a)));
|
||||
hwdev.scalarmultKey(aP,rct::pk2rct(additional_tx_pub_keys[i - 1]), rct::sk2rct(a));
|
||||
shared_secret[i] = rct2pk(aP);
|
||||
if (is_subaddress)
|
||||
{
|
||||
crypto::generate_tx_proof(prefix_hash, address.m_view_public_key, additional_tx_pub_keys[i - 1], address.m_spend_public_key, shared_secret[i], a, sig[i]);
|
||||
hwdev.generate_tx_proof(prefix_hash, address.m_view_public_key, additional_tx_pub_keys[i - 1], address.m_spend_public_key, shared_secret[i], a, sig[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
crypto::generate_tx_proof(prefix_hash, address.m_view_public_key, additional_tx_pub_keys[i - 1], boost::none, shared_secret[i], a, sig[i]);
|
||||
hwdev.generate_tx_proof(prefix_hash, address.m_view_public_key, additional_tx_pub_keys[i - 1], boost::none, shared_secret[i], a, sig[i]);
|
||||
}
|
||||
}
|
||||
sig_str = std::string("InProofV1");
|
||||
|
|
Loading…
Reference in New Issue