New scheme key destination contrfol
Implies protocol version management.
This commit is contained in:
parent
31bdf7bd11
commit
460da140ec
|
@ -405,49 +405,12 @@ namespace cryptonote
|
||||||
for(const tx_destination_entry& dst_entr: destinations)
|
for(const tx_destination_entry& dst_entr: destinations)
|
||||||
{
|
{
|
||||||
CHECK_AND_ASSERT_MES(dst_entr.amount > 0 || tx.version > 1, false, "Destination with wrong amount: " << dst_entr.amount);
|
CHECK_AND_ASSERT_MES(dst_entr.amount > 0 || tx.version > 1, false, "Destination with wrong amount: " << dst_entr.amount);
|
||||||
crypto::key_derivation derivation;
|
|
||||||
crypto::public_key out_eph_public_key;
|
crypto::public_key out_eph_public_key;
|
||||||
|
|
||||||
// make additional tx pubkey if necessary
|
hwdev.generate_output_ephemeral_keys(tx.version,sender_account_keys, txkey_pub, tx_key,
|
||||||
keypair additional_txkey;
|
dst_entr, change_addr, output_index,
|
||||||
if (need_additional_txkeys)
|
need_additional_txkeys, additional_tx_keys,
|
||||||
{
|
additional_tx_public_keys, amount_keys, out_eph_public_key);
|
||||||
additional_txkey.sec = additional_tx_keys[output_index];
|
|
||||||
if (dst_entr.is_subaddress)
|
|
||||||
additional_txkey.pub = rct::rct2pk(hwdev.scalarmultKey(rct::pk2rct(dst_entr.addr.m_spend_public_key), rct::sk2rct(additional_txkey.sec)));
|
|
||||||
else
|
|
||||||
additional_txkey.pub = rct::rct2pk(hwdev.scalarmultBase(rct::sk2rct(additional_txkey.sec)));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool r;
|
|
||||||
if (change_addr && dst_entr.addr == *change_addr)
|
|
||||||
{
|
|
||||||
// sending change to yourself; derivation = a*R
|
|
||||||
r = hwdev.generate_key_derivation(txkey_pub, sender_account_keys.m_view_secret_key, derivation);
|
|
||||||
CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to generate_key_derivation(" << txkey_pub << ", " << sender_account_keys.m_view_secret_key << ")");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// sending to the recipient; derivation = r*A (or s*C in the subaddress scheme)
|
|
||||||
r = hwdev.generate_key_derivation(dst_entr.addr.m_view_public_key, dst_entr.is_subaddress && need_additional_txkeys ? additional_txkey.sec : tx_key, derivation);
|
|
||||||
CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to generate_key_derivation(" << dst_entr.addr.m_view_public_key << ", " << (dst_entr.is_subaddress && need_additional_txkeys ? additional_txkey.sec : tx_key) << ")");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (need_additional_txkeys)
|
|
||||||
{
|
|
||||||
additional_tx_public_keys.push_back(additional_txkey.pub);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tx.version > 1)
|
|
||||||
{
|
|
||||||
crypto::secret_key scalar1;
|
|
||||||
hwdev.derivation_to_scalar(derivation, output_index, scalar1);
|
|
||||||
amount_keys.push_back(rct::sk2rct(scalar1));
|
|
||||||
}
|
|
||||||
r = hwdev.derive_public_key(derivation, output_index, dst_entr.addr.m_spend_public_key, out_eph_public_key);
|
|
||||||
CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to derive_public_key(" << derivation << ", " << output_index << ", "<< dst_entr.addr.m_spend_public_key << ")");
|
|
||||||
|
|
||||||
hwdev.add_output_key_mapping(dst_entr.addr.m_view_public_key, dst_entr.addr.m_spend_public_key, dst_entr.is_subaddress, output_index, amount_keys.back(), out_eph_public_key);
|
|
||||||
|
|
||||||
tx_out out;
|
tx_out out;
|
||||||
out.amount = dst_entr.amount;
|
out.amount = dst_entr.amount;
|
||||||
|
|
|
@ -97,6 +97,12 @@ namespace cryptonote
|
||||||
bool construct_tx(const account_keys& sender_account_keys, std::vector<tx_source_entry> &sources, const std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time);
|
bool construct_tx(const account_keys& sender_account_keys, std::vector<tx_source_entry> &sources, const std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time);
|
||||||
bool construct_tx_with_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys, bool rct = false, const rct::RCTConfig &rct_config = { rct::RangeProofBorromean, 0 }, rct::multisig_out *msout = NULL, bool shuffle_outs = true);
|
bool construct_tx_with_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys, bool rct = false, const rct::RCTConfig &rct_config = { rct::RangeProofBorromean, 0 }, rct::multisig_out *msout = NULL, bool shuffle_outs = true);
|
||||||
bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys, bool rct = false, const rct::RCTConfig &rct_config = { rct::RangeProofBorromean, 0 }, rct::multisig_out *msout = NULL);
|
bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys, bool rct = false, const rct::RCTConfig &rct_config = { rct::RangeProofBorromean, 0 }, rct::multisig_out *msout = NULL);
|
||||||
|
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(
|
bool generate_genesis_block(
|
||||||
block& bl
|
block& bl
|
||||||
|
|
|
@ -69,6 +69,7 @@ namespace cryptonote
|
||||||
struct account_public_address;
|
struct account_public_address;
|
||||||
struct account_keys;
|
struct account_keys;
|
||||||
struct subaddress_index;
|
struct subaddress_index;
|
||||||
|
struct tx_destination_entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace hw {
|
namespace hw {
|
||||||
|
@ -211,9 +212,12 @@ namespace hw {
|
||||||
virtual bool ecdhEncode(rct::ecdhTuple & unmasked, const rct::key & sharedSec, bool short_amount) = 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;
|
virtual bool ecdhDecode(rct::ecdhTuple & masked, const rct::key & sharedSec, bool short_amount) = 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,
|
virtual 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 rct::key &amount_key, const crypto::public_key &out_eph_public_key) = 0;
|
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) = 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;
|
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;
|
||||||
virtual bool mlsag_prepare(const rct::key &H, const rct::key &xx, rct::key &a, rct::key &aG, rct::key &aHP, rct::key &rvII) = 0;
|
virtual bool mlsag_prepare(const rct::key &H, const rct::key &xx, rct::key &a, rct::key &aG, rct::key &aHP, rct::key &rvII) = 0;
|
||||||
|
|
|
@ -34,8 +34,10 @@
|
||||||
#include "int-util.h"
|
#include "int-util.h"
|
||||||
#include "cryptonote_basic/account.h"
|
#include "cryptonote_basic/account.h"
|
||||||
#include "cryptonote_basic/subaddress_index.h"
|
#include "cryptonote_basic/subaddress_index.h"
|
||||||
|
#include "cryptonote_core/cryptonote_tx_utils.h"
|
||||||
#include "ringct/rctOps.h"
|
#include "ringct/rctOps.h"
|
||||||
|
|
||||||
|
#include "log.hpp"
|
||||||
#define ENCRYPTED_PAYMENT_ID_TAIL 0x8d
|
#define ENCRYPTED_PAYMENT_ID_TAIL 0x8d
|
||||||
#define CHACHA8_KEY_TAIL 0x8c
|
#define CHACHA8_KEY_TAIL 0x8c
|
||||||
|
|
||||||
|
@ -278,10 +280,55 @@ namespace hw {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool device_default::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 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,
|
crypto::key_derivation derivation;
|
||||||
const rct::key &amount_key, const crypto::public_key &out_eph_public_key) {
|
|
||||||
return true;
|
// make additional tx pubkey if necessary
|
||||||
|
cryptonote::keypair additional_txkey;
|
||||||
|
if (need_additional_txkeys)
|
||||||
|
{
|
||||||
|
additional_txkey.sec = additional_tx_keys[output_index];
|
||||||
|
if (dst_entr.is_subaddress)
|
||||||
|
additional_txkey.pub = rct::rct2pk(rct::scalarmultKey(rct::pk2rct(dst_entr.addr.m_spend_public_key), rct::sk2rct(additional_txkey.sec)));
|
||||||
|
else
|
||||||
|
additional_txkey.pub = rct::rct2pk(rct::scalarmultBase(rct::sk2rct(additional_txkey.sec)));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool r;
|
||||||
|
if (change_addr && dst_entr.addr == *change_addr)
|
||||||
|
{
|
||||||
|
// sending change to yourself; derivation = a*R
|
||||||
|
r = generate_key_derivation(txkey_pub, sender_account_keys.m_view_secret_key, derivation);
|
||||||
|
CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to generate_key_derivation(" << txkey_pub << ", " << sender_account_keys.m_view_secret_key << ")");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// sending to the recipient; derivation = r*A (or s*C in the subaddress scheme)
|
||||||
|
r = generate_key_derivation(dst_entr.addr.m_view_public_key, dst_entr.is_subaddress && need_additional_txkeys ? additional_txkey.sec : tx_key, derivation);
|
||||||
|
CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to generate_key_derivation(" << dst_entr.addr.m_view_public_key << ", " << (dst_entr.is_subaddress && need_additional_txkeys ? additional_txkey.sec : tx_key) << ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (need_additional_txkeys)
|
||||||
|
{
|
||||||
|
additional_tx_public_keys.push_back(additional_txkey.pub);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tx_version > 1)
|
||||||
|
{
|
||||||
|
crypto::secret_key scalar1;
|
||||||
|
derivation_to_scalar(derivation, output_index, scalar1);
|
||||||
|
amount_keys.push_back(rct::sk2rct(scalar1));
|
||||||
|
}
|
||||||
|
r = derive_public_key(derivation, output_index, dst_entr.addr.m_spend_public_key, out_eph_public_key);
|
||||||
|
CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to derive_public_key(" << derivation << ", " << output_index << ", "<< dst_entr.addr.m_spend_public_key << ")");
|
||||||
|
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
|
|
|
@ -114,9 +114,12 @@ namespace hw {
|
||||||
bool ecdhEncode(rct::ecdhTuple & unmasked, const rct::key & sharedSec, bool short_amount) 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;
|
bool ecdhDecode(rct::ecdhTuple & masked, const rct::key & sharedSec, bool short_amount) 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,
|
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 rct::key &amount_key, const crypto::public_key &out_eph_public_key) override;
|
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) 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;
|
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;
|
||||||
bool mlsag_prepare(const rct::key &H, const rct::key &xx, rct::key &a, rct::key &aG, rct::key &aHP, rct::key &rvII) override;
|
bool mlsag_prepare(const rct::key &H, const rct::key &xx, rct::key &a, rct::key &aG, rct::key &aHP, rct::key &rvII) override;
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include "ringct/rctOps.h"
|
#include "ringct/rctOps.h"
|
||||||
#include "cryptonote_basic/account.h"
|
#include "cryptonote_basic/account.h"
|
||||||
#include "cryptonote_basic/subaddress_index.h"
|
#include "cryptonote_basic/subaddress_index.h"
|
||||||
|
#include "cryptonote_core/cryptonote_tx_utils.h"
|
||||||
|
|
||||||
#include <boost/thread/locks.hpp>
|
#include <boost/thread/locks.hpp>
|
||||||
#include <boost/thread/lock_guard.hpp>
|
#include <boost/thread/lock_guard.hpp>
|
||||||
|
@ -67,10 +68,12 @@ namespace hw {
|
||||||
/* === Keymap ==== */
|
/* === Keymap ==== */
|
||||||
/* ===================================================================== */
|
/* ===================================================================== */
|
||||||
|
|
||||||
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) {
|
ABPkeys::ABPkeys(const rct::key& A, const rct::key& B, const bool is_subaddr, const bool is_change, const bool need_additional_txkeys, const size_t real_output_index, const rct::key& P, const rct::key& AK) {
|
||||||
Aout = A;
|
Aout = A;
|
||||||
Bout = B;
|
Bout = B;
|
||||||
is_subaddress = is_subaddr;
|
is_subaddress = is_subaddr;
|
||||||
|
is_change_address = is_change;
|
||||||
|
additional_key = need_additional_txkeys;
|
||||||
index = real_output_index;
|
index = real_output_index;
|
||||||
Pout = P;
|
Pout = P;
|
||||||
AKout = AK;
|
AKout = AK;
|
||||||
|
@ -80,6 +83,8 @@ namespace hw {
|
||||||
Aout = keys.Aout;
|
Aout = keys.Aout;
|
||||||
Bout = keys.Bout;
|
Bout = keys.Bout;
|
||||||
is_subaddress = keys.is_subaddress;
|
is_subaddress = keys.is_subaddress;
|
||||||
|
is_change_address = keys.is_change_address;
|
||||||
|
additional_key = keys.additional_key;
|
||||||
index = keys.index;
|
index = keys.index;
|
||||||
Pout = keys.Pout;
|
Pout = keys.Pout;
|
||||||
AKout = keys.AKout;
|
AKout = keys.AKout;
|
||||||
|
@ -137,6 +142,8 @@ namespace hw {
|
||||||
|
|
||||||
static int device_id = 0;
|
static int device_id = 0;
|
||||||
|
|
||||||
|
#define PROTOCOL_VERSION 2
|
||||||
|
|
||||||
#define INS_NONE 0x00
|
#define INS_NONE 0x00
|
||||||
#define INS_RESET 0x02
|
#define INS_RESET 0x02
|
||||||
|
|
||||||
|
@ -168,6 +175,7 @@ namespace hw {
|
||||||
#define INS_STEALTH 0x76
|
#define INS_STEALTH 0x76
|
||||||
#define INS_BLIND 0x78
|
#define INS_BLIND 0x78
|
||||||
#define INS_UNBLIND 0x7A
|
#define INS_UNBLIND 0x7A
|
||||||
|
#define INS_GEN_TXOUT_KEYS 0x7B
|
||||||
#define INS_VALIDATE 0x7C
|
#define INS_VALIDATE 0x7C
|
||||||
#define INS_MLSAG 0x7E
|
#define INS_MLSAG 0x7E
|
||||||
#define INS_CLOSE_TX 0x80
|
#define INS_CLOSE_TX 0x80
|
||||||
|
@ -268,7 +276,7 @@ namespace hw {
|
||||||
int device_ledger::set_command_header(unsigned char ins, unsigned char p1, unsigned char p2) {
|
int device_ledger::set_command_header(unsigned char ins, unsigned char p1, unsigned char p2) {
|
||||||
reset_buffer();
|
reset_buffer();
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
this->buffer_send[0] = 0x00;
|
this->buffer_send[0] = PROTOCOL_VERSION;
|
||||||
this->buffer_send[1] = ins;
|
this->buffer_send[1] = ins;
|
||||||
this->buffer_send[2] = p1;
|
this->buffer_send[2] = p1;
|
||||||
this->buffer_send[3] = p2;
|
this->buffer_send[3] = p2;
|
||||||
|
@ -1160,10 +1168,139 @@ namespace hw {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
bool device_ledger::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,
|
||||||
AUTO_LOCK_CMD();
|
const cryptonote::tx_destination_entry &dst_entr, const boost::optional<cryptonote::account_public_address> &change_addr, const size_t output_index,
|
||||||
key_map.add(ABPkeys(rct::pk2rct(Aout),rct::pk2rct(Bout), is_subaddress, real_output_index, rct::pk2rct(out_eph_public_key), amount_key));
|
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) {
|
||||||
|
AUTO_LOCK_CMD();
|
||||||
|
|
||||||
|
#ifdef DEBUG_HWDEVICE
|
||||||
|
const size_t &tx_version_x = tx_version;
|
||||||
|
const cryptonote::account_keys sender_account_keys_x = 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;
|
||||||
|
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;
|
||||||
|
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);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
this->buffer_send[offset+1] = tx_version>>16;
|
||||||
|
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);
|
||||||
|
offset += 32;
|
||||||
|
//Aout
|
||||||
|
memmove(&this->buffer_send[offset], dst_entr.addr.m_view_public_key.data, 32);
|
||||||
|
offset += 32;
|
||||||
|
//Bout
|
||||||
|
memmove(&this->buffer_send[offset], dst_entr.addr.m_spend_public_key.data, 32);
|
||||||
|
offset += 32;
|
||||||
|
//output index
|
||||||
|
this->buffer_send[offset+0] = output_index>>24;
|
||||||
|
this->buffer_send[offset+1] = output_index>>16;
|
||||||
|
this->buffer_send[offset+2] = output_index>>8;
|
||||||
|
this->buffer_send[offset+3] = output_index>>0;
|
||||||
|
offset += 4;
|
||||||
|
//is_change,
|
||||||
|
this->buffer_send[offset] = is_change;
|
||||||
|
offset++;
|
||||||
|
//is_subaddress
|
||||||
|
this->buffer_send[offset] = dst_entr.is_subaddress;
|
||||||
|
offset++;
|
||||||
|
//need_additional_key
|
||||||
|
this->buffer_send[offset] = need_additional_txkeys;
|
||||||
|
offset++;
|
||||||
|
|
||||||
|
this->buffer_send[4] = offset-5;
|
||||||
|
this->length_send = offset;
|
||||||
|
this->exchange();
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
ASSERT_X(recv_len>=32, "Not enought data from device");
|
||||||
|
crypto::secret_key scalar1;
|
||||||
|
memmove(scalar1.data, &this->buffer_recv[offset],32);
|
||||||
|
amount_keys.push_back(rct::sk2rct(scalar1));
|
||||||
|
offset += 32;
|
||||||
|
recv_len -= 32;
|
||||||
|
}
|
||||||
|
ASSERT_X(recv_len>=32, "Not enought data from device");
|
||||||
|
memmove(out_eph_public_key.data, &this->buffer_recv[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,
|
||||||
|
need_additional_txkeys, output_index,
|
||||||
|
amount_keys.back(), out_eph_public_key);
|
||||||
|
|
||||||
|
#ifdef DEBUG_HWDEVICE
|
||||||
|
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", "out_eph_public_key", out_eph_public_key_x.data, out_eph_public_key.data);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool device_ledger::add_output_key_mapping(const crypto::public_key &Aout, const crypto::public_key &Bout, const bool is_subaddress, const bool is_change,
|
||||||
|
const bool need_additional, const size_t real_output_index,
|
||||||
|
const rct::key &amount_key, const crypto::public_key &out_eph_public_key) {
|
||||||
|
key_map.add(ABPkeys(rct::pk2rct(Aout),rct::pk2rct(Bout), is_subaddress, is_change, need_additional, real_output_index, rct::pk2rct(out_eph_public_key), amount_key));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1328,6 +1465,9 @@ namespace hw {
|
||||||
//is_subaddress
|
//is_subaddress
|
||||||
this->buffer_send[offset] = outKeys.is_subaddress;
|
this->buffer_send[offset] = outKeys.is_subaddress;
|
||||||
offset++;
|
offset++;
|
||||||
|
//is_change_address
|
||||||
|
this->buffer_send[offset] = outKeys.is_change_address;
|
||||||
|
offset++;
|
||||||
//Aout
|
//Aout
|
||||||
memmove(this->buffer_send+offset, outKeys.Aout.bytes, 32);
|
memmove(this->buffer_send+offset, outKeys.Aout.bytes, 32);
|
||||||
offset+=32;
|
offset+=32;
|
||||||
|
@ -1348,8 +1488,8 @@ namespace hw {
|
||||||
//k
|
//k
|
||||||
memmove(this->buffer_send+offset, data+kv_offset,32);
|
memmove(this->buffer_send+offset, data+kv_offset,32);
|
||||||
offset += 32;
|
offset += 32;
|
||||||
//v
|
|
||||||
kv_offset += 32;
|
kv_offset += 32;
|
||||||
|
//v
|
||||||
memmove(this->buffer_send+offset, data+kv_offset,32);
|
memmove(this->buffer_send+offset, data+kv_offset,32);
|
||||||
offset += 32;
|
offset += 32;
|
||||||
kv_offset += 32;
|
kv_offset += 32;
|
||||||
|
|
|
@ -56,12 +56,14 @@ namespace hw {
|
||||||
rct::key Aout;
|
rct::key Aout;
|
||||||
rct::key Bout;
|
rct::key Bout;
|
||||||
bool is_subaddress;
|
bool is_subaddress;
|
||||||
|
bool is_change_address;
|
||||||
|
bool additional_key ;
|
||||||
size_t index;
|
size_t index;
|
||||||
rct::key Pout;
|
rct::key Pout;
|
||||||
rct::key AKout;
|
rct::key AKout;
|
||||||
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 rct::key& A, const rct::key& B, const bool is_subaddr, bool is_subaddress, bool is_change_address, size_t index, const rct::key& P,const rct::key& AK);
|
||||||
ABPkeys(const ABPkeys& keys) ;
|
ABPkeys(const ABPkeys& keys) ;
|
||||||
ABPkeys() {index=0;is_subaddress=false;}
|
ABPkeys() {index=0;is_subaddress=false;is_subaddress=false;is_change_address=false;}
|
||||||
};
|
};
|
||||||
|
|
||||||
class Keymap {
|
class Keymap {
|
||||||
|
@ -105,7 +107,9 @@ namespace hw {
|
||||||
device_mode mode;
|
device_mode mode;
|
||||||
// map public destination key to ephemeral destination key
|
// map public destination key to ephemeral destination key
|
||||||
Keymap key_map;
|
Keymap key_map;
|
||||||
|
bool add_output_key_mapping(const crypto::public_key &Aout, const crypto::public_key &Bout, const bool is_subaddress, const bool is_change,
|
||||||
|
const bool need_additional, const size_t real_output_index,
|
||||||
|
const rct::key &amount_key, const crypto::public_key &out_eph_public_key);
|
||||||
// To speed up blockchain parsing the view key maybe handle here.
|
// To speed up blockchain parsing the view key maybe handle here.
|
||||||
crypto::secret_key viewkey;
|
crypto::secret_key viewkey;
|
||||||
bool has_view_key;
|
bool has_view_key;
|
||||||
|
@ -194,9 +198,12 @@ namespace hw {
|
||||||
bool ecdhEncode(rct::ecdhTuple & unmasked, const rct::key & sharedSec, bool short_format) 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;
|
bool ecdhDecode(rct::ecdhTuple & masked, const rct::key & sharedSec, bool short_format) 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,
|
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 rct::key &amount_key, const crypto::public_key &out_eph_public_key) override;
|
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) 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;
|
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;
|
||||||
bool mlsag_prepare(const rct::key &H, const rct::key &xx, rct::key &a, rct::key &aG, rct::key &aHP, rct::key &rvII) override;
|
bool mlsag_prepare(const rct::key &H, const rct::key &xx, rct::key &a, rct::key &aG, rct::key &aHP, rct::key &rvII) override;
|
||||||
|
|
Loading…
Reference in New Issue