aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/blockchain_db/blockchain_db.h16
-rw-r--r--src/blockchain_db/lmdb/db_lmdb.cpp86
-rw-r--r--src/cryptonote_basic/cryptonote_format_utils.cpp20
-rw-r--r--src/cryptonote_basic/cryptonote_format_utils.h2
-rw-r--r--src/cryptonote_core/cryptonote_core.cpp51
-rw-r--r--src/cryptonote_core/cryptonote_core.h7
-rw-r--r--src/cryptonote_core/tx_pool.cpp10
-rw-r--r--src/cryptonote_core/tx_pool.h4
-rw-r--r--src/device/device.hpp1
-rw-r--r--src/device/device_default.hpp2
-rw-r--r--src/device/device_ledger.cpp75
-rw-r--r--src/device/device_ledger.hpp1
-rw-r--r--src/device/log.cpp4
-rw-r--r--src/device/log.hpp1
-rw-r--r--src/device_trezor/device_trezor.cpp28
-rw-r--r--src/device_trezor/trezor/protocol.cpp225
-rw-r--r--src/device_trezor/trezor/protocol.hpp45
17 files changed, 351 insertions, 227 deletions
diff --git a/src/blockchain_db/blockchain_db.h b/src/blockchain_db/blockchain_db.h
index 263948fa2..a163ef98c 100644
--- a/src/blockchain_db/blockchain_db.h
+++ b/src/blockchain_db/blockchain_db.h
@@ -1883,16 +1883,18 @@ public:
}
virtual ~db_txn_guard()
{
- if (active)
- stop();
+ stop();
}
void stop()
{
- if (readonly)
- db->block_rtxn_stop();
- else
- db->block_wtxn_stop();
- active = false;
+ if (active)
+ {
+ if (readonly)
+ db->block_rtxn_stop();
+ else
+ db->block_wtxn_stop();
+ active = false;
+ }
}
void abort()
{
diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp
index db7fa6c7c..f80013d02 100644
--- a/src/blockchain_db/lmdb/db_lmdb.cpp
+++ b/src/blockchain_db/lmdb/db_lmdb.cpp
@@ -465,6 +465,32 @@ void mdb_txn_safe::increment_txns(int i)
num_active_txns += i;
}
+#define TXN_PREFIX(flags); \
+ mdb_txn_safe auto_txn; \
+ mdb_txn_safe* txn_ptr = &auto_txn; \
+ if (m_batch_active) \
+ txn_ptr = m_write_txn; \
+ else \
+ { \
+ if (auto mdb_res = lmdb_txn_begin(m_env, NULL, flags, auto_txn)) \
+ throw0(DB_ERROR(lmdb_error(std::string("Failed to create a transaction for the db in ")+__FUNCTION__+": ", mdb_res).c_str())); \
+ } \
+
+#define TXN_PREFIX_RDONLY() \
+ MDB_txn *m_txn; \
+ mdb_txn_cursors *m_cursors; \
+ mdb_txn_safe auto_txn; \
+ bool my_rtxn = block_rtxn_start(&m_txn, &m_cursors); \
+ if (my_rtxn) auto_txn.m_tinfo = m_tinfo.get(); \
+ else auto_txn.uncheck()
+#define TXN_POSTFIX_RDONLY()
+
+#define TXN_POSTFIX_SUCCESS() \
+ do { \
+ if (! m_batch_active) \
+ auto_txn.commit(); \
+ } while(0)
+
void lmdb_resized(MDB_env *env, int isactive)
{
mdb_txn_safe::prevent_new_txns();
@@ -713,21 +739,20 @@ uint64_t BlockchainLMDB::get_estimated_batch_size(uint64_t batch_num_blocks, uin
}
else
{
- MDB_txn *rtxn;
- mdb_txn_cursors *rcurs;
- bool my_rtxn = block_rtxn_start(&rtxn, &rcurs);
- for (uint64_t block_num = block_start; block_num <= block_stop; ++block_num)
{
- // we have access to block weight, which will be greater or equal to block size,
- // so use this as a proxy. If it's too much off, we might have to check actual size,
- // which involves reading more data, so is not really wanted
- size_t block_weight = get_block_weight(block_num);
- total_block_size += block_weight;
- // Track number of blocks being totalled here instead of assuming, in case
- // some blocks were to be skipped for being outliers.
- ++num_blocks_used;
+ TXN_PREFIX_RDONLY();
+ for (uint64_t block_num = block_start; block_num <= block_stop; ++block_num)
+ {
+ // we have access to block weight, which will be greater or equal to block size,
+ // so use this as a proxy. If it's too much off, we might have to check actual size,
+ // which involves reading more data, so is not really wanted
+ size_t block_weight = get_block_weight(block_num);
+ total_block_size += block_weight;
+ // Track number of blocks being totalled here instead of assuming, in case
+ // some blocks were to be skipped for being outliers.
+ ++num_blocks_used;
+ }
}
- if (my_rtxn) block_rtxn_stop();
avg_block_size = total_block_size / (num_blocks_used ? num_blocks_used : 1);
MDEBUG("average block size across recent " << num_blocks_used << " blocks: " << avg_block_size);
}
@@ -1678,32 +1703,6 @@ void BlockchainLMDB::unlock()
check_open();
}
-#define TXN_PREFIX(flags); \
- mdb_txn_safe auto_txn; \
- mdb_txn_safe* txn_ptr = &auto_txn; \
- if (m_batch_active) \
- txn_ptr = m_write_txn; \
- else \
- { \
- if (auto mdb_res = lmdb_txn_begin(m_env, NULL, flags, auto_txn)) \
- throw0(DB_ERROR(lmdb_error(std::string("Failed to create a transaction for the db in ")+__FUNCTION__+": ", mdb_res).c_str())); \
- } \
-
-#define TXN_PREFIX_RDONLY() \
- MDB_txn *m_txn; \
- mdb_txn_cursors *m_cursors; \
- mdb_txn_safe auto_txn; \
- bool my_rtxn = block_rtxn_start(&m_txn, &m_cursors); \
- if (my_rtxn) auto_txn.m_tinfo = m_tinfo.get(); \
- else auto_txn.uncheck()
-#define TXN_POSTFIX_RDONLY()
-
-#define TXN_POSTFIX_SUCCESS() \
- do { \
- if (! m_batch_active) \
- auto_txn.commit(); \
- } while(0)
-
// The below two macros are for DB access within block add/remove, whether
// regular batch txn is in use or not. m_write_txn is used as a batch txn, even
@@ -3923,13 +3922,20 @@ void BlockchainLMDB::block_rtxn_stop() const
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
mdb_txn_reset(m_tinfo->m_ti_rtxn);
memset(&m_tinfo->m_ti_rflags, 0, sizeof(m_tinfo->m_ti_rflags));
+ /* cancel out the increment from rtxn_start */
+ mdb_txn_safe::increment_txns(-1);
}
bool BlockchainLMDB::block_rtxn_start() const
{
MDB_txn *mtxn;
mdb_txn_cursors *mcur;
- return block_rtxn_start(&mtxn, &mcur);
+ /* auto_txn is only used for the create gate */
+ mdb_txn_safe auto_txn;
+ bool ret = block_rtxn_start(&mtxn, &mcur);
+ if (ret)
+ auto_txn.increment_txns(1); /* remember there is an active readtxn */
+ return ret;
}
void BlockchainLMDB::block_wtxn_start()
diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp
index 388013f96..829e5fc70 100644
--- a/src/cryptonote_basic/cryptonote_format_utils.cpp
+++ b/src/cryptonote_basic/cryptonote_format_utils.cpp
@@ -989,7 +989,7 @@ namespace cryptonote
return true;
}
//---------------------------------------------------------------
- bool out_can_be_to_acc(const boost::optional<crypto::view_tag>& view_tag_opt, const crypto::key_derivation& derivation, const size_t output_index)
+ bool out_can_be_to_acc(const boost::optional<crypto::view_tag>& view_tag_opt, const crypto::key_derivation& derivation, const size_t output_index, hw::device* hwdev)
{
// If there is no view tag to check, the output can possibly belong to the account.
// Will need to derive the output pub key to be certain whether or not the output belongs to the account.
@@ -1002,7 +1002,15 @@ namespace cryptonote
// Therefore can fail out early to avoid expensive crypto ops needlessly deriving output public key to
// determine if output belongs to the account.
crypto::view_tag derived_view_tag;
- crypto::derive_view_tag(derivation, output_index, derived_view_tag);
+ if (hwdev != nullptr)
+ {
+ bool r = hwdev->derive_view_tag(derivation, output_index, derived_view_tag);
+ CHECK_AND_ASSERT_MES(r, false, "Failed to derive view tag");
+ }
+ else
+ {
+ crypto::derive_view_tag(derivation, output_index, derived_view_tag);
+ }
return view_tag == derived_view_tag;
}
//---------------------------------------------------------------
@@ -1012,7 +1020,7 @@ namespace cryptonote
bool r = acc.get_device().generate_key_derivation(tx_pub_key, acc.m_view_secret_key, derivation);
CHECK_AND_ASSERT_MES(r, false, "Failed to generate key derivation");
crypto::public_key pk;
- if (out_can_be_to_acc(view_tag_opt, derivation, output_index))
+ if (out_can_be_to_acc(view_tag_opt, derivation, output_index, &acc.get_device()))
{
r = acc.get_device().derive_public_key(derivation, output_index, acc.m_account_address.m_spend_public_key, pk);
CHECK_AND_ASSERT_MES(r, false, "Failed to derive public key");
@@ -1026,7 +1034,7 @@ namespace cryptonote
CHECK_AND_ASSERT_MES(output_index < additional_tx_pub_keys.size(), false, "wrong number of additional tx pubkeys");
r = acc.get_device().generate_key_derivation(additional_tx_pub_keys[output_index], acc.m_view_secret_key, derivation);
CHECK_AND_ASSERT_MES(r, false, "Failed to generate key derivation");
- if (out_can_be_to_acc(view_tag_opt, derivation, output_index))
+ if (out_can_be_to_acc(view_tag_opt, derivation, output_index, &acc.get_device()))
{
r = acc.get_device().derive_public_key(derivation, output_index, acc.m_account_address.m_spend_public_key, pk);
CHECK_AND_ASSERT_MES(r, false, "Failed to derive public key");
@@ -1040,7 +1048,7 @@ namespace cryptonote
{
// try the shared tx pubkey
crypto::public_key subaddress_spendkey;
- if (out_can_be_to_acc(view_tag_opt, derivation, output_index))
+ if (out_can_be_to_acc(view_tag_opt, derivation, output_index, &hwdev))
{
CHECK_AND_ASSERT_MES(hwdev.derive_subaddress_public_key(out_key, derivation, output_index, subaddress_spendkey), boost::none, "Failed to derive subaddress public key");
auto found = subaddresses.find(subaddress_spendkey);
@@ -1052,7 +1060,7 @@ namespace cryptonote
if (!additional_derivations.empty())
{
CHECK_AND_ASSERT_MES(output_index < additional_derivations.size(), boost::none, "wrong number of additional derivations");
- if (out_can_be_to_acc(view_tag_opt, additional_derivations[output_index], output_index))
+ if (out_can_be_to_acc(view_tag_opt, additional_derivations[output_index], output_index, &hwdev))
{
CHECK_AND_ASSERT_MES(hwdev.derive_subaddress_public_key(out_key, additional_derivations[output_index], output_index, subaddress_spendkey), boost::none, "Failed to derive subaddress public key");
auto found = subaddresses.find(subaddress_spendkey);
diff --git a/src/cryptonote_basic/cryptonote_format_utils.h b/src/cryptonote_basic/cryptonote_format_utils.h
index 8f5459ca7..b97c9d499 100644
--- a/src/cryptonote_basic/cryptonote_format_utils.h
+++ b/src/cryptonote_basic/cryptonote_format_utils.h
@@ -91,7 +91,7 @@ namespace cryptonote
bool get_encrypted_payment_id_from_tx_extra_nonce(const blobdata& extra_nonce, crypto::hash8& payment_id);
void set_tx_out(const uint64_t amount, const crypto::public_key& output_public_key, const bool use_view_tags, const crypto::view_tag& view_tag, tx_out& out);
bool check_output_types(const transaction& tx, const uint8_t hf_version);
- bool out_can_be_to_acc(const boost::optional<crypto::view_tag>& view_tag_opt, const crypto::key_derivation& derivation, const size_t output_index);
+ bool out_can_be_to_acc(const boost::optional<crypto::view_tag>& view_tag_opt, const crypto::key_derivation& derivation, const size_t output_index, hw::device *hwdev = nullptr);
bool is_out_to_acc(const account_keys& acc, const crypto::public_key& output_public_key, const crypto::public_key& tx_pub_key, const std::vector<crypto::public_key>& additional_tx_public_keys, size_t output_index, const boost::optional<crypto::view_tag>& view_tag_opt = boost::optional<crypto::view_tag>());
struct subaddress_receive_info
{
diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp
index a78f5d673..95cd1c83b 100644
--- a/src/cryptonote_core/cryptonote_core.cpp
+++ b/src/cryptonote_core/cryptonote_core.cpp
@@ -1406,21 +1406,66 @@ namespace cryptonote
return true;
}
//-----------------------------------------------------------------------------------------------
+ bool core::notify_txpool_event(const epee::span<const cryptonote::blobdata> tx_blobs, epee::span<const crypto::hash> tx_hashes, epee::span<const cryptonote::transaction> txs, const std::vector<bool> &just_broadcasted) const
+ {
+ if (!m_zmq_pub)
+ return true;
+
+ if (tx_blobs.size() != tx_hashes.size() || tx_blobs.size() != txs.size() || tx_blobs.size() != just_broadcasted.size())
+ return false;
+
+ /* Publish txs via ZMQ that are "just broadcasted" by the daemon. This is
+ done here in addition to `handle_incoming_txs` in order to guarantee txs
+ are pub'd via ZMQ when we know the daemon has/will broadcast to other
+ nodes & *after* the tx is visible in the pool. This should get called
+ when the user submits a tx to a daemon in the "fluff" epoch relaying txs
+ via a public network. */
+ if (std::count(just_broadcasted.begin(), just_broadcasted.end(), true) == 0)
+ return true;
+
+ std::vector<txpool_event> results{};
+ results.resize(tx_blobs.size());
+ for (std::size_t i = 0; i < results.size(); ++i)
+ {
+ results[i].tx = std::move(txs[i]);
+ results[i].hash = std::move(tx_hashes[i]);
+ results[i].blob_size = tx_blobs[i].size();
+ results[i].weight = results[i].tx.pruned ? get_pruned_transaction_weight(results[i].tx) : get_transaction_weight(results[i].tx, results[i].blob_size);
+ results[i].res = just_broadcasted[i];
+ }
+
+ m_zmq_pub(std::move(results));
+
+ return true;
+ }
+ //-----------------------------------------------------------------------------------------------
void core::on_transactions_relayed(const epee::span<const cryptonote::blobdata> tx_blobs, const relay_method tx_relay)
{
+ // lock ensures duplicate txs aren't pub'd via zmq
+ CRITICAL_REGION_LOCAL(m_incoming_tx_lock);
+
std::vector<crypto::hash> tx_hashes{};
tx_hashes.resize(tx_blobs.size());
+ std::vector<cryptonote::transaction> txs{};
+ txs.resize(tx_blobs.size());
+
for (std::size_t i = 0; i < tx_blobs.size(); ++i)
{
- cryptonote::transaction tx{};
- if (!parse_and_validate_tx_from_blob(tx_blobs[i], tx, tx_hashes[i]))
+ if (!parse_and_validate_tx_from_blob(tx_blobs[i], txs[i], tx_hashes[i]))
{
LOG_ERROR("Failed to parse relayed transaction");
return;
}
}
- m_mempool.set_relayed(epee::to_span(tx_hashes), tx_relay);
+
+ std::vector<bool> just_broadcasted{};
+ just_broadcasted.reserve(tx_hashes.size());
+
+ m_mempool.set_relayed(epee::to_span(tx_hashes), tx_relay, just_broadcasted);
+
+ if (m_zmq_pub && matches_category(tx_relay, relay_category::legacy))
+ notify_txpool_event(tx_blobs, epee::to_span(tx_hashes), epee::to_span(txs), just_broadcasted);
}
//-----------------------------------------------------------------------------------------------
bool core::get_block_template(block& b, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce, uint64_t &seed_height, crypto::hash &seed_hash)
diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h
index 0b36730b6..5f134a999 100644
--- a/src/cryptonote_core/cryptonote_core.h
+++ b/src/cryptonote_core/cryptonote_core.h
@@ -1036,6 +1036,13 @@ namespace cryptonote
bool relay_txpool_transactions();
/**
+ * @brief sends notification of txpool events to subscribers
+ *
+ * @return true on success, false otherwise
+ */
+ bool notify_txpool_event(const epee::span<const cryptonote::blobdata> tx_blobs, epee::span<const crypto::hash> tx_hashes, epee::span<const cryptonote::transaction> txs, const std::vector<bool> &just_broadcasted) const;
+
+ /**
* @brief checks DNS versions
*
* @return true on success, false otherwise
diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp
index 1c99ed132..be81d39f1 100644
--- a/src/cryptonote_core/tx_pool.cpp
+++ b/src/cryptonote_core/tx_pool.cpp
@@ -820,8 +820,10 @@ namespace cryptonote
return true;
}
//---------------------------------------------------------------------------------
- void tx_memory_pool::set_relayed(const epee::span<const crypto::hash> hashes, const relay_method method)
+ void tx_memory_pool::set_relayed(const epee::span<const crypto::hash> hashes, const relay_method method, std::vector<bool> &just_broadcasted)
{
+ just_broadcasted.clear();
+
crypto::random_poisson_seconds embargo_duration{dandelionpp_embargo_average};
const auto now = std::chrono::system_clock::now();
uint64_t next_relay = uint64_t{std::numeric_limits<time_t>::max()};
@@ -831,12 +833,14 @@ namespace cryptonote
LockedTXN lock(m_blockchain.get_db());
for (const auto& hash : hashes)
{
+ bool was_just_broadcasted = false;
try
{
txpool_tx_meta_t meta;
if (m_blockchain.get_txpool_tx_meta(hash, meta))
{
// txes can be received as "stem" or "fluff" in either order
+ const bool already_broadcasted = meta.matches(relay_category::broadcasted);
meta.upgrade_relay_method(method);
meta.relayed = true;
@@ -849,6 +853,9 @@ namespace cryptonote
meta.last_relayed_time = std::chrono::system_clock::to_time_t(now);
m_blockchain.update_txpool_tx(hash, meta);
+
+ // wait until db update succeeds to ensure tx is visible in the pool
+ was_just_broadcasted = !already_broadcasted && meta.matches(relay_category::broadcasted);
}
}
catch (const std::exception &e)
@@ -856,6 +863,7 @@ namespace cryptonote
MERROR("Failed to update txpool transaction metadata: " << e.what());
// continue
}
+ just_broadcasted.emplace_back(was_just_broadcasted);
}
lock.commit();
set_if_less(m_next_check, time_t(next_relay));
diff --git a/src/cryptonote_core/tx_pool.h b/src/cryptonote_core/tx_pool.h
index df58688ff..accd8c863 100644
--- a/src/cryptonote_core/tx_pool.h
+++ b/src/cryptonote_core/tx_pool.h
@@ -357,8 +357,10 @@ namespace cryptonote
*
* @param hashes list of tx hashes that are about to be relayed
* @param tx_relay update how the tx left this node
+ * @param just_broadcasted true if a tx was just broadcasted
+ *
*/
- void set_relayed(epee::span<const crypto::hash> hashes, relay_method tx_relay);
+ void set_relayed(epee::span<const crypto::hash> hashes, relay_method tx_relay, std::vector<bool> &just_broadcasted);
/**
* @brief get the total number of transactions in the pool
diff --git a/src/device/device.hpp b/src/device/device.hpp
index eca91006f..392703a24 100644
--- a/src/device/device.hpp
+++ b/src/device/device.hpp
@@ -177,6 +177,7 @@ namespace hw {
virtual bool derive_public_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::public_key &pub, crypto::public_key &derived_pub) = 0;
virtual bool secret_key_to_public_key(const crypto::secret_key &sec, crypto::public_key &pub) = 0;
virtual bool generate_key_image(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_image &image) = 0;
+ virtual bool derive_view_tag(const crypto::key_derivation &derivation, const std::size_t output_index, crypto::view_tag &view_tag) = 0;
// alternative prototypes available in libringct
rct::key scalarmultKey(const rct::key &P, const rct::key &a)
diff --git a/src/device/device_default.hpp b/src/device/device_default.hpp
index 7d3543652..58149cdbf 100644
--- a/src/device/device_default.hpp
+++ b/src/device/device_default.hpp
@@ -101,7 +101,7 @@ namespace hw {
bool derive_public_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::public_key &pub, crypto::public_key &derived_pub) override;
bool secret_key_to_public_key(const crypto::secret_key &sec, crypto::public_key &pub) override;
bool generate_key_image(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_image &image) override;
- bool derive_view_tag(const crypto::key_derivation &derivation, const std::size_t output_index, crypto::view_tag &view_tag);
+ bool derive_view_tag(const crypto::key_derivation &derivation, const std::size_t output_index, crypto::view_tag &view_tag) override;
/* ======================================================================= */
diff --git a/src/device/device_ledger.cpp b/src/device/device_ledger.cpp
index aa73e998c..8069c074e 100644
--- a/src/device/device_ledger.cpp
+++ b/src/device/device_ledger.cpp
@@ -266,6 +266,7 @@ namespace hw {
#define INS_DERIVE_PUBLIC_KEY 0x36
#define INS_DERIVE_SECRET_KEY 0x38
#define INS_GEN_KEY_IMAGE 0x3A
+ #define INS_DERIVE_VIEW_TAG 0x3B
#define INS_SECRET_KEY_ADD 0x3C
#define INS_SECRET_KEY_SUB 0x3E
#define INS_GENERATE_KEYPAIR 0x40
@@ -1308,6 +1309,54 @@ namespace hw {
return true;
}
+ bool device_ledger::derive_view_tag(const crypto::key_derivation &derivation, const std::size_t output_index, crypto::view_tag &view_tag){
+ #ifdef DEBUG_HWDEVICE
+ 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;
+ crypto::view_tag view_tag_x;
+ log_hexbuffer("derive_view_tag: [[IN]] derivation ", derivation_x.data, 32);
+ log_message ("derive_view_tag: [[IN]] output_index", std::to_string(output_index_x));
+ this->controle_device->derive_view_tag(derivation_x, output_index_x, view_tag_x);
+ log_hexbuffer("derive_view_tag: [[OUT]] view_tag ", &view_tag_x.data, 1);
+ #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_view_tag : PARSE mode with known viewkey");
+ crypto::derive_view_tag(derivation, output_index, view_tag);
+ } else {
+ AUTO_LOCK_CMD();
+ int offset = set_command_header_noopt(INS_DERIVE_VIEW_TAG);
+ //derivation
+ this->send_secret((unsigned char*)derivation.data, offset);
+ //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;
+
+ this->buffer_send[4] = offset-5;
+ this->length_send = offset;
+ this->exchange();
+
+ //view tag
+ memmove(&view_tag.data, &this->buffer_recv[0], 1);
+ }
+
+ #ifdef DEBUG_HWDEVICE
+ hw::ledger::check1("derive_view_tag", "view_tag", &view_tag_x.data, &view_tag.data);
+ #endif
+
+ return true;
+ }
+
/* ======================================================================= */
/* TRANSACTION */
/* ======================================================================= */
@@ -1548,7 +1597,6 @@ namespace hw {
const size_t output_index_x = output_index;
const bool need_additional_txkeys_x = need_additional_txkeys;
const bool use_view_tags_x = use_view_tags;
- const crypto::view_tag view_tag_x = view_tag;
std::vector<crypto::secret_key> additional_tx_keys_x;
for (const auto &k: additional_tx_keys) {
@@ -1558,6 +1606,7 @@ namespace hw {
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;
+ crypto::view_tag view_tag_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);
@@ -1575,11 +1624,15 @@ namespace hw {
if(need_additional_txkeys_x) {
log_hexbuffer("generate_output_ephemeral_keys: [[IN]] additional_tx_keys[oi]", additional_tx_keys_x[output_index].data, 32);
}
+ log_message ("generate_output_ephemeral_keys: [[IN]] use_view_tags", std::to_string(use_view_tags_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, use_view_tags_x, view_tag_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);
}
+ if(use_view_tags_x) {
+ log_hexbuffer("generate_output_ephemeral_keys: [[OUT]] view_tag", &view_tag_x.data, 1);
+ }
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
@@ -1633,6 +1686,9 @@ namespace hw {
memset(&this->buffer_send[offset], 0, 32);
offset += 32;
}
+ //use_view_tags
+ this->buffer_send[offset] = use_view_tags;
+ offset++;
this->buffer_send[4] = offset-5;
this->length_send = offset;
@@ -1663,6 +1719,14 @@ namespace hw {
recv_len -= 32;
}
+ if (use_view_tags)
+ {
+ ASSERT_X(recv_len>=1, "Not enough data from device");
+ memmove(&view_tag.data, &this->buffer_recv[offset], 1);
+ offset++;
+ recv_len -= 1;
+ }
+
// 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,
@@ -1675,6 +1739,9 @@ namespace hw {
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);
+ if (use_view_tags) {
+ hw::ledger::check1("generate_output_ephemeral_keys", "view_tag", &view_tag_x.data, &view_tag.data);
+ }
#endif
return true;
@@ -1860,7 +1927,7 @@ namespace hw {
// ====== Aout, Bout, AKout, C, v, k ======
kv_offset = data_offset;
- if (type==rct::RCTTypeBulletproof2 || type==rct::RCTTypeCLSAG) {
+ if (type==rct::RCTTypeBulletproof2 || type==rct::RCTTypeCLSAG || type==rct::RCTTypeBulletproofPlus) {
C_offset = kv_offset+ (8)*outputs_size;
} else {
C_offset = kv_offset+ (32+32)*outputs_size;
@@ -1877,7 +1944,7 @@ namespace hw {
offset = set_command_header(INS_VALIDATE, 0x02, i+1);
//options
this->buffer_send[offset] = (i==outputs_size-1)? 0x00:0x80 ;
- this->buffer_send[offset] |= (type==rct::RCTTypeBulletproof2 || type==rct::RCTTypeCLSAG)?0x02:0x00;
+ this->buffer_send[offset] |= (type==rct::RCTTypeBulletproof2 || type==rct::RCTTypeCLSAG || type==rct::RCTTypeBulletproofPlus)?0x02:0x00;
offset += 1;
//is_subaddress
this->buffer_send[offset] = outKeys.is_subaddress;
@@ -1898,7 +1965,7 @@ namespace hw {
memmove(this->buffer_send+offset, data+C_offset,32);
offset += 32;
C_offset += 32;
- if (type==rct::RCTTypeBulletproof2 || type==rct::RCTTypeCLSAG) {
+ if (type==rct::RCTTypeBulletproof2 || type==rct::RCTTypeCLSAG || type==rct::RCTTypeBulletproofPlus) {
//k
memset(this->buffer_send+offset, 0, 32);
offset += 32;
diff --git a/src/device/device_ledger.hpp b/src/device/device_ledger.hpp
index 074bfaa8d..89b3ee955 100644
--- a/src/device/device_ledger.hpp
+++ b/src/device/device_ledger.hpp
@@ -249,6 +249,7 @@ namespace hw {
bool derive_public_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::public_key &pub, crypto::public_key &derived_pub) override;
bool secret_key_to_public_key(const crypto::secret_key &sec, crypto::public_key &pub) override;
bool generate_key_image(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_image &image) override;
+ bool derive_view_tag(const crypto::key_derivation &derivation, const size_t output_index, crypto::view_tag &view_tag) override;
/* ======================================================================= */
/* TRANSACTION */
diff --git a/src/device/log.cpp b/src/device/log.cpp
index 9b882b784..b159632d9 100644
--- a/src/device/log.cpp
+++ b/src/device/log.cpp
@@ -165,6 +165,10 @@ namespace hw {
void check8(const std::string &msg, const std::string &info, const char *h, const char *d, bool crypted) {
check(msg, info, h, d, 8, crypted);
}
+
+ void check1(const std::string &msg, const std::string &info, const char *h, const char *d, bool crypted) {
+ check(msg, info, h, d, 1, crypted);
+ }
#endif
}
diff --git a/src/device/log.hpp b/src/device/log.hpp
index 660adc63e..a0c89ec71 100644
--- a/src/device/log.hpp
+++ b/src/device/log.hpp
@@ -75,6 +75,7 @@ namespace hw {
void check32(const std::string &msg, const std::string &info, const char *h, const char *d, bool crypted=false);
void check8(const std::string &msg, const std::string &info, const char *h, const char *d, bool crypted=false);
+ void check1(const std::string &msg, const std::string &info, const char *h, const char *d, bool crypted=false);
void set_check_verbose(bool verbose);
#endif
diff --git a/src/device_trezor/device_trezor.cpp b/src/device_trezor/device_trezor.cpp
index 6f7ae9a6b..58c36f2c9 100644
--- a/src/device_trezor/device_trezor.cpp
+++ b/src/device_trezor/device_trezor.cpp
@@ -324,8 +324,8 @@ namespace trezor {
std::vector<protocol::ki::MoneroTransferDetails> mtds;
std::vector<protocol::ki::MoneroExportedKeyImage> kis;
- protocol::ki::key_image_data(wallet, transfers, mtds, client_version() <= 1);
- protocol::ki::generate_commitment(mtds, transfers, req, client_version() <= 1);
+ protocol::ki::key_image_data(wallet, transfers, mtds);
+ protocol::ki::generate_commitment(mtds, transfers, req);
EVENT_PROGRESS(0.);
this->set_msg_addr<messages::monero::MoneroKeyImageExportInitRequest>(req.get());
@@ -635,11 +635,7 @@ namespace trezor {
}
// Step: sort
- auto perm_req = signer->step_permutation();
- if (perm_req){
- auto perm_ack = this->client_exchange<messages::monero::MoneroTransactionInputsPermutationAck>(perm_req);
- signer->step_permutation_ack(perm_ack);
- }
+ signer->sort_ki();
EVENT_PROGRESS(3, 1, 1);
// Step: input_vini
@@ -697,13 +693,13 @@ namespace trezor {
unsigned device_trezor::client_version()
{
auto trezor_version = get_version();
- if (trezor_version <= pack_version(2, 0, 10)){
- throw exc::TrezorException("Trezor firmware 2.0.10 and lower are not supported. Please update.");
+ if (trezor_version < pack_version(2, 4, 3)){
+ throw exc::TrezorException("Minimal Trezor firmware version is 2.4.3. Please update.");
}
- unsigned client_version = 1;
- if (trezor_version >= pack_version(2, 3, 1)){
- client_version = 3;
+ unsigned client_version = 3;
+ if (trezor_version >= pack_version(2, 5, 2)){
+ client_version = 4;
}
#ifdef WITH_TREZOR_DEBUGGING
@@ -739,14 +735,6 @@ namespace trezor {
CHECK_AND_ASSERT_THROW_MES(init_msg, "TransactionInitRequest is empty");
CHECK_AND_ASSERT_THROW_MES(init_msg->has_tsx_data(), "TransactionInitRequest has no transaction data");
CHECK_AND_ASSERT_THROW_MES(m_features, "Device state not initialized"); // make sure the caller did not reset features
- const bool nonce_required = init_msg->tsx_data().has_payment_id() && init_msg->tsx_data().payment_id().size() > 0;
-
- if (nonce_required && init_msg->tsx_data().payment_id().size() == 8){
- // Versions 2.0.9 and lower do not support payment ID
- if (get_version() <= pack_version(2, 0, 9)) {
- throw exc::TrezorException("Trezor firmware 2.0.9 and lower does not support transactions with short payment IDs or integrated addresses. Please update.");
- }
- }
}
void device_trezor::transaction_check(const protocol::tx::TData & tdata, const hw::tx_aux_data & aux_data)
diff --git a/src/device_trezor/trezor/protocol.cpp b/src/device_trezor/trezor/protocol.cpp
index a400e82c7..0e59a16ba 100644
--- a/src/device_trezor/trezor/protocol.cpp
+++ b/src/device_trezor/trezor/protocol.cpp
@@ -38,6 +38,7 @@
#include <crypto/hmac-keccak.h>
#include <ringct/rctSigs.h>
#include <ringct/bulletproofs.h>
+#include <ringct/bulletproofs_plus.h>
#include "cryptonote_config.h"
#include <sodium.h>
#include <sodium/crypto_verify_32.h>
@@ -145,8 +146,7 @@ namespace ki {
bool key_image_data(wallet_shim * wallet,
const std::vector<tools::wallet2::transfer_details> & transfers,
- std::vector<MoneroTransferDetails> & res,
- bool need_all_additionals)
+ std::vector<MoneroTransferDetails> & res)
{
for(auto & td : transfers){
::crypto::public_key tx_pub_key = wallet->get_tx_pub_key_from_received_outs(td);
@@ -159,11 +159,7 @@ namespace ki {
cres.set_internal_output_index(td.m_internal_output_index);
cres.set_sub_addr_major(td.m_subaddr_index.major);
cres.set_sub_addr_minor(td.m_subaddr_index.minor);
- if (need_all_additionals) {
- for (auto &aux : additional_tx_pub_keys) {
- cres.add_additional_tx_pub_keys(key_to_string(aux));
- }
- } else if (!additional_tx_pub_keys.empty() && additional_tx_pub_keys.size() > td.m_internal_output_index) {
+ if (!additional_tx_pub_keys.empty() && additional_tx_pub_keys.size() > td.m_internal_output_index) {
cres.add_additional_tx_pub_keys(key_to_string(additional_tx_pub_keys[td.m_internal_output_index]));
}
}
@@ -194,8 +190,7 @@ namespace ki {
void generate_commitment(std::vector<MoneroTransferDetails> & mtds,
const std::vector<tools::wallet2::transfer_details> & transfers,
- std::shared_ptr<messages::monero::MoneroKeyImageExportInitRequest> & req,
- bool need_subaddr_indices)
+ std::shared_ptr<messages::monero::MoneroKeyImageExportInitRequest> & req)
{
req = std::make_shared<messages::monero::MoneroKeyImageExportInitRequest>();
@@ -219,16 +214,6 @@ namespace ki {
auto & st = search.first->second;
st.insert(cur.m_subaddr_index.minor);
}
-
- if (need_subaddr_indices) {
- for (auto &x: sub_indices) {
- auto subs = req->add_subs();
- subs->set_account(x.first);
- for (auto minor : x.second) {
- subs->add_minor_indices(minor);
- }
- }
- }
}
void live_refresh_ack(const ::crypto::secret_key & view_key_priv,
@@ -399,7 +384,7 @@ namespace tx {
m_tx_idx = tx_idx;
m_ct.tx_data = cur_src_tx();
m_multisig = false;
- m_client_version = 1;
+ m_client_version = 3;
}
void Signer::extract_payment_id(){
@@ -474,25 +459,19 @@ namespace tx {
auto & cur = src.outputs[i];
auto out = dst->add_outputs();
- if (i == src.real_output || need_ring_indices || client_version() <= 1) {
+ if (i == src.real_output || need_ring_indices) {
out->set_idx(cur.first);
}
- if (i == src.real_output || need_ring_keys || client_version() <= 1) {
+ if (i == src.real_output || need_ring_keys) {
translate_rct_key(out->mutable_key(), &(cur.second));
}
}
dst->set_real_out_tx_key(key_to_string(src.real_out_tx_key));
dst->set_real_output_in_tx_index(src.real_output_in_tx_index);
-
- if (client_version() <= 1) {
- for (auto &cur : src.real_out_additional_tx_keys) {
- dst->add_real_out_additional_tx_keys(key_to_string(cur));
- }
- } else if (!src.real_out_additional_tx_keys.empty()) {
+ if (!src.real_out_additional_tx_keys.empty()) {
dst->add_real_out_additional_tx_keys(key_to_string(src.real_out_additional_tx_keys.at(src.real_output_in_tx_index)));
}
-
dst->set_amount(src.amount);
dst->set_rct(src.rct);
dst->set_mask(key_to_string(src.mask));
@@ -532,7 +511,7 @@ namespace tx {
m_ct.tx.version = 2;
m_ct.tx.unlock_time = tx.unlock_time;
- m_client_version = (m_aux_data->client_version ? m_aux_data->client_version.get() : 1);
+ m_client_version = (m_aux_data->client_version ? m_aux_data->client_version.get() : 3);
tsx_data.set_version(1);
tsx_data.set_client_version(client_version());
@@ -543,18 +522,13 @@ namespace tx {
tsx_data.set_monero_version(std::string(MONERO_VERSION) + "|" + MONERO_VERSION_TAG);
tsx_data.set_hard_fork(m_aux_data->hard_fork ? m_aux_data->hard_fork.get() : 0);
- if (client_version() <= 1){
- assign_to_repeatable(tsx_data.mutable_minor_indices(), tx.subaddr_indices.begin(), tx.subaddr_indices.end());
- }
-
// Rsig decision
auto rsig_data = tsx_data.mutable_rsig_data();
m_ct.rsig_type = get_rsig_type(tx.rct_config, tx.splitted_dsts.size());
rsig_data->set_rsig_type(m_ct.rsig_type);
- if (tx.rct_config.range_proof_type != rct::RangeProofBorromean){
- m_ct.bp_version = (m_aux_data->bp_version ? m_aux_data->bp_version.get() : 1);
- rsig_data->set_bp_version((uint32_t) m_ct.bp_version);
- }
+ CHECK_AND_ASSERT_THROW_MES(tx.rct_config.range_proof_type != rct::RangeProofBorromean, "Borromean rsig not supported");
+ m_ct.bp_version = (m_aux_data->bp_version ? m_aux_data->bp_version.get() : 1);
+ rsig_data->set_bp_version((uint32_t) m_ct.bp_version);
generate_rsig_batch_sizes(m_ct.grouping_vct, m_ct.rsig_type, tx.splitted_dsts.size());
assign_to_repeatable(rsig_data->mutable_grouping(), m_ct.grouping_vct.begin(), m_ct.grouping_vct.end());
@@ -652,22 +626,6 @@ namespace tx {
});
}
- std::shared_ptr<messages::monero::MoneroTransactionInputsPermutationRequest> Signer::step_permutation(){
- sort_ki();
- if (client_version() >= 2){
- return nullptr;
- }
-
- auto res = std::make_shared<messages::monero::MoneroTransactionInputsPermutationRequest>();
- assign_to_repeatable(res->mutable_perm(), m_ct.source_permutation.begin(), m_ct.source_permutation.end());
-
- return res;
- }
-
- void Signer::step_permutation_ack(std::shared_ptr<const messages::monero::MoneroTransactionInputsPermutationAck> ack){
-
- }
-
std::shared_ptr<messages::monero::MoneroTransactionInputViniRequest> Signer::step_set_vini_input(size_t idx){
CHECK_AND_ASSERT_THROW_MES(idx < m_ct.tx_data.sources.size(), "Invalid transaction index");
CHECK_AND_ASSERT_THROW_MES(idx < m_ct.tx.vin.size(), "Invalid transaction index");
@@ -711,8 +669,10 @@ namespace tx {
}
void Signer::step_set_output_ack(std::shared_ptr<const messages::monero::MoneroTransactionSetOutputAck> ack){
+ CHECK_AND_ASSERT_THROW_MES(is_req_bulletproof(), "Borromean rsig not supported");
cryptonote::tx_out tx_out;
rct::Bulletproof bproof{};
+ rct::BulletproofPlus bproof_plus{};
rct::ctkey out_pk{};
rct::ecdhTuple ecdh{};
@@ -727,7 +687,7 @@ namespace tx {
rsig_buff = rsig_data.rsig();
}
- if (client_version() >= 1 && rsig_data.has_mask()){
+ if (rsig_data.has_mask()){
rct::key cmask{};
string_to_key(cmask, rsig_data.mask());
m_ct.rsig_gamma.emplace_back(cmask);
@@ -751,22 +711,32 @@ namespace tx {
memcpy(ecdh.amount.bytes, ack->ecdh_info().data(), 8);
}
- if (has_rsig && is_req_bulletproof() && !cn_deserialize(rsig_buff, bproof)){
- throw exc::ProtocolException("Cannot deserialize bulletproof rangesig");
- }
-
m_ct.tx.vout.emplace_back(tx_out);
m_ct.tx_out_hmacs.push_back(ack->vouti_hmac());
m_ct.tx_out_pk.emplace_back(out_pk);
m_ct.tx_out_ecdh.emplace_back(ecdh);
- // ClientV0, if no rsig was generated on Trezor, do not continue.
- // ClientV1+ generates BP after all masks in the current batch are generated
- if (!has_rsig || (client_version() >= 1 && is_offloading())){
+ rsig_v bp_obj{};
+ if (has_rsig) {
+ bool deserialize_success;
+ if (is_req_bulletproof_plus()) {
+ deserialize_success = cn_deserialize(rsig_buff, bproof_plus);
+ bp_obj = bproof_plus;
+ } else {
+ deserialize_success = cn_deserialize(rsig_buff, bproof);
+ bp_obj = bproof;
+ }
+ if (!deserialize_success) {
+ throw exc::ProtocolException("Cannot deserialize bulletproof rangesig");
+ }
+ }
+
+ // Generates BP after all masks in the current batch are generated
+ if (!has_rsig || is_offloading()){
return;
}
- process_bproof(bproof);
+ process_bproof(bp_obj);
m_ct.cur_batch_idx += 1;
m_ct.cur_output_in_batch_idx = 0;
}
@@ -791,13 +761,21 @@ namespace tx {
masks.push_back(m_ct.rsig_gamma[bidx]);
}
- auto bp = bulletproof_PROVE(amounts, masks);
- auto serRsig = cn_serialize(bp);
- m_ct.tx_out_rsigs.emplace_back(bp);
+ std::string serRsig;
+ if (is_req_bulletproof_plus()) {
+ auto bp = bulletproof_plus_PROVE(amounts, masks);
+ serRsig = cn_serialize(bp);
+ m_ct.tx_out_rsigs.emplace_back(bp);
+ } else {
+ auto bp = bulletproof_PROVE(amounts, masks);
+ serRsig = cn_serialize(bp);
+ m_ct.tx_out_rsigs.emplace_back(bp);
+ }
+
rsig_data.set_rsig(serRsig);
}
- void Signer::process_bproof(rct::Bulletproof & bproof){
+ void Signer::process_bproof(rsig_v & bproof){
CHECK_AND_ASSERT_THROW_MES(m_ct.cur_batch_idx < m_ct.grouping_vct.size(), "Invalid batch index");
auto batch_size = m_ct.grouping_vct[m_ct.cur_batch_idx];
for (size_t i = 0; i < batch_size; ++i){
@@ -806,12 +784,22 @@ namespace tx {
rct::key commitment = m_ct.tx_out_pk[bidx].mask;
commitment = rct::scalarmultKey(commitment, rct::INV_EIGHT);
- bproof.V.push_back(commitment);
+ if (is_req_bulletproof_plus()) {
+ boost::get<rct::BulletproofPlus>(bproof).V.push_back(commitment);
+ } else {
+ boost::get<rct::Bulletproof>(bproof).V.push_back(commitment);
+ }
}
m_ct.tx_out_rsigs.emplace_back(bproof);
- if (!rct::bulletproof_VERIFY(boost::get<rct::Bulletproof>(m_ct.tx_out_rsigs.back()))) {
- throw exc::ProtocolException("Returned range signature is invalid");
+ if (is_req_bulletproof_plus()) {
+ if (!rct::bulletproof_plus_VERIFY(boost::get<rct::BulletproofPlus>(m_ct.tx_out_rsigs.back()))) {
+ throw exc::ProtocolException("Returned range signature is invalid");
+ }
+ } else {
+ if (!rct::bulletproof_VERIFY(boost::get<rct::Bulletproof>(m_ct.tx_out_rsigs.back()))) {
+ throw exc::ProtocolException("Returned range signature is invalid");
+ }
}
}
@@ -840,6 +828,7 @@ namespace tx {
}
void Signer::step_all_outs_set_ack(std::shared_ptr<const messages::monero::MoneroTransactionAllOutSetAck> ack, hw::device &hwdev){
+ CHECK_AND_ASSERT_THROW_MES(is_req_bulletproof(), "Borromean rsig not supported");
m_ct.rv = std::make_shared<rct::rctSig>();
m_ct.rv->txnFee = ack->rv().txn_fee();
m_ct.rv->type = static_cast<uint8_t>(ack->rv().rv_type());
@@ -864,24 +853,15 @@ namespace tx {
// RctSig
auto num_sources = m_ct.tx_data.sources.size();
- if (is_simple() || is_req_bulletproof()){
- auto dst = &m_ct.rv->pseudoOuts;
- if (is_bulletproof()){
- dst = &m_ct.rv->p.pseudoOuts;
- }
-
- dst->clear();
- for (const auto &pseudo_out : m_ct.pseudo_outs) {
- dst->emplace_back();
- string_to_key(dst->back(), pseudo_out);
- }
-
- m_ct.rv->mixRing.resize(num_sources);
- } else {
- m_ct.rv->mixRing.resize(m_ct.tsx_data.mixin());
- m_ct.rv->mixRing[0].resize(num_sources);
+ auto dst = &m_ct.rv->p.pseudoOuts;
+ dst->clear();
+ for (const auto &pseudo_out : m_ct.pseudo_outs) {
+ dst->emplace_back();
+ string_to_key(dst->back(), pseudo_out);
}
+ m_ct.rv->mixRing.resize(num_sources);
+
CHECK_AND_ASSERT_THROW_MES(m_ct.tx_out_pk.size() == m_ct.tx_out_ecdh.size(), "Invalid vector sizes");
for(size_t i = 0; i < m_ct.tx_out_ecdh.size(); ++i){
m_ct.rv->outPk.push_back(m_ct.tx_out_pk[i]);
@@ -889,10 +869,10 @@ namespace tx {
}
for(size_t i = 0; i < m_ct.tx_out_rsigs.size(); ++i){
- if (is_bulletproof()){
- m_ct.rv->p.bulletproofs.push_back(boost::get<rct::Bulletproof>(m_ct.tx_out_rsigs[i]));
+ if (is_req_bulletproof_plus()) {
+ m_ct.rv->p.bulletproofs_plus.push_back(boost::get<rct::BulletproofPlus>(m_ct.tx_out_rsigs[i]));
} else {
- m_ct.rv->p.rangeSigs.push_back(boost::get<rct::rangeSig>(m_ct.tx_out_rsigs[i]));
+ m_ct.rv->p.bulletproofs.push_back(boost::get<rct::Bulletproof>(m_ct.tx_out_rsigs[i]));
}
}
@@ -936,8 +916,8 @@ namespace tx {
void Signer::step_sign_input_ack(std::shared_ptr<const messages::monero::MoneroTransactionSignInputAck> ack){
m_ct.signatures.push_back(ack->signature());
- // Sync updated pseudo_outputs, client_version>=1, HF10+
- if (client_version() >= 1 && ack->has_pseudo_out()){
+ // Sync updated pseudo_outputs
+ if (ack->has_pseudo_out()){
CHECK_AND_ASSERT_THROW_MES(m_ct.cur_input_idx < m_ct.pseudo_outs.size(), "Invalid pseudo-out index");
m_ct.pseudo_outs[m_ct.cur_input_idx] = ack->pseudo_out();
if (is_bulletproof()){
@@ -955,6 +935,8 @@ namespace tx {
}
void Signer::step_final_ack(std::shared_ptr<const messages::monero::MoneroTransactionFinalAck> ack){
+ CHECK_AND_ASSERT_THROW_MES(is_clsag(), "Only CLSAGs signatures are supported");
+
if (m_multisig){
auto & cout_key = ack->cout_key();
for(auto & cur : m_ct.couts){
@@ -975,47 +957,34 @@ namespace tx {
m_ct.enc_keys = ack->tx_enc_keys();
// Opening the sealed signatures
- if (client_version() >= 3){
- if(!ack->has_opening_key()){
- throw exc::ProtocolException("Client version 3+ requires sealed signatures");
- }
+ if(!ack->has_opening_key()){
+ throw exc::ProtocolException("Client version 3+ requires sealed signatures");
+ }
- for(size_t i = 0; i < m_ct.signatures.size(); ++i){
- CHECK_AND_ASSERT_THROW_MES(m_ct.signatures[i].size() > crypto::chacha::TAG_SIZE, "Invalid signature size");
- std::string nonce = compute_sealing_key(ack->opening_key(), i, true);
- std::string key = compute_sealing_key(ack->opening_key(), i, false);
- size_t plen = m_ct.signatures[i].size() - crypto::chacha::TAG_SIZE;
- std::unique_ptr<uint8_t[]> plaintext(new uint8_t[plen]);
- uint8_t * buff = plaintext.get();
-
- protocol::crypto::chacha::decrypt(
- m_ct.signatures[i].data(),
- m_ct.signatures[i].size(),
- reinterpret_cast<const uint8_t *>(key.data()),
- reinterpret_cast<const uint8_t *>(nonce.data()),
- reinterpret_cast<char *>(buff), &plen);
- m_ct.signatures[i].assign(reinterpret_cast<const char *>(buff), plen);
- }
+ for(size_t i = 0; i < m_ct.signatures.size(); ++i){
+ CHECK_AND_ASSERT_THROW_MES(m_ct.signatures[i].size() > crypto::chacha::TAG_SIZE, "Invalid signature size");
+ std::string nonce = compute_sealing_key(ack->opening_key(), i, true);
+ std::string key = compute_sealing_key(ack->opening_key(), i, false);
+ size_t plen = m_ct.signatures[i].size() - crypto::chacha::TAG_SIZE;
+ std::unique_ptr<uint8_t[]> plaintext(new uint8_t[plen]);
+ uint8_t * buff = plaintext.get();
+
+ protocol::crypto::chacha::decrypt(
+ m_ct.signatures[i].data(),
+ m_ct.signatures[i].size(),
+ reinterpret_cast<const uint8_t *>(key.data()),
+ reinterpret_cast<const uint8_t *>(nonce.data()),
+ reinterpret_cast<char *>(buff), &plen);
+ m_ct.signatures[i].assign(reinterpret_cast<const char *>(buff), plen);
}
- if (m_ct.rv->type == rct::RCTTypeCLSAG){
- m_ct.rv->p.CLSAGs.reserve(m_ct.signatures.size());
- for (size_t i = 0; i < m_ct.signatures.size(); ++i) {
- rct::clsag clsag;
- if (!cn_deserialize(m_ct.signatures[i], clsag)) {
- throw exc::ProtocolException("Cannot deserialize clsag[i]");
- }
- m_ct.rv->p.CLSAGs.push_back(clsag);
- }
- } else {
- m_ct.rv->p.MGs.reserve(m_ct.signatures.size());
- for (size_t i = 0; i < m_ct.signatures.size(); ++i) {
- rct::mgSig mg;
- if (!cn_deserialize(m_ct.signatures[i], mg)) {
- throw exc::ProtocolException("Cannot deserialize mg[i]");
- }
- m_ct.rv->p.MGs.push_back(mg);
+ m_ct.rv->p.CLSAGs.reserve(m_ct.signatures.size());
+ for (size_t i = 0; i < m_ct.signatures.size(); ++i) {
+ rct::clsag clsag;
+ if (!cn_deserialize(m_ct.signatures[i], clsag)) {
+ throw exc::ProtocolException("Cannot deserialize clsag[i]");
}
+ m_ct.rv->p.CLSAGs.push_back(clsag);
}
m_ct.tx.rct_signatures = *(m_ct.rv);
diff --git a/src/device_trezor/trezor/protocol.hpp b/src/device_trezor/trezor/protocol.hpp
index 858db1520..fa8355200 100644
--- a/src/device_trezor/trezor/protocol.hpp
+++ b/src/device_trezor/trezor/protocol.hpp
@@ -116,8 +116,7 @@ namespace ki {
*/
bool key_image_data(wallet_shim * wallet,
const std::vector<tools::wallet2::transfer_details> & transfers,
- std::vector<MoneroTransferDetails> & res,
- bool need_all_additionals=false);
+ std::vector<MoneroTransferDetails> & res);
/**
* Computes a hash over MoneroTransferDetails. Commitment used in the KI sync.
@@ -129,8 +128,7 @@ namespace ki {
*/
void generate_commitment(std::vector<MoneroTransferDetails> & mtds,
const std::vector<tools::wallet2::transfer_details> & transfers,
- std::shared_ptr<messages::monero::MoneroKeyImageExportInitRequest> & req,
- bool need_subaddr_indices=false);
+ std::shared_ptr<messages::monero::MoneroKeyImageExportInitRequest> & req);
/**
* Processes Live refresh step response, parses KI, checks the signature
@@ -166,7 +164,7 @@ namespace tx {
::crypto::secret_key compute_enc_key(const ::crypto::secret_key & private_view_key, const std::string & aux, const std::string & salt);
std::string compute_sealing_key(const std::string & master_key, size_t idx, bool is_iv=false);
- typedef boost::variant<rct::rangeSig, rct::Bulletproof> rsig_v;
+ typedef boost::variant<rct::Bulletproof, rct::BulletproofPlus> rsig_v;
/**
* Transaction signer state holder.
@@ -247,7 +245,7 @@ namespace tx {
void compute_integrated_indices(TsxData * tsx_data);
bool should_compute_bp_now() const;
void compute_bproof(messages::monero::MoneroTransactionRsigData & rsig_data);
- void process_bproof(rct::Bulletproof & bproof);
+ void process_bproof(rsig_v & bproof);
void set_tx_input(MoneroTransactionSourceEntry * dst, size_t idx, bool need_ring_keys=false, bool need_ring_indices=false);
public:
@@ -260,8 +258,6 @@ namespace tx {
void step_set_input_ack(std::shared_ptr<const messages::monero::MoneroTransactionSetInputAck> ack);
void sort_ki();
- std::shared_ptr<messages::monero::MoneroTransactionInputsPermutationRequest> step_permutation();
- void step_permutation_ack(std::shared_ptr<const messages::monero::MoneroTransactionInputsPermutationAck> ack);
std::shared_ptr<messages::monero::MoneroTransactionInputViniRequest> step_set_vini_input(size_t idx);
void step_set_vini_input_ack(std::shared_ptr<const messages::monero::MoneroTransactionInputViniAck> ack);
@@ -290,11 +286,15 @@ namespace tx {
return m_client_version;
}
- bool is_simple() const {
+ uint8_t get_rv_type() const {
if (!m_ct.rv){
throw std::invalid_argument("RV not initialized");
}
- auto tp = m_ct.rv->type;
+ return m_ct.rv->type;
+ }
+
+ bool is_simple() const {
+ auto tp = get_rv_type();
return tp == rct::RCTTypeSimple;
}
@@ -302,12 +302,27 @@ namespace tx {
return m_ct.tx_data.rct_config.range_proof_type != rct::RangeProofBorromean;
}
+ bool is_req_clsag() const {
+ return is_req_bulletproof() && m_ct.tx_data.rct_config.bp_version >= 3;
+ }
+
+ bool is_req_bulletproof_plus() const {
+ return is_req_bulletproof() && m_ct.tx_data.rct_config.bp_version == 4; // rct::genRctSimple
+ }
+
bool is_bulletproof() const {
- if (!m_ct.rv){
- throw std::invalid_argument("RV not initialized");
- }
- auto tp = m_ct.rv->type;
- return tp == rct::RCTTypeBulletproof || tp == rct::RCTTypeBulletproof2 || tp == rct::RCTTypeCLSAG;
+ auto tp = get_rv_type();
+ return rct::is_rct_bulletproof(tp) || rct::is_rct_bulletproof_plus(tp);
+ }
+
+ bool is_bulletproof_plus() const {
+ auto tp = get_rv_type();
+ return rct::is_rct_bulletproof_plus(tp);
+ }
+
+ bool is_clsag() const {
+ auto tp = get_rv_type();
+ return rct::is_rct_clsag(tp);
}
bool is_offloading() const {