Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 114297d784 | |||
| 6368aee05f | |||
| 8599cdf95b | |||
| d39f2f180e | |||
| c763febe98 | |||
| cef01372b1 | |||
| e15dbb5db2 | |||
| 82d706aacb | |||
| f3522764a1 | |||
| 0448a6bf9a | |||
| 2ce22c2508 | |||
| 1334bac45a | |||
| e909e3eef1 | |||
| 8c999520d1 | |||
| 945bdc72e7 | |||
| c6d843b6f5 | |||
| b285ec550d |
@@ -109,7 +109,7 @@ jobs:
|
||||
with:
|
||||
name: ${{ matrix.toolchain.name }}
|
||||
path: |
|
||||
/home/runner/work/${{ github.event.repository.name }}/${{ github.event.repository.name }}/build/${{ matrix.toolchain.host }}/release/bin/salvium-wallet-cli*
|
||||
/home/runner/work/${{ github.event.repository.name }}/${{ github.event.repository.name }}/build/${{ matrix.toolchain.host }}/release/bin/salvium-wallet-*
|
||||
/home/runner/work/${{ github.event.repository.name }}/${{ github.event.repository.name }}/build/${{ matrix.toolchain.host }}/release/bin/salviumd*
|
||||
- name: zip daemon & cli
|
||||
run: |
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Salvium Zero v0.6.2
|
||||
# Salvium Zero v0.7.2
|
||||
|
||||
Copyright (c) 2023-2024, Salvium
|
||||
Portions Copyright (c) 2014-2023, The Monero Project
|
||||
@@ -172,7 +172,7 @@ invokes cmake commands as needed.
|
||||
|
||||
```bash
|
||||
cd salvium
|
||||
git checkout v0.6.2
|
||||
git checkout v0.7.0
|
||||
make
|
||||
```
|
||||
|
||||
@@ -251,7 +251,7 @@ Tested on a Raspberry Pi Zero with a clean install of minimal Raspbian Stretch (
|
||||
```bash
|
||||
git clone https://github.com/salvium/salvium
|
||||
cd salvium
|
||||
git checkout v0.6.2
|
||||
git checkout v0.7.0
|
||||
```
|
||||
|
||||
* Build:
|
||||
@@ -370,10 +370,10 @@ application.
|
||||
cd salvium
|
||||
```
|
||||
|
||||
* If you would like a specific [version/tag](https://github.com/salvium/salvium/tags), do a git checkout for that version. eg. 'v0.6.2'. If you don't care about the version and just want binaries from master, skip this step:
|
||||
* If you would like a specific [version/tag](https://github.com/salvium/salvium/tags), do a git checkout for that version. eg. 'v0.7.0'. If you don't care about the version and just want binaries from master, skip this step:
|
||||
|
||||
```bash
|
||||
git checkout v0.6.2
|
||||
git checkout v0.7.0
|
||||
```
|
||||
|
||||
* If you are on a 64-bit system, run:
|
||||
|
||||
@@ -267,7 +267,7 @@ uint64_t BlockchainDB::add_block( const std::pair<block, blobdata>& blck
|
||||
, const difficulty_type& cumulative_difficulty
|
||||
, const uint64_t& coins_generated
|
||||
, const std::vector<std::pair<transaction, blobdata>>& txs
|
||||
, const cryptonote::network_type& nettype
|
||||
, const cryptonote::network_type nettype
|
||||
, cryptonote::yield_block_info& ybi
|
||||
)
|
||||
{
|
||||
|
||||
@@ -430,7 +430,7 @@ private:
|
||||
const crypto::hash& blk_hash,
|
||||
uint64_t slippage_total,
|
||||
uint64_t yield_total,
|
||||
const cryptonote::network_type& nettype,
|
||||
const cryptonote::network_type nettype,
|
||||
cryptonote::yield_block_info& ybi
|
||||
) = 0;
|
||||
|
||||
@@ -884,7 +884,7 @@ public:
|
||||
, const difficulty_type& cumulative_difficulty
|
||||
, const uint64_t& coins_generated
|
||||
, const std::vector<std::pair<transaction, blobdata>>& txs
|
||||
, const cryptonote::network_type& nettype
|
||||
, const cryptonote::network_type nettype
|
||||
, cryptonote::yield_block_info& ybi
|
||||
);
|
||||
|
||||
|
||||
@@ -866,7 +866,7 @@ int BlockchainLMDB::get_yield_tx_info(const uint64_t height, std::vector<yield_t
|
||||
return 0;
|
||||
}
|
||||
|
||||
void BlockchainLMDB::add_block(const block& blk, size_t block_weight, uint64_t long_term_block_weight, const difficulty_type& cumulative_difficulty, const uint64_t& coins_generated, uint64_t num_rct_outs, oracle::asset_type_counts& cum_rct_by_asset_type, const crypto::hash& blk_hash, uint64_t slippage_total, uint64_t yield_total, const cryptonote::network_type& nettype, cryptonote::yield_block_info& ybi)
|
||||
void BlockchainLMDB::add_block(const block& blk, size_t block_weight, uint64_t long_term_block_weight, const difficulty_type& cumulative_difficulty, const uint64_t& coins_generated, uint64_t num_rct_outs, oracle::asset_type_counts& cum_rct_by_asset_type, const crypto::hash& blk_hash, uint64_t slippage_total, uint64_t yield_total, const cryptonote::network_type nettype, cryptonote::yield_block_info& ybi)
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
check_open();
|
||||
@@ -4724,7 +4724,7 @@ void BlockchainLMDB::block_rtxn_abort() const
|
||||
}
|
||||
|
||||
uint64_t BlockchainLMDB::add_block(const std::pair<block, blobdata>& blk, size_t block_weight, uint64_t long_term_block_weight, const difficulty_type& cumulative_difficulty, const uint64_t& coins_generated,
|
||||
const std::vector<std::pair<transaction, blobdata>>& txs, const cryptonote::network_type& nettype, cryptonote::yield_block_info& ybi)
|
||||
const std::vector<std::pair<transaction, blobdata>>& txs, const cryptonote::network_type nettype, cryptonote::yield_block_info& ybi)
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
check_open();
|
||||
|
||||
@@ -341,7 +341,7 @@ public:
|
||||
, const difficulty_type& cumulative_difficulty
|
||||
, const uint64_t& coins_generated
|
||||
, const std::vector<std::pair<transaction, blobdata>>& txs
|
||||
, const cryptonote::network_type& nettype
|
||||
, const cryptonote::network_type nettype
|
||||
, cryptonote::yield_block_info& ybi
|
||||
);
|
||||
|
||||
@@ -400,7 +400,7 @@ private:
|
||||
const crypto::hash& blk_hash,
|
||||
uint64_t slippage_total,
|
||||
uint64_t yield_total,
|
||||
const cryptonote::network_type& nettype,
|
||||
const cryptonote::network_type nettype,
|
||||
cryptonote::yield_block_info& ybi
|
||||
);
|
||||
|
||||
|
||||
+27
-14
@@ -76,7 +76,7 @@ public:
|
||||
virtual uint64_t get_block_height(const crypto::hash& h) const override { return 0; }
|
||||
virtual cryptonote::block_header get_block_header(const crypto::hash& h) const override { return cryptonote::block_header(); }
|
||||
virtual uint64_t get_block_timestamp(const uint64_t& height) const override { return 0; }
|
||||
virtual std::vector<uint64_t> get_block_cumulative_rct_outputs(const std::vector<uint64_t> &heights) const override { return {}; }
|
||||
virtual std::pair<std::vector<uint64_t>, uint64_t> get_block_cumulative_rct_outputs(const std::vector<uint64_t> &heights, const std::string asset_type) const override { return {}; }
|
||||
virtual uint64_t get_top_block_timestamp() const override { return 0; }
|
||||
virtual size_t get_block_weight(const uint64_t& height) const override { return 128; }
|
||||
virtual std::vector<uint64_t> get_block_weights(uint64_t start_height, size_t count) const override { return {}; }
|
||||
@@ -92,6 +92,7 @@ public:
|
||||
virtual crypto::hash top_block_hash(uint64_t *block_height = NULL) const override { if (block_height) *block_height = 0; return crypto::hash(); }
|
||||
virtual cryptonote::block get_top_block() const override { return cryptonote::block(); }
|
||||
virtual uint64_t height() const override { return 1; }
|
||||
virtual std::map<std::string, uint64_t> get_circulating_supply() const override { return std::map<std::string, uint64_t>{}; }
|
||||
virtual bool tx_exists(const crypto::hash& h) const override { return false; }
|
||||
virtual bool tx_exists(const crypto::hash& h, uint64_t& tx_index) const override { return false; }
|
||||
virtual uint64_t get_tx_unlock_time(const crypto::hash& h) const override { return 0; }
|
||||
@@ -101,20 +102,23 @@ public:
|
||||
virtual std::vector<cryptonote::transaction> get_tx_list(const std::vector<crypto::hash>& hlist) const override { return std::vector<cryptonote::transaction>(); }
|
||||
virtual uint64_t get_tx_block_height(const crypto::hash& h) const override { return 0; }
|
||||
virtual uint64_t get_num_outputs(const uint64_t& amount) const override { return 1; }
|
||||
virtual uint64_t get_num_outputs_of_asset_type(const std::string asset_type) const override { return 1; }
|
||||
virtual uint64_t get_indexing_base() const override { return 0; }
|
||||
virtual cryptonote::output_data_t get_output_key(const uint64_t& amount, const uint64_t& index, bool include_commitmemt) const override { return cryptonote::output_data_t(); }
|
||||
virtual cryptonote::tx_out_index get_output_tx_and_index_from_global(const uint64_t& index) const override { return cryptonote::tx_out_index(); }
|
||||
virtual cryptonote::tx_out_index get_output_tx_and_index(const uint64_t& amount, const uint64_t& index) const override { return cryptonote::tx_out_index(); }
|
||||
virtual void get_output_tx_and_index(const uint64_t& amount, const std::vector<uint64_t> &offsets, std::vector<cryptonote::tx_out_index> &indices) const override {}
|
||||
virtual void get_output_key(const epee::span<const uint64_t> &amounts, const std::vector<uint64_t> &offsets, std::vector<cryptonote::output_data_t> &outputs, bool allow_partial = false) const override {}
|
||||
virtual void get_output_id_from_asset_type_output_index(const std::string asset_type, const std::vector<uint64_t> &asset_type_output_indices, std::vector<uint64_t> &output_indices) const override {}
|
||||
virtual uint64_t get_output_id_from_asset_type_output_index(const std::string asset_type, const uint64_t &asset_type_output_index) const override { return 1; }
|
||||
virtual bool can_thread_bulk_indices() const override { return false; }
|
||||
virtual std::vector<std::vector<uint64_t>> get_tx_amount_output_indices(const uint64_t tx_index, size_t n_txes) const override { return std::vector<std::vector<uint64_t>>(); }
|
||||
virtual std::vector<std::vector<std::pair<uint64_t, uint64_t>>> get_tx_amount_output_indices(const uint64_t tx_index, size_t n_txes) const override { return std::vector<std::vector<std::pair<uint64_t, uint64_t>>>(); }
|
||||
virtual bool has_key_image(const crypto::key_image& img) const override { return false; }
|
||||
virtual void remove_block() override { }
|
||||
virtual uint64_t add_transaction_data(const crypto::hash& blk_hash, const std::pair<cryptonote::transaction, cryptonote::blobdata_ref>& tx, const crypto::hash& tx_hash, const crypto::hash& tx_prunable_hash) override {return 0;}
|
||||
virtual void remove_transaction_data(const crypto::hash& tx_hash, const cryptonote::transaction& tx) override {}
|
||||
virtual uint64_t add_output(const crypto::hash& tx_hash, const cryptonote::tx_out& tx_output, const uint64_t& local_index, const uint64_t unlock_time, const rct::key *commitment) override {return 0;}
|
||||
virtual void add_tx_amount_output_indices(const uint64_t tx_index, const std::vector<uint64_t>& amount_output_indices) override {}
|
||||
virtual uint64_t add_transaction_data(const crypto::hash& blk_hash, const std::pair<cryptonote::transaction, cryptonote::blobdata_ref>& tx, const crypto::hash& tx_hash, const crypto::hash& tx_prunable_hash, const bool miner_tx) override {return 0;}
|
||||
virtual void remove_transaction_data(const crypto::hash& tx_hash, const cryptonote::transaction& tx, const bool miner_tx) override {}
|
||||
virtual std::pair<uint64_t, uint64_t> add_output(const crypto::hash& tx_hash, const cryptonote::tx_out& tx_output, const uint64_t& local_index, const uint64_t unlock_time, const rct::key *commitment) override {return std::make_pair(0,0);}
|
||||
virtual void add_tx_amount_output_indices(const uint64_t tx_index, const std::vector<std::pair<uint64_t, uint64_t>>& amount_output_indices) override {}
|
||||
virtual void add_spent_key(const crypto::key_image& k_image) override {}
|
||||
virtual void remove_spent_key(const crypto::key_image& k_image) override {}
|
||||
|
||||
@@ -135,17 +139,26 @@ public:
|
||||
virtual bool get_txpool_tx_meta(const crypto::hash& txid, cryptonote::txpool_tx_meta_t &meta) const override { return false; }
|
||||
virtual bool get_txpool_tx_blob(const crypto::hash& txid, cryptonote::blobdata &bd, relay_category tx_category) const override { return false; }
|
||||
virtual uint64_t get_database_size() const override { return 0; }
|
||||
|
||||
virtual int get_yield_block_info(const uint64_t height, yield_block_info& ybi) const override { return 0; }
|
||||
virtual int get_yield_tx_info(const uint64_t height, std::vector<yield_tx_info>& yti_container) const override { return 0; }
|
||||
|
||||
virtual cryptonote::blobdata get_txpool_tx_blob(const crypto::hash& txid, relay_category tx_category) const override { return ""; }
|
||||
virtual bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const cryptonote::txpool_tx_meta_t&, const cryptonote::blobdata_ref*)>, bool include_blob = false, relay_category category = relay_category::broadcasted) const override { return false; }
|
||||
|
||||
virtual void add_block( const cryptonote::block& blk
|
||||
, size_t block_weight
|
||||
, uint64_t long_term_block_weight
|
||||
, const cryptonote::difficulty_type& cumulative_difficulty
|
||||
, const uint64_t& coins_generated
|
||||
, uint64_t num_rct_outs
|
||||
, const crypto::hash& blk_hash
|
||||
) override { }
|
||||
virtual void add_block( const block& blk,
|
||||
size_t block_weight,
|
||||
uint64_t long_term_block_weight,
|
||||
const difficulty_type& cumulative_difficulty,
|
||||
const uint64_t& coins_generated,
|
||||
uint64_t num_rct_outs,
|
||||
oracle::asset_type_counts& cum_rct_by_asset_type,
|
||||
const crypto::hash& blk_hash,
|
||||
uint64_t slippage_total,
|
||||
uint64_t yield_total,
|
||||
const cryptonote::network_type nettype,
|
||||
cryptonote::yield_block_info& ybi
|
||||
) override { }
|
||||
virtual cryptonote::block get_block_from_height(const uint64_t& height) const override { return cryptonote::block(); }
|
||||
virtual void set_hard_fork_version(uint64_t height, uint8_t version) override {}
|
||||
virtual uint8_t get_hard_fork_version(uint64_t height) const override { return 0; }
|
||||
|
||||
Binary file not shown.
@@ -204,6 +204,7 @@ namespace cryptonote
|
||||
ADD_CHECKPOINT2(180, "e20bc8ac6aabb6b0792f23a29ce42a577c6a57d177a8ac1a51b68fb6de508045", "0x262b40");
|
||||
ADD_CHECKPOINT2(190, "f69fdad7a15471b63a82668b618ee5b2a384291269d944b11974a723c1604124", "0x2856a3");
|
||||
ADD_CHECKPOINT2(200, "eba53fa7006dfcdc837a56c0bc8f0e1883cf34861c26934d680252a6878a3f5d", "0x2aa022");
|
||||
ADD_CHECKPOINT2(90000, "e125b5c1b26521f98e29df6ec88f041c176a2c0a3fcacd5bd0ad2278e9b02fd2", "0xc99801f937888"); // 3546475285149832
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
+20
-4
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2014-2022, The Monero Project
|
||||
// Copyright (c) 2014-2024, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
@@ -171,7 +171,9 @@ namespace crypto {
|
||||
/* Generate a value filled with random bytes.
|
||||
*/
|
||||
template<typename T>
|
||||
typename std::enable_if<std::is_pod<T>::value, T>::type rand() {
|
||||
T rand() {
|
||||
static_assert(std::is_standard_layout_v<T>, "cannot write random bytes into non-standard layout type");
|
||||
static_assert(std::is_trivially_copyable_v<T>, "cannot write random bytes into non-trivially copyable type");
|
||||
typename std::remove_cv<T>::type res;
|
||||
generate_random_bytes_thread_safe(sizeof(T), (uint8_t*)&res);
|
||||
return res;
|
||||
@@ -314,8 +316,14 @@ namespace crypto {
|
||||
inline std::ostream &operator <<(std::ostream &o, const crypto::public_key &v) {
|
||||
epee::to_hex::formatted(o, epee::as_byte_span(v)); return o;
|
||||
}
|
||||
inline std::ostream &operator <<(std::ostream &o, const crypto::secret_key &v) {
|
||||
epee::to_hex::formatted(o, epee::as_byte_span(v)); return o;
|
||||
/* Do NOT overload the << operator for crypto::secret_key here. Use secret_key_explicit_print_ref
|
||||
* instead to prevent accidental implicit dumping of secret key material to the logs (which has
|
||||
* happened before). For the same reason, do not overload it for crypto::ec_scalar either since
|
||||
* crypto::secret_key is a subclass. I'm not sorry that it's obtuse; that's the point, bozo.
|
||||
*/
|
||||
struct secret_key_explicit_print_ref { const crypto::secret_key &sk; };
|
||||
inline std::ostream &operator <<(std::ostream &o, const secret_key_explicit_print_ref v) {
|
||||
epee::to_hex::formatted(o, epee::as_byte_span(unwrap(unwrap(v.sk)))); return o;
|
||||
}
|
||||
inline std::ostream &operator <<(std::ostream &o, const crypto::key_derivation &v) {
|
||||
epee::to_hex::formatted(o, epee::as_byte_span(v)); return o;
|
||||
@@ -335,8 +343,16 @@ namespace crypto {
|
||||
|
||||
inline bool operator<(const public_key &p1, const public_key &p2) { return memcmp(&p1, &p2, sizeof(public_key)) < 0; }
|
||||
inline bool operator>(const public_key &p1, const public_key &p2) { return p2 < p1; }
|
||||
inline bool operator<(const key_image &p1, const key_image &p2) { return memcmp(&p1, &p2, sizeof(key_image)) < 0; }
|
||||
inline bool operator>(const key_image &p1, const key_image &p2) { return p2 < p1; }
|
||||
}
|
||||
|
||||
// type conversions for easier calls to sc_add(), sc_sub(), hash functions
|
||||
inline unsigned char* to_bytes(crypto::ec_scalar &scalar) { return &reinterpret_cast<unsigned char&>(scalar); }
|
||||
inline const unsigned char* to_bytes(const crypto::ec_scalar &scalar) { return &reinterpret_cast<const unsigned char&>(scalar); }
|
||||
inline unsigned char* to_bytes(crypto::ec_point &point) { return &reinterpret_cast<unsigned char&>(point); }
|
||||
inline const unsigned char* to_bytes(const crypto::ec_point &point) { return &reinterpret_cast<const unsigned char&>(point); }
|
||||
|
||||
CRYPTO_MAKE_HASHABLE(public_key)
|
||||
CRYPTO_MAKE_HASHABLE_CONSTANT_TIME(secret_key)
|
||||
CRYPTO_MAKE_HASHABLE_CONSTANT_TIME(public_key_memsafe)
|
||||
|
||||
@@ -350,6 +350,14 @@ namespace boost
|
||||
a & x.D;
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
inline void serialize(Archive &a, rct::zk_proof &x, const boost::serialization::version_type ver)
|
||||
{
|
||||
a & x.R;
|
||||
a & x.z1;
|
||||
a & x.z2;
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
inline void serialize(Archive &a, rct::ecdhTuple &x, const boost::serialization::version_type ver)
|
||||
{
|
||||
@@ -403,7 +411,7 @@ namespace boost
|
||||
a & x.type;
|
||||
if (x.type == rct::RCTTypeNull)
|
||||
return;
|
||||
if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple && x.type != rct::RCTTypeBulletproof && x.type != rct::RCTTypeBulletproof2 && x.type != rct::RCTTypeCLSAG && x.type != rct::RCTTypeBulletproofPlus)
|
||||
if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple && x.type != rct::RCTTypeBulletproof && x.type != rct::RCTTypeBulletproof2 && x.type != rct::RCTTypeCLSAG && x.type != rct::RCTTypeBulletproofPlus && x.type != rct::RCTTypeFullProofs)
|
||||
throw boost::archive::archive_exception(boost::archive::archive_exception::other_exception, "Unsupported rct type");
|
||||
// a & x.message; message is not serialized, as it can be reconstructed from the tx data
|
||||
// a & x.mixRing; mixRing is not serialized, as it can be reconstructed from the offsets
|
||||
@@ -413,6 +421,10 @@ namespace boost
|
||||
serializeOutPk(a, x.outPk, ver);
|
||||
a & x.txnFee;
|
||||
a & x.p_r;
|
||||
if (x.type == rct::RCTTypeFullProofs) {
|
||||
a & x.pr_proof;
|
||||
a & x.sa_proof;
|
||||
}
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
@@ -438,7 +450,7 @@ namespace boost
|
||||
a & x.type;
|
||||
if (x.type == rct::RCTTypeNull)
|
||||
return;
|
||||
if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple && x.type != rct::RCTTypeBulletproof && x.type != rct::RCTTypeBulletproof2 && x.type != rct::RCTTypeCLSAG && x.type != rct::RCTTypeBulletproofPlus)
|
||||
if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple && x.type != rct::RCTTypeBulletproof && x.type != rct::RCTTypeBulletproof2 && x.type != rct::RCTTypeCLSAG && x.type != rct::RCTTypeBulletproofPlus && x.type != rct::RCTTypeFullProofs)
|
||||
throw boost::archive::archive_exception(boost::archive::archive_exception::other_exception, "Unsupported rct type");
|
||||
// a & x.message; message is not serialized, as it can be reconstructed from the tx data
|
||||
// a & x.mixRing; mixRing is not serialized, as it can be reconstructed from the offsets
|
||||
@@ -448,6 +460,10 @@ namespace boost
|
||||
serializeOutPk(a, x.outPk, ver);
|
||||
a & x.txnFee;
|
||||
a & x.p_r;
|
||||
if (x.type == rct::RCTTypeFullProofs) {
|
||||
a & x.pr_proof;
|
||||
a & x.sa_proof;
|
||||
}
|
||||
//--------------
|
||||
a & x.p.rangeSigs;
|
||||
if (x.p.rangeSigs.empty())
|
||||
@@ -459,7 +475,7 @@ namespace boost
|
||||
a & x.p.MGs;
|
||||
if (ver >= 1u)
|
||||
a & x.p.CLSAGs;
|
||||
if (x.type == rct::RCTTypeBulletproof || x.type == rct::RCTTypeBulletproof2 || x.type == rct::RCTTypeCLSAG || x.type == rct::RCTTypeBulletproofPlus)
|
||||
if (x.type == rct::RCTTypeBulletproof || x.type == rct::RCTTypeBulletproof2 || x.type == rct::RCTTypeCLSAG || x.type == rct::RCTTypeBulletproofPlus || x.type == rct::RCTTypeFullProofs)
|
||||
a & x.p.pseudoOuts;
|
||||
}
|
||||
|
||||
@@ -501,5 +517,5 @@ namespace boost
|
||||
}
|
||||
|
||||
BOOST_CLASS_VERSION(rct::rctSigPrunable, 2)
|
||||
BOOST_CLASS_VERSION(rct::rctSig, 2)
|
||||
BOOST_CLASS_VERSION(rct::rctSig, 3)
|
||||
BOOST_CLASS_VERSION(rct::multisig_out, 1)
|
||||
|
||||
@@ -110,7 +110,7 @@ namespace cryptonote
|
||||
uint64_t get_transaction_weight_clawback(const transaction &tx, size_t n_padded_outputs)
|
||||
{
|
||||
const rct::rctSig &rv = tx.rct_signatures;
|
||||
const bool plus = rv.type == rct::RCTTypeBulletproofPlus;
|
||||
const bool plus = (rv.type == rct::RCTTypeBulletproofPlus || rv.type == rct::RCTTypeFullProofs);
|
||||
const uint64_t bp_base = (32 * ((plus ? 6 : 9) + 7 * 2)) / 2; // notional size of a 2 output proof, normalized to 1 proof (ie, divided by 2)
|
||||
const size_t n_outputs = tx.vout.size();
|
||||
if (n_padded_outputs <= 2)
|
||||
@@ -296,7 +296,7 @@ namespace cryptonote
|
||||
bool r = hwdev.generate_key_derivation(tx_public_key, ack.m_view_secret_key, recv_derivation);
|
||||
if (!r)
|
||||
{
|
||||
MWARNING("key image helper: failed to generate_key_derivation(" << tx_public_key << ", " << ack.m_view_secret_key << ")");
|
||||
MWARNING("key image helper: failed to generate_key_derivation(" << tx_public_key << ", <viewkey>)");
|
||||
memcpy(&recv_derivation, rct::identity().bytes, sizeof(recv_derivation));
|
||||
}
|
||||
|
||||
@@ -307,7 +307,7 @@ namespace cryptonote
|
||||
r = hwdev.generate_key_derivation(additional_tx_public_keys[i], ack.m_view_secret_key, additional_recv_derivation);
|
||||
if (!r)
|
||||
{
|
||||
MWARNING("key image helper: failed to generate_key_derivation(" << additional_tx_public_keys[i] << ", " << ack.m_view_secret_key << ")");
|
||||
MWARNING("key image helper: failed to generate_key_derivation(" << additional_tx_public_keys[i] << ", <viewkey>)");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -517,7 +517,7 @@ namespace cryptonote
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(tx.pruned, std::numeric_limits<uint64_t>::max(), "get_pruned_transaction_weight does not support non pruned txes");
|
||||
CHECK_AND_ASSERT_MES(tx.version >= 2, std::numeric_limits<uint64_t>::max(), "get_pruned_transaction_weight does not support v1 txes");
|
||||
CHECK_AND_ASSERT_MES(tx.rct_signatures.type == rct::RCTTypeBulletproof2 || tx.rct_signatures.type == rct::RCTTypeCLSAG || tx.rct_signatures.type == rct::RCTTypeBulletproofPlus,
|
||||
CHECK_AND_ASSERT_MES(tx.rct_signatures.type == rct::RCTTypeBulletproof2 || tx.rct_signatures.type == rct::RCTTypeCLSAG || tx.rct_signatures.type == rct::RCTTypeBulletproofPlus || tx.rct_signatures.type == rct::RCTTypeFullProofs,
|
||||
std::numeric_limits<uint64_t>::max(), "Unsupported rct_signatures type in get_pruned_transaction_weight");
|
||||
CHECK_AND_ASSERT_MES(!tx.vin.empty(), std::numeric_limits<uint64_t>::max(), "empty vin");
|
||||
CHECK_AND_ASSERT_MES(tx.vin[0].type() == typeid(cryptonote::txin_to_key), std::numeric_limits<uint64_t>::max(), "empty vin");
|
||||
|
||||
@@ -218,8 +218,11 @@
|
||||
#define HF_VERSION_2021_SCALING 2
|
||||
#define HF_VERSION_ENABLE_N_OUTS 2
|
||||
|
||||
#define HF_VERSION_REQUIRE_VIEW_TAGS 3
|
||||
#define HF_VERSION_FULL_PROOFS 3
|
||||
|
||||
#define HF_VERSION_ENFORCE_FULL_PROOFS 4
|
||||
|
||||
#define HF_VERSION_REQUIRE_VIEW_TAGS 255
|
||||
#define HF_VERSION_ENABLE_CONVERT 255
|
||||
#define HF_VERSION_ENABLE_ORACLE 255
|
||||
#define HF_VERSION_SLIPPAGE_YIELD 255
|
||||
|
||||
@@ -1034,13 +1034,27 @@ size_t Blockchain::recalculate_difficulties(boost::optional<uint64_t> start_heig
|
||||
LOG_PRINT_L3("Blockchain::" << __func__);
|
||||
CRITICAL_REGION_LOCAL(m_blockchain_lock);
|
||||
|
||||
const uint64_t start_height = start_height_opt ? *start_height_opt : check_difficulty_checkpoints().second;
|
||||
//uint64_t start_height = start_height_opt ? *start_height_opt : check_difficulty_checkpoints().second;
|
||||
uint8_t version = get_current_hard_fork_version();
|
||||
uint64_t start_height = 0;
|
||||
if (start_height_opt) {
|
||||
start_height = *start_height_opt;
|
||||
} else {
|
||||
bool found = false;
|
||||
for (size_t i=0; i<num_mainnet_hard_forks; ++i) {
|
||||
if (version == mainnet_hard_forks[i].version) {
|
||||
start_height = mainnet_hard_forks[i].height;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
start_height = std::max(start_height, check_difficulty_checkpoints().second);
|
||||
}
|
||||
const uint64_t top_height = m_db->height() - 1;
|
||||
MGINFO("Recalculating difficulties from height " << start_height << " to height " << top_height);
|
||||
|
||||
std::vector<uint64_t> timestamps;
|
||||
std::vector<difficulty_type> difficulties;
|
||||
uint8_t version = get_current_hard_fork_version();
|
||||
size_t difficulty_blocks_count;
|
||||
if (version == 1) {
|
||||
difficulty_blocks_count = DIFFICULTY_BLOCKS_COUNT;
|
||||
@@ -1483,10 +1497,14 @@ bool Blockchain::validate_miner_transaction(const block& b, size_t cumulative_bl
|
||||
switch (version) {
|
||||
case HF_VERSION_BULLETPROOF_PLUS:
|
||||
case HF_VERSION_ENABLE_N_OUTS:
|
||||
case HF_VERSION_FULL_PROOFS:
|
||||
case HF_VERSION_ENFORCE_FULL_PROOFS:
|
||||
if (b.miner_tx.amount_burnt > 0) {
|
||||
CHECK_AND_ASSERT_MES(money_in_use + b.miner_tx.amount_burnt > money_in_use, false, "miner transaction is overflowed by amount_burnt");
|
||||
money_in_use += b.miner_tx.amount_burnt;
|
||||
}
|
||||
if (already_generated_coins != 0)
|
||||
CHECK_AND_ASSERT_MES(money_in_use / 5 == b.miner_tx.amount_burnt, false, "miner_transaction has incorrect amount_burnt amount");
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
@@ -1541,16 +1559,19 @@ bool Blockchain::validate_protocol_transaction(const block& b, uint64_t height,
|
||||
if (o.target.type() == typeid(txout_to_key)) {
|
||||
txout_to_key out = boost::get<txout_to_key>(o.target);
|
||||
CHECK_AND_ASSERT_MES(out.unlock_time == CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, false, "Invalid unlock time on protocol_tx output");
|
||||
CHECK_AND_ASSERT_MES(outputs.count(out.key) == 0, false, "Output duplicated in protocol_tx");
|
||||
outputs[out.key] = std::make_tuple(out.asset_type, o.amount, out.unlock_time);
|
||||
} else if (o.target.type() == typeid(txout_to_tagged_key)) {
|
||||
txout_to_tagged_key out = boost::get<txout_to_tagged_key>(o.target);
|
||||
CHECK_AND_ASSERT_MES(out.unlock_time == CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, false, "Invalid unlock time on protocol_tx output");
|
||||
CHECK_AND_ASSERT_MES(outputs.count(out.key) == 0, false, "Output duplicated in protocol_tx");
|
||||
outputs[out.key] = std::make_tuple(out.asset_type, o.amount, out.unlock_time);
|
||||
} else {
|
||||
MERROR("Block at height: " << height << " attempting to add protocol transaction with invalid type " << o.target.type().name());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
CHECK_AND_ASSERT_MES(outputs.size() == b.protocol_tx.vout.size(), false, "Mismatch between vout and outputs for protocol_tx - aborting");
|
||||
|
||||
// Maintain a count of outputs that we have verified
|
||||
std::vector<crypto::public_key> outputs_verified;
|
||||
@@ -3472,9 +3493,9 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
// from v4, forbid invalid pubkeys
|
||||
if (hf_version >= 4) {
|
||||
if (hf_version >= 1) {
|
||||
for (const auto &o: tx.vout) {
|
||||
crypto::public_key output_public_key;
|
||||
if (!get_output_public_key(o, output_public_key)) {
|
||||
@@ -3487,7 +3508,7 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// from v8, allow bulletproofs
|
||||
if (hf_version < 8) {
|
||||
if (tx.version >= 2) {
|
||||
@@ -3586,10 +3607,9 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// from v16, forbid bulletproofs
|
||||
if (hf_version > HF_VERSION_BULLETPROOF_PLUS) {
|
||||
// from v1, forbid bulletproofs
|
||||
if (hf_version >= HF_VERSION_BULLETPROOF_PLUS) {
|
||||
if (tx.version >= 2) {
|
||||
const bool bulletproof = rct::is_rct_bulletproof(tx.rct_signatures.type);
|
||||
if (bulletproof)
|
||||
@@ -3600,7 +3620,25 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// from v4, only allow bulletproofs plus _with_ full proofs on RCT transactions
|
||||
if (hf_version >= HF_VERSION_ENFORCE_FULL_PROOFS) {
|
||||
if (tx.type == cryptonote::transaction_type::TRANSFER || tx.type == cryptonote::transaction_type::STAKE || tx.type == cryptonote::transaction_type::BURN || tx.type == cryptonote::transaction_type::CONVERT) {
|
||||
if (tx.rct_signatures.type != rct::RCTTypeFullProofs) {
|
||||
MERROR_VER("FullProofs required after v" + std::to_string(HF_VERSION_FULL_PROOFS));
|
||||
tvc.m_invalid_output = true;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (tx.rct_signatures.type != rct::RCTTypeNull) {
|
||||
MERROR_VER("NULL RCT required for coinbase TXs after v" + std::to_string(HF_VERSION_FULL_PROOFS));
|
||||
tvc.m_invalid_output = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// from v15, require view tags and asset types on outputs
|
||||
if (!check_output_types(tx, hf_version))
|
||||
{
|
||||
@@ -3644,6 +3682,15 @@ bool Blockchain::check_tx_type_and_version(const transaction& tx, tx_verificatio
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure CONVERT TXs are disabled until we are ready - belt and braces!
|
||||
if (hf_version < HF_VERSION_ENABLE_CONVERT) {
|
||||
if (tx.type == cryptonote::transaction_type::CONVERT) {
|
||||
MERROR("CONVERT TXs are not permitted prior to v" + std::to_string(HF_VERSION_ENABLE_CONVERT));
|
||||
tvc.m_version_mismatch = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -3685,7 +3732,7 @@ bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_pr
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (rv.type == rct::RCTTypeSimple || rv.type == rct::RCTTypeBulletproof || rv.type == rct::RCTTypeBulletproof2 || rv.type == rct::RCTTypeCLSAG || rv.type == rct::RCTTypeBulletproofPlus)
|
||||
else if (rv.type == rct::RCTTypeSimple || rv.type == rct::RCTTypeBulletproof || rv.type == rct::RCTTypeBulletproof2 || rv.type == rct::RCTTypeCLSAG || rv.type == rct::RCTTypeBulletproofPlus || rv.type == rct::RCTTypeFullProofs)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(!pubkeys.empty() && !pubkeys[0].empty(), false, "empty pubkeys");
|
||||
rv.mixRing.resize(pubkeys.size());
|
||||
@@ -3726,7 +3773,7 @@ bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_pr
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (rv.type == rct::RCTTypeCLSAG || rv.type == rct::RCTTypeBulletproofPlus)
|
||||
else if (rv.type == rct::RCTTypeCLSAG || rv.type == rct::RCTTypeBulletproofPlus || rv.type == rct::RCTTypeFullProofs)
|
||||
{
|
||||
if (!tx.pruned)
|
||||
{
|
||||
@@ -3973,7 +4020,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
|
||||
false, "Transaction spends at least one output which is too young");
|
||||
|
||||
// Warn that new RCT types are present, and thus the cache is not being used effectively
|
||||
static constexpr const std::uint8_t RCT_CACHE_TYPE = rct::RCTTypeBulletproofPlus;
|
||||
static constexpr const std::uint8_t RCT_CACHE_TYPE = rct::RCTTypeFullProofs;
|
||||
if (tx.rct_signatures.type > RCT_CACHE_TYPE)
|
||||
{
|
||||
MWARNING("RCT cache is not caching new verification results. Please update RCT_CACHE_TYPE!");
|
||||
@@ -4004,6 +4051,17 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
|
||||
// obviously, the original and simple rct APIs use a mixRing that's indexes
|
||||
// in opposite orders, because it'd be too simple otherwise...
|
||||
const rct::rctSig &rv = tx.rct_signatures;
|
||||
|
||||
// Check that after full proofs are enabled, the RCT version is set to enforce full proofs
|
||||
if (hf_version >= HF_VERSION_ENFORCE_FULL_PROOFS)
|
||||
{
|
||||
if (rv.type != rct::RCTTypeNull && rv.type != rct::RCTTypeFullProofs)
|
||||
{
|
||||
MERROR_VER("Unsupported rct type (full proofs are required): " << rv.type);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
switch (rv.type)
|
||||
{
|
||||
case rct::RCTTypeNull: {
|
||||
@@ -4016,6 +4074,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
|
||||
case rct::RCTTypeBulletproof2:
|
||||
case rct::RCTTypeCLSAG:
|
||||
case rct::RCTTypeBulletproofPlus:
|
||||
case rct::RCTTypeFullProofs:
|
||||
{
|
||||
if (!ver_rct_non_semantics_simple_cached(tx, pubkeys, m_rct_ver_cache, RCT_CACHE_TYPE, hf_version))
|
||||
{
|
||||
@@ -4093,22 +4152,6 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
|
||||
MERROR_VER("Unsupported rct type: " << rv.type);
|
||||
return false;
|
||||
}
|
||||
|
||||
// for bulletproofs, check they're only multi-output after v8
|
||||
if (rct::is_rct_bulletproof(rv.type))
|
||||
{
|
||||
if (hf_version < 8)
|
||||
{
|
||||
for (const rct::Bulletproof &proof: rv.p.bulletproofs)
|
||||
{
|
||||
if (proof.V.size() > 1)
|
||||
{
|
||||
MERROR_VER("Multi output bulletproofs are invalid before v8");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -6128,7 +6171,7 @@ void Blockchain::cancel()
|
||||
}
|
||||
|
||||
#if defined(PER_BLOCK_CHECKPOINT)
|
||||
static const char expected_block_hashes_hash[] = "3cb6d33c311e54f2b8439a3e4cc047f6b9b74db9fd92955f1db131a5dfce1edf";
|
||||
static const char expected_block_hashes_hash[] = "5065d5361119a526b7a45e9e5bdf1d5be86f80e9eb43b0398bf0e47489c81c6d";
|
||||
void Blockchain::load_compiled_in_block_hashes(const GetCheckpointsCallback& get_checkpoints)
|
||||
{
|
||||
if (get_checkpoints == nullptr || !m_fast_sync)
|
||||
|
||||
@@ -923,6 +923,16 @@ namespace cryptonote
|
||||
if (tx_info[n].tx->version < 2)
|
||||
continue;
|
||||
const rct::rctSig &rv = tx_info[n].tx->rct_signatures;
|
||||
const uint8_t hf_version = m_blockchain_storage.get_current_hard_fork_version();
|
||||
if (hf_version >= HF_VERSION_ENFORCE_FULL_PROOFS) {
|
||||
if (rv.type != rct::RCTTypeNull && rv.type != rct::RCTTypeFullProofs) {
|
||||
MERROR_VER("Invalid RCT type provided");
|
||||
set_semantics_failed(tx_info[n].tx_hash);
|
||||
tx_info[n].tvc.m_verifivation_failed = true;
|
||||
tx_info[n].result = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
switch (rv.type) {
|
||||
case rct::RCTTypeNull:
|
||||
// coinbase should not come here, so we reject for all other types
|
||||
@@ -970,6 +980,7 @@ namespace cryptonote
|
||||
rvv.push_back(&rv); // delayed batch verification
|
||||
break;
|
||||
case rct::RCTTypeBulletproofPlus:
|
||||
case rct::RCTTypeFullProofs:
|
||||
if (!is_canonical_bulletproof_plus_layout(rv.p.bulletproofs_plus))
|
||||
{
|
||||
MERROR_VER("Bulletproof_plus does not have canonical form");
|
||||
@@ -996,7 +1007,7 @@ namespace cryptonote
|
||||
{
|
||||
if (!tx_info[n].result)
|
||||
continue;
|
||||
if (tx_info[n].tx->rct_signatures.type != rct::RCTTypeBulletproof && tx_info[n].tx->rct_signatures.type != rct::RCTTypeBulletproof2 && tx_info[n].tx->rct_signatures.type != rct::RCTTypeCLSAG && tx_info[n].tx->rct_signatures.type != rct::RCTTypeBulletproofPlus)
|
||||
if (tx_info[n].tx->rct_signatures.type != rct::RCTTypeBulletproof && tx_info[n].tx->rct_signatures.type != rct::RCTTypeBulletproof2 && tx_info[n].tx->rct_signatures.type != rct::RCTTypeCLSAG && tx_info[n].tx->rct_signatures.type != rct::RCTTypeBulletproofPlus && tx_info[n].tx->rct_signatures.type != rct::RCTTypeFullProofs)
|
||||
continue;
|
||||
if (!rct::verRctSemanticsSimple(tx_info[n].tx->rct_signatures,
|
||||
tx_info[n].tx->type == cryptonote::transaction_type::BURN ? tx_info[n].tx->amount_burnt :
|
||||
|
||||
@@ -115,7 +115,7 @@ namespace cryptonote
|
||||
CHECK_AND_ASSERT_THROW_MES(tmp == rct::identity(), "invert failed");
|
||||
return inv;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
void classify_addresses(const std::vector<tx_destination_entry> &destinations, const boost::optional<cryptonote::account_public_address>& change_addr, size_t &num_stdaddresses, size_t &num_subaddresses, account_public_address &single_dest_subaddress)
|
||||
{
|
||||
@@ -502,7 +502,7 @@ namespace cryptonote
|
||||
crypto::key_derivation derivation = AUTO_VAL_INIT(derivation);
|
||||
crypto::public_key out_eph_public_key = AUTO_VAL_INIT(out_eph_public_key);
|
||||
bool r = crypto::generate_key_derivation(miner_address.m_view_public_key, txkey.sec, derivation);
|
||||
CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to generate_key_derivation(" << miner_address.m_view_public_key << ", " << txkey.sec << ")");
|
||||
CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to generate_key_derivation(" << miner_address.m_view_public_key << ", " << crypto::secret_key_explicit_print_ref{txkey.sec} << ")");
|
||||
|
||||
r = crypto::derive_public_key(derivation, tx.vout.size(), miner_address.m_spend_public_key, out_eph_public_key);
|
||||
CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to derive_public_key(" << derivation << ", " << 0 << ", "<< miner_address.m_spend_public_key << ")");
|
||||
@@ -515,7 +515,7 @@ namespace cryptonote
|
||||
crypto::key_derivation derivation_treasury = AUTO_VAL_INIT(derivation_treasury);
|
||||
crypto::public_key out_eph_public_key_treasury = AUTO_VAL_INIT(out_eph_public_key_treasury);
|
||||
r = crypto::generate_key_derivation(treasury_address.m_view_public_key, txkey.sec, derivation_treasury);
|
||||
CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to generate_key_derivation(" << treasury_address.m_view_public_key << ", " << txkey.sec << ")");
|
||||
CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to generate_key_derivation(" << treasury_address.m_view_public_key << ", " << crypto::secret_key_explicit_print_ref{txkey.sec} << ")");
|
||||
|
||||
r = crypto::derive_public_key(derivation_treasury, tx.vout.size(), treasury_address.m_spend_public_key, out_eph_public_key_treasury);
|
||||
CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to derive_public_key(" << derivation << ", " << 0 << ", "<< miner_address.m_spend_public_key << ")");
|
||||
@@ -569,7 +569,7 @@ namespace cryptonote
|
||||
crypto::key_derivation derivation = AUTO_VAL_INIT(derivation);
|
||||
crypto::public_key out_eph_public_key = AUTO_VAL_INIT(out_eph_public_key);
|
||||
bool r = crypto::generate_key_derivation(miner_address.m_view_public_key, txkey.sec, derivation);
|
||||
CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to generate_key_derivation(" << miner_address.m_view_public_key << ", " << txkey.sec << ")");
|
||||
CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to generate_key_derivation(" << miner_address.m_view_public_key << ", " << crypto::secret_key_explicit_print_ref{txkey.sec} << ")");
|
||||
|
||||
r = crypto::derive_public_key(derivation, 0, miner_address.m_spend_public_key, out_eph_public_key);
|
||||
CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to derive_public_key(" << derivation << ", " << 0 << ", "<< miner_address.m_spend_public_key << ")");
|
||||
@@ -589,6 +589,8 @@ namespace cryptonote
|
||||
switch (hard_fork_version) {
|
||||
case HF_VERSION_BULLETPROOF_PLUS:
|
||||
case HF_VERSION_ENABLE_N_OUTS:
|
||||
case HF_VERSION_FULL_PROOFS:
|
||||
case HF_VERSION_ENFORCE_FULL_PROOFS:
|
||||
// SRCG: subtract 20% that will be rewarded to staking users
|
||||
CHECK_AND_ASSERT_MES(tx.amount_burnt == 0, false, "while creating outs: amount_burnt is nonzero");
|
||||
tx.amount_burnt = amount / 5;
|
||||
@@ -856,6 +858,8 @@ namespace cryptonote
|
||||
uint64_t summary_outs_money = 0;
|
||||
//fill outputs
|
||||
size_t output_index = 0;
|
||||
crypto::secret_key x_change = crypto::null_skey;
|
||||
rct::key key_yF;
|
||||
uint8_t change_index = 0;
|
||||
for(const tx_destination_entry& dst_entr: destinations)
|
||||
{
|
||||
@@ -887,7 +891,7 @@ namespace cryptonote
|
||||
LOG_ERROR("*****************************************************************************");
|
||||
LOG_ERROR("in construct_tx_With_tx_key()");
|
||||
LOG_ERROR("TX type : TRANSFER");
|
||||
LOG_ERROR("tx_key : " << tx_key);
|
||||
LOG_ERROR("tx_key : " << crypto::secret_key_explicit_print_ref{tx_key});
|
||||
LOG_ERROR("tx_pubkey : " << txkey_pub);
|
||||
LOG_ERROR("P_change : " << dst_entr.addr.m_spend_public_key);
|
||||
LOG_ERROR("aP_change : " << dst_entr.addr.m_view_public_key);
|
||||
@@ -910,6 +914,35 @@ namespace cryptonote
|
||||
remove_field_from_tx_extra(tx.extra, typeid(tx_extra_additional_pub_keys));
|
||||
|
||||
if (hf_version >= HF_VERSION_ENABLE_N_OUTS && tx.type == cryptonote::transaction_type::TRANSFER) {
|
||||
|
||||
if (hf_version >= HF_VERSION_FULL_PROOFS) {
|
||||
|
||||
// Get the secret spend key for the change element
|
||||
crypto::secret_key spend_skey = crypto::null_skey;
|
||||
if (sender_account_keys.m_multisig_keys.empty())
|
||||
{
|
||||
// if not multisig, use normal spend skey
|
||||
spend_skey = sender_account_keys.m_spend_secret_key;
|
||||
}
|
||||
else
|
||||
{
|
||||
// if multisig, use sum of multisig privkeys (local account's share of aggregate spend key)
|
||||
for (const auto &multisig_key : sender_account_keys.m_multisig_keys)
|
||||
{
|
||||
sc_add((unsigned char*)spend_skey.data,
|
||||
(const unsigned char*)multisig_key.data,
|
||||
(const unsigned char*)spend_skey.data);
|
||||
}
|
||||
}
|
||||
|
||||
// Obtain a separate key_derivation for the P_change output
|
||||
// (using the TX public key and the sender's private view key)
|
||||
crypto::key_derivation derivation = AUTO_VAL_INIT(derivation);
|
||||
CHECK_AND_ASSERT_MES(hwdev.generate_key_derivation(txkey_pub, sender_account_keys.m_view_secret_key, derivation), false, "Failed to generate key_derivation for P_change");
|
||||
|
||||
// Calculate the secret spend key "x_change" for the P_change output
|
||||
CHECK_AND_ASSERT_MES(hwdev.derive_secret_key(derivation, change_index, spend_skey, x_change), false, "Failed to derive secret key for P_change");
|
||||
}
|
||||
|
||||
// Get the output public key for the change output
|
||||
crypto::public_key P_change = crypto::null_pkey;
|
||||
@@ -939,6 +972,12 @@ namespace cryptonote
|
||||
// Push the F point into the TX vector of F points
|
||||
tx.return_address_list.push_back(F);
|
||||
|
||||
// Calculate the shared secret yF
|
||||
if (hf_version >= HF_VERSION_FULL_PROOFS) {
|
||||
rct::key key_aP = rct::scalarmultKey(rct::pk2rct(P_change), rct::sk2rct(sender_account_keys.m_view_secret_key));
|
||||
key_yF = rct::hash_to_scalar(key_aP);
|
||||
}
|
||||
|
||||
// Calculate the encrypted_change_index data for this output
|
||||
struct {
|
||||
char domain_separator[8];
|
||||
@@ -1038,7 +1077,7 @@ namespace cryptonote
|
||||
crypto::generate_ring_signature(tx_prefix_hash, boost::get<txin_to_key>(tx.vin[i]).k_image, keys_ptrs, in_contexts[i].in_ephemeral.sec, src_entr.real_output, sigs.data());
|
||||
ss_ring_s << "signatures:" << ENDL;
|
||||
std::for_each(sigs.begin(), sigs.end(), [&](const crypto::signature& s){ss_ring_s << s << ENDL;});
|
||||
ss_ring_s << "prefix_hash:" << tx_prefix_hash << ENDL << "in_ephemeral_key: " << in_contexts[i].in_ephemeral.sec << ENDL << "real_output: " << src_entr.real_output << ENDL;
|
||||
ss_ring_s << "prefix_hash:" << tx_prefix_hash << ENDL << "in_ephemeral_key: " << crypto::secret_key_explicit_print_ref{in_contexts[i].in_ephemeral.sec} << ENDL << "real_output: " << src_entr.real_output << ENDL;
|
||||
i++;
|
||||
}
|
||||
|
||||
@@ -1162,22 +1201,25 @@ namespace cryptonote
|
||||
rct::ctkeyV outSk;
|
||||
if (use_simple_rct)
|
||||
tx.rct_signatures = rct::genRctSimple(
|
||||
rct::hash2rct(tx_prefix_hash),
|
||||
inSk,
|
||||
destinations,
|
||||
tx_type,
|
||||
source_asset,
|
||||
destination_asset_types,
|
||||
inamounts,
|
||||
outamounts,
|
||||
fee,
|
||||
mixRing,
|
||||
amount_keys,
|
||||
index,
|
||||
outSk,
|
||||
rct_config,
|
||||
hwdev
|
||||
);
|
||||
rct::hash2rct(tx_prefix_hash),
|
||||
inSk,
|
||||
destinations,
|
||||
tx_type,
|
||||
source_asset,
|
||||
destination_asset_types,
|
||||
inamounts,
|
||||
outamounts,
|
||||
fee,
|
||||
mixRing,
|
||||
amount_keys,
|
||||
index,
|
||||
outSk,
|
||||
rct_config,
|
||||
hwdev,
|
||||
rct::sk2rct(x_change),
|
||||
change_index,
|
||||
key_yF
|
||||
);
|
||||
else
|
||||
tx.rct_signatures = rct::genRct(rct::hash2rct(tx_prefix_hash), inSk, destinations, outamounts, mixRing, amount_keys, sources[0].real_output, outSk, rct_config, hwdev); // same index assumption
|
||||
memwipe(inSk.data(), inSk.size() * sizeof(rct::ctkey));
|
||||
|
||||
@@ -130,7 +130,7 @@ bool ver_rct_non_semantics_simple_cached
|
||||
// mixring. Future versions of the protocol may differ in this regard, but if this assumptions
|
||||
// holds true in the future, enable the verification hash by modifying the `untested_tx`
|
||||
// condition below.
|
||||
const bool untested_tx = tx.version > 3 || tx.rct_signatures.type > rct::RCTTypeBulletproofPlus;
|
||||
const bool untested_tx = tx.version > 3 || tx.rct_signatures.type > rct::RCTTypeFullProofs;
|
||||
VER_ASSERT(!untested_tx, "Unknown TX type. Make sure RCT cache works correctly with this type and then enable it in the code here.");
|
||||
|
||||
// Don't cache older (or newer) rctSig types
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2017-2023, The Monero Project
|
||||
// Copyright (c) 2017-2024, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
@@ -317,13 +317,15 @@ namespace hw {
|
||||
{
|
||||
// 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 << ")");
|
||||
CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to generate_key_derivation(" << txkey_pub << ", <viewkey>)");
|
||||
}
|
||||
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) << ")");
|
||||
const crypto::secret_key &tx_privkey{dst_entr.is_subaddress && need_additional_txkeys ? additional_txkey.sec : tx_key};
|
||||
r = generate_key_derivation(dst_entr.addr.m_view_public_key, tx_privkey, derivation);
|
||||
CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to generate_key_derivation("
|
||||
<< dst_entr.addr.m_view_public_key << ", " << crypto::secret_key_explicit_print_ref{tx_privkey} << ")");
|
||||
}
|
||||
|
||||
if (need_additional_txkeys)
|
||||
|
||||
@@ -1929,7 +1929,7 @@ namespace hw {
|
||||
|
||||
// ====== Aout, Bout, AKout, C, v, k ======
|
||||
kv_offset = data_offset;
|
||||
if (type==rct::RCTTypeBulletproof2 || type==rct::RCTTypeCLSAG || type==rct::RCTTypeBulletproofPlus) {
|
||||
if (type==rct::RCTTypeBulletproof2 || type==rct::RCTTypeCLSAG || type==rct::RCTTypeBulletproofPlus || type==rct::RCTTypeFullProofs) {
|
||||
C_offset = kv_offset+ (8)*outputs_size;
|
||||
} else {
|
||||
C_offset = kv_offset+ (32+32)*outputs_size;
|
||||
@@ -1946,7 +1946,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 || type==rct::RCTTypeBulletproofPlus)?0x02:0x00;
|
||||
this->buffer_send[offset] |= (type==rct::RCTTypeBulletproof2 || type==rct::RCTTypeCLSAG || type==rct::RCTTypeBulletproofPlus || type==rct::RCTTypeFullProofs)?0x02:0x00;
|
||||
offset += 1;
|
||||
//is_subaddress
|
||||
this->buffer_send[offset] = outKeys.is_subaddress;
|
||||
@@ -1967,7 +1967,7 @@ namespace hw {
|
||||
memmove(this->buffer_send+offset, data+C_offset,32);
|
||||
offset += 32;
|
||||
C_offset += 32;
|
||||
if (type==rct::RCTTypeBulletproof2 || type==rct::RCTTypeCLSAG || type==rct::RCTTypeBulletproofPlus) {
|
||||
if (type==rct::RCTTypeBulletproof2 || type==rct::RCTTypeCLSAG || type==rct::RCTTypeBulletproofPlus || type==rct::RCTTypeFullProofs) {
|
||||
//k
|
||||
memset(this->buffer_send+offset, 0, 32);
|
||||
offset += 32;
|
||||
|
||||
@@ -36,7 +36,13 @@ const hardfork_t mainnet_hard_forks[] = {
|
||||
{ 1, 1, 0, 1341378000 },
|
||||
|
||||
// version 2 starts from block 89800, which is on or around the 4th of November, 2024. Fork time finalised on 2024-10-21. No fork voting occurs for the v2 fork.
|
||||
{ 2, 89800, 0, 1729518000 },
|
||||
{ 2, 89800, 0, 1729518000 },
|
||||
|
||||
// version 3 starts from block 121100, which is on or around the 19th of December, 2024. Fork time finalised on 2024-12-18. No fork voting occurs for the v3 fork.
|
||||
{ 3, 121100, 0, 1734516900 },
|
||||
|
||||
// version 4 starts from block 121100, which is on or around the 20th of December, 2024. Fork time finalised on 2024-12-19. No fork voting occurs for the v4 fork.
|
||||
{ 4, 121800, 0, 1734607000 },
|
||||
};
|
||||
const size_t num_mainnet_hard_forks = sizeof(mainnet_hard_forks) / sizeof(mainnet_hard_forks[0]);
|
||||
const uint64_t mainnet_hard_fork_version_1_till = ((uint64_t)-1);
|
||||
@@ -47,6 +53,9 @@ const hardfork_t testnet_hard_forks[] = {
|
||||
|
||||
// version 2 starts from block 250
|
||||
{ 2, 250, 0, 1445355000 },
|
||||
|
||||
// version 3 starts from block 500
|
||||
{ 3, 500, 0, 1729518000 },
|
||||
};
|
||||
const size_t num_testnet_hard_forks = sizeof(testnet_hard_forks) / sizeof(testnet_hard_forks[0]);
|
||||
const uint64_t testnet_hard_fork_version_1_till = ((uint64_t)-1);
|
||||
|
||||
@@ -543,6 +543,9 @@ static bool compute_keys_for_destinations(
|
||||
if (destinations[i].is_change) {
|
||||
found_change = true;
|
||||
change_index = output_index; // Store the change_index - we will need this
|
||||
|
||||
// Calculate the change spend key (x_change)
|
||||
|
||||
}
|
||||
output_index++;
|
||||
}
|
||||
@@ -666,6 +669,8 @@ static void make_new_range_proofs(const int bp_version,
|
||||
sigs.bulletproofs.push_back(rct::bulletproof_PROVE(output_amounts, output_amount_masks));
|
||||
else if (bp_version == 4)
|
||||
sigs.bulletproofs_plus.push_back(rct::bulletproof_plus_PROVE(output_amounts, output_amount_masks));
|
||||
else if (bp_version == 5)
|
||||
sigs.bulletproofs_plus.push_back(rct::bulletproof_plus_PROVE(output_amounts, output_amount_masks));
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
@@ -701,6 +706,12 @@ static bool try_reconstruct_range_proofs(const int bp_version,
|
||||
return false;
|
||||
return rct::bulletproof_plus_VERIFY(reconstructed_sigs.bulletproofs_plus);
|
||||
}
|
||||
else if (bp_version == 5)
|
||||
{
|
||||
if (not try_reconstruct_range_proofs(original_sigs.bulletproofs_plus, reconstructed_sigs.bulletproofs_plus))
|
||||
return false;
|
||||
return rct::bulletproof_plus_VERIFY(reconstructed_sigs.bulletproofs_plus);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -818,11 +829,15 @@ static bool set_tx_rct_signatures(
|
||||
const bool reconstruction,
|
||||
cryptonote::transaction& unsigned_tx,
|
||||
std::vector<CLSAG_context_t>& CLSAG_contexts,
|
||||
rct::keyV& cached_w
|
||||
rct::keyV& cached_w,
|
||||
const uint8_t change_index,
|
||||
const rct::key& x_change,
|
||||
const rct::key& hs_yF
|
||||
)
|
||||
{
|
||||
if (rct_config.bp_version != 3 &&
|
||||
rct_config.bp_version != 4)
|
||||
rct_config.bp_version != 4 &&
|
||||
rct_config.bp_version != 5)
|
||||
return false;
|
||||
if (rct_config.range_proof_type != rct::RangeProofPaddedBulletproof)
|
||||
return false;
|
||||
@@ -838,6 +853,8 @@ static bool set_tx_rct_signatures(
|
||||
rv.type = rct::RCTTypeCLSAG;
|
||||
else if (rct_config.bp_version == 4)
|
||||
rv.type = rct::RCTTypeBulletproofPlus;
|
||||
else if (rct_config.bp_version == 5)
|
||||
rv.type = rct::RCTTypeFullProofs;
|
||||
else
|
||||
return false;
|
||||
rv.txnFee = fee;
|
||||
@@ -915,11 +932,39 @@ static bool set_tx_rct_signatures(
|
||||
}
|
||||
sc_sub(difference.bytes, sumpouts.bytes, sumouts.bytes);
|
||||
rct::genC(rv.p_r, difference, 0);
|
||||
if (rv.type == rct::RCTTypeFullProofs) {
|
||||
rv.pr_proof = rct::PRProof_Gen(difference);
|
||||
#ifdef DBG
|
||||
CHECK_AND_ASSERT_THROW_MES(rct::PRProof_Ver(rv.p_r, rv.pr_proof), "PRProof_Ver() failed on recently created proof");
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
// Check if spend authority proof is needed (only for TRANSFER TXs)
|
||||
if (unsigned_tx.type == cryptonote::transaction_type::TRANSFER && rv.type == rct::RCTTypeFullProofs) {
|
||||
rv.sa_proof = rct::SAProof_Gen(output_public_keys[change_index], x_change, hs_yF);
|
||||
#ifdef DBG
|
||||
CHECK_AND_ASSERT_THROW_MES(rct::SAProof_Ver(rv.sa_proof, output_public_keys[change_index], hs_yF), "SAProof_Ver() failed on recently created proof");
|
||||
#endif
|
||||
}
|
||||
*/
|
||||
}
|
||||
// check balance if reconstructing the tx
|
||||
else {
|
||||
rv.p.pseudoOuts = unsigned_tx.rct_signatures.p.pseudoOuts;
|
||||
rv.p_r = unsigned_tx.rct_signatures.p_r;
|
||||
if (rv.type == rct::RCTTypeFullProofs) {
|
||||
if (!rct::PRProof_Ver(unsigned_tx.rct_signatures.p_r, unsigned_tx.rct_signatures.pr_proof))
|
||||
return false;
|
||||
rv.p_r = unsigned_tx.rct_signatures.p_r;
|
||||
rv.pr_proof = unsigned_tx.rct_signatures.pr_proof;
|
||||
/*
|
||||
if (!rct::SAProof_Ver(unsigned_tx.rct_signatures.sa_proof, output_public_keys[change_index], hs_yF))
|
||||
return false;
|
||||
rv.sa_proof = unsigned_tx.rct_signatures.sa_proof; // should verify this during reconstruction
|
||||
*/
|
||||
} else {
|
||||
rv.p_r = unsigned_tx.rct_signatures.p_r;
|
||||
}
|
||||
if (num_sources != rv.p.pseudoOuts.size())
|
||||
return false;
|
||||
rct::key balance_accumulator = rct::scalarmultH(rct::d2h(fee));
|
||||
@@ -1164,6 +1209,8 @@ bool tx_builder_ringct_t::init(
|
||||
// Check that the change element was found
|
||||
if (!found_change)
|
||||
return false;
|
||||
|
||||
//
|
||||
|
||||
// add inputs to tx
|
||||
set_tx_inputs(sources, unsigned_tx);
|
||||
@@ -1178,6 +1225,8 @@ bool tx_builder_ringct_t::init(
|
||||
if (not set_tx_outputs_result)
|
||||
return false;
|
||||
|
||||
rct::key hs_yF;
|
||||
rct::key x_change;
|
||||
if (hf_version >= HF_VERSION_ENABLE_N_OUTS && unsigned_tx.type == cryptonote::transaction_type::TRANSFER) {
|
||||
|
||||
// Get the output public key for the change output
|
||||
@@ -1213,6 +1262,7 @@ bool tx_builder_ringct_t::init(
|
||||
rct::key key_F = rct::scalarmultKey(key_aP_change, key_inv_y);
|
||||
rct::key key_verify = rct::scalarmultKey(key_F, key_y);
|
||||
CHECK_AND_ASSERT_MES(key_verify == key_aP_change, false, "at get_return_address: failed to verify invert() function with smK() approach");
|
||||
hs_yF = rct::hash_to_scalar(key_verify);
|
||||
|
||||
// Push the F point into the TX vector of F points
|
||||
if (not reconstruction)
|
||||
@@ -1233,6 +1283,38 @@ bool tx_builder_ringct_t::init(
|
||||
unsigned_tx.return_address_change_mask.push_back(eci_data);
|
||||
}
|
||||
|
||||
if (hf_version >= HF_VERSION_FULL_PROOFS) {
|
||||
|
||||
// Get the secret spend key for the change element
|
||||
crypto::secret_key spend_skey = crypto::null_skey;
|
||||
for (const auto &multisig_key : account_keys.m_multisig_keys) {
|
||||
sc_add((unsigned char*)spend_skey.data,
|
||||
(const unsigned char*)multisig_key.data,
|
||||
(const unsigned char*)spend_skey.data);
|
||||
}
|
||||
|
||||
// Calculate z_i (the shared secret between sender and ourselves for the original TX)
|
||||
crypto::public_key txkey_pub = crypto::null_pkey; // R
|
||||
const std::vector<crypto::public_key> in_additional_tx_pub_keys = cryptonote::get_additional_tx_pub_keys_from_extra(unsigned_tx);
|
||||
if (in_additional_tx_pub_keys.size() != 0) {
|
||||
CHECK_AND_ASSERT_MES(in_additional_tx_pub_keys.size() == unsigned_tx.vout.size(), false, "incorrect number of additional TX pubkeys in origin TX for return_payment");
|
||||
txkey_pub = in_additional_tx_pub_keys[change_index];
|
||||
} else {
|
||||
txkey_pub = cryptonote::get_tx_pub_key_from_extra(unsigned_tx);
|
||||
}
|
||||
|
||||
// Obtain a separate key_derivation for the P_change output
|
||||
// (using the TX public key and the sender's private view key)
|
||||
hw::device &hwdev = account_keys.get_device();
|
||||
crypto::key_derivation derivation = AUTO_VAL_INIT(derivation);
|
||||
CHECK_AND_ASSERT_MES(hwdev.generate_key_derivation(txkey_pub, account_keys.m_view_secret_key, derivation), false, "Failed to generate key_derivation for P_change");
|
||||
|
||||
// Calculate the secret spend key "x_change" for the P_change output
|
||||
crypto::secret_key s_change = crypto::null_skey;
|
||||
CHECK_AND_ASSERT_MES(hwdev.derive_secret_key(derivation, change_index, spend_skey, s_change), false, "Failed to derive secret key for P_change");
|
||||
x_change = rct::sk2rct(s_change);
|
||||
}
|
||||
|
||||
} else if (unsigned_tx.type == cryptonote::transaction_type::TRANSFER || unsigned_tx.type == cryptonote::transaction_type::STAKE) {
|
||||
|
||||
// Get the tx public key
|
||||
@@ -1245,7 +1327,7 @@ bool tx_builder_ringct_t::init(
|
||||
|
||||
// prepare input signatures
|
||||
if (not set_tx_rct_signatures(fee, sources, destination_amounts, input_secret_keys, output_public_keys, output_amount_secret_keys,
|
||||
rct_config, reconstruction, unsigned_tx, CLSAG_contexts, cached_w))
|
||||
rct_config, reconstruction, unsigned_tx, CLSAG_contexts, cached_w, change_index, x_change, hs_yF))
|
||||
return false;
|
||||
|
||||
initialized = true;
|
||||
|
||||
+155
-39
@@ -521,7 +521,45 @@ namespace rct {
|
||||
sc_sub(c.bytes, c_old.bytes, rv.cc.bytes);
|
||||
return sc_isnonzero(c.bytes) == 0;
|
||||
}
|
||||
|
||||
|
||||
zk_proof PRProof_Gen(const rct::key &difference) {
|
||||
zk_proof proof;
|
||||
|
||||
// Generate a random scalar for blinding
|
||||
rct::key r = rct::skGen();
|
||||
|
||||
// Compute R = r * G
|
||||
proof.R = rct::scalarmultBase(r);
|
||||
|
||||
// Compute the commitment to the difference
|
||||
rct::key comm_diff;
|
||||
genC(comm_diff, difference, 0);
|
||||
|
||||
// Calculate challenge c = H_p(R)
|
||||
std::vector<rct::key> keys{proof.R, comm_diff};
|
||||
rct::key c = rct::hash_to_scalar(keys);
|
||||
|
||||
// Calculate response z = r + c * difference
|
||||
sc_muladd(proof.z1.bytes, difference.bytes, c.bytes, r.bytes);
|
||||
proof.z2 = rct::zero();
|
||||
|
||||
return proof;
|
||||
}
|
||||
|
||||
bool PRProof_Ver(const rct::key &C, const zk_proof &proof) {
|
||||
// Compute challenge c = H_p(R)
|
||||
std::vector<rct::key> keys{proof.R, C};
|
||||
rct::key c = rct::hash_to_scalar(keys);
|
||||
|
||||
// Recalculate R' = z * G - c * C (where C is the commitment rv.p_r)
|
||||
rct::key zG = rct::scalarmultBase(proof.z1);
|
||||
rct::key cC = rct::scalarmultKey(C, c);
|
||||
rct::key R_prime;
|
||||
rct::subKeys(R_prime, zG, cC);
|
||||
|
||||
// Verify R' ?= R
|
||||
return rct::equalKeys(R_prime, proof.R);
|
||||
}
|
||||
|
||||
|
||||
//proveRange and verRange
|
||||
@@ -639,7 +677,7 @@ namespace rct {
|
||||
kv.push_back(p.t);
|
||||
}
|
||||
}
|
||||
else if (rv.type == RCTTypeBulletproofPlus)
|
||||
else if (rv.type == RCTTypeBulletproofPlus || rv.type == RCTTypeFullProofs)
|
||||
{
|
||||
kv.reserve((6*2+6) * rv.p.bulletproofs_plus.size());
|
||||
for (const auto &p: rv.p.bulletproofs_plus)
|
||||
@@ -1032,6 +1070,55 @@ namespace rct {
|
||||
return index;
|
||||
}
|
||||
|
||||
zk_proof SAProof_Gen(const key &P, const key &x_change, const key &key_yF) {
|
||||
|
||||
// Sanity checks for inputs
|
||||
CHECK_AND_ASSERT_THROW_MES(!rct::equalKeys(P, rct::zero()), "SAProof_Gen() failed - invalid public key provided");
|
||||
CHECK_AND_ASSERT_THROW_MES(!rct::equalKeys(x_change, rct::zero()), "SAProof_Gen() failed - invalid x_change key provided");
|
||||
CHECK_AND_ASSERT_THROW_MES(!rct::equalKeys(key_yF, rct::zero()), "SAProof_Gen() failed - invalid shared secret key provided");
|
||||
|
||||
// Declare a return structure
|
||||
zk_proof proof{};
|
||||
proof.z2 = rct::zero();
|
||||
|
||||
// Calculate a random r value and calculate a commitment R for it
|
||||
rct::key r = rct::skGen();
|
||||
proof.R = rct::scalarmultBase(r);
|
||||
|
||||
// Calculate the challenge hash from the commitment plus the pubkey plus the shared secret
|
||||
keyV challenge_keys{proof.R, P, key_yF};
|
||||
rct::key c = rct::hash_to_scalar(challenge_keys);
|
||||
|
||||
rct::key z_x;
|
||||
sc_muladd(z_x.bytes, x_change.bytes, c.bytes, r.bytes);
|
||||
proof.z1 = z_x;
|
||||
|
||||
// Return the proof to the caller
|
||||
return proof;
|
||||
}
|
||||
|
||||
bool SAProof_Ver(const zk_proof &proof, const key &P, const key &key_yF) {
|
||||
|
||||
// Sanity checks for inputs
|
||||
CHECK_AND_ASSERT_THROW_MES(!rct::equalKeys(P, rct::zero()), "SAProof_Ver() failed - invalid public key provided");
|
||||
CHECK_AND_ASSERT_THROW_MES(!rct::equalKeys(key_yF, rct::zero()), "SAProof_Ver() failed - invalid shared secret key provided");
|
||||
|
||||
// Recompute the challenge hash
|
||||
keyV challenge_keys{proof.R, P, key_yF};
|
||||
rct::key c = rct::hash_to_scalar(challenge_keys);
|
||||
|
||||
// Recalculate the expected commitment using the formula: z_x * G = R + c * P
|
||||
rct::key expected_commitment = rct::addKeys(proof.R, rct::scalarmultKey(P, c));
|
||||
|
||||
// Verify z_x * G matches the expected commitment
|
||||
if (!rct::equalKeys(rct::scalarmultBase(proof.z1), expected_commitment)) {
|
||||
return false; // Verification failed
|
||||
}
|
||||
|
||||
// All checks passed
|
||||
return true;
|
||||
}
|
||||
|
||||
//RingCT protocol
|
||||
//genRct:
|
||||
// creates an rctSig with all data necessary to verify the rangeProofs and that the signer owns one of the
|
||||
@@ -1074,7 +1161,7 @@ namespace rct {
|
||||
//mask amount and mask
|
||||
rv.ecdhInfo[i].mask = copy(outSk[i].mask);
|
||||
rv.ecdhInfo[i].amount = d2h(amounts[i]);
|
||||
hwdev.ecdhEncode(rv.ecdhInfo[i], amount_keys[i], rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG || rv.type == RCTTypeBulletproofPlus);
|
||||
hwdev.ecdhEncode(rv.ecdhInfo[i], amount_keys[i], rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG || rv.type == RCTTypeBulletproofPlus || rv.type == RCTTypeFullProofs);
|
||||
}
|
||||
|
||||
//set txn fee
|
||||
@@ -1104,21 +1191,25 @@ namespace rct {
|
||||
//RCT simple
|
||||
//for post-rct only
|
||||
rctSig genRctSimple(
|
||||
const key &message,
|
||||
const ctkeyV & inSk,
|
||||
const keyV & destinations,
|
||||
const cryptonote::transaction_type tx_type,
|
||||
const std::string& in_asset_type,
|
||||
const std::vector<std::string> & destination_asset_types,
|
||||
const std::vector<xmr_amount> &inamounts,
|
||||
const std::vector<xmr_amount> &outamounts,
|
||||
xmr_amount txnFee,
|
||||
const ctkeyM & mixRing,
|
||||
const keyV &amount_keys,
|
||||
const std::vector<unsigned int> & index,
|
||||
ctkeyV &outSk,
|
||||
const RCTConfig &rct_config,
|
||||
hw::device &hwdev)
|
||||
const key &message,
|
||||
const ctkeyV & inSk,
|
||||
const keyV & destinations,
|
||||
const cryptonote::transaction_type tx_type,
|
||||
const std::string& in_asset_type,
|
||||
const std::vector<std::string> & destination_asset_types,
|
||||
const std::vector<xmr_amount> &inamounts,
|
||||
const std::vector<xmr_amount> &outamounts,
|
||||
xmr_amount txnFee,
|
||||
const ctkeyM & mixRing,
|
||||
const keyV &amount_keys,
|
||||
const std::vector<unsigned int> & index,
|
||||
ctkeyV &outSk,
|
||||
const RCTConfig &rct_config,
|
||||
hw::device &hwdev,
|
||||
const key &x_change,
|
||||
const size_t change_index,
|
||||
const key &key_yF
|
||||
)
|
||||
{
|
||||
const bool bulletproof_or_plus = rct_config.range_proof_type > RangeProofBorromean;
|
||||
CHECK_AND_ASSERT_THROW_MES(destination_asset_types.size() == destinations.size(), "Different number of amount_keys/destinations");
|
||||
@@ -1141,6 +1232,9 @@ namespace rct {
|
||||
case 4:
|
||||
rv.type = RCTTypeBulletproofPlus;
|
||||
break;
|
||||
case 5:
|
||||
rv.type = RCTTypeFullProofs;
|
||||
break;
|
||||
default:
|
||||
ASSERT_MES_AND_THROW("Unsupported BP version: " << rct_config.bp_version);
|
||||
}
|
||||
@@ -1257,7 +1351,7 @@ namespace rct {
|
||||
//mask amount and mask
|
||||
rv.ecdhInfo[i].mask = copy(outSk[i].mask);
|
||||
rv.ecdhInfo[i].amount = d2h(outamounts[i]);
|
||||
hwdev.ecdhEncode(rv.ecdhInfo[i], amount_keys[i], rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG || rv.type == RCTTypeBulletproofPlus);
|
||||
hwdev.ecdhEncode(rv.ecdhInfo[i], amount_keys[i], rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG || rv.type == RCTTypeBulletproofPlus || rv.type == RCTTypeFullProofs);
|
||||
}
|
||||
|
||||
//set txn fee
|
||||
@@ -1282,7 +1376,23 @@ namespace rct {
|
||||
sc_sub(difference.bytes, sumpouts.bytes, sumout.bytes);
|
||||
genC(rv.p_r, difference, 0);
|
||||
DP(rv.p_r);
|
||||
if (rv.type == RCTTypeFullProofs) {
|
||||
rv.pr_proof = PRProof_Gen(difference);
|
||||
#ifdef DBG
|
||||
CHECK_AND_ASSERT_THROW_MES(PRProof_Ver(rv.p_r, rv.pr_proof), "PRProof_Ver() failed on recently created proof");
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
// Check if spend authority proof is needed (only for TRANSFER TXs)
|
||||
if (tx_type == cryptonote::transaction_type::TRANSFER && rv.type == rct::RCTTypeFullProofs) {
|
||||
rv.sa_proof = SAProof_Gen(destinations[change_index], x_change, key_yF);
|
||||
#ifdef DBG
|
||||
CHECK_AND_ASSERT_THROW_MES(SAProof_Ver(rv.sa_proof, destinations[change_index], key_yF), "SAProof_Ver() failed on recently created proof");
|
||||
#endif
|
||||
}
|
||||
*/
|
||||
|
||||
key full_message = get_pre_mlsag_hash(rv,hwdev);
|
||||
|
||||
for (i = 0 ; i < inamounts.size(); i++)
|
||||
@@ -1299,24 +1409,28 @@ namespace rct {
|
||||
rv.p.MGs[i] = proveRctMGSimple(full_message, rv.mixRing[i], inSk[i], a[i], pseudoOuts[i], index[i], hwdev);
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
rctSig genRctSimple(
|
||||
const key &message,
|
||||
const ctkeyV & inSk,
|
||||
const ctkeyV & inPk,
|
||||
const keyV & destinations,
|
||||
const cryptonote::transaction_type tx_type,
|
||||
const std::string& in_asset_type,
|
||||
const std::vector<std::string> & destination_asset_types,
|
||||
const std::vector<xmr_amount> &inamounts,
|
||||
const std::vector<xmr_amount> &outamounts,
|
||||
const keyV &amount_keys,
|
||||
xmr_amount txnFee,
|
||||
unsigned int mixin,
|
||||
const RCTConfig &rct_config,
|
||||
hw::device &hwdev
|
||||
const key &message,
|
||||
const ctkeyV & inSk,
|
||||
const ctkeyV & inPk,
|
||||
const keyV & destinations,
|
||||
const cryptonote::transaction_type tx_type,
|
||||
const std::string& in_asset_type,
|
||||
const std::vector<std::string> & destination_asset_types,
|
||||
const std::vector<xmr_amount> &inamounts,
|
||||
const std::vector<xmr_amount> &outamounts,
|
||||
const keyV &amount_keys,
|
||||
xmr_amount txnFee,
|
||||
unsigned int mixin,
|
||||
const RCTConfig &rct_config,
|
||||
hw::device &hwdev,
|
||||
const key &x_change,
|
||||
const size_t change_index,
|
||||
const key &key_yF
|
||||
) {
|
||||
std::vector<unsigned int> index;
|
||||
index.resize(inPk.size());
|
||||
@@ -1327,7 +1441,7 @@ namespace rct {
|
||||
mixRing[i].resize(mixin+1);
|
||||
index[i] = populateFromBlockchainSimple(mixRing[i], inPk[i], mixin);
|
||||
}
|
||||
return genRctSimple(message, inSk, destinations, tx_type, in_asset_type, destination_asset_types, inamounts, outamounts, txnFee, mixRing, amount_keys, index, outSk, rct_config, hwdev);
|
||||
return genRctSimple(message, inSk, destinations, tx_type, in_asset_type, destination_asset_types, inamounts, outamounts, txnFee, mixRing, amount_keys, index, outSk, rct_config, hwdev, x_change, change_index, key_yF);
|
||||
}
|
||||
|
||||
//RingCT protocol
|
||||
@@ -1416,8 +1530,10 @@ namespace rct {
|
||||
std::vector<const BulletproofPlus*> bpp_proofs;
|
||||
size_t max_non_bp_proofs = 0, offset = 0;
|
||||
|
||||
CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple || rv.type == RCTTypeBulletproof || rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG || rv.type == RCTTypeBulletproofPlus,
|
||||
CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple || rv.type == RCTTypeBulletproof || rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG || rv.type == RCTTypeBulletproofPlus || rv.type == RCTTypeFullProofs,
|
||||
false, "verRctSemanticsSimple called on non simple rctSig");
|
||||
if (rv.type == RCTTypeFullProofs)
|
||||
CHECK_AND_ASSERT_MES(PRProof_Ver(rv.p_r, rv.pr_proof), false, "Invalid p_r commitment to difference");
|
||||
const bool bulletproof = is_rct_bulletproof(rv.type);
|
||||
const bool bulletproof_plus = is_rct_bulletproof_plus(rv.type);
|
||||
if (bulletproof || bulletproof_plus)
|
||||
@@ -1540,7 +1656,7 @@ namespace rct {
|
||||
{
|
||||
PERF_TIMER(verRctNonSemanticsSimple);
|
||||
|
||||
CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple || rv.type == RCTTypeBulletproof || rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG || rv.type == RCTTypeBulletproofPlus,
|
||||
CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple || rv.type == RCTTypeBulletproof || rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG || rv.type == RCTTypeBulletproofPlus || rv.type == RCTTypeFullProofs,
|
||||
false, "verRctNonSemanticsSimple called on non simple rctSig");
|
||||
const bool bulletproof = is_rct_bulletproof(rv.type);
|
||||
const bool bulletproof_plus = is_rct_bulletproof_plus(rv.type);
|
||||
@@ -1612,7 +1728,7 @@ namespace rct {
|
||||
|
||||
//mask amount and mask
|
||||
ecdhTuple ecdh_info = rv.ecdhInfo[i];
|
||||
hwdev.ecdhDecode(ecdh_info, sk, rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG || rv.type == RCTTypeBulletproofPlus);
|
||||
hwdev.ecdhDecode(ecdh_info, sk, rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG || rv.type == RCTTypeBulletproofPlus || rv.type == RCTTypeFullProofs);
|
||||
mask = ecdh_info.mask;
|
||||
key amount = ecdh_info.amount;
|
||||
key C = rv.outPk[i].mask;
|
||||
@@ -1636,14 +1752,14 @@ namespace rct {
|
||||
}
|
||||
|
||||
xmr_amount decodeRctSimple(const rctSig & rv, const key & sk, unsigned int i, key &mask, hw::device &hwdev) {
|
||||
CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple || rv.type == RCTTypeBulletproof || rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG || rv.type == RCTTypeBulletproofPlus,
|
||||
CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple || rv.type == RCTTypeBulletproof || rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG || rv.type == RCTTypeBulletproofPlus || rv.type == RCTTypeFullProofs,
|
||||
false, "decodeRct called on non simple rctSig");
|
||||
CHECK_AND_ASSERT_THROW_MES(i < rv.ecdhInfo.size(), "Bad index");
|
||||
CHECK_AND_ASSERT_THROW_MES(rv.outPk.size() == rv.ecdhInfo.size(), "Mismatched sizes of rv.outPk and rv.ecdhInfo");
|
||||
|
||||
//mask amount and mask
|
||||
ecdhTuple ecdh_info = rv.ecdhInfo[i];
|
||||
hwdev.ecdhDecode(ecdh_info, sk, rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG || rv.type == RCTTypeBulletproofPlus);
|
||||
hwdev.ecdhDecode(ecdh_info, sk, rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG || rv.type == RCTTypeBulletproofPlus || rv.type == RCTTypeFullProofs);
|
||||
mask = ecdh_info.mask;
|
||||
key amount = ecdh_info.amount;
|
||||
key C = rv.outPk[i].mask;
|
||||
|
||||
+14
-2
@@ -85,6 +85,12 @@ namespace rct {
|
||||
clsag proveRctCLSAGSimple(const key &, const ctkeyV &, const ctkey &, const key &, const key &, unsigned int, hw::device &);
|
||||
bool verRctCLSAGSimple(const key &, const clsag &, const ctkeyV &, const key &);
|
||||
|
||||
zk_proof PRProof_Gen(const rct::key &difference);
|
||||
bool PRProof_Ver(const rct::key &C, const zk_proof &proof);
|
||||
|
||||
zk_proof SAProof_Gen(const key &P, const key &x_change, const key &key_yF);
|
||||
bool SAProof_Ver(const zk_proof &proof, const key &P, const key &key_yF);
|
||||
|
||||
//proveRange and verRange
|
||||
//proveRange gives C, and mask such that \sumCi = C
|
||||
// c.f. https://eprint.iacr.org/2015/1098 section 5.1
|
||||
@@ -142,7 +148,10 @@ namespace rct {
|
||||
xmr_amount txnFee,
|
||||
unsigned int mixin,
|
||||
const RCTConfig &rct_config,
|
||||
hw::device &hwdev
|
||||
hw::device &hwdev,
|
||||
const key &x_change = rct::zero(),
|
||||
const size_t change_index = 0,
|
||||
const key &key_yF = rct::zero()
|
||||
);
|
||||
rctSig genRctSimple(
|
||||
const key & message,
|
||||
@@ -159,7 +168,10 @@ namespace rct {
|
||||
const std::vector<unsigned int> & index,
|
||||
ctkeyV &outSk,
|
||||
const RCTConfig &rct_config,
|
||||
hw::device &hwdev
|
||||
hw::device &hwdev,
|
||||
const key &x_change = rct::zero(),
|
||||
const size_t change_index = 0,
|
||||
const key &key_yF = rct::zero()
|
||||
);
|
||||
bool verRct(const rctSig & rv, bool semantics);
|
||||
static inline bool verRct(const rctSig & rv) { return verRct(rv, true) && verRct(rv, false); }
|
||||
|
||||
@@ -197,6 +197,7 @@ namespace rct {
|
||||
case RCTTypeBulletproof2:
|
||||
case RCTTypeCLSAG:
|
||||
case RCTTypeBulletproofPlus:
|
||||
case RCTTypeFullProofs:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@@ -221,6 +222,7 @@ namespace rct {
|
||||
switch (type)
|
||||
{
|
||||
case RCTTypeBulletproofPlus:
|
||||
case RCTTypeFullProofs:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@@ -245,6 +247,7 @@ namespace rct {
|
||||
{
|
||||
case RCTTypeCLSAG:
|
||||
case RCTTypeBulletproofPlus:
|
||||
case RCTTypeFullProofs:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
||||
+36
-9
@@ -90,6 +90,18 @@ namespace rct {
|
||||
typedef std::vector<key> keyV; //vector of keys
|
||||
typedef std::vector<keyV> keyM; //matrix of keys (indexed by column first)
|
||||
|
||||
struct zk_proof {
|
||||
key R; // Commitment
|
||||
key z1; // Response
|
||||
key z2; // Response
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(R)
|
||||
FIELD(z1)
|
||||
FIELD(z2)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
//containers For CT operations
|
||||
//if it's representing a private ctkey then "dest" contains the secret key of the address
|
||||
// while "mask" contains a where C = aG + bH is CT pedersen commitment and b is the amount
|
||||
@@ -304,6 +316,7 @@ namespace rct {
|
||||
RCTTypeBulletproof2 = 4,
|
||||
RCTTypeCLSAG = 5,
|
||||
RCTTypeBulletproofPlus = 6,
|
||||
RCTTypeFullProofs = 7
|
||||
};
|
||||
enum RangeProofType { RangeProofBorromean, RangeProofBulletproof, RangeProofMultiOutputBulletproof, RangeProofPaddedBulletproof };
|
||||
struct RCTConfig {
|
||||
@@ -326,9 +339,11 @@ namespace rct {
|
||||
ctkeyV outPk;
|
||||
xmr_amount txnFee; // contains b
|
||||
key p_r;
|
||||
zk_proof pr_proof; // p_r
|
||||
zk_proof sa_proof; // spend authority proof
|
||||
|
||||
rctSigBase() :
|
||||
type(RCTTypeNull), message{}, mixRing{}, pseudoOuts{}, ecdhInfo{}, outPk{}, txnFee(0)
|
||||
type(RCTTypeNull), message{}, mixRing{}, pseudoOuts{}, ecdhInfo{}, outPk{}, txnFee(0), p_r{}, pr_proof{}, sa_proof{}
|
||||
{}
|
||||
|
||||
template<bool W, template <bool> class Archive>
|
||||
@@ -337,7 +352,7 @@ namespace rct {
|
||||
FIELD(type)
|
||||
if (type == RCTTypeNull)
|
||||
return ar.good();
|
||||
if (type != RCTTypeFull && type != RCTTypeSimple && type != RCTTypeBulletproof && type != RCTTypeBulletproof2 && type != RCTTypeCLSAG && type != RCTTypeBulletproofPlus)
|
||||
if (type != RCTTypeFull && type != RCTTypeSimple && type != RCTTypeBulletproof && type != RCTTypeBulletproof2 && type != RCTTypeCLSAG && type != RCTTypeBulletproofPlus && type != RCTTypeFullProofs)
|
||||
return false;
|
||||
VARINT_FIELD(txnFee)
|
||||
// inputs/outputs not saved, only here for serialization help
|
||||
@@ -366,7 +381,7 @@ namespace rct {
|
||||
return false;
|
||||
for (size_t i = 0; i < outputs; ++i)
|
||||
{
|
||||
if (type == RCTTypeBulletproof2 || type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus)
|
||||
if (type == RCTTypeBulletproof2 || type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus || type == RCTTypeFullProofs)
|
||||
{
|
||||
// Since RCTTypeBulletproof2 enote types, we don't serialize the blinding factor, and only serialize the
|
||||
// first 8 bytes of ecdhInfo[i].amount
|
||||
@@ -403,6 +418,11 @@ namespace rct {
|
||||
}
|
||||
ar.end_array();
|
||||
FIELD(p_r)
|
||||
if (type == RCTTypeFullProofs)
|
||||
{
|
||||
FIELD(pr_proof)
|
||||
FIELD(sa_proof)
|
||||
}
|
||||
return ar.good();
|
||||
}
|
||||
|
||||
@@ -415,6 +435,10 @@ namespace rct {
|
||||
FIELD(outPk)
|
||||
VARINT_FIELD(txnFee)
|
||||
FIELD(p_r)
|
||||
if (type == RCTTypeFullProofs) {
|
||||
FIELD(pr_proof)
|
||||
FIELD(sa_proof)
|
||||
}
|
||||
END_SERIALIZE()
|
||||
};
|
||||
struct rctSigPrunable {
|
||||
@@ -437,9 +461,9 @@ namespace rct {
|
||||
return false;
|
||||
if (type == RCTTypeNull)
|
||||
return ar.good();
|
||||
if (type != RCTTypeFull && type != RCTTypeSimple && type != RCTTypeBulletproof && type != RCTTypeBulletproof2 && type != RCTTypeCLSAG && type != RCTTypeBulletproofPlus)
|
||||
if (type != RCTTypeFull && type != RCTTypeSimple && type != RCTTypeBulletproof && type != RCTTypeBulletproof2 && type != RCTTypeCLSAG && type != RCTTypeBulletproofPlus && type != RCTTypeFullProofs)
|
||||
return false;
|
||||
if (type == RCTTypeBulletproofPlus)
|
||||
if (type == RCTTypeBulletproofPlus || type == RCTTypeFullProofs)
|
||||
{
|
||||
uint32_t nbp = bulletproofs_plus.size();
|
||||
VARINT_FIELD(nbp)
|
||||
@@ -496,7 +520,7 @@ namespace rct {
|
||||
ar.end_array();
|
||||
}
|
||||
|
||||
if (type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus)
|
||||
if (type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus || type == RCTTypeFullProofs)
|
||||
{
|
||||
ar.tag("CLSAGs");
|
||||
ar.begin_array();
|
||||
@@ -587,7 +611,7 @@ namespace rct {
|
||||
}
|
||||
ar.end_array();
|
||||
}
|
||||
if (type == RCTTypeBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus)
|
||||
if (type == RCTTypeBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus || type == RCTTypeFullProofs)
|
||||
{
|
||||
ar.tag("pseudoOuts");
|
||||
ar.begin_array();
|
||||
@@ -619,12 +643,12 @@ namespace rct {
|
||||
|
||||
keyV& get_pseudo_outs()
|
||||
{
|
||||
return type == RCTTypeBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus ? p.pseudoOuts : pseudoOuts;
|
||||
return type == RCTTypeBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus || type == RCTTypeFullProofs ? p.pseudoOuts : pseudoOuts;
|
||||
}
|
||||
|
||||
keyV const& get_pseudo_outs() const
|
||||
{
|
||||
return type == RCTTypeBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus ? p.pseudoOuts : pseudoOuts;
|
||||
return type == RCTTypeBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus || type == RCTTypeFullProofs ? p.pseudoOuts : pseudoOuts;
|
||||
}
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
@@ -795,6 +819,7 @@ VARIANT_TAG(debug_archive, rct::multisig_kLRki, "rct::multisig_kLRki");
|
||||
VARIANT_TAG(debug_archive, rct::multisig_out, "rct::multisig_out");
|
||||
VARIANT_TAG(debug_archive, rct::clsag, "rct::clsag");
|
||||
VARIANT_TAG(debug_archive, rct::BulletproofPlus, "rct::bulletproof_plus");
|
||||
VARIANT_TAG(debug_archive, rct::zk_proof, "rct::zk_proof");
|
||||
|
||||
VARIANT_TAG(binary_archive, rct::key, 0x90);
|
||||
VARIANT_TAG(binary_archive, rct::key64, 0x91);
|
||||
@@ -813,6 +838,7 @@ VARIANT_TAG(binary_archive, rct::multisig_kLRki, 0x9d);
|
||||
VARIANT_TAG(binary_archive, rct::multisig_out, 0x9e);
|
||||
VARIANT_TAG(binary_archive, rct::clsag, 0x9f);
|
||||
VARIANT_TAG(binary_archive, rct::BulletproofPlus, 0xa0);
|
||||
VARIANT_TAG(binary_archive, rct::zk_proof, 0xa1);
|
||||
|
||||
VARIANT_TAG(json_archive, rct::key, "rct_key");
|
||||
VARIANT_TAG(json_archive, rct::key64, "rct_key64");
|
||||
@@ -831,5 +857,6 @@ VARIANT_TAG(json_archive, rct::multisig_kLRki, "rct_multisig_kLR");
|
||||
VARIANT_TAG(json_archive, rct::multisig_out, "rct_multisig_out");
|
||||
VARIANT_TAG(json_archive, rct::clsag, "rct_clsag");
|
||||
VARIANT_TAG(json_archive, rct::BulletproofPlus, "rct_bulletproof_plus");
|
||||
VARIANT_TAG(json_archive, rct::zk_proof, "rct_zk_proof");
|
||||
|
||||
#endif /* RCTTYPES_H */
|
||||
|
||||
@@ -1173,6 +1173,10 @@ void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::rctSig&
|
||||
INSERT_INTO_JSON_OBJECT(dest, commitments, transform(sig.outPk, just_mask));
|
||||
INSERT_INTO_JSON_OBJECT(dest, fee, sig.txnFee);
|
||||
INSERT_INTO_JSON_OBJECT(dest, p_r, sig.p_r);
|
||||
if (sig.type == rct::RCTTypeFullProofs) {
|
||||
INSERT_INTO_JSON_OBJECT(dest, pr_proof, sig.pr_proof);
|
||||
INSERT_INTO_JSON_OBJECT(dest, sa_proof, sig.sa_proof);
|
||||
}
|
||||
}
|
||||
|
||||
// prunable
|
||||
@@ -1210,6 +1214,10 @@ void fromJsonValue(const rapidjson::Value& val, rct::rctSig& sig)
|
||||
GET_FROM_JSON_OBJECT(val, sig.outPk, commitments);
|
||||
GET_FROM_JSON_OBJECT(val, sig.txnFee, fee);
|
||||
GET_FROM_JSON_OBJECT(val, sig.p_r, p_r);
|
||||
if (sig.type == rct::RCTTypeFullProofs) {
|
||||
GET_FROM_JSON_OBJECT(val, sig.pr_proof, pr_proof);
|
||||
GET_FROM_JSON_OBJECT(val, sig.sa_proof, sa_proof);
|
||||
}
|
||||
}
|
||||
|
||||
// prunable
|
||||
@@ -1465,6 +1473,29 @@ void fromJsonValue(const rapidjson::Value& val, rct::clsag& sig)
|
||||
GET_FROM_JSON_OBJECT(val, sig.D, D);
|
||||
}
|
||||
|
||||
void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::zk_proof& proof)
|
||||
{
|
||||
dest.StartObject();
|
||||
|
||||
INSERT_INTO_JSON_OBJECT(dest, R, proof.R);
|
||||
INSERT_INTO_JSON_OBJECT(dest, z1, proof.z1);
|
||||
INSERT_INTO_JSON_OBJECT(dest, z2, proof.z2);
|
||||
|
||||
dest.EndObject();
|
||||
}
|
||||
|
||||
void fromJsonValue(const rapidjson::Value& val, rct::zk_proof& proof)
|
||||
{
|
||||
if (!val.IsObject())
|
||||
{
|
||||
throw WRONG_TYPE("zk_proof (rct::zk_proof)");
|
||||
}
|
||||
|
||||
GET_FROM_JSON_OBJECT(val, proof.R, R);
|
||||
GET_FROM_JSON_OBJECT(val, proof.z1, z1);
|
||||
GET_FROM_JSON_OBJECT(val, proof.z2, z2);
|
||||
}
|
||||
|
||||
void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::DaemonInfo& info)
|
||||
{
|
||||
dest.StartObject();
|
||||
|
||||
@@ -307,6 +307,9 @@ void fromJsonValue(const rapidjson::Value& val, rct::mgSig& sig);
|
||||
void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::clsag& sig);
|
||||
void fromJsonValue(const rapidjson::Value& val, rct::clsag& sig);
|
||||
|
||||
void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::zk_proof& p);
|
||||
void fromJsonValue(const rapidjson::Value& val, rct::zk_proof& p);
|
||||
|
||||
void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::DaemonInfo& info);
|
||||
void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::DaemonInfo& info);
|
||||
|
||||
|
||||
@@ -1999,7 +1999,7 @@ bool simple_wallet::rpc_payment_info(const std::vector<std::string> &args)
|
||||
crypto::public_key pkey;
|
||||
crypto::secret_key_to_public_key(m_wallet->get_rpc_client_secret_key(), pkey);
|
||||
message_writer() << tr("RPC client ID: ") << pkey;
|
||||
message_writer() << tr("RPC client secret key: ") << m_wallet->get_rpc_client_secret_key();
|
||||
message_writer() << tr("RPC client secret key: ") << crypto::secret_key_explicit_print_ref{m_wallet->get_rpc_client_secret_key()};
|
||||
if (!m_wallet->get_rpc_payment_info(false, payment_required, credits, diff, credits_per_hash_found, hashing_blob, height, seed_height, seed_hash, next_seed_hash, cookie))
|
||||
{
|
||||
fail_msg_writer() << tr("Failed to query daemon");
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
#define DEF_SALVIUM_VERSION_TAG "@VERSIONTAG@"
|
||||
#define DEF_SALVIUM_VERSION "0.6.2"
|
||||
#define DEF_SALVIUM_VERSION "0.7.2"
|
||||
#define DEF_MONERO_VERSION_TAG "release"
|
||||
#define DEF_MONERO_VERSION "0.18.3.3"
|
||||
#define DEF_MONERO_RELEASE_NAME "Zero"
|
||||
|
||||
+139
-29
@@ -881,6 +881,11 @@ uint8_t get_view_tag_fork()
|
||||
return HF_VERSION_VIEW_TAGS;
|
||||
}
|
||||
|
||||
uint8_t get_full_proofs_fork()
|
||||
{
|
||||
return HF_VERSION_FULL_PROOFS;
|
||||
}
|
||||
|
||||
uint64_t calculate_fee(bool use_per_byte_fee, const cryptonote::transaction &tx, size_t blob_size, uint64_t base_fee, uint64_t fee_quantization_mask)
|
||||
{
|
||||
if (use_per_byte_fee)
|
||||
@@ -2142,6 +2147,7 @@ static uint64_t decodeRct(const rct::rctSig & rv, const crypto::key_derivation &
|
||||
case rct::RCTTypeBulletproof2:
|
||||
case rct::RCTTypeCLSAG:
|
||||
case rct::RCTTypeBulletproofPlus:
|
||||
case rct::RCTTypeFullProofs:
|
||||
return rct::decodeRctSimple(rv, rct::sk2rct(scalar1), i, mask, hwdev);
|
||||
case rct::RCTTypeFull:
|
||||
return rct::decodeRct(rv, rct::sk2rct(scalar1), i, mask, hwdev);
|
||||
@@ -2236,7 +2242,7 @@ void wallet2::scan_output(const cryptonote::transaction &tx, bool miner_tx, cons
|
||||
*/
|
||||
// Populate the unlock_time
|
||||
THROW_WALLET_EXCEPTION_IF(!cryptonote::get_output_unlock_time(tx.vout[i], tx_scan_info.unlock_time), error::wallet_internal_error, "failed to get output unlock_time");
|
||||
|
||||
|
||||
outs.push_back(i);
|
||||
THROW_WALLET_EXCEPTION_IF(tx_money_got_in_outs[tx_scan_info.received->index][tx_scan_info.asset_type] >= std::numeric_limits<uint64_t>::max() - tx_scan_info.money_transfered,
|
||||
error::wallet_internal_error, "Overflow in received amounts");
|
||||
@@ -2475,6 +2481,77 @@ bool wallet2::get_yield_summary_info(uint64_t &total_burnt,
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::verify_spend_authority_proof(const cryptonote::transaction &tx, const size_t i, const tx_scan_info_t &tx_scan_info)
|
||||
{
|
||||
// Sanity checks
|
||||
if (tx.type != cryptonote::transaction_type::TRANSFER) return true;
|
||||
if (tx.version < TRANSACTION_VERSION_N_OUTS) return true;
|
||||
if (tx.rct_signatures.type != rct::RCTTypeFullProofs) return true;
|
||||
|
||||
// To verify the spend authority proof, we need to know the y value to process the F value
|
||||
ec_scalar y;
|
||||
|
||||
// Get P_change from the TX
|
||||
crypto::public_key P_change = crypto::null_pkey;
|
||||
|
||||
// Calculate z_i (the shared secret between sender and ourselves for the original TX)
|
||||
crypto::public_key txkey_pub = null_pkey; // R
|
||||
const std::vector<crypto::public_key> in_additional_tx_pub_keys = get_additional_tx_pub_keys_from_extra(tx);
|
||||
if (in_additional_tx_pub_keys.size() != 0) {
|
||||
THROW_WALLET_EXCEPTION_IF(in_additional_tx_pub_keys.size() != tx.vout.size(),
|
||||
error::wallet_internal_error,
|
||||
tr("at verify_spend_authority_proof(): incorrect number of additional TX pubkeys in TX"));
|
||||
txkey_pub = in_additional_tx_pub_keys[i];
|
||||
} else {
|
||||
txkey_pub = get_tx_pub_key_from_extra(tx);
|
||||
}
|
||||
crypto::key_derivation derivation = AUTO_VAL_INIT(derivation);
|
||||
THROW_WALLET_EXCEPTION_IF(!generate_key_derivation(txkey_pub, m_account.get_keys().m_view_secret_key, derivation),
|
||||
error::wallet_internal_error,
|
||||
tr("at verify_spend_authority_proof(): failed to generate_key_derivation"));
|
||||
crypto::secret_key z_i;
|
||||
derivation_to_scalar(derivation, i, z_i);
|
||||
|
||||
// Calculate the y value for return_payment support
|
||||
struct {
|
||||
char domain_separator[8];
|
||||
rct::key amount_key;
|
||||
} buf;
|
||||
std::memset(buf.domain_separator, 0x0, sizeof(buf.domain_separator));
|
||||
std::strncpy(buf.domain_separator, "RETURN", 7);
|
||||
buf.amount_key = rct::sk2rct(z_i);
|
||||
crypto::hash_to_scalar(&buf, sizeof(buf), y);
|
||||
|
||||
// The change_index needs decoding too
|
||||
uint8_t eci_data = tx.return_address_change_mask[i];
|
||||
|
||||
// Calculate the encrypted_change_index data for this output
|
||||
std::memset(buf.domain_separator, 0x0, sizeof(buf.domain_separator));
|
||||
std::strncpy(buf.domain_separator, "CHG_IDX", 8);
|
||||
crypto::secret_key eci_out;
|
||||
keccak((uint8_t *)&buf, sizeof(buf), (uint8_t*)&eci_out, sizeof(eci_out));
|
||||
uint8_t change_index = eci_data ^ eci_out.data[0];
|
||||
THROW_WALLET_EXCEPTION_IF(change_index >= tx.vout.size(), error::wallet_internal_error, tr("at verify_spend_authority_proof(): invalid change_index calculated"));
|
||||
|
||||
// Now we know the index, we can get P_change
|
||||
THROW_WALLET_EXCEPTION_IF(!cryptonote::get_output_public_key(tx.vout[change_index], P_change), error::wallet_internal_error, tr("at verify_spend_authority_proof(): failed to get P_change"));
|
||||
rct::key key_P_change = rct::pk2rct(P_change);
|
||||
|
||||
// Calculate the shared secret yF
|
||||
rct::key key_y = (rct::key&)(y);
|
||||
rct::key key_F = (rct::key&)(tx.return_address_list[i]);
|
||||
rct::key key_yF = rct::scalarmultKey(key_F, key_y);
|
||||
rct::key hs_yF = rct::hash_to_scalar(key_yF);
|
||||
|
||||
// Now we can verify the proof itself
|
||||
if (!rct::SAProof_Ver(tx.rct_signatures.sa_proof, key_P_change, hs_yF)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Return success to caller
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote::transaction& tx, const std::vector<uint64_t> &o_indices, const std::vector<uint64_t> &asset_type_output_indices, uint64_t height, uint8_t block_version, uint64_t ts, bool miner_tx, bool pool, bool double_spend_seen, const tx_cache_data &tx_cache_data, std::map<std::pair<uint64_t, uint64_t>, size_t> *output_tracker_cache, bool ignore_callbacks)
|
||||
{
|
||||
PERF_TIMER(process_new_transaction);
|
||||
@@ -2778,6 +2855,17 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
|
||||
if (m_multisig_rescan_info && m_multisig_rescan_info->front().size() >= m_transfers.size())
|
||||
update_multisig_rescan_info(*m_multisig_rescan_k, *m_multisig_rescan_info, m_transfers.size() - 1);
|
||||
}
|
||||
|
||||
/*
|
||||
// Verify the spend authority proof
|
||||
if (!verify_spend_authority_proof(tx, o, tx_scan_info[o])) {
|
||||
// Freeze the output
|
||||
LOG_ERROR("Spend authority proof for TX: " << txid << " failed verification. The output has been frozen.");
|
||||
LOG_ERROR("Please review the transaction and verify that the sender is someone you trust before thawing this payment.");
|
||||
td.m_frozen = true;
|
||||
}
|
||||
*/
|
||||
|
||||
LOG_PRINT_L0("Received money: " << print_money(td.amount()) << ", with tx: " << txid);
|
||||
if (!ignore_callbacks && 0 != m_callback)
|
||||
m_callback->on_money_received(height, txid, tx, td.m_amount, td.asset_type, 0, td.m_subaddr_index, spends_one_of_ours(tx), td.m_tx.unlock_time, td.m_td_origin_idx);
|
||||
@@ -2894,6 +2982,16 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
|
||||
}
|
||||
THROW_WALLET_EXCEPTION_IF(td.get_public_key() != tx_scan_info[o].in_ephemeral.pub, error::wallet_internal_error, "Inconsistent public keys");
|
||||
THROW_WALLET_EXCEPTION_IF(td.m_spent, error::wallet_internal_error, "Inconsistent spent status");
|
||||
|
||||
/*
|
||||
// Verify the spend authority proof
|
||||
if (!verify_spend_authority_proof(tx, o, tx_scan_info[o])) {
|
||||
// Freeze the output
|
||||
LOG_ERROR("Spend authority proof for TX: " << txid << " failed verification. The output has been frozen.");
|
||||
LOG_ERROR("Please review the transaction and verify that the sender is someone you trust before thawing this payment.");
|
||||
td.m_frozen = true;
|
||||
}
|
||||
*/
|
||||
|
||||
LOG_PRINT_L0("Received money: " << print_money(td.amount()) << ", with tx: " << txid);
|
||||
if (!ignore_callbacks && 0 != m_callback)
|
||||
@@ -10258,11 +10356,11 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
|
||||
ptx.construction_data.extra = tx.extra;
|
||||
ptx.construction_data.unlock_time = unlock_time;
|
||||
ptx.construction_data.use_rct = true;
|
||||
ptx.construction_data.rct_config = {
|
||||
ptx.construction_data.rct_config = rct_config;/*{
|
||||
rct::RangeProofPaddedBulletproof,
|
||||
use_fork_rules(HF_VERSION_BULLETPROOF_PLUS, -10) ? 4 : 3
|
||||
};
|
||||
ptx.construction_data.use_view_tags = use_fork_rules(get_view_tag_fork(), 0);
|
||||
};*/
|
||||
ptx.construction_data.use_view_tags = use_view_tags;//use_fork_rules(get_view_tag_fork(), 0);
|
||||
ptx.construction_data.dests = dsts;
|
||||
// record which subaddress indices are being used as inputs
|
||||
ptx.construction_data.subaddr_account = subaddr_account;
|
||||
@@ -10553,7 +10651,8 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
||||
const bool bulletproof = true;
|
||||
const bool bulletproof_plus = true;
|
||||
const bool clsag = true;
|
||||
const rct::RCTConfig rct_config { rct::RangeProofPaddedBulletproof, 4 };
|
||||
const bool use_fullproofs = use_fork_rules(get_full_proofs_fork(), 0);
|
||||
const rct::RCTConfig rct_config { rct::RangeProofPaddedBulletproof, use_fullproofs ? 5 : 4 };
|
||||
const bool use_view_tags = use_fork_rules(get_view_tag_fork(), 0);
|
||||
std::unordered_set<crypto::public_key> valid_public_keys_cache;
|
||||
|
||||
@@ -11251,7 +11350,8 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_all(uint64_t below
|
||||
const bool bulletproof = true;
|
||||
const bool bulletproof_plus = true;
|
||||
const bool clsag = true;
|
||||
const rct::RCTConfig rct_config { rct::RangeProofPaddedBulletproof, 4 };
|
||||
const bool use_fullproofs = use_fork_rules(get_full_proofs_fork(), 0);
|
||||
const rct::RCTConfig rct_config { rct::RangeProofPaddedBulletproof, use_fullproofs ? 5 : 4 };
|
||||
const bool use_view_tags = use_fork_rules(get_view_tag_fork(), 0);
|
||||
const uint64_t base_fee = get_base_fee(priority);
|
||||
const size_t tx_weight_one_ring = estimate_tx_weight(use_rct, 1, fake_outs_count, 2, 0, bulletproof, clsag, bulletproof_plus, use_view_tags);
|
||||
@@ -11363,8 +11463,8 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_return(std::vector
|
||||
crypto::public_key P_change = crypto::null_pkey;
|
||||
uint8_t change_index;
|
||||
uint32_t hf_version = get_current_hard_fork();
|
||||
if (hf_version >= HF_VERSION_ENABLE_N_OUTS && td_origin.m_tx.version >= TRANSACTION_VERSION_N_OUTS) {
|
||||
|
||||
if (td_origin.m_tx.version >= TRANSACTION_VERSION_N_OUTS) {
|
||||
|
||||
// Calculate z_i (the shared secret between sender and ourselves for the original TX)
|
||||
crypto::public_key txkey_pub = null_pkey; // R
|
||||
const std::vector<crypto::public_key> in_additional_tx_pub_keys = get_additional_tx_pub_keys_from_extra(td_origin.m_tx);
|
||||
@@ -11392,21 +11492,43 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_return(std::vector
|
||||
std::strncpy(buf.domain_separator, "RETURN", 7);
|
||||
buf.amount_key = rct::sk2rct(z_i);
|
||||
crypto::hash_to_scalar(&buf, sizeof(buf), y);
|
||||
|
||||
|
||||
// The change_index needs decoding too
|
||||
uint8_t eci_data = td_origin.m_tx.return_address_change_mask[td_origin.m_internal_output_index];
|
||||
|
||||
|
||||
// Calculate the encrypted_change_index data for this output
|
||||
std::memset(buf.domain_separator, 0x0, sizeof(buf.domain_separator));
|
||||
std::strncpy(buf.domain_separator, "CHG_IDX", 8);
|
||||
crypto::secret_key eci_out;
|
||||
keccak((uint8_t *)&buf, sizeof(buf), (uint8_t*)&eci_out, sizeof(eci_out));
|
||||
change_index = eci_data ^ eci_out.data[0];
|
||||
|
||||
|
||||
return_address = td_origin.m_tx.return_address_list[td_origin.m_internal_output_index];
|
||||
|
||||
} else {
|
||||
// Sanity check that we aren't attempting to return our own TX change output to ourselves
|
||||
THROW_WALLET_EXCEPTION_IF(change_index == td_origin.m_internal_output_index, error::wallet_internal_error, tr("Attempting to return change to ourself"));
|
||||
|
||||
// Sanity check that we can obtain the change output from the origin TX
|
||||
THROW_WALLET_EXCEPTION_IF(!cryptonote::get_output_public_key(td_origin.m_tx.vout[change_index], P_change),
|
||||
error::wallet_internal_error,
|
||||
tr("Failed to identify change output"));
|
||||
|
||||
} else {
|
||||
|
||||
// Change index is the one we didn't receive
|
||||
change_index = (td_origin.m_internal_output_index == 0) ? 1 : 0;
|
||||
|
||||
// Return address was provided
|
||||
return_address = td_origin.m_tx.return_address;
|
||||
|
||||
// Sanity check that we aren't attempting to return our own TX change output to ourselves
|
||||
THROW_WALLET_EXCEPTION_IF(change_index == td_origin.m_internal_output_index, error::wallet_internal_error, tr("Attempting to return change to ourself"));
|
||||
|
||||
// Sanity check that we can obtain the change output from the origin TX
|
||||
THROW_WALLET_EXCEPTION_IF(!cryptonote::get_output_public_key(td_origin.m_tx.vout[change_index], P_change),
|
||||
error::wallet_internal_error,
|
||||
tr("Failed to identify change output"));
|
||||
|
||||
// Calculate y
|
||||
struct {
|
||||
char domain_separator[8];
|
||||
@@ -11416,21 +11538,8 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_return(std::vector
|
||||
std::strncpy(buf.domain_separator, "RETURN", 6);
|
||||
buf.pubkey = P_change;
|
||||
crypto::hash_to_scalar(&buf, sizeof(buf), y);
|
||||
|
||||
// Change index is the one we didn't receive
|
||||
change_index = (td_origin.m_internal_output_index == 0) ? 1 : 0;
|
||||
|
||||
return_address = td_origin.m_tx.return_address;
|
||||
}
|
||||
|
||||
// Sanity check that we aren't attempting to return our own TX change output to ourselves
|
||||
THROW_WALLET_EXCEPTION_IF(change_index == td_origin.m_internal_output_index, error::wallet_internal_error, tr("Attempting to return change to ourself"));
|
||||
|
||||
// Sanity check that we can obtain the change output from the origin TX
|
||||
THROW_WALLET_EXCEPTION_IF(!cryptonote::get_output_public_key(td_origin.m_tx.vout[change_index], P_change),
|
||||
error::wallet_internal_error,
|
||||
tr("Failed to identify change output"));
|
||||
|
||||
// Calculate yF
|
||||
rct::key key_y = (rct::key&)(y);
|
||||
rct::key key_F = (rct::key&)(return_address);
|
||||
@@ -11443,7 +11552,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_return(std::vector
|
||||
|
||||
LOG_ERROR("*****************************************************************************");
|
||||
LOG_ERROR("TX type : RETURN");
|
||||
LOG_ERROR("a : " << m_account.get_keys().m_view_secret_key);
|
||||
LOG_ERROR("a : " << crypto::secret_key_explicit_print_ref{m_account.get_keys().m_view_secret_key});
|
||||
LOG_ERROR("F : " << key_F);
|
||||
LOG_ERROR("y : " << key_y);
|
||||
LOG_ERROR("P_change : " << P_change);
|
||||
@@ -11484,7 +11593,8 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
|
||||
const bool bulletproof = true;
|
||||
const bool bulletproof_plus = true;
|
||||
const bool clsag = true;
|
||||
const rct::RCTConfig rct_config { rct::RangeProofPaddedBulletproof, 4 };
|
||||
const bool use_fullproofs = use_fork_rules(get_full_proofs_fork(), 0);
|
||||
const rct::RCTConfig rct_config { rct::RangeProofPaddedBulletproof, use_fullproofs ? 5 : 4 };
|
||||
const bool use_view_tags = use_fork_rules(get_view_tag_fork(), 0);
|
||||
const uint64_t base_fee = get_base_fee(priority);
|
||||
const uint64_t fee_quantization_mask = get_fee_quantization_mask();
|
||||
@@ -12405,7 +12515,7 @@ void wallet2::check_tx_key_helper(const cryptonote::transaction &tx, const crypt
|
||||
crypto::secret_key scalar1;
|
||||
crypto::derivation_to_scalar(found_derivation, n, scalar1);
|
||||
rct::ecdhTuple ecdh_info = tx.rct_signatures.ecdhInfo[n];
|
||||
rct::ecdhDecode(ecdh_info, rct::sk2rct(scalar1), tx.rct_signatures.type == rct::RCTTypeBulletproof2 || tx.rct_signatures.type == rct::RCTTypeCLSAG || tx.rct_signatures.type == rct::RCTTypeBulletproofPlus);
|
||||
rct::ecdhDecode(ecdh_info, rct::sk2rct(scalar1), tx.rct_signatures.type == rct::RCTTypeBulletproof2 || tx.rct_signatures.type == rct::RCTTypeCLSAG || tx.rct_signatures.type == rct::RCTTypeBulletproofPlus || tx.rct_signatures.type == rct::RCTTypeFullProofs);
|
||||
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");
|
||||
@@ -13099,7 +13209,7 @@ bool wallet2::check_reserve_proof(const cryptonote::account_public_address &addr
|
||||
crypto::secret_key shared_secret;
|
||||
crypto::derivation_to_scalar(derivation, proof.index_in_tx, shared_secret);
|
||||
rct::ecdhTuple ecdh_info = tx.rct_signatures.ecdhInfo[proof.index_in_tx];
|
||||
rct::ecdhDecode(ecdh_info, rct::sk2rct(shared_secret), tx.rct_signatures.type == rct::RCTTypeBulletproof2 || tx.rct_signatures.type == rct::RCTTypeCLSAG || tx.rct_signatures.type == rct::RCTTypeBulletproofPlus);
|
||||
rct::ecdhDecode(ecdh_info, rct::sk2rct(shared_secret), tx.rct_signatures.type == rct::RCTTypeBulletproof2 || tx.rct_signatures.type == rct::RCTTypeCLSAG || tx.rct_signatures.type == rct::RCTTypeBulletproofPlus || tx.rct_signatures.type == rct::RCTTypeFullProofs);
|
||||
amount = rct::h2d(ecdh_info.amount);
|
||||
}
|
||||
total += amount;
|
||||
|
||||
@@ -1191,6 +1191,8 @@ private:
|
||||
|
||||
std::vector<cryptonote::public_node> get_public_nodes(bool white_only = true);
|
||||
|
||||
bool verify_spend_authority_proof(const cryptonote::transaction &tx, const size_t i, const tx_scan_info_t &tx_scan_info);
|
||||
|
||||
template <class t_archive>
|
||||
inline void serialize(t_archive &a, const unsigned int ver)
|
||||
{
|
||||
|
||||
@@ -67,6 +67,10 @@ public:
|
||||
, uint64_t num_rct_outs
|
||||
, oracle::asset_type_counts& cum_rct_by_asset_type
|
||||
, const crypto::hash& blk_hash
|
||||
, uint64_t slippage_total
|
||||
, uint64_t yield_total
|
||||
, const cryptonote::network_type nettype
|
||||
, cryptonote::yield_block_info& ybi
|
||||
) override {
|
||||
blocks.push_back({block_weight, long_term_block_weight});
|
||||
}
|
||||
@@ -111,9 +115,6 @@ private:
|
||||
}
|
||||
|
||||
#define PREFIX_WINDOW(hf_version,window) \
|
||||
std::unique_ptr<cryptonote::Blockchain> bc; \
|
||||
cryptonote::tx_memory_pool txpool(*bc); \
|
||||
bc.reset(new cryptonote::Blockchain(txpool)); \
|
||||
struct get_test_options { \
|
||||
const std::pair<uint8_t, uint64_t> hard_forks[3]; \
|
||||
const cryptonote::test_options test_options = { \
|
||||
@@ -122,7 +123,9 @@ private:
|
||||
}; \
|
||||
get_test_options(): hard_forks{std::make_pair(1, (uint64_t)0), std::make_pair((uint8_t)hf_version, (uint64_t)LONG_TERM_BLOCK_WEIGHT_WINDOW), std::make_pair((uint8_t)0, (uint64_t)0)} {} \
|
||||
} opts; \
|
||||
cryptonote::Blockchain *blockchain = bc.get(); \
|
||||
cryptonote::BlockchainAndPool bap; \
|
||||
cryptonote::Blockchain *blockchain = &bap.blockchain; \
|
||||
cryptonote::Blockchain *bc = blockchain; \
|
||||
bool r = blockchain->init(new TestDB(), cryptonote::FAKECHAIN, true, &opts.test_options, 0, NULL); \
|
||||
if (!r) \
|
||||
{ \
|
||||
@@ -149,7 +152,8 @@ static void test(test_t t, uint64_t blocks)
|
||||
cryptonote::block b;
|
||||
b.major_version = 1;
|
||||
b.minor_version = 1;
|
||||
bc->get_db().add_block(std::make_pair(b, ""), 300000, 300000, bc->get_db().height(), bc->get_db().height(), {});
|
||||
cryptonote::yield_block_info ybi;
|
||||
bc->get_db().add_block(std::make_pair(b, ""), 300000, 300000, bc->get_db().height(), bc->get_db().height(), {}, cryptonote::FAKECHAIN, ybi);
|
||||
if (!bc->update_next_cumulative_weight_limit())
|
||||
{
|
||||
fprintf(stderr, "Failed to update cumulative weight limit 1\n");
|
||||
@@ -181,9 +185,10 @@ static void test(test_t t, uint64_t blocks)
|
||||
}
|
||||
uint64_t ltw = bc->get_next_long_term_block_weight(w);
|
||||
cryptonote::block b;
|
||||
b.major_version = 10;
|
||||
b.minor_version = 10;
|
||||
bc->get_db().add_block(std::make_pair(std::move(b), ""), w, ltw, bc->get_db().height(), bc->get_db().height(), {});
|
||||
b.major_version = HF_VERSION_2021_SCALING;
|
||||
b.minor_version = HF_VERSION_2021_SCALING;
|
||||
cryptonote::yield_block_info ybi;
|
||||
bc->get_db().add_block(std::make_pair(std::move(b), ""), w, ltw, bc->get_db().height(), bc->get_db().height(), {}, cryptonote::FAKECHAIN, ybi);
|
||||
|
||||
if (!bc->update_next_cumulative_weight_limit())
|
||||
{
|
||||
|
||||
@@ -350,7 +350,7 @@ bool gen_block_miner_tx_has_2_in::generate(std::vector<test_event_entry>& events
|
||||
destinations.push_back(de);
|
||||
|
||||
transaction tmp_tx;
|
||||
if (!construct_tx(miner_account.get_keys(), sources, destinations, 1/*hf_version*/, "FULM", "FULM", cryptonote::transaction_type::TRANSFER, boost::none, std::vector<uint8_t>(), tmp_tx, 0))
|
||||
if (!construct_tx(miner_account.get_keys(), sources, destinations, 1/*hf_version*/, "SAL", cryptonote::transaction_type::TRANSFER, boost::none, std::vector<uint8_t>(), tmp_tx, 0))
|
||||
return false;
|
||||
|
||||
MAKE_MINER_TX_MANUALLY(miner_tx, blk_0);
|
||||
@@ -393,7 +393,7 @@ bool gen_block_miner_tx_with_txin_to_key::generate(std::vector<test_event_entry>
|
||||
destinations.push_back(de);
|
||||
|
||||
transaction tmp_tx;
|
||||
if (!construct_tx(miner_account.get_keys(), sources, destinations, 1/*hf_version*/, "FULM", "FULM", cryptonote::transaction_type::TRANSFER, boost::none, std::vector<uint8_t>(), tmp_tx, 0))
|
||||
if (!construct_tx(miner_account.get_keys(), sources, destinations, 1/*hf_version*/, "SAL", cryptonote::transaction_type::TRANSFER, boost::none, std::vector<uint8_t>(), tmp_tx, 0))
|
||||
return false;
|
||||
|
||||
MAKE_MINER_TX_MANUALLY(miner_tx, blk_1);
|
||||
@@ -687,7 +687,7 @@ bool gen_block_miner_tx_out_has_no_view_tag_before_hf_view_tags::generate(std::v
|
||||
cryptonote::get_output_public_key(miner_tx.vout[0], output_public_key);
|
||||
|
||||
// explicitly call the setter to ensure it does not set a view tag on the miner tx output
|
||||
cryptonote::set_tx_out(miner_tx.vout[0].amount, "FULM", CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, output_public_key, use_view_tags, view_tag, miner_tx.vout[0]);
|
||||
cryptonote::set_tx_out(miner_tx.vout[0].amount, "SAL", CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, output_public_key, use_view_tags, view_tag, miner_tx.vout[0]);
|
||||
CHECK_AND_ASSERT_MES(!cryptonote::get_output_view_tag(miner_tx.vout[0]), false, "output should still not have a view tag");
|
||||
|
||||
block blk_1;
|
||||
@@ -713,7 +713,7 @@ bool gen_block_miner_tx_out_has_no_view_tag_from_hf_view_tags::generate(std::vec
|
||||
cryptonote::get_output_public_key(miner_tx.vout[0], output_public_key);
|
||||
|
||||
// remove the view tag that is currently set on the miner tx output at this point
|
||||
cryptonote::set_tx_out(miner_tx.vout[0].amount, "FULM", CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, output_public_key, use_view_tags, view_tag, miner_tx.vout[0]);
|
||||
cryptonote::set_tx_out(miner_tx.vout[0].amount, "SAL", CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, output_public_key, use_view_tags, view_tag, miner_tx.vout[0]);
|
||||
CHECK_AND_ASSERT_MES(!cryptonote::get_output_view_tag(miner_tx.vout[0]), false, "output should not have a view tag");
|
||||
|
||||
block blk_1;
|
||||
@@ -745,7 +745,7 @@ bool gen_block_miner_tx_out_has_view_tag_before_hf_view_tags::generate(std::vect
|
||||
crypto::derive_view_tag(derivation, 0, view_tag);
|
||||
|
||||
// set the view tag on the miner tx output
|
||||
cryptonote::set_tx_out(miner_tx.vout[0].amount, "FULM", CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, output_public_key, use_view_tags, view_tag, miner_tx.vout[0]);
|
||||
cryptonote::set_tx_out(miner_tx.vout[0].amount, "SAL", CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, output_public_key, use_view_tags, view_tag, miner_tx.vout[0]);
|
||||
boost::optional<crypto::view_tag> actual_vt = cryptonote::get_output_view_tag(miner_tx.vout[0]);
|
||||
CHECK_AND_ASSERT_MES(actual_vt && *actual_vt == view_tag, false, "unexpected output view tag");
|
||||
|
||||
@@ -781,7 +781,7 @@ bool gen_block_miner_tx_out_has_view_tag_from_hf_view_tags::generate(std::vector
|
||||
CHECK_AND_ASSERT_MES(actual_vt && *actual_vt == view_tag, false, "unexpected output view tag");
|
||||
|
||||
// set the view tag on the miner tx output
|
||||
cryptonote::set_tx_out(miner_tx.vout[0].amount, "FULM", CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, output_public_key, use_view_tags, view_tag, miner_tx.vout[0]);
|
||||
cryptonote::set_tx_out(miner_tx.vout[0].amount, "SAL", CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, output_public_key, use_view_tags, view_tag, miner_tx.vout[0]);
|
||||
boost::optional<crypto::view_tag> actual_vt_after_setting = cryptonote::get_output_view_tag(miner_tx.vout[0]);
|
||||
CHECK_AND_ASSERT_MES(actual_vt_after_setting && *actual_vt_after_setting == view_tag, false, "unexpected output view tag after setting");
|
||||
|
||||
|
||||
@@ -81,15 +81,19 @@ namespace
|
||||
public:
|
||||
TestDB() { m_open = true; }
|
||||
|
||||
virtual void add_block( const cryptonote::block& blk
|
||||
, size_t block_weight
|
||||
, uint64_t long_term_block_weight
|
||||
, const cryptonote::difficulty_type& cumulative_difficulty
|
||||
, const uint64_t& coins_generated
|
||||
, uint64_t num_rct_outs
|
||||
, oracle::asset_type_counts& cum_rct_by_asset_type
|
||||
, const crypto::hash& blk_hash
|
||||
) override
|
||||
virtual void add_block( const block& blk,
|
||||
size_t block_weight,
|
||||
uint64_t long_term_block_weight,
|
||||
const difficulty_type& cumulative_difficulty,
|
||||
const uint64_t& coins_generated,
|
||||
uint64_t num_rct_outs,
|
||||
oracle::asset_type_counts& cum_rct_by_asset_type,
|
||||
const crypto::hash& blk_hash,
|
||||
uint64_t slippage_total,
|
||||
uint64_t yield_total,
|
||||
const cryptonote::network_type nettype,
|
||||
cryptonote::yield_block_info& ybi
|
||||
) override
|
||||
{
|
||||
blocks.push_back({blk, blk_hash});
|
||||
}
|
||||
@@ -144,9 +148,8 @@ namespace
|
||||
|
||||
}
|
||||
|
||||
static std::unique_ptr<cryptonote::Blockchain> init_blockchain(const std::vector<test_event_entry> & events, cryptonote::network_type nettype)
|
||||
static std::unique_ptr<cryptonote::BlockchainAndPool> init_blockchain(const std::vector<test_event_entry> & events, cryptonote::network_type nettype)
|
||||
{
|
||||
std::unique_ptr<cryptonote::Blockchain> bc;
|
||||
v_hardforks_t hardforks;
|
||||
cryptonote::test_options test_options_tmp{nullptr, 0};
|
||||
const cryptonote::test_options * test_options = &test_options_tmp;
|
||||
@@ -160,10 +163,8 @@ static std::unique_ptr<cryptonote::Blockchain> init_blockchain(const std::vector
|
||||
test_options_tmp.hard_forks = hardforks.data();
|
||||
test_options = &test_options_tmp;
|
||||
|
||||
cryptonote::tx_memory_pool txpool(*bc);
|
||||
bc.reset(new cryptonote::Blockchain(txpool));
|
||||
std::unique_ptr<cryptonote::BlockchainAndPool> bap(new BlockchainAndPool());
|
||||
|
||||
cryptonote::Blockchain *blockchain = bc.get();
|
||||
auto bdb = new TestDB();
|
||||
|
||||
BOOST_FOREACH(const test_event_entry &ev, events)
|
||||
@@ -176,12 +177,13 @@ static std::unique_ptr<cryptonote::Blockchain> init_blockchain(const std::vector
|
||||
const block *blk = &boost::get<block>(ev);
|
||||
auto blk_hash = get_block_hash(*blk);
|
||||
oracle::asset_type_counts num_rct_outs_by_asset_type;
|
||||
bdb->add_block(*blk, 1, 1, 1, 0, 0, num_rct_outs_by_asset_type, blk_hash);
|
||||
cryptonote::yield_block_info ybi;
|
||||
bdb->add_block(*blk, 1, 1, 1, 0, 0, num_rct_outs_by_asset_type, blk_hash, 0, 0, cryptonote::FAKECHAIN, ybi);
|
||||
}
|
||||
|
||||
bool r = blockchain->init(bdb, nettype, true, test_options, 2, nullptr);
|
||||
bool r = bap->blockchain.init(bdb, nettype, true, test_options, 2, nullptr);
|
||||
CHECK_AND_ASSERT_THROW_MES(r, "could not init blockchain from events");
|
||||
return bc;
|
||||
return bap;
|
||||
}
|
||||
|
||||
void test_generator::get_block_chain(std::vector<block_info>& blockchain, const crypto::hash& head, size_t n) const
|
||||
@@ -395,7 +397,7 @@ bool test_generator::construct_block_manually_tx(cryptonote::block& blk, const c
|
||||
void test_generator::fill_nonce(cryptonote::block& blk, const difficulty_type& diffic, uint64_t height)
|
||||
{
|
||||
const cryptonote::Blockchain *blockchain = nullptr;
|
||||
std::unique_ptr<cryptonote::Blockchain> bc;
|
||||
std::unique_ptr<cryptonote::BlockchainAndPool> bap;
|
||||
|
||||
if (blk.major_version >= RX_BLOCK_VERSION && diffic > 1)
|
||||
{
|
||||
@@ -405,8 +407,8 @@ void test_generator::fill_nonce(cryptonote::block& blk, const difficulty_type& d
|
||||
}
|
||||
else
|
||||
{
|
||||
bc = init_blockchain(*m_events, m_nettype);
|
||||
blockchain = bc.get();
|
||||
bap = init_blockchain(*m_events, m_nettype);
|
||||
blockchain = &bap->blockchain;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -489,7 +491,8 @@ bool init_spent_output_indices(map_output_idx_t& outs, map_output_t& outs_mine,
|
||||
crypto::public_key out_key = boost::get<txout_to_key>(oi.out).key;
|
||||
std::unordered_map<crypto::public_key, cryptonote::subaddress_index> subaddresses;
|
||||
subaddresses[from.get_keys().m_account_address.m_spend_public_key] = {0,0};
|
||||
generate_key_image_helper(from.get_keys(), subaddresses, out_key, get_tx_pub_key_from_extra(*oi.p_tx), get_additional_tx_pub_keys_from_extra(*oi.p_tx), oi.out_no, in_ephemeral, img, hw::get_device(("default")));
|
||||
cryptonote::origin_data od{3, crypto::null_pkey, 0};
|
||||
generate_key_image_helper(from.get_keys(), subaddresses, out_key, get_tx_pub_key_from_extra(*oi.p_tx), get_additional_tx_pub_keys_from_extra(*oi.p_tx), oi.out_no, in_ephemeral, img, hw::get_device(("default")), false, od);
|
||||
|
||||
// lookup for this key image in the events vector
|
||||
BOOST_FOREACH(auto& tx_pair, mtx) {
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
#include <boost/functional/hash.hpp>
|
||||
|
||||
#include "include_base_utils.h"
|
||||
#include "common/boost_serialization_helper.h"
|
||||
#include "chaingen_serialization.h"
|
||||
#include "common/command_line.h"
|
||||
#include "common/threadpool.h"
|
||||
|
||||
|
||||
@@ -144,7 +144,7 @@ bool gen_double_spend_in_tx<txs_keeped_by_block>::generate(std::vector<test_even
|
||||
destinations.push_back(de);
|
||||
|
||||
cryptonote::transaction tx_1;
|
||||
if (!construct_tx(bob_account.get_keys(), sources, destinations, 1/*hf_version*/, "FULM", "FULM", cryptonote::transaction_type::TRANSFER, boost::none, std::vector<uint8_t>(), tx_1, 0))
|
||||
if (!construct_tx(bob_account.get_keys(), sources, destinations, 1/*hf_version*/, "SAL", cryptonote::transaction_type::TRANSFER, boost::none, std::vector<uint8_t>(), tx_1, 0))
|
||||
return false;
|
||||
|
||||
SET_EVENT_VISITOR_SETT(events, txs_keeped_by_block ? event_visitor_settings::set_txs_keeped_by_block : 0);
|
||||
|
||||
@@ -174,7 +174,7 @@ bool gen_uint_overflow_2::generate(std::vector<test_event_entry>& events) const
|
||||
destinations.push_back(tx_destination_entry(sources.front().amount - MONEY_SUPPLY - MONEY_SUPPLY + 1 - TESTS_DEFAULT_FEE, bob_addr, false));
|
||||
|
||||
cryptonote::transaction tx_1;
|
||||
if (!construct_tx(miner_account.get_keys(), sources, destinations, 1/*hf_version*/, "FULM", "FULM", cryptonote::transaction_type::TRANSFER, boost::none, std::vector<uint8_t>(), tx_1, 0))
|
||||
if (!construct_tx(miner_account.get_keys(), sources, destinations, 1/*hf_version*/, "SAL", cryptonote::transaction_type::TRANSFER, boost::none, std::vector<uint8_t>(), tx_1, 0))
|
||||
return false;
|
||||
events.push_back(tx_1);
|
||||
|
||||
@@ -200,7 +200,7 @@ bool gen_uint_overflow_2::generate(std::vector<test_event_entry>& events) const
|
||||
destinations.push_back(de);
|
||||
|
||||
cryptonote::transaction tx_2;
|
||||
if (!construct_tx(bob_account.get_keys(), sources, destinations, 1/*hf_version*/, "FULM", "FULM", cryptonote::transaction_type::TRANSFER, boost::none, std::vector<uint8_t>(), tx_2, 0))
|
||||
if (!construct_tx(bob_account.get_keys(), sources, destinations, 1/*hf_version*/, "SAL", cryptonote::transaction_type::TRANSFER, boost::none, std::vector<uint8_t>(), tx_2, 0))
|
||||
return false;
|
||||
events.push_back(tx_2);
|
||||
|
||||
|
||||
@@ -227,13 +227,13 @@ bool gen_multisig_tx_validation_base::generate_with(std::vector<test_event_entry
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to generate multisig export key image");
|
||||
}
|
||||
MDEBUG("Party " << msidx << ":");
|
||||
MDEBUG("spend: sec " << miner_account[msidx].get_keys().m_spend_secret_key << ", pub " << miner_account[msidx].get_keys().m_account_address.m_spend_public_key);
|
||||
MDEBUG("view: sec " << miner_account[msidx].get_keys().m_view_secret_key << ", pub " << miner_account[msidx].get_keys().m_account_address.m_view_public_key);
|
||||
MDEBUG("spend: sec " << crypto::secret_key_explicit_print_ref{miner_account[msidx].get_keys().m_spend_secret_key} << ", pub " << miner_account[msidx].get_keys().m_account_address.m_spend_public_key);
|
||||
MDEBUG("view: sec " << crypto::secret_key_explicit_print_ref{miner_account[msidx].get_keys().m_view_secret_key} << ", pub " << miner_account[msidx].get_keys().m_account_address.m_view_public_key);
|
||||
for (const auto &k: miner_account[msidx].get_multisig_keys())
|
||||
MDEBUG("msk: " << k);
|
||||
MDEBUG("msk: " << crypto::secret_key_explicit_print_ref{k});
|
||||
for (size_t n = 0; n < account_k[msidx][tdidx].size(); ++n)
|
||||
{
|
||||
MDEBUG("k: " << account_k[msidx][tdidx][n]);
|
||||
MDEBUG("k: " << crypto::secret_key_explicit_print_ref{account_k[msidx][tdidx][n]});
|
||||
MDEBUG("L: " << account_L[msidx][tdidx][n]);
|
||||
MDEBUG("R: " << account_R[msidx][tdidx][n]);
|
||||
}
|
||||
@@ -245,6 +245,7 @@ bool gen_multisig_tx_validation_base::generate_with(std::vector<test_event_entry
|
||||
// create kLRki
|
||||
std::vector<rct::multisig_kLRki> kLRkis;
|
||||
std::unordered_set<crypto::public_key> used_L;
|
||||
const cryptonote::origin_data origin_tx_data{3,crypto::null_pkey, 0};
|
||||
for (size_t tdidx = 0; tdidx < inputs; ++tdidx)
|
||||
{
|
||||
kLRkis.push_back(rct::multisig_kLRki());
|
||||
@@ -253,13 +254,13 @@ bool gen_multisig_tx_validation_base::generate_with(std::vector<test_event_entry
|
||||
for (size_t msidx = 0; msidx < total; ++msidx)
|
||||
for (size_t n = 0; n < account_ki[msidx][tdidx].size(); ++n)
|
||||
pkis.push_back(account_ki[msidx][tdidx][n]);
|
||||
r = multisig::generate_multisig_composite_key_image(miner_account[0].get_keys(), subaddresses, output_pub_key[tdidx], tx_pub_key[tdidx], additional_tx_keys, 0, pkis, (crypto::key_image&)kLRki.ki);
|
||||
r = multisig::generate_multisig_composite_key_image(miner_account[0].get_keys(), subaddresses, output_pub_key[tdidx], tx_pub_key[tdidx], additional_tx_keys, 0, pkis, (crypto::key_image&)kLRki.ki, false, origin_tx_data);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to generate composite key image");
|
||||
MDEBUG("composite ki: " << kLRki.ki);
|
||||
for (size_t n = 1; n < total; ++n)
|
||||
{
|
||||
rct::key ki;
|
||||
r = multisig::generate_multisig_composite_key_image(miner_account[n].get_keys(), subaddresses, output_pub_key[tdidx], tx_pub_key[tdidx], additional_tx_keys, 0, pkis, (crypto::key_image&)ki);
|
||||
r = multisig::generate_multisig_composite_key_image(miner_account[n].get_keys(), subaddresses, output_pub_key[tdidx], tx_pub_key[tdidx], additional_tx_keys, 0, pkis, (crypto::key_image&)ki, false, origin_tx_data);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to generate composite key image");
|
||||
CHECK_AND_ASSERT_MES(kLRki.ki == ki, false, "Composite key images do not match");
|
||||
}
|
||||
@@ -310,7 +311,7 @@ bool gen_multisig_tx_validation_base::generate_with(std::vector<test_event_entry
|
||||
crypto::secret_key multisig_tx_key_entropy;
|
||||
auto sources_copy = sources;
|
||||
multisig::signing::tx_builder_ringct_t tx_builder;
|
||||
CHECK_AND_ASSERT_MES(tx_builder.init(miner_account[creator].get_keys(), {}, 0, 0, {0}, sources, destinations, {}, {rct::RangeProofPaddedBulletproof, 4}, true, false, tx_key, additional_tx_secret_keys, multisig_tx_key_entropy, tx), false, "error: multisig::signing::tx_builder_ringct_t::init");
|
||||
CHECK_AND_ASSERT_MES(tx_builder.init(miner_account[creator].get_keys(), {}, cryptonote::transaction_type::TRANSFER, 1, 0, 0, {0}, sources, destinations, {}, {rct::RangeProofPaddedBulletproof, 4}, true, false, tx_key, additional_tx_secret_keys, multisig_tx_key_entropy, tx), false, "error: multisig::signing::tx_builder_ringct_t::init");
|
||||
|
||||
// work out the permutation done on sources
|
||||
std::vector<size_t> ins_order;
|
||||
@@ -399,14 +400,14 @@ bool gen_multisig_tx_validation_base::generate_with(std::vector<test_event_entry
|
||||
}
|
||||
tools::apply_permutation(ins_order, k);
|
||||
multisig::signing::tx_builder_ringct_t signer_tx_builder;
|
||||
CHECK_AND_ASSERT_MES(signer_tx_builder.init(miner_account[signer].get_keys(), {}, 0, 0, {0}, sources, destinations, {}, {rct::RangeProofPaddedBulletproof, 4}, true, true, tx_key, additional_tx_secret_keys, multisig_tx_key_entropy, tx), false, "error: multisig::signing::tx_builder_ringct_t::init");
|
||||
CHECK_AND_ASSERT_MES(signer_tx_builder.init(miner_account[signer].get_keys(), {}, cryptonote::transaction_type::TRANSFER, 1, 0, 0, {0}, sources, destinations, {}, {rct::RangeProofPaddedBulletproof, 4}, true, true, tx_key, additional_tx_secret_keys, multisig_tx_key_entropy, tx), false, "error: multisig::signing::tx_builder_ringct_t::init");
|
||||
|
||||
MDEBUG("signing with k size " << k.size());
|
||||
for (size_t n = 0; n < multisig::signing::kAlphaComponents; ++n)
|
||||
MDEBUG("signing with k " << k.back()[n]);
|
||||
MDEBUG("signing with sk " << skey);
|
||||
for (const auto &sk: used_keys)
|
||||
MDEBUG(" created with sk " << sk);
|
||||
MDEBUG(" created with sk " << crypto::secret_key_explicit_print_ref{sk});
|
||||
CHECK_AND_ASSERT_MES(signer_tx_builder.next_partial_sign(sig.total_alpha_G, sig.total_alpha_H, k, skey, sig.c_0, sig.s), false, "error: multisig::signing::tx_builder_ringct_t::next_partial_sign");
|
||||
|
||||
// in round-robin signing, the last signer finalizes the tx
|
||||
|
||||
@@ -157,7 +157,7 @@ bool test_transaction_generation_and_ring_signature()
|
||||
destinations.push_back(td);
|
||||
|
||||
transaction tx_rc1;
|
||||
bool r = construct_tx(miner_acc2.get_keys(), sources, destinations, 1/*hf_version*/, "FULM", "FULM", cryptonote::transaction_type::TRANSFER, boost::none, std::vector<uint8_t>(), tx_rc1, 0);
|
||||
bool r = construct_tx(miner_acc2.get_keys(), sources, destinations, 1/*hf_version*/, "SAL", cryptonote::transaction_type::TRANSFER, boost::none, std::vector<uint8_t>(), tx_rc1, 0);
|
||||
CHECK_AND_ASSERT_MES(r, false, "failed to construct transaction");
|
||||
|
||||
crypto::hash pref_hash = get_transaction_prefix_hash(tx_rc1);
|
||||
|
||||
@@ -63,7 +63,8 @@ namespace
|
||||
std::unordered_map<crypto::public_key, cryptonote::subaddress_index> subaddresses;
|
||||
subaddresses[sender_account_keys.m_account_address.m_spend_public_key] = {0,0};
|
||||
auto& out_key = reinterpret_cast<const crypto::public_key&>(src_entr.outputs[src_entr.real_output].second.dest);
|
||||
generate_key_image_helper(sender_account_keys, subaddresses, out_key, src_entr.real_out_tx_key, src_entr.real_out_additional_tx_keys, src_entr.real_output_in_tx_index, in_ephemeral, img, hw::get_device(("default")));
|
||||
const cryptonote::origin_data od{3, crypto::null_pkey, src_entr.real_output};
|
||||
generate_key_image_helper(sender_account_keys, subaddresses, out_key, src_entr.real_out_tx_key, src_entr.real_out_additional_tx_keys, src_entr.real_output_in_tx_index, in_ephemeral, img, hw::get_device(("default")), false, od);
|
||||
|
||||
// put key image into tx input
|
||||
txin_to_key input_to_key;
|
||||
|
||||
@@ -107,7 +107,7 @@ bool gen_v2_tx_validation_base::generate_with(std::vector<test_event_entry>& eve
|
||||
destinations.push_back(td);
|
||||
|
||||
transaction tx;
|
||||
bool r = construct_tx(miner_accounts[0].get_keys(), sources, destinations, 1/*hf_version*/, "FULM", "FULM", cryptonote::transaction_type::TRANSFER, boost::none, std::vector<uint8_t>(), tx, 0);
|
||||
bool r = construct_tx(miner_accounts[0].get_keys(), sources, destinations, 1/*hf_version*/, "SAL", cryptonote::transaction_type::TRANSFER, boost::none, std::vector<uint8_t>(), tx, 0);
|
||||
CHECK_AND_ASSERT_MES(r, false, "failed to construct transaction");
|
||||
if (!valid)
|
||||
DO_CALLBACK(events, "mark_invalid_tx");
|
||||
|
||||
@@ -172,7 +172,7 @@ bool transactions_flow_test(std::string& working_folder,
|
||||
|
||||
//wait for money, until balance will have enough money
|
||||
w1.refresh(true, blocks_fetched, received_money, ok);
|
||||
while(w1.unlocked_balance(0, true) < amount_to_transfer)
|
||||
while(w1.unlocked_balance(0, "SAL", true) < amount_to_transfer)
|
||||
{
|
||||
misc_utils::sleep_no_w(1000);
|
||||
w1.refresh(true, blocks_fetched, received_money, ok);
|
||||
@@ -185,7 +185,7 @@ bool transactions_flow_test(std::string& working_folder,
|
||||
{
|
||||
tools::wallet2::transfer_container incoming_transfers;
|
||||
w1.get_transfers(incoming_transfers);
|
||||
if(incoming_transfers.size() > FIRST_N_TRANSFERS && get_money_in_first_transfers(incoming_transfers, FIRST_N_TRANSFERS) < w1.unlocked_balance(0, true) )
|
||||
if(incoming_transfers.size() > FIRST_N_TRANSFERS && get_money_in_first_transfers(incoming_transfers, FIRST_N_TRANSFERS) < w1.unlocked_balance(0, "SAL", true) )
|
||||
{
|
||||
//lets go!
|
||||
size_t count = 0;
|
||||
@@ -220,7 +220,7 @@ bool transactions_flow_test(std::string& working_folder,
|
||||
for(i = 0; i != transactions_count; i++)
|
||||
{
|
||||
uint64_t amount_to_tx = (amount_to_transfer - transfered_money) > transfer_size ? transfer_size: (amount_to_transfer - transfered_money);
|
||||
while(w1.unlocked_balance(0, true) < amount_to_tx + TEST_FEE)
|
||||
while(w1.unlocked_balance(0, "SAL", true) < amount_to_tx + TEST_FEE)
|
||||
{
|
||||
misc_utils::sleep_no_w(1000);
|
||||
LOG_PRINT_L0("not enough money, waiting for cashback or mining");
|
||||
@@ -269,7 +269,7 @@ bool transactions_flow_test(std::string& working_folder,
|
||||
misc_utils::sleep_no_w(DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN*1000);//wait two blocks before sync on another wallet on another daemon
|
||||
}
|
||||
|
||||
uint64_t money_2 = w2.balance(0, true);
|
||||
uint64_t money_2 = w2.balance(0, "SAL", true);
|
||||
if(money_2 == transfered_money)
|
||||
{
|
||||
MGINFO_GREEN("-----------------------FINISHING TRANSACTIONS FLOW TEST OK-----------------------");
|
||||
|
||||
@@ -57,7 +57,7 @@ public:
|
||||
std::vector<tx_destination_entry> destinations;
|
||||
destinations.push_back(tx_destination_entry(1, m_alice.get_keys().m_account_address, false));
|
||||
|
||||
if (!construct_tx(this->m_miners[this->real_source_idx].get_keys(), this->m_sources, destinations, 1/*hf_version*/, "FULM", "FULM", cryptonote::transaction_type::TRANSFER, boost::none, std::vector<uint8_t>(), m_tx, 0))
|
||||
if (!construct_tx(this->m_miners[this->real_source_idx].get_keys(), this->m_sources, destinations, 1/*hf_version*/, "SAL", cryptonote::transaction_type::TRANSFER, boost::none, std::vector<uint8_t>(), m_tx, 0))
|
||||
return false;
|
||||
|
||||
const cryptonote::txin_to_key& txin = boost::get<cryptonote::txin_to_key>(m_tx.vin[0]);
|
||||
|
||||
@@ -57,7 +57,7 @@ public:
|
||||
std::vector<tx_destination_entry> destinations;
|
||||
destinations.push_back(tx_destination_entry(1, m_alice.get_keys().m_account_address, false));
|
||||
|
||||
if (!construct_tx(this->m_miners[this->real_source_idx].get_keys(), this->m_sources, destinations, 1/*hf_version*/, "FULM", "FULM", cryptonote::transaction_type::TRANSFER, boost::none, std::vector<uint8_t>(), m_tx, 0))
|
||||
if (!construct_tx(this->m_miners[this->real_source_idx].get_keys(), this->m_sources, destinations, 1/*hf_version*/, "SAL", cryptonote::transaction_type::TRANSFER, boost::none, std::vector<uint8_t>(), m_tx, 0))
|
||||
return false;
|
||||
|
||||
const cryptonote::txin_to_key& txin = boost::get<cryptonote::txin_to_key>(m_tx.vin[0]);
|
||||
|
||||
@@ -49,6 +49,7 @@ public:
|
||||
std::unordered_map<crypto::public_key, cryptonote::subaddress_index> subaddresses;
|
||||
subaddresses[m_bob.get_keys().m_account_address.m_spend_public_key] = {0,0};
|
||||
crypto::public_key out_key = boost::get<cryptonote::txout_to_key>(m_tx.vout[0].target).key;
|
||||
return cryptonote::generate_key_image_helper(m_bob.get_keys(), subaddresses, out_key, m_tx_pub_key, m_additional_tx_pub_keys, 0, in_ephemeral, ki, hw::get_device("default"));
|
||||
cryptonote::origin_data od{3,crypto::null_pkey,0};
|
||||
return cryptonote::generate_key_image_helper(m_bob.get_keys(), subaddresses, out_key, m_tx_pub_key, m_additional_tx_pub_keys, 0, in_ephemeral, ki, hw::get_device("default"), false, od);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -84,7 +84,7 @@ TEST(AddressFromTXT, Failure)
|
||||
|
||||
TEST(AddressFromURL, Success)
|
||||
{
|
||||
const std::string addr = FULMO_DONATION_ADDR;
|
||||
const std::string addr = SALVIUM_DONATION_ADDR;
|
||||
|
||||
bool dnssec_result = false;
|
||||
|
||||
|
||||
@@ -274,8 +274,9 @@ TYPED_TEST(BlockchainDBTest, AddBlock)
|
||||
// no blocks have been added yet (because genesis has no parent).
|
||||
//ASSERT_THROW(this->m_db->add_block(this->m_blocks[1], t_sizes[1], t_sizes[1], t_diffs[1], t_coins[1], this->m_txs[1]), BLOCK_PARENT_DNE);
|
||||
|
||||
ASSERT_NO_THROW(this->m_db->add_block(this->m_blocks[0], t_sizes[0], t_sizes[0], t_diffs[0], t_coins[0], this->m_txs[0]));
|
||||
ASSERT_NO_THROW(this->m_db->add_block(this->m_blocks[1], t_sizes[1], t_sizes[1], t_diffs[1], t_coins[1], this->m_txs[1]));
|
||||
cryptonote::yield_block_info ybi;
|
||||
ASSERT_NO_THROW(this->m_db->add_block(this->m_blocks[0], t_sizes[0], t_sizes[0], t_diffs[0], t_coins[0], this->m_txs[0], cryptonote::FAKECHAIN, ybi));
|
||||
ASSERT_NO_THROW(this->m_db->add_block(this->m_blocks[1], t_sizes[1], t_sizes[1], t_diffs[1], t_coins[1], this->m_txs[1], cryptonote::FAKECHAIN, ybi));
|
||||
|
||||
block b;
|
||||
ASSERT_TRUE(this->m_db->block_exists(get_block_hash(this->m_blocks[0].first)));
|
||||
@@ -288,7 +289,7 @@ TYPED_TEST(BlockchainDBTest, AddBlock)
|
||||
ASSERT_TRUE(compare_blocks(this->m_blocks[0].first, b));
|
||||
|
||||
// assert that we can't add the same block twice
|
||||
ASSERT_THROW(this->m_db->add_block(this->m_blocks[0], t_sizes[0], t_sizes[0], t_diffs[0], t_coins[0], this->m_txs[0]), TX_EXISTS);
|
||||
ASSERT_THROW(this->m_db->add_block(this->m_blocks[0], t_sizes[0], t_sizes[0], t_diffs[0], t_coins[0], this->m_txs[0], cryptonote::FAKECHAIN, ybi), TX_EXISTS);
|
||||
|
||||
for (auto& h : this->m_blocks[0].first.tx_hashes)
|
||||
{
|
||||
@@ -314,14 +315,15 @@ TYPED_TEST(BlockchainDBTest, RetrieveBlockData)
|
||||
|
||||
db_wtxn_guard guard(this->m_db);
|
||||
|
||||
ASSERT_NO_THROW(this->m_db->add_block(this->m_blocks[0], t_sizes[0], t_sizes[0], t_diffs[0], t_coins[0], this->m_txs[0]));
|
||||
cryptonote::yield_block_info ybi;
|
||||
ASSERT_NO_THROW(this->m_db->add_block(this->m_blocks[0], t_sizes[0], t_sizes[0], t_diffs[0], t_coins[0], this->m_txs[0], cryptonote::FAKECHAIN, ybi));
|
||||
|
||||
ASSERT_EQ(t_sizes[0], this->m_db->get_block_weight(0));
|
||||
ASSERT_EQ(t_diffs[0], this->m_db->get_block_cumulative_difficulty(0));
|
||||
ASSERT_EQ(t_diffs[0], this->m_db->get_block_difficulty(0));
|
||||
ASSERT_EQ(t_coins[0], this->m_db->get_block_already_generated_coins(0));
|
||||
|
||||
ASSERT_NO_THROW(this->m_db->add_block(this->m_blocks[1], t_sizes[1], t_sizes[1], t_diffs[1], t_coins[1], this->m_txs[1]));
|
||||
ASSERT_NO_THROW(this->m_db->add_block(this->m_blocks[1], t_sizes[1], t_sizes[1], t_diffs[1], t_coins[1], this->m_txs[1], cryptonote::FAKECHAIN, ybi));
|
||||
ASSERT_EQ(t_diffs[1] - t_diffs[0], this->m_db->get_block_difficulty(1));
|
||||
|
||||
ASSERT_HASH_EQ(get_block_hash(this->m_blocks[0].first), this->m_db->get_block_hash_from_height(0));
|
||||
|
||||
@@ -133,10 +133,10 @@ TEST(bulletproofs, multi_splitting)
|
||||
rct::ctkeyV outSk;
|
||||
rct::RCTConfig rct_config { rct::RangeProofPaddedBulletproof, 4 };
|
||||
cryptonote::transaction_type tx_type = cryptonote::transaction_type::TRANSFER;
|
||||
std::string in_asset_type = "FULM";
|
||||
std::string in_asset_type = "SAL";
|
||||
std::vector<std::string> destination_asset_types;
|
||||
for (size_t i = 0; i < destinations.size(); ++i)
|
||||
destination_asset_types.push_back("FULM");
|
||||
destination_asset_types.push_back("SAL");
|
||||
|
||||
rct::rctSig s = rct::genRctSimple(rct::zero(), sc, destinations, tx_type, in_asset_type, destination_asset_types, inamounts, outamounts, available, mixRing, amount_keys, index, outSk, rct_config, hw::get_device("default"));
|
||||
ASSERT_TRUE(rct::verRctSimple(s));
|
||||
|
||||
@@ -72,10 +72,10 @@ TEST(Crypto, Ostream)
|
||||
EXPECT_TRUE(is_formatted<crypto::hash8>());
|
||||
EXPECT_TRUE(is_formatted<crypto::hash>());
|
||||
EXPECT_TRUE(is_formatted<crypto::public_key>());
|
||||
EXPECT_TRUE(is_formatted<crypto::secret_key>());
|
||||
EXPECT_TRUE(is_formatted<crypto::signature>());
|
||||
EXPECT_TRUE(is_formatted<crypto::key_derivation>());
|
||||
EXPECT_TRUE(is_formatted<crypto::key_image>());
|
||||
EXPECT_TRUE(is_formatted<rct::key>());
|
||||
}
|
||||
|
||||
TEST(Crypto, null_keys)
|
||||
|
||||
@@ -47,14 +47,18 @@ namespace
|
||||
class TestDB: public cryptonote::BaseTestDB {
|
||||
public:
|
||||
virtual uint64_t height() const override { return blocks.size(); }
|
||||
virtual void add_block( const block& blk
|
||||
virtual void add_block( const cryptonote::block& blk
|
||||
, size_t block_weight
|
||||
, uint64_t long_term_block_weight
|
||||
, const difficulty_type& cumulative_difficulty
|
||||
, const cryptonote::difficulty_type& cumulative_difficulty
|
||||
, const uint64_t& coins_generated
|
||||
, uint64_t num_rct_outs
|
||||
, oracle::asset_type_counts& cum_rct_by_asset_type
|
||||
, const crypto::hash& blk_hash
|
||||
, uint64_t slippage_total
|
||||
, uint64_t yield_total
|
||||
, const cryptonote::network_type nettype
|
||||
, cryptonote::yield_block_info& ybi
|
||||
) override {
|
||||
blocks.push_back(blk);
|
||||
}
|
||||
@@ -99,6 +103,7 @@ TEST(major, Only)
|
||||
TestDB db;
|
||||
HardFork hf(db, 1, 0, 0, 0, 1, 0); // no voting
|
||||
oracle::asset_type_counts num_rct_outs_by_asset_type;
|
||||
cryptonote::yield_block_info ybi;
|
||||
|
||||
// v h t
|
||||
ASSERT_TRUE(hf.add_fork(1, 0, 0));
|
||||
@@ -109,20 +114,20 @@ TEST(major, Only)
|
||||
ASSERT_FALSE(hf.add(mkblock(0, 2), 0));
|
||||
ASSERT_FALSE(hf.add(mkblock(2, 2), 0));
|
||||
ASSERT_TRUE(hf.add(mkblock(1, 2), 0));
|
||||
db.add_block(mkblock(1, 1), 0, 0, 0, 0, 0, num_rct_outs_by_asset_type, crypto::hash());
|
||||
db.add_block(mkblock(1, 1), 0, 0, 0, 0, 0, num_rct_outs_by_asset_type, crypto::hash(), 0, 0, cryptonote::FAKECHAIN, ybi);
|
||||
|
||||
// block height 1, only version 1 is accepted
|
||||
ASSERT_FALSE(hf.add(mkblock(0, 2), 1));
|
||||
ASSERT_FALSE(hf.add(mkblock(2, 2), 1));
|
||||
ASSERT_TRUE(hf.add(mkblock(1, 2), 1));
|
||||
db.add_block(mkblock(1, 1), 0, 0, 0, 0, 0, num_rct_outs_by_asset_type, crypto::hash());
|
||||
db.add_block(mkblock(1, 1), 0, 0, 0, 0, 0, num_rct_outs_by_asset_type, crypto::hash(), 0, 0, cryptonote::FAKECHAIN, ybi);
|
||||
|
||||
// block height 2, only version 2 is accepted
|
||||
ASSERT_FALSE(hf.add(mkblock(0, 2), 2));
|
||||
ASSERT_FALSE(hf.add(mkblock(1, 2), 2));
|
||||
ASSERT_FALSE(hf.add(mkblock(3, 2), 2));
|
||||
ASSERT_TRUE(hf.add(mkblock(2, 2), 2));
|
||||
db.add_block(mkblock(2, 1), 0, 0, 0, 0, 0, num_rct_outs_by_asset_type, crypto::hash());
|
||||
db.add_block(mkblock(2, 1), 0, 0, 0, 0, 0, num_rct_outs_by_asset_type, crypto::hash(), 0, 0, cryptonote::FAKECHAIN, ybi);
|
||||
}
|
||||
|
||||
TEST(empty_hardforks, Success)
|
||||
@@ -130,6 +135,7 @@ TEST(empty_hardforks, Success)
|
||||
TestDB db;
|
||||
HardFork hf(db);
|
||||
oracle::asset_type_counts num_rct_outs_by_asset_type;
|
||||
cryptonote::yield_block_info ybi;
|
||||
|
||||
ASSERT_TRUE(hf.add_fork(1, 0, 0));
|
||||
hf.init();
|
||||
@@ -137,7 +143,7 @@ TEST(empty_hardforks, Success)
|
||||
ASSERT_TRUE(hf.get_state(time(NULL) + 3600*24*400) == HardFork::Ready);
|
||||
|
||||
for (uint64_t h = 0; h <= 10; ++h) {
|
||||
db.add_block(mkblock(hf, h, 1), 0, 0, 0, 0, 0, num_rct_outs_by_asset_type, crypto::hash());
|
||||
db.add_block(mkblock(hf, h, 1), 0, 0, 0, 0, 0, num_rct_outs_by_asset_type, crypto::hash(), 0, 0, cryptonote::FAKECHAIN, ybi);
|
||||
ASSERT_TRUE(hf.add(db.get_block_from_height(h), h));
|
||||
}
|
||||
ASSERT_EQ(hf.get(0), 1);
|
||||
@@ -164,6 +170,7 @@ TEST(check_for_height, Success)
|
||||
TestDB db;
|
||||
HardFork hf(db, 1, 0, 0, 0, 1, 0); // no voting
|
||||
oracle::asset_type_counts num_rct_outs_by_asset_type;
|
||||
cryptonote::yield_block_info ybi;
|
||||
|
||||
ASSERT_TRUE(hf.add_fork(1, 0, 0));
|
||||
ASSERT_TRUE(hf.add_fork(2, 5, 1));
|
||||
@@ -172,14 +179,14 @@ TEST(check_for_height, Success)
|
||||
for (uint64_t h = 0; h <= 4; ++h) {
|
||||
ASSERT_TRUE(hf.check_for_height(mkblock(1, 1), h));
|
||||
ASSERT_FALSE(hf.check_for_height(mkblock(2, 2), h)); // block version is too high
|
||||
db.add_block(mkblock(hf, h, 1), 0, 0, 0, 0, 0, num_rct_outs_by_asset_type, crypto::hash());
|
||||
db.add_block(mkblock(hf, h, 1), 0, 0, 0, 0, 0, num_rct_outs_by_asset_type, crypto::hash(), 0, 0, cryptonote::FAKECHAIN, ybi);
|
||||
ASSERT_TRUE(hf.add(db.get_block_from_height(h), h));
|
||||
}
|
||||
|
||||
for (uint64_t h = 5; h <= 10; ++h) {
|
||||
ASSERT_FALSE(hf.check_for_height(mkblock(1, 1), h)); // block version is too low
|
||||
ASSERT_TRUE(hf.check_for_height(mkblock(2, 2), h));
|
||||
db.add_block(mkblock(hf, h, 2), 0, 0, 0, 0, 0, num_rct_outs_by_asset_type, crypto::hash());
|
||||
db.add_block(mkblock(hf, h, 2), 0, 0, 0, 0, 0, num_rct_outs_by_asset_type, crypto::hash(), 0, 0, cryptonote::FAKECHAIN, ybi);
|
||||
ASSERT_TRUE(hf.add(db.get_block_from_height(h), h));
|
||||
}
|
||||
}
|
||||
@@ -189,6 +196,7 @@ TEST(get, next_version)
|
||||
TestDB db;
|
||||
HardFork hf(db);
|
||||
oracle::asset_type_counts num_rct_outs_by_asset_type;
|
||||
cryptonote::yield_block_info ybi;
|
||||
|
||||
ASSERT_TRUE(hf.add_fork(1, 0, 0));
|
||||
ASSERT_TRUE(hf.add_fork(2, 5, 1));
|
||||
@@ -197,19 +205,19 @@ TEST(get, next_version)
|
||||
|
||||
for (uint64_t h = 0; h <= 4; ++h) {
|
||||
ASSERT_EQ(2, hf.get_next_version());
|
||||
db.add_block(mkblock(hf, h, 1), 0, 0, 0, 0, 0, num_rct_outs_by_asset_type, crypto::hash());
|
||||
db.add_block(mkblock(hf, h, 1), 0, 0, 0, 0, 0, num_rct_outs_by_asset_type, crypto::hash(), 0, 0, cryptonote::FAKECHAIN, ybi);
|
||||
ASSERT_TRUE(hf.add(db.get_block_from_height(h), h));
|
||||
}
|
||||
|
||||
for (uint64_t h = 5; h <= 9; ++h) {
|
||||
ASSERT_EQ(4, hf.get_next_version());
|
||||
db.add_block(mkblock(hf, h, 2), 0, 0, 0, 0, 0, num_rct_outs_by_asset_type, crypto::hash());
|
||||
db.add_block(mkblock(hf, h, 2), 0, 0, 0, 0, 0, num_rct_outs_by_asset_type, crypto::hash(), 0, 0, cryptonote::FAKECHAIN, ybi);
|
||||
ASSERT_TRUE(hf.add(db.get_block_from_height(h), h));
|
||||
}
|
||||
|
||||
for (uint64_t h = 10; h <= 15; ++h) {
|
||||
ASSERT_EQ(4, hf.get_next_version());
|
||||
db.add_block(mkblock(hf, h, 4), 0, 0, 0, 0, 0, num_rct_outs_by_asset_type, crypto::hash());
|
||||
db.add_block(mkblock(hf, h, 4), 0, 0, 0, 0, 0, num_rct_outs_by_asset_type, crypto::hash(), 0, 0, cryptonote::FAKECHAIN, ybi);
|
||||
ASSERT_TRUE(hf.add(db.get_block_from_height(h), h));
|
||||
}
|
||||
}
|
||||
@@ -243,6 +251,7 @@ TEST(steps_asap, Success)
|
||||
TestDB db;
|
||||
HardFork hf(db, 1,0,1,1,1);
|
||||
oracle::asset_type_counts num_rct_outs_by_asset_type;
|
||||
cryptonote::yield_block_info ybi;
|
||||
|
||||
// v h t
|
||||
ASSERT_TRUE(hf.add_fork(1, 0, 0));
|
||||
@@ -252,7 +261,7 @@ TEST(steps_asap, Success)
|
||||
hf.init();
|
||||
|
||||
for (uint64_t h = 0; h < 10; ++h) {
|
||||
db.add_block(mkblock(hf, h, 9), 0, 0, 0, 0, 0, num_rct_outs_by_asset_type, crypto::hash());
|
||||
db.add_block(mkblock(hf, h, 9), 0, 0, 0, 0, 0, num_rct_outs_by_asset_type, crypto::hash(), 0, 0, cryptonote::FAKECHAIN, ybi);
|
||||
ASSERT_TRUE(hf.add(db.get_block_from_height(h), h));
|
||||
}
|
||||
|
||||
@@ -273,6 +282,7 @@ TEST(steps_1, Success)
|
||||
TestDB db;
|
||||
HardFork hf(db, 1,0,1,1,1);
|
||||
oracle::asset_type_counts num_rct_outs_by_asset_type;
|
||||
cryptonote::yield_block_info ybi;
|
||||
|
||||
ASSERT_TRUE(hf.add_fork(1, 0, 0));
|
||||
for (int n = 1 ; n < 10; ++n)
|
||||
@@ -280,7 +290,7 @@ TEST(steps_1, Success)
|
||||
hf.init();
|
||||
|
||||
for (uint64_t h = 0 ; h < 10; ++h) {
|
||||
db.add_block(mkblock(hf, h, h+1), 0, 0, 0, 0, 0, num_rct_outs_by_asset_type, crypto::hash());
|
||||
db.add_block(mkblock(hf, h, h+1), 0, 0, 0, 0, 0, num_rct_outs_by_asset_type, crypto::hash(), 0, 0, cryptonote::FAKECHAIN, ybi);
|
||||
ASSERT_TRUE(hf.add(db.get_block_from_height(h), h));
|
||||
}
|
||||
|
||||
@@ -295,7 +305,8 @@ TEST(reorganize, Same)
|
||||
TestDB db;
|
||||
HardFork hf(db, 1, 0, 1, 1, history, 100);
|
||||
oracle::asset_type_counts num_rct_outs_by_asset_type;
|
||||
|
||||
cryptonote::yield_block_info ybi;
|
||||
|
||||
// v h t
|
||||
ASSERT_TRUE(hf.add_fork(1, 0, 0));
|
||||
ASSERT_TRUE(hf.add_fork(4, 2, 1));
|
||||
@@ -306,7 +317,7 @@ TEST(reorganize, Same)
|
||||
// index 0 1 2 3 4 5 6 7 8 9
|
||||
static const uint8_t block_versions[] = { 1, 1, 4, 4, 7, 7, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 };
|
||||
for (uint64_t h = 0; h < 20; ++h) {
|
||||
db.add_block(mkblock(hf, h, block_versions[h]), 0, 0, 0, 0, 0, num_rct_outs_by_asset_type, crypto::hash());
|
||||
db.add_block(mkblock(hf, h, block_versions[h]), 0, 0, 0, 0, 0, num_rct_outs_by_asset_type, crypto::hash(), 0, 0, cryptonote::FAKECHAIN, ybi);
|
||||
ASSERT_TRUE(hf.add(db.get_block_from_height(h), h));
|
||||
}
|
||||
|
||||
@@ -325,6 +336,7 @@ TEST(reorganize, Changed)
|
||||
TestDB db;
|
||||
HardFork hf(db, 1, 0, 1, 1, 4, 100);
|
||||
oracle::asset_type_counts num_rct_outs_by_asset_type;
|
||||
cryptonote::yield_block_info ybi;
|
||||
|
||||
// v h t
|
||||
ASSERT_TRUE(hf.add_fork(1, 0, 0));
|
||||
@@ -338,7 +350,7 @@ TEST(reorganize, Changed)
|
||||
static const uint8_t block_versions[] = { 1, 1, 4, 4, 7, 7, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 };
|
||||
static const uint8_t expected_versions[] = { 1, 1, 1, 1, 1, 1, 4, 4, 7, 7, 9, 9, 9, 9, 9, 9 };
|
||||
for (uint64_t h = 0; h < 16; ++h) {
|
||||
db.add_block(mkblock(hf, h, block_versions[h]), 0, 0, 0, 0, 0, num_rct_outs_by_asset_type, crypto::hash());
|
||||
db.add_block(mkblock(hf, h, block_versions[h]), 0, 0, 0, 0, 0, num_rct_outs_by_asset_type, crypto::hash(), 0, 0, cryptonote::FAKECHAIN, ybi);
|
||||
ASSERT_TRUE (hf.add(db.get_block_from_height(h), h));
|
||||
}
|
||||
|
||||
@@ -358,7 +370,7 @@ TEST(reorganize, Changed)
|
||||
ASSERT_EQ(db.height(), 3);
|
||||
hf.reorganize_from_block_height(2);
|
||||
for (uint64_t h = 3; h < 16; ++h) {
|
||||
db.add_block(mkblock(hf, h, block_versions_new[h]), 0, 0, 0, 0, 0, num_rct_outs_by_asset_type, crypto::hash());
|
||||
db.add_block(mkblock(hf, h, block_versions_new[h]), 0, 0, 0, 0, 0, num_rct_outs_by_asset_type, crypto::hash(), 0, 0, cryptonote::FAKECHAIN, ybi);
|
||||
bool ret = hf.add(db.get_block_from_height(h), h);
|
||||
ASSERT_EQ (ret, h < 15);
|
||||
}
|
||||
@@ -372,6 +384,7 @@ TEST(reorganize, Changed)
|
||||
TEST(voting, threshold)
|
||||
{
|
||||
oracle::asset_type_counts num_rct_outs_by_asset_type;
|
||||
cryptonote::yield_block_info ybi;
|
||||
for (int threshold = 87; threshold <= 88; ++threshold) {
|
||||
TestDB db;
|
||||
HardFork hf(db, 1, 0, 1, 1, 8, threshold);
|
||||
@@ -383,7 +396,7 @@ TEST(voting, threshold)
|
||||
|
||||
for (uint64_t h = 0; h <= 8; ++h) {
|
||||
uint8_t v = 1 + !!(h % 8);
|
||||
db.add_block(mkblock(hf, h, v), 0, 0, 0, 0, 0, num_rct_outs_by_asset_type, crypto::hash());
|
||||
db.add_block(mkblock(hf, h, v), 0, 0, 0, 0, 0, num_rct_outs_by_asset_type, crypto::hash(), 0, 0, cryptonote::FAKECHAIN, ybi);
|
||||
bool ret = hf.add(db.get_block_from_height(h), h);
|
||||
if (h >= 8 && threshold == 87) {
|
||||
// for threshold 87, we reach the treshold at height 7, so from height 8, hard fork to version 2, but 8 tries to add 1
|
||||
@@ -402,6 +415,7 @@ TEST(voting, threshold)
|
||||
TEST(voting, different_thresholds)
|
||||
{
|
||||
oracle::asset_type_counts num_rct_outs_by_asset_type;
|
||||
cryptonote::yield_block_info ybi;
|
||||
for (int threshold = 87; threshold <= 88; ++threshold) {
|
||||
TestDB db;
|
||||
HardFork hf(db, 1, 0, 1, 1, 4, 50); // window size 4
|
||||
@@ -418,7 +432,7 @@ TEST(voting, different_thresholds)
|
||||
static const uint8_t expected_versions[] = { 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4 };
|
||||
|
||||
for (uint64_t h = 0; h < sizeof(block_versions) / sizeof(block_versions[0]); ++h) {
|
||||
db.add_block(mkblock(hf, h, block_versions[h]), 0, 0, 0, 0, 0, num_rct_outs_by_asset_type, crypto::hash());
|
||||
db.add_block(mkblock(hf, h, block_versions[h]), 0, 0, 0, 0, 0, num_rct_outs_by_asset_type, crypto::hash(), 0, 0, cryptonote::FAKECHAIN, ybi);
|
||||
bool ret = hf.add(db.get_block_from_height(h), h);
|
||||
ASSERT_EQ(ret, true);
|
||||
}
|
||||
@@ -433,6 +447,7 @@ TEST(voting, info)
|
||||
TestDB db;
|
||||
HardFork hf(db, 1, 0, 1, 1, 4, 50); // window size 4, default threshold 50%
|
||||
oracle::asset_type_counts num_rct_outs_by_asset_type;
|
||||
cryptonote::yield_block_info ybi;
|
||||
|
||||
// v h ts
|
||||
ASSERT_TRUE(hf.add_fork(1, 0, 0));
|
||||
@@ -472,7 +487,7 @@ TEST(voting, info)
|
||||
ASSERT_EQ(expected_thresholds[h], threshold);
|
||||
ASSERT_EQ(4, voting);
|
||||
|
||||
db.add_block(mkblock(hf, h, block_versions[h]), 0, 0, 0, 0, 0, num_rct_outs_by_asset_type, crypto::hash());
|
||||
db.add_block(mkblock(hf, h, block_versions[h]), 0, 0, 0, 0, 0, num_rct_outs_by_asset_type, crypto::hash(), 0, 0, cryptonote::FAKECHAIN, ybi);
|
||||
ASSERT_TRUE(hf.add(db.get_block_from_height(h), h));
|
||||
}
|
||||
}
|
||||
@@ -536,7 +551,8 @@ TEST(reorganize, changed)
|
||||
do { \
|
||||
cryptonote::block b = mkblock(hf, h, v); \
|
||||
oracle::asset_type_counts num_rct_outs_by_asset_type; \
|
||||
db.add_block(b, 0, 0, 0, 0, 0, num_rct_outs_by_asset_type, crypto::hash()); \
|
||||
cryptonote::yield_block_info ybi; \
|
||||
db.add_block(b, 0, 0, 0, 0, 0, num_rct_outs_by_asset_type, crypto::hash(), 0, 0, cryptonote::FAKECHAIN, ybi); \
|
||||
ASSERT_##a(hf.add(b, h)); \
|
||||
} while(0)
|
||||
#define ADD_TRUE(v, h) ADD(v, h, TRUE)
|
||||
|
||||
@@ -59,6 +59,10 @@ public:
|
||||
, uint64_t num_rct_outs
|
||||
, oracle::asset_type_counts& cum_rct_by_asset_type
|
||||
, const crypto::hash& blk_hash
|
||||
, uint64_t slippage_total
|
||||
, uint64_t yield_total
|
||||
, const cryptonote::network_type nettype
|
||||
, cryptonote::yield_block_info& ybi
|
||||
) override {
|
||||
blocks.push_back({block_weight, long_term_block_weight});
|
||||
}
|
||||
@@ -107,16 +111,10 @@ static uint32_t lcg()
|
||||
|
||||
}
|
||||
|
||||
struct BlockchainAndPool
|
||||
{
|
||||
cryptonote::tx_memory_pool txpool;
|
||||
cryptonote::Blockchain bc;
|
||||
BlockchainAndPool(): txpool(bc), bc(txpool) {}
|
||||
};
|
||||
|
||||
#define PREFIX_WINDOW(hf_version,window) \
|
||||
BlockchainAndPool bap; \
|
||||
cryptonote::Blockchain *bc = &bap.bc; \
|
||||
cryptonote::BlockchainAndPool bap; \
|
||||
cryptonote::Blockchain *bc = &bap.blockchain; \
|
||||
cryptonote::yield_block_info ybi; \
|
||||
struct get_test_options { \
|
||||
const std::pair<uint8_t, uint64_t> hard_forks[3]; \
|
||||
const cryptonote::test_options test_options = { \
|
||||
@@ -148,7 +146,7 @@ TEST(long_term_block_weight, identical_before_fork)
|
||||
{
|
||||
size_t w = h < CRYPTONOTE_REWARD_BLOCKS_WINDOW ? CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5 : bc->get_current_cumulative_block_weight_limit();
|
||||
uint64_t ltw = bc->get_next_long_term_block_weight(w);
|
||||
bc->get_db().add_block(std::make_pair(cryptonote::block(), ""), w, ltw, h, h, {});
|
||||
bc->get_db().add_block(std::make_pair(cryptonote::block(), ""), w, ltw, h, h, {}, cryptonote::FAKECHAIN, ybi);
|
||||
ASSERT_TRUE(bc->update_next_cumulative_weight_limit());
|
||||
}
|
||||
for (uint64_t h = 0; h < 10 * TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW; ++h)
|
||||
@@ -165,7 +163,7 @@ TEST(long_term_block_weight, identical_after_fork_before_long_term_window)
|
||||
{
|
||||
size_t w = h < TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW ? CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5 : bc->get_current_cumulative_block_weight_limit();
|
||||
uint64_t ltw = bc->get_next_long_term_block_weight(w);
|
||||
bc->get_db().add_block(std::make_pair(cryptonote::block(), ""), w, ltw, h, h, {});
|
||||
bc->get_db().add_block(std::make_pair(cryptonote::block(), ""), w, ltw, h, h, {}, cryptonote::FAKECHAIN, ybi);
|
||||
ASSERT_TRUE(bc->update_next_cumulative_weight_limit());
|
||||
}
|
||||
for (uint64_t h = 0; h < TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW; ++h)
|
||||
@@ -182,7 +180,7 @@ TEST(long_term_block_weight, ceiling_at_30000000)
|
||||
{
|
||||
size_t w = h < TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW ? CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5 : bc->get_current_cumulative_block_weight_limit();
|
||||
uint64_t ltw = bc->get_next_long_term_block_weight(w);
|
||||
bc->get_db().add_block(std::make_pair(cryptonote::block(), ""), w, ltw, h, h, {});
|
||||
bc->get_db().add_block(std::make_pair(cryptonote::block(), ""), w, ltw, h, h, {}, cryptonote::FAKECHAIN, ybi);
|
||||
ASSERT_TRUE(bc->update_next_cumulative_weight_limit());
|
||||
}
|
||||
ASSERT_EQ(bc->get_current_cumulative_block_weight_median(), 15000000);
|
||||
@@ -197,7 +195,7 @@ TEST(long_term_block_weight, multi_pop)
|
||||
{
|
||||
size_t w = h < TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW ? CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5 : bc->get_current_cumulative_block_weight_limit();
|
||||
uint64_t ltw = bc->get_next_long_term_block_weight(w);
|
||||
bc->get_db().add_block(std::make_pair(cryptonote::block(), ""), w, ltw, h, h, {});
|
||||
bc->get_db().add_block(std::make_pair(cryptonote::block(), ""), w, ltw, h, h, {}, cryptonote::FAKECHAIN, ybi);
|
||||
ASSERT_TRUE(bc->update_next_cumulative_weight_limit());
|
||||
}
|
||||
|
||||
@@ -209,7 +207,7 @@ TEST(long_term_block_weight, multi_pop)
|
||||
{
|
||||
size_t w = bc->get_current_cumulative_block_weight_limit();
|
||||
uint64_t ltw = bc->get_next_long_term_block_weight(w);
|
||||
bc->get_db().add_block(std::make_pair(cryptonote::block(), ""), w, ltw, h, h, {});
|
||||
bc->get_db().add_block(std::make_pair(cryptonote::block(), ""), w, ltw, h, h, {}, cryptonote::FAKECHAIN, ybi);
|
||||
ASSERT_TRUE(bc->update_next_cumulative_weight_limit());
|
||||
}
|
||||
|
||||
@@ -231,7 +229,7 @@ TEST(long_term_block_weight, multiple_updates)
|
||||
{
|
||||
size_t w = h < TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW ? CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5 : bc->get_current_cumulative_block_weight_limit();
|
||||
uint64_t ltw = bc->get_next_long_term_block_weight(w);
|
||||
bc->get_db().add_block(std::make_pair(cryptonote::block(), ""), w, ltw, h, h, {});
|
||||
bc->get_db().add_block(std::make_pair(cryptonote::block(), ""), w, ltw, h, h, {}, cryptonote::FAKECHAIN, ybi);
|
||||
ASSERT_TRUE(bc->update_next_cumulative_weight_limit());
|
||||
const uint64_t effective_median = bc->get_current_cumulative_block_weight_median();
|
||||
const uint64_t effective_limit = bc->get_current_cumulative_block_weight_limit();
|
||||
@@ -255,7 +253,7 @@ TEST(long_term_block_weight, pop_invariant_max)
|
||||
{
|
||||
size_t w = bc->get_db().height() < TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW ? CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5 : bc->get_current_cumulative_block_weight_limit();
|
||||
uint64_t ltw = bc->get_next_long_term_block_weight(w);
|
||||
bc->get_db().add_block(std::make_pair(cryptonote::block(), ""), w, ltw, h, h, {});
|
||||
bc->get_db().add_block(std::make_pair(cryptonote::block(), ""), w, ltw, h, h, {}, cryptonote::FAKECHAIN, ybi);
|
||||
ASSERT_TRUE(bc->update_next_cumulative_weight_limit());
|
||||
}
|
||||
|
||||
@@ -283,7 +281,7 @@ TEST(long_term_block_weight, pop_invariant_max)
|
||||
{
|
||||
size_t w = bc->get_db().height() < TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW ? CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5 : bc->get_current_cumulative_block_weight_limit();
|
||||
uint64_t ltw = bc->get_next_long_term_block_weight(w);
|
||||
bc->get_db().add_block(std::make_pair(cryptonote::block(), ""), w, ltw, bc->get_db().height(), bc->get_db().height(), {});
|
||||
bc->get_db().add_block(std::make_pair(cryptonote::block(), ""), w, ltw, bc->get_db().height(), bc->get_db().height(), {}, cryptonote::FAKECHAIN, ybi);
|
||||
ASSERT_TRUE(bc->update_next_cumulative_weight_limit());
|
||||
}
|
||||
|
||||
@@ -305,7 +303,7 @@ TEST(long_term_block_weight, pop_invariant_random)
|
||||
uint32_t r = lcg();
|
||||
size_t w = bc->get_db().height() < TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW ? CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5 : (r % bc->get_current_cumulative_block_weight_limit());
|
||||
uint64_t ltw = bc->get_next_long_term_block_weight(w);
|
||||
bc->get_db().add_block(std::make_pair(cryptonote::block(), ""), w, ltw, h, h, {});
|
||||
bc->get_db().add_block(std::make_pair(cryptonote::block(), ""), w, ltw, h, h, {}, cryptonote::FAKECHAIN, ybi);
|
||||
ASSERT_TRUE(bc->update_next_cumulative_weight_limit());
|
||||
}
|
||||
|
||||
@@ -340,7 +338,7 @@ TEST(long_term_block_weight, pop_invariant_random)
|
||||
uint32_t r = lcg();
|
||||
size_t w = bc->get_db().height() < TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW ? CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5 : (r % bc->get_current_cumulative_block_weight_limit());
|
||||
uint64_t ltw = bc->get_next_long_term_block_weight(w);
|
||||
bc->get_db().add_block(std::make_pair(cryptonote::block(), ""), w, ltw, bc->get_db().height(), bc->get_db().height(), {});
|
||||
bc->get_db().add_block(std::make_pair(cryptonote::block(), ""), w, ltw, bc->get_db().height(), bc->get_db().height(), {}, cryptonote::FAKECHAIN, ybi);
|
||||
ASSERT_TRUE(bc->update_next_cumulative_weight_limit());
|
||||
const uint64_t effective_median = bc->get_current_cumulative_block_weight_median();
|
||||
const uint64_t effective_limit = bc->get_current_cumulative_block_weight_limit();
|
||||
@@ -368,7 +366,7 @@ TEST(long_term_block_weight, long_growth_spike_and_drop)
|
||||
{
|
||||
size_t w = CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5;
|
||||
uint64_t ltw = bc->get_next_long_term_block_weight(w);
|
||||
bc->get_db().add_block(std::make_pair(cryptonote::block(), ""), w, ltw, h, h, {});
|
||||
bc->get_db().add_block(std::make_pair(cryptonote::block(), ""), w, ltw, h, h, {}, cryptonote::FAKECHAIN, ybi);
|
||||
ASSERT_TRUE(bc->update_next_cumulative_weight_limit(&long_term_effective_median_block_weight));
|
||||
}
|
||||
ASSERT_EQ(long_term_effective_median_block_weight, 300000);
|
||||
@@ -380,7 +378,7 @@ TEST(long_term_block_weight, long_growth_spike_and_drop)
|
||||
float t = h / float(365 * 720 * TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW / 100000);
|
||||
size_t w = 300000 + t * 30000;
|
||||
uint64_t ltw = bc->get_next_long_term_block_weight(w);
|
||||
bc->get_db().add_block(std::make_pair(cryptonote::block(), ""), w, ltw, h, h, {});
|
||||
bc->get_db().add_block(std::make_pair(cryptonote::block(), ""), w, ltw, h, h, {}, cryptonote::FAKECHAIN, ybi);
|
||||
ASSERT_TRUE(bc->update_next_cumulative_weight_limit(&long_term_effective_median_block_weight));
|
||||
}
|
||||
ASSERT_GT(long_term_effective_median_block_weight, 300000 * 1.07);
|
||||
@@ -391,7 +389,7 @@ TEST(long_term_block_weight, long_growth_spike_and_drop)
|
||||
{
|
||||
size_t w = bc->get_current_cumulative_block_weight_limit();
|
||||
uint64_t ltw = bc->get_next_long_term_block_weight(w);
|
||||
bc->get_db().add_block(std::make_pair(cryptonote::block(), ""), w, ltw, h, h, {});
|
||||
bc->get_db().add_block(std::make_pair(cryptonote::block(), ""), w, ltw, h, h, {}, cryptonote::FAKECHAIN, ybi);
|
||||
ASSERT_TRUE(bc->update_next_cumulative_weight_limit(&long_term_effective_median_block_weight));
|
||||
}
|
||||
ASSERT_GT(long_term_effective_median_block_weight, 300000 * 1.07);
|
||||
@@ -402,7 +400,7 @@ TEST(long_term_block_weight, long_growth_spike_and_drop)
|
||||
{
|
||||
size_t w = bc->get_current_cumulative_block_weight_median() * .25;
|
||||
uint64_t ltw = bc->get_next_long_term_block_weight(w);
|
||||
bc->get_db().add_block(std::make_pair(cryptonote::block(), ""), w, ltw, h, h, {});
|
||||
bc->get_db().add_block(std::make_pair(cryptonote::block(), ""), w, ltw, h, h, {}, cryptonote::FAKECHAIN, ybi);
|
||||
ASSERT_TRUE(bc->update_next_cumulative_weight_limit(&long_term_effective_median_block_weight));
|
||||
}
|
||||
ASSERT_GT(long_term_effective_median_block_weight, 300000 * 1.07);
|
||||
|
||||
+37
-42
@@ -555,8 +555,6 @@ TEST(i2p_address, invalid)
|
||||
EXPECT_TRUE(net::i2p_address::make(".b32.i2p:").has_error());
|
||||
EXPECT_TRUE(net::i2p_address::make(b32_i2p + 1).has_error());
|
||||
EXPECT_TRUE(net::i2p_address::make(boost::string_ref{b32_i2p, sizeof(b32_i2p) - 2}).has_error());
|
||||
EXPECT_TRUE(net::i2p_address::make(std::string{b32_i2p} + ":65536").has_error());
|
||||
EXPECT_TRUE(net::i2p_address::make(std::string{b32_i2p} + ":-1").has_error());
|
||||
|
||||
std::string i2p{b32_i2p};
|
||||
i2p.at(10) = 1;
|
||||
@@ -570,7 +568,7 @@ TEST(i2p_address, unblockable_types)
|
||||
ASSERT_NE(nullptr, i2p.host_str());
|
||||
EXPECT_STREQ("<unknown i2p host>", i2p.host_str());
|
||||
EXPECT_STREQ("<unknown i2p host>", i2p.str().c_str());
|
||||
EXPECT_EQ(0u, i2p.port());
|
||||
EXPECT_EQ(1u, i2p.port());
|
||||
EXPECT_TRUE(i2p.is_unknown());
|
||||
EXPECT_FALSE(i2p.is_local());
|
||||
EXPECT_FALSE(i2p.is_loopback());
|
||||
@@ -581,7 +579,7 @@ TEST(i2p_address, unblockable_types)
|
||||
ASSERT_NE(nullptr, i2p.host_str());
|
||||
EXPECT_STREQ("<unknown i2p host>", i2p.host_str());
|
||||
EXPECT_STREQ("<unknown i2p host>", i2p.str().c_str());
|
||||
EXPECT_EQ(0u, i2p.port());
|
||||
EXPECT_EQ(1u, i2p.port());
|
||||
EXPECT_TRUE(i2p.is_unknown());
|
||||
EXPECT_FALSE(i2p.is_local());
|
||||
EXPECT_FALSE(i2p.is_loopback());
|
||||
@@ -596,14 +594,14 @@ TEST(i2p_address, valid)
|
||||
const auto address1 = net::i2p_address::make(b32_i2p);
|
||||
|
||||
ASSERT_TRUE(address1.has_value());
|
||||
EXPECT_EQ(0u, address1->port());
|
||||
EXPECT_EQ(1u, address1->port());
|
||||
EXPECT_STREQ(b32_i2p, address1->host_str());
|
||||
EXPECT_STREQ(b32_i2p, address1->str().c_str());
|
||||
EXPECT_TRUE(address1->is_blockable());
|
||||
|
||||
net::i2p_address address2{*address1};
|
||||
|
||||
EXPECT_EQ(0u, address2.port());
|
||||
EXPECT_EQ(1u, address2.port());
|
||||
EXPECT_STREQ(b32_i2p, address2.host_str());
|
||||
EXPECT_STREQ(b32_i2p, address2.str().c_str());
|
||||
EXPECT_TRUE(address2.is_blockable());
|
||||
@@ -620,9 +618,9 @@ TEST(i2p_address, valid)
|
||||
|
||||
address2 = MONERO_UNWRAP(net::i2p_address::make(std::string{b32_i2p_2} + ":6545"));
|
||||
|
||||
EXPECT_EQ(6545, address2.port());
|
||||
EXPECT_EQ(1u, address2.port());
|
||||
EXPECT_STREQ(b32_i2p_2, address2.host_str());
|
||||
EXPECT_EQ(std::string{b32_i2p_2} + ":6545", address2.str().c_str());
|
||||
EXPECT_EQ(std::string{b32_i2p_2}, address2.str().c_str());
|
||||
EXPECT_TRUE(address2.is_blockable());
|
||||
EXPECT_FALSE(address2.equal(*address1));
|
||||
EXPECT_FALSE(address1->equal(address2));
|
||||
@@ -635,22 +633,22 @@ TEST(i2p_address, valid)
|
||||
EXPECT_FALSE(address2.less(*address1));
|
||||
EXPECT_TRUE(address1->less(address2));
|
||||
|
||||
net::i2p_address address3 = MONERO_UNWRAP(net::i2p_address::make(std::string{b32_i2p} + ":", 65535));
|
||||
net::i2p_address address3 = MONERO_UNWRAP(net::i2p_address::make(std::string{b32_i2p} + ":65535"));
|
||||
|
||||
EXPECT_EQ(65535, address3.port());
|
||||
EXPECT_EQ(1u, address3.port());
|
||||
EXPECT_STREQ(b32_i2p, address3.host_str());
|
||||
EXPECT_EQ(std::string{b32_i2p} + ":65535", address3.str().c_str());
|
||||
EXPECT_EQ(std::string{b32_i2p}, address3.str().c_str());
|
||||
EXPECT_TRUE(address3.is_blockable());
|
||||
EXPECT_FALSE(address3.equal(*address1));
|
||||
EXPECT_FALSE(address1->equal(address3));
|
||||
EXPECT_FALSE(address3 == *address1);
|
||||
EXPECT_FALSE(*address1 == address3);
|
||||
EXPECT_TRUE(address3 != *address1);
|
||||
EXPECT_TRUE(*address1 != address3);
|
||||
EXPECT_TRUE(address3.equal(*address1));
|
||||
EXPECT_TRUE(address1->equal(address3));
|
||||
EXPECT_TRUE(address3 == *address1);
|
||||
EXPECT_TRUE(*address1 == address3);
|
||||
EXPECT_FALSE(address3 != *address1);
|
||||
EXPECT_FALSE(*address1 != address3);
|
||||
EXPECT_TRUE(address3.is_same_host(*address1));
|
||||
EXPECT_TRUE(address1->is_same_host(address3));
|
||||
EXPECT_FALSE(address3.less(*address1));
|
||||
EXPECT_TRUE(address1->less(address3));
|
||||
EXPECT_FALSE(address1->less(address3));
|
||||
|
||||
EXPECT_FALSE(address3.equal(address2));
|
||||
EXPECT_FALSE(address2.equal(address3));
|
||||
@@ -666,8 +664,8 @@ TEST(i2p_address, valid)
|
||||
|
||||
TEST(i2p_address, generic_network_address)
|
||||
{
|
||||
const epee::net_utils::network_address i2p1{MONERO_UNWRAP(net::i2p_address::make(b32_i2p, 8080))};
|
||||
const epee::net_utils::network_address i2p2{MONERO_UNWRAP(net::i2p_address::make(b32_i2p, 8080))};
|
||||
const epee::net_utils::network_address i2p1{MONERO_UNWRAP(net::i2p_address::make(b32_i2p))};
|
||||
const epee::net_utils::network_address i2p2{MONERO_UNWRAP(net::i2p_address::make(b32_i2p))};
|
||||
const epee::net_utils::network_address ip{epee::net_utils::ipv4_network_address{100, 200}};
|
||||
|
||||
EXPECT_EQ(i2p1, i2p2);
|
||||
@@ -675,7 +673,7 @@ TEST(i2p_address, generic_network_address)
|
||||
EXPECT_LT(ip, i2p1);
|
||||
|
||||
EXPECT_STREQ(b32_i2p, i2p1.host_str().c_str());
|
||||
EXPECT_EQ(std::string{b32_i2p} + ":8080", i2p1.str());
|
||||
EXPECT_STREQ(b32_i2p, i2p1.str().c_str());
|
||||
EXPECT_EQ(epee::net_utils::address_type::i2p, i2p1.get_type_id());
|
||||
EXPECT_EQ(epee::net_utils::address_type::i2p, i2p2.get_type_id());
|
||||
EXPECT_EQ(epee::net_utils::address_type::ipv4, ip.get_type_id());
|
||||
@@ -703,11 +701,11 @@ TEST(i2p_address, epee_serializev_b32)
|
||||
{
|
||||
epee::byte_slice buffer{};
|
||||
{
|
||||
test_command_i2p command{MONERO_UNWRAP(net::i2p_address::make(b32_i2p, 10))};
|
||||
test_command_i2p command{MONERO_UNWRAP(net::i2p_address::make(b32_i2p))};
|
||||
EXPECT_FALSE(command.i2p.is_unknown());
|
||||
EXPECT_NE(net::i2p_address{}, command.i2p);
|
||||
EXPECT_STREQ(b32_i2p, command.i2p.host_str());
|
||||
EXPECT_EQ(10u, command.i2p.port());
|
||||
EXPECT_EQ(1u, command.i2p.port());
|
||||
|
||||
epee::serialization::portable_storage stg{};
|
||||
EXPECT_TRUE(command.store(stg));
|
||||
@@ -719,7 +717,7 @@ TEST(i2p_address, epee_serializev_b32)
|
||||
EXPECT_TRUE(command.i2p.is_unknown());
|
||||
EXPECT_EQ(net::i2p_address{}, command.i2p);
|
||||
EXPECT_STREQ(net::i2p_address::unknown_str(), command.i2p.host_str());
|
||||
EXPECT_EQ(0u, command.i2p.port());
|
||||
EXPECT_EQ(1u, command.i2p.port());
|
||||
|
||||
epee::serialization::portable_storage stg{};
|
||||
EXPECT_TRUE(stg.load_from_binary(epee::to_span(buffer)));
|
||||
@@ -728,7 +726,7 @@ TEST(i2p_address, epee_serializev_b32)
|
||||
EXPECT_FALSE(command.i2p.is_unknown());
|
||||
EXPECT_NE(net::i2p_address{}, command.i2p);
|
||||
EXPECT_STREQ(b32_i2p, command.i2p.host_str());
|
||||
EXPECT_EQ(10u, command.i2p.port());
|
||||
EXPECT_EQ(1u, command.i2p.port());
|
||||
|
||||
// make sure that exceeding max buffer doesn't destroy i2p_address::_load
|
||||
{
|
||||
@@ -747,7 +745,7 @@ TEST(i2p_address, epee_serializev_b32)
|
||||
EXPECT_TRUE(command.i2p.is_unknown());
|
||||
EXPECT_EQ(net::i2p_address{}, command.i2p);
|
||||
EXPECT_STRNE(b32_i2p, command.i2p.host_str());
|
||||
EXPECT_EQ(0u, command.i2p.port());
|
||||
EXPECT_EQ(1u, command.i2p.port());
|
||||
}
|
||||
|
||||
TEST(i2p_address, epee_serialize_unknown)
|
||||
@@ -758,7 +756,7 @@ TEST(i2p_address, epee_serialize_unknown)
|
||||
EXPECT_TRUE(command.i2p.is_unknown());
|
||||
EXPECT_EQ(net::i2p_address{}, command.i2p);
|
||||
EXPECT_STREQ(net::i2p_address::unknown_str(), command.i2p.host_str());
|
||||
EXPECT_EQ(0u, command.i2p.port());
|
||||
EXPECT_EQ(1u, command.i2p.port());
|
||||
|
||||
epee::serialization::portable_storage stg{};
|
||||
EXPECT_TRUE(command.store(stg));
|
||||
@@ -770,7 +768,7 @@ TEST(i2p_address, epee_serialize_unknown)
|
||||
EXPECT_TRUE(command.i2p.is_unknown());
|
||||
EXPECT_EQ(net::i2p_address{}, command.i2p);
|
||||
EXPECT_STRNE(b32_i2p, command.i2p.host_str());
|
||||
EXPECT_EQ(0u, command.i2p.port());
|
||||
EXPECT_EQ(1u, command.i2p.port());
|
||||
|
||||
epee::serialization::portable_storage stg{};
|
||||
EXPECT_TRUE(stg.load_from_binary(epee::to_span(buffer)));
|
||||
@@ -779,7 +777,7 @@ TEST(i2p_address, epee_serialize_unknown)
|
||||
EXPECT_TRUE(command.i2p.is_unknown());
|
||||
EXPECT_EQ(net::i2p_address{}, command.i2p);
|
||||
EXPECT_STREQ(net::i2p_address::unknown_str(), command.i2p.host_str());
|
||||
EXPECT_EQ(0u, command.i2p.port());
|
||||
EXPECT_EQ(1u, command.i2p.port());
|
||||
|
||||
// make sure that exceeding max buffer doesn't destroy i2p_address::_load
|
||||
{
|
||||
@@ -798,18 +796,18 @@ TEST(i2p_address, epee_serialize_unknown)
|
||||
EXPECT_TRUE(command.i2p.is_unknown());
|
||||
EXPECT_EQ(net::i2p_address{}, command.i2p);
|
||||
EXPECT_STRNE(b32_i2p, command.i2p.host_str());
|
||||
EXPECT_EQ(0u, command.i2p.port());
|
||||
EXPECT_EQ(1u, command.i2p.port());
|
||||
}
|
||||
|
||||
TEST(i2p_address, boost_serialize_b32)
|
||||
{
|
||||
std::string buffer{};
|
||||
{
|
||||
const net::i2p_address i2p = MONERO_UNWRAP(net::i2p_address::make(b32_i2p, 10));
|
||||
const net::i2p_address i2p = MONERO_UNWRAP(net::i2p_address::make(b32_i2p));
|
||||
EXPECT_FALSE(i2p.is_unknown());
|
||||
EXPECT_NE(net::i2p_address{}, i2p);
|
||||
EXPECT_STREQ(b32_i2p, i2p.host_str());
|
||||
EXPECT_EQ(10u, i2p.port());
|
||||
EXPECT_EQ(1u, i2p.port());
|
||||
|
||||
std::ostringstream stream{};
|
||||
{
|
||||
@@ -824,7 +822,7 @@ TEST(i2p_address, boost_serialize_b32)
|
||||
EXPECT_TRUE(i2p.is_unknown());
|
||||
EXPECT_EQ(net::i2p_address{}, i2p);
|
||||
EXPECT_STREQ(net::i2p_address::unknown_str(), i2p.host_str());
|
||||
EXPECT_EQ(0u, i2p.port());
|
||||
EXPECT_EQ(1u, i2p.port());
|
||||
|
||||
std::istringstream stream{buffer};
|
||||
boost::archive::portable_binary_iarchive archive{stream};
|
||||
@@ -833,7 +831,7 @@ TEST(i2p_address, boost_serialize_b32)
|
||||
EXPECT_FALSE(i2p.is_unknown());
|
||||
EXPECT_NE(net::i2p_address{}, i2p);
|
||||
EXPECT_STREQ(b32_i2p, i2p.host_str());
|
||||
EXPECT_EQ(10u, i2p.port());
|
||||
EXPECT_EQ(1u, i2p.port());
|
||||
}
|
||||
|
||||
TEST(i2p_address, boost_serialize_unknown)
|
||||
@@ -844,7 +842,7 @@ TEST(i2p_address, boost_serialize_unknown)
|
||||
EXPECT_TRUE(i2p.is_unknown());
|
||||
EXPECT_EQ(net::i2p_address::unknown(), i2p);
|
||||
EXPECT_STREQ(net::i2p_address::unknown_str(), i2p.host_str());
|
||||
EXPECT_EQ(0u, i2p.port());
|
||||
EXPECT_EQ(1u, i2p.port());
|
||||
|
||||
std::ostringstream stream{};
|
||||
{
|
||||
@@ -859,7 +857,7 @@ TEST(i2p_address, boost_serialize_unknown)
|
||||
EXPECT_TRUE(i2p.is_unknown());
|
||||
EXPECT_EQ(net::i2p_address{}, i2p);
|
||||
EXPECT_STREQ(net::i2p_address::unknown_str(), i2p.host_str());
|
||||
EXPECT_EQ(0u, i2p.port());
|
||||
EXPECT_EQ(1u, i2p.port());
|
||||
|
||||
std::istringstream stream{buffer};
|
||||
boost::archive::portable_binary_iarchive archive{stream};
|
||||
@@ -868,7 +866,7 @@ TEST(i2p_address, boost_serialize_unknown)
|
||||
EXPECT_TRUE(i2p.is_unknown());
|
||||
EXPECT_EQ(net::i2p_address::unknown(), i2p);
|
||||
EXPECT_STREQ(net::i2p_address::unknown_str(), i2p.host_str());
|
||||
EXPECT_EQ(0u, i2p.port());
|
||||
EXPECT_EQ(1u, i2p.port());
|
||||
}
|
||||
|
||||
TEST(get_network_address, i2p)
|
||||
@@ -884,16 +882,13 @@ TEST(get_network_address, i2p)
|
||||
ASSERT_TRUE(bool(address));
|
||||
EXPECT_EQ(epee::net_utils::address_type::i2p, address->get_type_id());
|
||||
EXPECT_STREQ(b32_i2p, address->host_str().c_str());
|
||||
EXPECT_EQ(std::string{b32_i2p} + ":1000", address->str());
|
||||
EXPECT_EQ(std::string{b32_i2p}, address->str());
|
||||
|
||||
address = net::get_network_address(std::string{b32_i2p} + ":2000", 1000);
|
||||
ASSERT_TRUE(bool(address));
|
||||
EXPECT_EQ(epee::net_utils::address_type::i2p, address->get_type_id());
|
||||
EXPECT_STREQ(b32_i2p, address->host_str().c_str());
|
||||
EXPECT_EQ(std::string{b32_i2p} + ":2000", address->str());
|
||||
|
||||
address = net::get_network_address(std::string{b32_i2p} + ":65536", 1000);
|
||||
EXPECT_EQ(net::error::invalid_port, address);
|
||||
EXPECT_EQ(std::string{b32_i2p}, address->str());
|
||||
}
|
||||
|
||||
TEST(get_network_address, ipv4)
|
||||
|
||||
@@ -433,6 +433,7 @@ TEST(cryptonote_protocol_handler, race_condition)
|
||||
const block_t &block,
|
||||
const stat::chain &stat
|
||||
){
|
||||
cryptonote::yield_block_info ybi;
|
||||
core.get_blockchain_storage().get_db().batch_start({}, {});
|
||||
core.get_blockchain_storage().get_db().add_block(
|
||||
{block, cryptonote::block_to_blob(block)},
|
||||
@@ -442,7 +443,9 @@ TEST(cryptonote_protocol_handler, race_condition)
|
||||
),
|
||||
stat.diff,
|
||||
stat.reward,
|
||||
{}
|
||||
{},
|
||||
cryptonote::FAKECHAIN,
|
||||
ybi
|
||||
);
|
||||
core.get_blockchain_storage().get_db().batch_stop();
|
||||
};
|
||||
|
||||
@@ -30,10 +30,7 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "misc_log_ex.h"
|
||||
#include "rpc/rpc_handler.h"
|
||||
#include "blockchain_db/blockchain_db.h"
|
||||
#include "cryptonote_core/cryptonote_core.h"
|
||||
#include "cryptonote_core/tx_pool.h"
|
||||
#include "cryptonote_core/blockchain.h"
|
||||
#include "blockchain_db/testdb.h"
|
||||
|
||||
static const uint64_t test_distribution[32] = {
|
||||
@@ -77,9 +74,6 @@ public:
|
||||
|
||||
bool get_output_distribution(uint64_t amount, std::string asset_type, uint64_t from, uint64_t to, uint64_t &start_height, std::vector<uint64_t> &distribution, uint64_t &base, uint64_t &num_spendable_global_outs)
|
||||
{
|
||||
std::unique_ptr<cryptonote::Blockchain> bc;
|
||||
cryptonote::tx_memory_pool txpool(*bc);
|
||||
bc.reset(new cryptonote::Blockchain(txpool));
|
||||
struct get_test_options {
|
||||
const std::pair<uint8_t, uint64_t> hard_forks[2];
|
||||
const cryptonote::test_options test_options = {
|
||||
@@ -87,9 +81,9 @@ bool get_output_distribution(uint64_t amount, std::string asset_type, uint64_t f
|
||||
};
|
||||
get_test_options():hard_forks{std::make_pair((uint8_t)1, (uint64_t)0), std::make_pair((uint8_t)0, (uint64_t)0)}{}
|
||||
} opts;
|
||||
cryptonote::Blockchain *blockchain = bc.get();
|
||||
bool r = blockchain->init(new TestDB(test_distribution_size), cryptonote::FAKECHAIN, true, &opts.test_options, 0, NULL);
|
||||
return r && bc->get_output_distribution(amount, "FULM", from, to, start_height, distribution, base, num_spendable_global_outs);
|
||||
cryptonote::BlockchainAndPool bap;
|
||||
bool r = bap.blockchain.init(new TestDB(test_distribution_size), cryptonote::FAKECHAIN, true, &opts.test_options, 0, NULL);
|
||||
return r && bap.blockchain.get_output_distribution(amount, asset_type, from, to, start_height, distribution, base, num_spendable_global_outs);
|
||||
}
|
||||
|
||||
crypto::hash get_block_hash(uint64_t height)
|
||||
@@ -103,32 +97,32 @@ TEST(output_distribution, extend)
|
||||
{
|
||||
boost::optional<cryptonote::rpc::output_distribution_data> res;
|
||||
|
||||
res = cryptonote::rpc::RpcHandler::get_output_distribution(::get_output_distribution, 0, "FULM", 28, 29, ::get_block_hash, false, test_distribution_size);
|
||||
res = cryptonote::rpc::RpcHandler::get_output_distribution(::get_output_distribution, 0, "SAL", 28, 29, ::get_block_hash, false, test_distribution_size);
|
||||
ASSERT_TRUE(res != boost::none);
|
||||
ASSERT_EQ(res->distribution.size(), 2);
|
||||
ASSERT_EQ(res->distribution, std::vector<uint64_t>({5, 0}));
|
||||
|
||||
res = cryptonote::rpc::RpcHandler::get_output_distribution(::get_output_distribution, 0, "FULM", 28, 29, ::get_block_hash, true, test_distribution_size);
|
||||
res = cryptonote::rpc::RpcHandler::get_output_distribution(::get_output_distribution, 0, "SAL", 28, 29, ::get_block_hash, true, test_distribution_size);
|
||||
ASSERT_TRUE(res != boost::none);
|
||||
ASSERT_EQ(res->distribution.size(), 2);
|
||||
ASSERT_EQ(res->distribution, std::vector<uint64_t>({55, 55}));
|
||||
|
||||
res = cryptonote::rpc::RpcHandler::get_output_distribution(::get_output_distribution, 0, "FULM", 28, 30, ::get_block_hash, false, test_distribution_size);
|
||||
res = cryptonote::rpc::RpcHandler::get_output_distribution(::get_output_distribution, 0, "SAL", 28, 30, ::get_block_hash, false, test_distribution_size);
|
||||
ASSERT_TRUE(res != boost::none);
|
||||
ASSERT_EQ(res->distribution.size(), 3);
|
||||
ASSERT_EQ(res->distribution, std::vector<uint64_t>({5, 0, 2}));
|
||||
|
||||
res = cryptonote::rpc::RpcHandler::get_output_distribution(::get_output_distribution, 0, "FULM", 28, 30, ::get_block_hash, true, test_distribution_size);
|
||||
res = cryptonote::rpc::RpcHandler::get_output_distribution(::get_output_distribution, 0, "SAL", 28, 30, ::get_block_hash, true, test_distribution_size);
|
||||
ASSERT_TRUE(res != boost::none);
|
||||
ASSERT_EQ(res->distribution.size(), 3);
|
||||
ASSERT_EQ(res->distribution, std::vector<uint64_t>({55, 55, 57}));
|
||||
|
||||
res = cryptonote::rpc::RpcHandler::get_output_distribution(::get_output_distribution, 0, "FULM", 28, 31, ::get_block_hash, false, test_distribution_size);
|
||||
res = cryptonote::rpc::RpcHandler::get_output_distribution(::get_output_distribution, 0, "SAL", 28, 31, ::get_block_hash, false, test_distribution_size);
|
||||
ASSERT_TRUE(res != boost::none);
|
||||
ASSERT_EQ(res->distribution.size(), 4);
|
||||
ASSERT_EQ(res->distribution, std::vector<uint64_t>({5, 0, 2, 3}));
|
||||
|
||||
res = cryptonote::rpc::RpcHandler::get_output_distribution(::get_output_distribution, 0, "FULM", 28, 31, ::get_block_hash, true, test_distribution_size);
|
||||
res = cryptonote::rpc::RpcHandler::get_output_distribution(::get_output_distribution, 0, "SAL", 28, 31, ::get_block_hash, true, test_distribution_size);
|
||||
ASSERT_TRUE(res != boost::none);
|
||||
ASSERT_EQ(res->distribution.size(), 4);
|
||||
ASSERT_EQ(res->distribution, std::vector<uint64_t>({55, 55, 57, 60}));
|
||||
@@ -138,7 +132,7 @@ TEST(output_distribution, one)
|
||||
{
|
||||
boost::optional<cryptonote::rpc::output_distribution_data> res;
|
||||
|
||||
res = cryptonote::rpc::RpcHandler::get_output_distribution(::get_output_distribution, 0, "FULM", 0, 0, ::get_block_hash, false, test_distribution_size);
|
||||
res = cryptonote::rpc::RpcHandler::get_output_distribution(::get_output_distribution, 0, "SAL", 0, 0, ::get_block_hash, false, test_distribution_size);
|
||||
ASSERT_TRUE(res != boost::none);
|
||||
ASSERT_EQ(res->distribution.size(), 1);
|
||||
ASSERT_EQ(res->distribution.back(), 0);
|
||||
@@ -148,7 +142,7 @@ TEST(output_distribution, full_cumulative)
|
||||
{
|
||||
boost::optional<cryptonote::rpc::output_distribution_data> res;
|
||||
|
||||
res = cryptonote::rpc::RpcHandler::get_output_distribution(::get_output_distribution, 0, "FULM", 0, 31, ::get_block_hash, true, test_distribution_size);
|
||||
res = cryptonote::rpc::RpcHandler::get_output_distribution(::get_output_distribution, 0, "SAL", 0, 31, ::get_block_hash, true, test_distribution_size);
|
||||
ASSERT_TRUE(res != boost::none);
|
||||
ASSERT_EQ(res->distribution.size(), 32);
|
||||
ASSERT_EQ(res->distribution.back(), 60);
|
||||
@@ -158,7 +152,7 @@ TEST(output_distribution, full_noncumulative)
|
||||
{
|
||||
boost::optional<cryptonote::rpc::output_distribution_data> res;
|
||||
|
||||
res = cryptonote::rpc::RpcHandler::get_output_distribution(::get_output_distribution, 0, "FULM", 0, 31, ::get_block_hash, false, test_distribution_size);
|
||||
res = cryptonote::rpc::RpcHandler::get_output_distribution(::get_output_distribution, 0, "SAL", 0, 31, ::get_block_hash, false, test_distribution_size);
|
||||
ASSERT_TRUE(res != boost::none);
|
||||
ASSERT_EQ(res->distribution.size(), 32);
|
||||
for (size_t i = 0; i < 32; ++i)
|
||||
@@ -169,7 +163,7 @@ TEST(output_distribution, part_cumulative)
|
||||
{
|
||||
boost::optional<cryptonote::rpc::output_distribution_data> res;
|
||||
|
||||
res = cryptonote::rpc::RpcHandler::get_output_distribution(::get_output_distribution, 0, "FULM", 4, 8, ::get_block_hash, true, test_distribution_size);
|
||||
res = cryptonote::rpc::RpcHandler::get_output_distribution(::get_output_distribution, 0, "SAL", 4, 8, ::get_block_hash, true, test_distribution_size);
|
||||
ASSERT_TRUE(res != boost::none);
|
||||
ASSERT_EQ(res->distribution.size(), 5);
|
||||
ASSERT_EQ(res->distribution, std::vector<uint64_t>({0, 1, 6, 7, 11}));
|
||||
@@ -179,7 +173,7 @@ TEST(output_distribution, part_noncumulative)
|
||||
{
|
||||
boost::optional<cryptonote::rpc::output_distribution_data> res;
|
||||
|
||||
res = cryptonote::rpc::RpcHandler::get_output_distribution(::get_output_distribution, 0, "FULM", 4, 8, ::get_block_hash, false, test_distribution_size);
|
||||
res = cryptonote::rpc::RpcHandler::get_output_distribution(::get_output_distribution, 0, "SAL", 4, 8, ::get_block_hash, false, test_distribution_size);
|
||||
ASSERT_TRUE(res != boost::none);
|
||||
ASSERT_EQ(res->distribution.size(), 5);
|
||||
ASSERT_EQ(res->distribution, std::vector<uint64_t>({0, 1, 5, 1, 4}));
|
||||
|
||||
@@ -42,19 +42,12 @@ TEST(pricing_record, verify_serialization)
|
||||
oracle::pricing_record pr;
|
||||
oracle::pricing_record pr1;
|
||||
pr.pr_version = 1;
|
||||
pr.height = 1234;
|
||||
pr.supply = {100000,0};
|
||||
pr.timestamp = 1632401454;
|
||||
pr.spot = COIN<<1;
|
||||
pr.moving_average = (COIN * 3) >> 2;
|
||||
memset(pr.signature, 0, 64);
|
||||
pr.assets = {};
|
||||
pr.signature = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
|
||||
/*
|
||||
oracle::pricing_record_entry foo;
|
||||
foo.first = "FULM";
|
||||
foo.second.first = 2;
|
||||
foo.second.second = 3;
|
||||
pr.assets.push_back(foo);
|
||||
*/
|
||||
|
||||
std::string blob;
|
||||
ASSERT_TRUE(serialization::dump_binary(pr, blob));
|
||||
ASSERT_TRUE(serialization::parse_binary(blob, pr1));
|
||||
|
||||
@@ -345,10 +345,10 @@ TEST(ringct, range_proofs)
|
||||
ASSERT_TRUE(ok);
|
||||
|
||||
cryptonote::transaction_type tx_type = cryptonote::transaction_type::TRANSFER;
|
||||
std::string in_asset_type = "FULM";
|
||||
std::string in_asset_type = "SAL";
|
||||
std::vector<std::string> destination_asset_types;
|
||||
for (size_t i = 0; i < destinations.size(); ++i)
|
||||
destination_asset_types.push_back("FULM");
|
||||
destination_asset_types.push_back("SAL");
|
||||
|
||||
//compute rct data with mixin 3
|
||||
rctSig s = genRctSimple(rct::zero(), sc, pc, destinations, tx_type, in_asset_type, destination_asset_types, inamounts, amounts, amount_keys, 0, 3, rct_config, hw::get_device("default"));
|
||||
@@ -416,10 +416,10 @@ TEST(ringct, range_proofs_with_fee)
|
||||
const rct::RCTConfig rct_config { RangeProofBorromean, 0 };
|
||||
|
||||
cryptonote::transaction_type tx_type = cryptonote::transaction_type::TRANSFER;
|
||||
std::string in_asset_type = "FULM";
|
||||
std::string in_asset_type = "SAL";
|
||||
std::vector<std::string> destination_asset_types;
|
||||
for (size_t i = 0; i < destinations.size(); ++i)
|
||||
destination_asset_types.push_back("FULM");
|
||||
destination_asset_types.push_back("SAL");
|
||||
|
||||
//compute rct data with mixin 3
|
||||
rctSig s = genRctSimple(rct::zero(), sc, pc, destinations, tx_type, in_asset_type, destination_asset_types, inamounts, amounts, amount_keys, 1, 3, rct_config, hw::get_device("default"));
|
||||
@@ -499,10 +499,10 @@ TEST(ringct, simple)
|
||||
|
||||
const rct::RCTConfig rct_config { RangeProofBorromean, 0 };
|
||||
cryptonote::transaction_type tx_type = cryptonote::transaction_type::TRANSFER;
|
||||
std::string in_asset_type = "FULM";
|
||||
std::string in_asset_type = "SAL";
|
||||
std::vector<std::string> destination_asset_types;
|
||||
for (size_t i = 0; i < destinations.size(); ++i)
|
||||
destination_asset_types.push_back("FULM");
|
||||
destination_asset_types.push_back("SAL");
|
||||
|
||||
rctSig s = genRctSimple(message, sc, pc, destinations, tx_type, in_asset_type, destination_asset_types, inamounts, outamounts, amount_keys, txnfee, 2, rct_config, hw::get_device("default"));
|
||||
|
||||
@@ -538,7 +538,7 @@ static rct::rctSig make_sample_rct_sig(int n_inputs, const uint64_t input_amount
|
||||
}
|
||||
}
|
||||
|
||||
const rct::RCTConfig rct_config { RangeProofBorromean, 0 };
|
||||
const rct::RCTConfig rct_config { RangeProofBorromean, 0 };
|
||||
return genRct(rct::zero(), sc, pc, destinations, amounts, amount_keys, 3, rct_config, hw::get_device("default"));
|
||||
}
|
||||
|
||||
@@ -567,10 +567,10 @@ static rct::rctSig make_sample_simple_rct_sig(int n_inputs, const uint64_t input
|
||||
|
||||
const rct::RCTConfig rct_config { RangeProofBorromean, 0 };
|
||||
cryptonote::transaction_type tx_type = cryptonote::transaction_type::TRANSFER;
|
||||
std::string in_asset_type = "FULM";
|
||||
std::string in_asset_type = "SAL";
|
||||
std::vector<std::string> destination_asset_types;
|
||||
for (size_t i = 0; i < destinations.size(); ++i)
|
||||
destination_asset_types.push_back("FULM");
|
||||
destination_asset_types.push_back("SAL");
|
||||
|
||||
return genRctSimple(rct::zero(), sc, pc, destinations, tx_type, in_asset_type, destination_asset_types, inamounts, outamounts, amount_keys, fee, 3, rct_config, hw::get_device("default"));
|
||||
}
|
||||
@@ -1291,3 +1291,39 @@ TEST(ringct, aggregated)
|
||||
ASSERT_TRUE(verRctSemanticsSimple(s[n]));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(ringct, pr_proof)
|
||||
{
|
||||
// Create a random commitment with 0 amount
|
||||
int success = 0, failure = 0;
|
||||
for (size_t i=0; i<1000; i++) {
|
||||
key Sk = skGen();
|
||||
sc_reduce32(Sk.bytes);
|
||||
key C;
|
||||
genC(C, Sk, i%100 ? 0 : i%99);
|
||||
zk_proof proof = PRProof_Gen(Sk);
|
||||
if (PRProof_Ver(C, proof))
|
||||
success++;
|
||||
else
|
||||
failure++;
|
||||
}
|
||||
ASSERT_EQ(failure, 9);
|
||||
}
|
||||
|
||||
TEST(ringct, sa_proof)
|
||||
{
|
||||
// Create a random commitment with 0 amount
|
||||
int success = 0, failure = 0;
|
||||
for (size_t i=0; i<1000; i++) {
|
||||
key Sk = skGen();
|
||||
sc_reduce32(Sk.bytes);
|
||||
key C;
|
||||
genC(C, Sk, i%100 ? 0 : i%99);
|
||||
zk_proof proof = PRProof_Gen(Sk);
|
||||
if (PRProof_Ver(C, proof))
|
||||
success++;
|
||||
else
|
||||
failure++;
|
||||
}
|
||||
ASSERT_EQ(failure, 9);
|
||||
}
|
||||
|
||||
@@ -50,9 +50,6 @@ public:
|
||||
}
|
||||
|
||||
#define PREFIX_WINDOW(hf_version,window) \
|
||||
std::unique_ptr<cryptonote::Blockchain> bc; \
|
||||
cryptonote::tx_memory_pool txpool(*bc); \
|
||||
bc.reset(new cryptonote::Blockchain(txpool)); \
|
||||
struct get_test_options { \
|
||||
const std::pair<uint8_t, uint64_t> hard_forks[3]; \
|
||||
const cryptonote::test_options test_options = { \
|
||||
@@ -61,7 +58,9 @@ public:
|
||||
}; \
|
||||
get_test_options(): hard_forks{std::make_pair(1, (uint64_t)0), std::make_pair((uint8_t)hf_version, (uint64_t)1), std::make_pair((uint8_t)0, (uint64_t)0)} {} \
|
||||
} opts; \
|
||||
cryptonote::Blockchain *blockchain = bc.get(); \
|
||||
cryptonote::BlockchainAndPool bap; \
|
||||
cryptonote::Blockchain *blockchain = &bap.blockchain; \
|
||||
cryptonote::Blockchain *bc = blockchain; \
|
||||
bool r = blockchain->init(new TestDB(), cryptonote::FAKECHAIN, true, &opts.test_options, 0, NULL); \
|
||||
ASSERT_TRUE(r)
|
||||
|
||||
|
||||
@@ -59,9 +59,7 @@ struct Struct
|
||||
};
|
||||
|
||||
template <class Archive>
|
||||
struct serializer<Archive, Struct>
|
||||
{
|
||||
static bool serialize(Archive &ar, Struct &s) {
|
||||
static bool do_serialize(Archive &ar, Struct &s) {
|
||||
ar.begin_object();
|
||||
ar.tag("a");
|
||||
ar.serialize_int(s.a);
|
||||
@@ -71,8 +69,7 @@ struct serializer<Archive, Struct>
|
||||
ar.serialize_blob(s.blob, sizeof(s.blob));
|
||||
ar.end_object();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
struct Struct1
|
||||
{
|
||||
@@ -122,6 +119,22 @@ bool try_parse(const string &blob)
|
||||
return serialization::parse_binary(blob, s1);
|
||||
}
|
||||
|
||||
namespace example_namespace
|
||||
{
|
||||
struct ADLExampleStruct
|
||||
{
|
||||
std::string msg;
|
||||
};
|
||||
template <class Archive>
|
||||
static bool do_serialize(Archive &ar, ADLExampleStruct &aes)
|
||||
{
|
||||
ar.begin_object();
|
||||
FIELD_N("custom_fieldname", aes.msg);
|
||||
ar.end_object();
|
||||
return ar.good();
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Serialization, BinaryArchiveInts) {
|
||||
uint64_t x = 0xff00000000, x1;
|
||||
|
||||
@@ -595,10 +608,11 @@ TEST(Serialization, serializes_ringct_types)
|
||||
//compute rct data with mixin 3
|
||||
const rct::RCTConfig rct_config{ rct::RangeProofPaddedBulletproof, 2 };
|
||||
cryptonote::transaction_type tx_type = cryptonote::transaction_type::TRANSFER;
|
||||
std::string in_asset_type = "FULM";
|
||||
std::string in_asset_type = "SAL";
|
||||
std::vector<std::string> destination_asset_types;
|
||||
for (size_t i = 0; i < destinations.size(); ++i)
|
||||
destination_asset_types.push_back("FULM");
|
||||
destination_asset_types.push_back("SAL");
|
||||
|
||||
s0 = rct::genRctSimple(rct::zero(), sc, pc, destinations, tx_type, in_asset_type, destination_asset_types, inamounts, amounts, amount_keys, 0, 3, rct_config, hw::get_device("default"));
|
||||
|
||||
ASSERT_FALSE(s0.p.MGs.empty());
|
||||
@@ -1094,7 +1108,7 @@ TEST(Serialization, portability_signed_tx)
|
||||
ASSERT_TRUE(ptx.selected_transfers.front() == 2);
|
||||
// ptx.{key_images, tx_key}
|
||||
ASSERT_TRUE(ptx.key_images == "<6c3cd6af97c4070a7aef9b1344e7463e29c7cd245076fdb65da447a34da3ca76> ");
|
||||
ASSERT_TRUE(epee::string_tools::pod_to_hex(ptx.tx_key) == "0100000000000000000000000000000000000000000000000000000000000000");
|
||||
ASSERT_TRUE(epee::string_tools::pod_to_hex(unwrap(unwrap(ptx.tx_key))) == "0100000000000000000000000000000000000000000000000000000000000000");
|
||||
// ptx.dests
|
||||
ASSERT_TRUE(ptx.dests.size() == 1);
|
||||
ASSERT_TRUE(ptx.dests[0].amount == 1400000000000);
|
||||
@@ -1183,3 +1197,15 @@ TEST(Serialization, difficulty_type)
|
||||
|
||||
ASSERT_EQ(v_original, v_unserialized);
|
||||
}
|
||||
|
||||
TEST(Serialization, adl_free_function)
|
||||
{
|
||||
std::stringstream ss;
|
||||
json_archive<true> ar(ss);
|
||||
const std::string msg = "Howdy, World!";
|
||||
example_namespace::ADLExampleStruct aes{msg};
|
||||
ASSERT_TRUE(serialization::serialize(ar, aes));
|
||||
// VVVVVVVVVVVVVVVVVVVVVVVVVV weird string serialization artifact
|
||||
const std::string expected = "{\"custom_fieldname\": " + std::to_string(msg.size()) + '"' + epee::string_tools::buff_to_hex_nodelimer(msg) + "\"}";
|
||||
EXPECT_EQ(expected, ss.str());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user