From 8c999520d110ea3eacdb0c0d3912c42882f08122 Mon Sep 17 00:00:00 2001 From: SomeRandomDevopsGuy Date: Mon, 18 Nov 2024 19:39:04 +0100 Subject: [PATCH 01/17] add RPC (#11) Co-authored-by: srdg --- .github/workflows/depends.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/depends.yml b/.github/workflows/depends.yml index edea20d5e..1fd2668ff 100644 --- a/.github/workflows/depends.yml +++ b/.github/workflows/depends.yml @@ -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: | From e909e3eef1d1b19a14797dc42893cdf32d8735bd Mon Sep 17 00:00:00 2001 From: Some Random Crypto Guy Date: Sun, 15 Dec 2024 11:09:46 +0000 Subject: [PATCH 02/17] fixed unit tests; fixed core tests; fixed performance tests; added fix to prevent change in block reward split (thanks Akil); added prelim code for spend authority proof - not complete / working --- README.md | 10 +- src/blockchain_db/blockchain_db.cpp | 2 +- src/blockchain_db/blockchain_db.h | 4 +- src/blockchain_db/lmdb/db_lmdb.cpp | 4 +- src/blockchain_db/lmdb/db_lmdb.h | 4 +- src/blockchain_db/testdb.h | 41 +++-- src/crypto/crypto.h | 24 ++- .../cryptonote_format_utils.cpp | 4 +- src/cryptonote_config.h | 3 +- src/cryptonote_core/blockchain.cpp | 9 ++ src/cryptonote_core/cryptonote_tx_utils.cpp | 140 +++++++++++++++++- src/device/device_default.cpp | 10 +- src/hardforks/hardforks.cpp | 3 + src/multisig/multisig_tx_builder_ringct.cpp | 11 +- src/ringct/rctSigs.cpp | 90 +++++++++-- src/ringct/rctSigs.h | 3 + src/ringct/rctTypes.h | 43 ++++-- src/simplewallet/simplewallet.cpp | 2 +- src/version.cpp.in | 2 +- src/wallet/wallet2.cpp | 16 +- tests/block_weight/block_weight.cpp | 21 ++- tests/core_tests/block_validation.cpp | 12 +- tests/core_tests/chaingen.cpp | 45 +++--- tests/core_tests/chaingen.h | 2 +- tests/core_tests/double_spend.inl | 2 +- tests/core_tests/integer_overflow.cpp | 4 +- tests/core_tests/multisig.cpp | 19 +-- tests/core_tests/transaction_tests.cpp | 2 +- tests/core_tests/tx_validation.cpp | 3 +- tests/core_tests/v2_tests.cpp | 2 +- .../transactions_flow_test.cpp | 8 +- .../performance_tests/ge_frombytes_vartime.h | 2 +- tests/performance_tests/ge_tobytes.h | 2 +- .../generate_key_image_helper.h | 3 +- tests/unit_tests/address_from_url.cpp | 2 +- tests/unit_tests/blockchain_db.cpp | 12 +- tests/unit_tests/crypto.cpp | 2 +- tests/unit_tests/hardfork.cpp | 58 +++++--- tests/unit_tests/long_term_block_weight.cpp | 44 +++--- tests/unit_tests/net.cpp | 79 +++++----- tests/unit_tests/node_server.cpp | 5 +- tests/unit_tests/output_distribution.cpp | 34 ++--- tests/unit_tests/pricing_record.cpp | 15 +- tests/unit_tests/ringct.cpp | 52 ++++++- tests/unit_tests/scaling_2021.cpp | 7 +- tests/unit_tests/serialization.cpp | 37 ++++- 46 files changed, 631 insertions(+), 268 deletions(-) diff --git a/README.md b/README.md index 43826a3bd..78fb423cd 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Salvium Zero v0.6.4 +# Salvium Zero v0.7.0rc1 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.4 + 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.4 + 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.4'. 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.4 + git checkout v0.7.0 ``` * If you are on a 64-bit system, run: diff --git a/src/blockchain_db/blockchain_db.cpp b/src/blockchain_db/blockchain_db.cpp index 152062289..0a8057849 100644 --- a/src/blockchain_db/blockchain_db.cpp +++ b/src/blockchain_db/blockchain_db.cpp @@ -267,7 +267,7 @@ uint64_t BlockchainDB::add_block( const std::pair& blck , const difficulty_type& cumulative_difficulty , const uint64_t& coins_generated , const std::vector>& txs - , const cryptonote::network_type& nettype + , const cryptonote::network_type nettype , cryptonote::yield_block_info& ybi ) { diff --git a/src/blockchain_db/blockchain_db.h b/src/blockchain_db/blockchain_db.h index 205477822..1c570aa88 100644 --- a/src/blockchain_db/blockchain_db.h +++ b/src/blockchain_db/blockchain_db.h @@ -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>& txs - , const cryptonote::network_type& nettype + , const cryptonote::network_type nettype , cryptonote::yield_block_info& ybi ); diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index 9b7ce773a..168070e53 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -866,7 +866,7 @@ int BlockchainLMDB::get_yield_tx_info(const uint64_t height, std::vector& blk, size_t block_weight, uint64_t long_term_block_weight, const difficulty_type& cumulative_difficulty, const uint64_t& coins_generated, - const std::vector>& txs, const cryptonote::network_type& nettype, cryptonote::yield_block_info& ybi) + const std::vector>& txs, const cryptonote::network_type nettype, cryptonote::yield_block_info& ybi) { LOG_PRINT_L3("BlockchainLMDB::" << __func__); check_open(); diff --git a/src/blockchain_db/lmdb/db_lmdb.h b/src/blockchain_db/lmdb/db_lmdb.h index e0686ac4c..befd6c56e 100644 --- a/src/blockchain_db/lmdb/db_lmdb.h +++ b/src/blockchain_db/lmdb/db_lmdb.h @@ -341,7 +341,7 @@ public: , const difficulty_type& cumulative_difficulty , const uint64_t& coins_generated , const std::vector>& 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 ); diff --git a/src/blockchain_db/testdb.h b/src/blockchain_db/testdb.h index fe8078d5e..4021a70b2 100644 --- a/src/blockchain_db/testdb.h +++ b/src/blockchain_db/testdb.h @@ -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 get_block_cumulative_rct_outputs(const std::vector &heights) const override { return {}; } + virtual std::pair, uint64_t> get_block_cumulative_rct_outputs(const std::vector &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 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 get_circulating_supply() const override { return std::map{}; } 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 get_tx_list(const std::vector& hlist) const override { return std::vector(); } 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 &offsets, std::vector &indices) const override {} virtual void get_output_key(const epee::span &amounts, const std::vector &offsets, std::vector &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 &asset_type_output_indices, std::vector &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> get_tx_amount_output_indices(const uint64_t tx_index, size_t n_txes) const override { return std::vector>(); } + virtual std::vector>> get_tx_amount_output_indices(const uint64_t tx_index, size_t n_txes) const override { return std::vector>>(); } 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& 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& amount_output_indices) override {} + virtual uint64_t add_transaction_data(const crypto::hash& blk_hash, const std::pair& 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 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>& 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& 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 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; } diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h index d8cd6c6a0..925201782 100644 --- a/src/crypto/crypto.h +++ b/src/crypto/crypto.h @@ -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 std::enable_if::value, T>::type rand() { + T rand() { + static_assert(std::is_standard_layout_v, "cannot write random bytes into non-standard layout type"); + static_assert(std::is_trivially_copyable_v, "cannot write random bytes into non-trivially copyable type"); typename std::remove_cv::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(scalar); } +inline const unsigned char* to_bytes(const crypto::ec_scalar &scalar) { return &reinterpret_cast(scalar); } +inline unsigned char* to_bytes(crypto::ec_point &point) { return &reinterpret_cast(point); } +inline const unsigned char* to_bytes(const crypto::ec_point &point) { return &reinterpret_cast(point); } + CRYPTO_MAKE_HASHABLE(public_key) CRYPTO_MAKE_HASHABLE_CONSTANT_TIME(secret_key) CRYPTO_MAKE_HASHABLE_CONSTANT_TIME(public_key_memsafe) diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp index bc1ba1533..a88a15bce 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.cpp +++ b/src/cryptonote_basic/cryptonote_format_utils.cpp @@ -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 << ", )"); 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] << ", )"); } else { diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h index 3cb0fb6d5..b9b838eda 100644 --- a/src/cryptonote_config.h +++ b/src/cryptonote_config.h @@ -218,8 +218,9 @@ #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_REQUIRE_VIEW_TAGS 255 #define HF_VERSION_ENABLE_CONVERT 255 #define HF_VERSION_ENABLE_ORACLE 255 #define HF_VERSION_SLIPPAGE_YIELD 255 diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index ab561e1ce..1870d99c8 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -1501,6 +1501,7 @@ bool Blockchain::validate_miner_transaction(const block& b, size_t cumulative_bl 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; } + CHECK_AND_ASSERT_MES((money_in_use - fee) / 5 == b.miner_tx.amount_burnt, false, "miner_transaction has incorrect amount_burnt amount"); break; default: assert(false); @@ -3615,6 +3616,14 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context } } + if (hf_version >= HF_VERSION_FULL_PROOFS) { + 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; + } + } + // from v15, require view tags and asset types on outputs if (!check_output_types(tx, hf_version)) { diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp index e90994031..04ea0dc35 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.cpp +++ b/src/cryptonote_core/cryptonote_tx_utils.cpp @@ -115,6 +115,132 @@ namespace cryptonote CHECK_AND_ASSERT_THROW_MES(tmp == rct::identity(), "invert failed"); return inv; } + + rct::proofV SAProof_Gen(const std::vector &vout, const size_t change_index, const crypto::secret_key &x_change) { + + // Declare a return structure + rct::proofV proofV{}; + + // Sanity checks + CHECK_AND_ASSERT_THROW_MES(vout.size(), "SAProof_Gen() failed - no outputs provided"); + CHECK_AND_ASSERT_THROW_MES(vout.size()>=change_index, "SAProof_Gen() failed - invalid change_index provided"); + CHECK_AND_ASSERT_THROW_MES(x_change != rct::zero(), "SAProof_Gen() failed - invalid x_change key provided"); + + // Create a buffer for the hashable data + size_t size = vout.size() * (32+32); + std::vector buffer; + buffer.resize(size); + uint8_t *ptr = buffer.data(); + + // Iterate over the outputs + rct::keyV scalars; + rct::keyV commitments; + rct::keyV pubkeys; + for (size_t j=0; j> 1), pubkey.data, sizeof(rct::key)); + ptr += sizeof(rct::key); + } + CHECK_AND_ASSERT_THROW_MES(scalars.size() == vout.size(), "in SAProof_Gen() : incorrect number of scalars"); + CHECK_AND_ASSERT_THROW_MES(commitments.size() == vout.size(), "in SAProof_Gen() : incorrect number of commitments"); + CHECK_AND_ASSERT_THROW_MES(pubkeys.size() == vout.size(), "in SAProof_Gen() : incorrect number of pubkeys"); + + // Calculate the hash + rct::key hash; + rct::cn_fast_hash(hash, buffer.data(), buffer.size()); + rct::key c = rct::scalarmultBase(hash); + + for (size_t j=0; j &vout, const size_t change_index) { + // Sanity checks + CHECK_AND_ASSERT_THROW_MES(proofs.size() == vout.size(), "PRProof_Ver() failed - proof count does not match output count"); + CHECK_AND_ASSERT_THROW_MES(change_index < vout.size(), "PRProof_Ver() failed - invalid change index provided"); + + // Extract the proof for the change output - we don't care about the others because they're dummy proofs + const auto &proof = proofs[change_index]; + const rct::key &R = proof.R; // Commitment + const rct::key &z_x = proof.z1; // z_x value + const rct::key &z_y = proof.z2; // z_y value + + // Extract the public key of the change output + crypto::public_key pubkey = crypto::null_pkey; + CHECK_AND_ASSERT_THROW_MES(!cryptonote::get_output_public_key(vout[change_index], pubkey), "PRProof_Ver() failed - could not retrieve output public key"); + + // Convert the public key to rct format + rct::key P = rct::pk2rct(pubkey); + + // Recompute the challenge hash + size_t size = vout.size() * (32 + 32); + std::vector buffer(size); + uint8_t *ptr = buffer.data(); + + for (size_t j = 0; j < vout.size(); ++j) { + // Retrieve commitments and public keys for hashing + const rct::key &commitment = proofs[j].R; + crypto::public_key pubkey_temp; + CHECK_AND_ASSERT_THROW_MES(!cryptonote::get_output_public_key(vout[j], pubkey_temp), "PRProof_Ver() failed - could not retrieve public key"); + + // Copy data into the buffer + std::memcpy(ptr, commitment.bytes, sizeof(rct::key)); + std::memcpy(ptr + (size >> 1), pubkey_temp.data, sizeof(rct::key)); + ptr += sizeof(rct::key); + } + + // Compute the challenge hash + rct::key hash; + rct::cn_fast_hash(hash, buffer.data(), buffer.size()); + rct::key c = rct::scalarmultBase(hash); + + // Verify the proof for the change output + // Recalculate the expected commitment using the formula: z_x * G = R + c * P + rct::key expected_commitment = rct::addKeys(R, rct::scalarmultKey(c, P)); + + // Verify z_x * G matches the expected commitment + if (!rct::equalKeys(rct::scalarmultBase(z_x), expected_commitment)) { + return false; // Verification failed + } + + // Verify z_y * G matches the original commitment + if (!rct::equalKeys(rct::scalarmultBase(z_y), R)) { + return false; // Verification failed + } + + // All checks passed + return true; + } //--------------------------------------------------------------- void classify_addresses(const std::vector &destinations, const boost::optional& change_addr, size_t &num_stdaddresses, size_t &num_subaddresses, account_public_address &single_dest_subaddress) @@ -502,7 +628,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 +641,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 +695,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 << ")"); @@ -887,7 +1013,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 +1036,10 @@ 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) { + + // Calculate the spend authority proof + crypto::secret_key x_change = crypto::null_skey; + tx.rct_signatures.sa_proof = SAProof_Gen(tx.vout, change_index, x_change); // Get the output public key for the change output crypto::public_key P_change = crypto::null_pkey; @@ -1038,7 +1168,7 @@ namespace cryptonote crypto::generate_ring_signature(tx_prefix_hash, boost::get(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++; } diff --git a/src/device/device_default.cpp b/src/device/device_default.cpp index d938087fe..30bb4a2e8 100644 --- a/src/device/device_default.cpp +++ b/src/device/device_default.cpp @@ -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 << ", )"); } 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) diff --git a/src/hardforks/hardforks.cpp b/src/hardforks/hardforks.cpp index 5905df4bf..6ef62e4d7 100644 --- a/src/hardforks/hardforks.cpp +++ b/src/hardforks/hardforks.cpp @@ -47,6 +47,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); diff --git a/src/multisig/multisig_tx_builder_ringct.cpp b/src/multisig/multisig_tx_builder_ringct.cpp index a3c824e38..d17e993d6 100644 --- a/src/multisig/multisig_tx_builder_ringct.cpp +++ b/src/multisig/multisig_tx_builder_ringct.cpp @@ -822,7 +822,8 @@ static bool set_tx_rct_signatures( ) { 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 +839,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,10 +918,16 @@ 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 = PRProof_Gen(difference); + //rv.sa_proof = SAProof_Gen(); + } } // check balance if reconstructing the tx else { rv.p.pseudoOuts = unsigned_tx.rct_signatures.p.pseudoOuts; + rv.pr_proof = unsigned_tx.rct_signatures.pr_proof; // should verify this during reconstruction + rv.sa_proof = unsigned_tx.rct_signatures.sa_proof; // should verify this during reconstruction rv.p_r = unsigned_tx.rct_signatures.p_r; if (num_sources != rv.p.pseudoOuts.size()) return false; diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp index f1de51ecc..9be094845 100644 --- a/src/ringct/rctSigs.cpp +++ b/src/ringct/rctSigs.cpp @@ -521,7 +521,73 @@ namespace rct { sc_sub(c.bytes, c_old.bytes, rv.cc.bytes); return sc_isnonzero(c.bytes) == 0; } + + + // Optimized function to hash a vector of keys into a scalar + rct::key my_hash_to_scalar(std::vector& keys) { + // Create a fixed-size buffer large enough to hold all keys and a domain separator + size_t total_size = keys.size() * sizeof(rct::key) + sizeof("ZKP") - 1; + std::vector data(total_size); + + // Copy the keys into the buffer + size_t offset = 0; + for (const auto& key : keys) { + std::memcpy(data.data() + offset, key.bytes, sizeof(rct::key)); + offset += sizeof(rct::key); + } + + // Add the domain separator "ZKP" at the end of the buffer + const char* domain_separator = "ZKP"; + std::memcpy(data.data() + offset, domain_separator, sizeof("ZKP") - 1); + + // Hash the concatenated data into a fixed-size hash + rct::key hash_output; + keccak((const uint8_t *)data.data(), total_size, hash_output.bytes, sizeof(rct::key)); + sc_reduce32(hash_output.bytes); // Reduce to valid scalar + + return hash_output; + } + + 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 keys{proof.R, comm_diff}; + rct::key c = rct::hash_to_scalar(keys); + sc_reduce32(c.bytes); + + // 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 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 +705,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) @@ -1074,7 +1140,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 @@ -1141,6 +1207,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 +1326,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 +1351,8 @@ 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); key full_message = get_pre_mlsag_hash(rv,hwdev); for (i = 0 ; i < inamounts.size(); i++) @@ -1416,8 +1486,10 @@ namespace rct { std::vector 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 +1612,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 +1684,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 +1708,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; diff --git a/src/ringct/rctSigs.h b/src/ringct/rctSigs.h index 020394f9e..33c12f066 100644 --- a/src/ringct/rctSigs.h +++ b/src/ringct/rctSigs.h @@ -85,6 +85,9 @@ 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); + //proveRange and verRange //proveRange gives C, and mask such that \sumCi = C // c.f. https://eprint.iacr.org/2015/1098 section 5.1 diff --git a/src/ringct/rctTypes.h b/src/ringct/rctTypes.h index 32e4d694c..74783bd3e 100644 --- a/src/ringct/rctTypes.h +++ b/src/ringct/rctTypes.h @@ -90,6 +90,19 @@ namespace rct { typedef std::vector keyV; //vector of keys typedef std::vector 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() + }; + typedef std::vector proofV; + //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 +317,7 @@ namespace rct { RCTTypeBulletproof2 = 4, RCTTypeCLSAG = 5, RCTTypeBulletproofPlus = 6, + RCTTypeFullProofs = 7 }; enum RangeProofType { RangeProofBorromean, RangeProofBulletproof, RangeProofMultiOutputBulletproof, RangeProofPaddedBulletproof }; struct RCTConfig { @@ -326,9 +340,11 @@ namespace rct { ctkeyV outPk; xmr_amount txnFee; // contains b key p_r; + zk_proof pr_proof; // p_r + proofV sa_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 class Archive> @@ -337,7 +353,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 +382,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 +419,11 @@ namespace rct { } ar.end_array(); FIELD(p_r) + if (type == RCTTypeFullProofs) + { + FIELD(pr_proof) + FIELD(sa_proof) + } return ar.good(); } @@ -415,6 +436,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 +462,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 +521,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 +612,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 +644,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() diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index a5bac6509..6b53050f9 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -1999,7 +1999,7 @@ bool simple_wallet::rpc_payment_info(const std::vector &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"); diff --git a/src/version.cpp.in b/src/version.cpp.in index ef297056b..9fdaee1dd 100644 --- a/src/version.cpp.in +++ b/src/version.cpp.in @@ -1,5 +1,5 @@ #define DEF_SALVIUM_VERSION_TAG "@VERSIONTAG@" -#define DEF_SALVIUM_VERSION "0.6.4" +#define DEF_SALVIUM_VERSION "0.7.0rc1" #define DEF_MONERO_VERSION_TAG "release" #define DEF_MONERO_VERSION "0.18.3.3" #define DEF_MONERO_RELEASE_NAME "Zero" diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 950c51193..9d6f2009a 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -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) @@ -10553,7 +10558,8 @@ std::vector wallet2::create_transactions_2(std::vector valid_public_keys_cache; @@ -11251,7 +11257,8 @@ std::vector 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); @@ -11452,7 +11459,7 @@ std::vector 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); @@ -11493,7 +11500,8 @@ std::vector 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(); diff --git a/tests/block_weight/block_weight.cpp b/tests/block_weight/block_weight.cpp index 4cd3cdda1..13dcfbf75 100644 --- a/tests/block_weight/block_weight.cpp +++ b/tests/block_weight/block_weight.cpp @@ -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 bc; \ - cryptonote::tx_memory_pool txpool(*bc); \ - bc.reset(new cryptonote::Blockchain(txpool)); \ struct get_test_options { \ const std::pair 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()) { diff --git a/tests/core_tests/block_validation.cpp b/tests/core_tests/block_validation.cpp index 7c05b497e..3706f6cba 100644 --- a/tests/core_tests/block_validation.cpp +++ b/tests/core_tests/block_validation.cpp @@ -350,7 +350,7 @@ bool gen_block_miner_tx_has_2_in::generate(std::vector& 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(), tmp_tx, 0)) + if (!construct_tx(miner_account.get_keys(), sources, destinations, 1/*hf_version*/, "SAL", cryptonote::transaction_type::TRANSFER, boost::none, std::vector(), 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 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(), tmp_tx, 0)) + if (!construct_tx(miner_account.get_keys(), sources, destinations, 1/*hf_version*/, "SAL", cryptonote::transaction_type::TRANSFER, boost::none, std::vector(), 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 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 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"); diff --git a/tests/core_tests/chaingen.cpp b/tests/core_tests/chaingen.cpp index be63d0e4b..3f752c316 100644 --- a/tests/core_tests/chaingen.cpp +++ b/tests/core_tests/chaingen.cpp @@ -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 init_blockchain(const std::vector & events, cryptonote::network_type nettype) +static std::unique_ptr init_blockchain(const std::vector & events, cryptonote::network_type nettype) { - std::unique_ptr 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 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 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 init_blockchain(const std::vector const block *blk = &boost::get(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& 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 bc; + std::unique_ptr 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(oi.out).key; std::unordered_map 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) { diff --git a/tests/core_tests/chaingen.h b/tests/core_tests/chaingen.h index d5c9edc55..1f782831f 100644 --- a/tests/core_tests/chaingen.h +++ b/tests/core_tests/chaingen.h @@ -44,7 +44,7 @@ #include #include "include_base_utils.h" -#include "common/boost_serialization_helper.h" +#include "chaingen_serialization.h" #include "common/command_line.h" #include "common/threadpool.h" diff --git a/tests/core_tests/double_spend.inl b/tests/core_tests/double_spend.inl index 7683e2b55..4385563dd 100644 --- a/tests/core_tests/double_spend.inl +++ b/tests/core_tests/double_spend.inl @@ -144,7 +144,7 @@ bool gen_double_spend_in_tx::generate(std::vector(), tx_1, 0)) + if (!construct_tx(bob_account.get_keys(), sources, destinations, 1/*hf_version*/, "SAL", cryptonote::transaction_type::TRANSFER, boost::none, std::vector(), tx_1, 0)) return false; SET_EVENT_VISITOR_SETT(events, txs_keeped_by_block ? event_visitor_settings::set_txs_keeped_by_block : 0); diff --git a/tests/core_tests/integer_overflow.cpp b/tests/core_tests/integer_overflow.cpp index 41a359cfd..4d203b8bb 100644 --- a/tests/core_tests/integer_overflow.cpp +++ b/tests/core_tests/integer_overflow.cpp @@ -174,7 +174,7 @@ bool gen_uint_overflow_2::generate(std::vector& 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(), tx_1, 0)) + if (!construct_tx(miner_account.get_keys(), sources, destinations, 1/*hf_version*/, "SAL", cryptonote::transaction_type::TRANSFER, boost::none, std::vector(), tx_1, 0)) return false; events.push_back(tx_1); @@ -200,7 +200,7 @@ bool gen_uint_overflow_2::generate(std::vector& 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(), tx_2, 0)) + if (!construct_tx(bob_account.get_keys(), sources, destinations, 1/*hf_version*/, "SAL", cryptonote::transaction_type::TRANSFER, boost::none, std::vector(), tx_2, 0)) return false; events.push_back(tx_2); diff --git a/tests/core_tests/multisig.cpp b/tests/core_tests/multisig.cpp index 28b44d293..e4ee63b30 100644 --- a/tests/core_tests/multisig.cpp +++ b/tests/core_tests/multisig.cpp @@ -227,13 +227,13 @@ bool gen_multisig_tx_validation_base::generate_with(std::vector kLRkis; std::unordered_set 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 ins_order; @@ -399,14 +400,14 @@ bool gen_multisig_tx_validation_base::generate_with(std::vector(), 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(), tx_rc1, 0); CHECK_AND_ASSERT_MES(r, false, "failed to construct transaction"); crypto::hash pref_hash = get_transaction_prefix_hash(tx_rc1); diff --git a/tests/core_tests/tx_validation.cpp b/tests/core_tests/tx_validation.cpp index b2b742b93..911f82b01 100644 --- a/tests/core_tests/tx_validation.cpp +++ b/tests/core_tests/tx_validation.cpp @@ -63,7 +63,8 @@ namespace std::unordered_map subaddresses; subaddresses[sender_account_keys.m_account_address.m_spend_public_key] = {0,0}; auto& out_key = reinterpret_cast(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; diff --git a/tests/core_tests/v2_tests.cpp b/tests/core_tests/v2_tests.cpp index 9884384b9..093e290a8 100644 --- a/tests/core_tests/v2_tests.cpp +++ b/tests/core_tests/v2_tests.cpp @@ -107,7 +107,7 @@ bool gen_v2_tx_validation_base::generate_with(std::vector& 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(), 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(), tx, 0); CHECK_AND_ASSERT_MES(r, false, "failed to construct transaction"); if (!valid) DO_CALLBACK(events, "mark_invalid_tx"); diff --git a/tests/functional_tests/transactions_flow_test.cpp b/tests/functional_tests/transactions_flow_test.cpp index 784e7585c..15bf3fdbd 100644 --- a/tests/functional_tests/transactions_flow_test.cpp +++ b/tests/functional_tests/transactions_flow_test.cpp @@ -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-----------------------"); diff --git a/tests/performance_tests/ge_frombytes_vartime.h b/tests/performance_tests/ge_frombytes_vartime.h index 1d487eee8..341cc4019 100644 --- a/tests/performance_tests/ge_frombytes_vartime.h +++ b/tests/performance_tests/ge_frombytes_vartime.h @@ -57,7 +57,7 @@ public: std::vector 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(), 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(), m_tx, 0)) return false; const cryptonote::txin_to_key& txin = boost::get(m_tx.vin[0]); diff --git a/tests/performance_tests/ge_tobytes.h b/tests/performance_tests/ge_tobytes.h index ce39e37cd..fdc7d1dff 100644 --- a/tests/performance_tests/ge_tobytes.h +++ b/tests/performance_tests/ge_tobytes.h @@ -57,7 +57,7 @@ public: std::vector 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(), 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(), m_tx, 0)) return false; const cryptonote::txin_to_key& txin = boost::get(m_tx.vin[0]); diff --git a/tests/performance_tests/generate_key_image_helper.h b/tests/performance_tests/generate_key_image_helper.h index 2fa0cb244..f880d3798 100644 --- a/tests/performance_tests/generate_key_image_helper.h +++ b/tests/performance_tests/generate_key_image_helper.h @@ -49,6 +49,7 @@ public: std::unordered_map subaddresses; subaddresses[m_bob.get_keys().m_account_address.m_spend_public_key] = {0,0}; crypto::public_key out_key = boost::get(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); } }; diff --git a/tests/unit_tests/address_from_url.cpp b/tests/unit_tests/address_from_url.cpp index d6d25dbbf..71336c588 100644 --- a/tests/unit_tests/address_from_url.cpp +++ b/tests/unit_tests/address_from_url.cpp @@ -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; diff --git a/tests/unit_tests/blockchain_db.cpp b/tests/unit_tests/blockchain_db.cpp index 17828645a..e82d79a5e 100644 --- a/tests/unit_tests/blockchain_db.cpp +++ b/tests/unit_tests/blockchain_db.cpp @@ -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)); diff --git a/tests/unit_tests/crypto.cpp b/tests/unit_tests/crypto.cpp index 7f926534a..329992463 100644 --- a/tests/unit_tests/crypto.cpp +++ b/tests/unit_tests/crypto.cpp @@ -72,10 +72,10 @@ TEST(Crypto, Ostream) EXPECT_TRUE(is_formatted()); EXPECT_TRUE(is_formatted()); EXPECT_TRUE(is_formatted()); - EXPECT_TRUE(is_formatted()); EXPECT_TRUE(is_formatted()); EXPECT_TRUE(is_formatted()); EXPECT_TRUE(is_formatted()); + EXPECT_TRUE(is_formatted()); } TEST(Crypto, null_keys) diff --git a/tests/unit_tests/hardfork.cpp b/tests/unit_tests/hardfork.cpp index 391cb7af0..4fe550778 100644 --- a/tests/unit_tests/hardfork.cpp +++ b/tests/unit_tests/hardfork.cpp @@ -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) diff --git a/tests/unit_tests/long_term_block_weight.cpp b/tests/unit_tests/long_term_block_weight.cpp index caf1714ac..0ba4a79b5 100644 --- a/tests/unit_tests/long_term_block_weight.cpp +++ b/tests/unit_tests/long_term_block_weight.cpp @@ -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 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); diff --git a/tests/unit_tests/net.cpp b/tests/unit_tests/net.cpp index af0f07db0..dc79f80a1 100644 --- a/tests/unit_tests/net.cpp +++ b/tests/unit_tests/net.cpp @@ -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("", i2p.host_str()); EXPECT_STREQ("", 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("", i2p.host_str()); EXPECT_STREQ("", 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) diff --git a/tests/unit_tests/node_server.cpp b/tests/unit_tests/node_server.cpp index 584f98f7a..5ebe9cb2a 100644 --- a/tests/unit_tests/node_server.cpp +++ b/tests/unit_tests/node_server.cpp @@ -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(); }; diff --git a/tests/unit_tests/output_distribution.cpp b/tests/unit_tests/output_distribution.cpp index 814e575af..2e2547400 100644 --- a/tests/unit_tests/output_distribution.cpp +++ b/tests/unit_tests/output_distribution.cpp @@ -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 &distribution, uint64_t &base, uint64_t &num_spendable_global_outs) { - std::unique_ptr bc; - cryptonote::tx_memory_pool txpool(*bc); - bc.reset(new cryptonote::Blockchain(txpool)); struct get_test_options { const std::pair 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 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({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({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({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({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({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({55, 55, 57, 60})); @@ -138,7 +132,7 @@ TEST(output_distribution, one) { boost::optional 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 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 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 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({0, 1, 6, 7, 11})); @@ -179,7 +173,7 @@ TEST(output_distribution, part_noncumulative) { boost::optional 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({0, 1, 5, 1, 4})); diff --git a/tests/unit_tests/pricing_record.cpp b/tests/unit_tests/pricing_record.cpp index fc91ff820..b90b87f1e 100644 --- a/tests/unit_tests/pricing_record.cpp +++ b/tests/unit_tests/pricing_record.cpp @@ -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)); diff --git a/tests/unit_tests/ringct.cpp b/tests/unit_tests/ringct.cpp index efd195426..bbecd6fe5 100644 --- a/tests/unit_tests/ringct.cpp +++ b/tests/unit_tests/ringct.cpp @@ -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 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 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 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")); @@ -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 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); +} diff --git a/tests/unit_tests/scaling_2021.cpp b/tests/unit_tests/scaling_2021.cpp index 36a77c107..61040c0c7 100644 --- a/tests/unit_tests/scaling_2021.cpp +++ b/tests/unit_tests/scaling_2021.cpp @@ -50,9 +50,6 @@ public: } #define PREFIX_WINDOW(hf_version,window) \ - std::unique_ptr bc; \ - cryptonote::tx_memory_pool txpool(*bc); \ - bc.reset(new cryptonote::Blockchain(txpool)); \ struct get_test_options { \ const std::pair 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) diff --git a/tests/unit_tests/serialization.cpp b/tests/unit_tests/serialization.cpp index bdd41c69e..823ab609b 100644 --- a/tests/unit_tests/serialization.cpp +++ b/tests/unit_tests/serialization.cpp @@ -59,9 +59,7 @@ struct Struct }; template -struct serializer -{ - 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 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 + 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; @@ -1094,7 +1107,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 +1196,15 @@ TEST(Serialization, difficulty_type) ASSERT_EQ(v_original, v_unserialized); } + +TEST(Serialization, adl_free_function) +{ + std::stringstream ss; + json_archive 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()); +} From 1334bac45aea62d99af0bfffc2478df7a8964c50 Mon Sep 17 00:00:00 2001 From: Some Random Crypto Guy Date: Sun, 15 Dec 2024 11:50:14 +0000 Subject: [PATCH 03/17] fixed check on miner-staker split --- src/cryptonote_core/blockchain.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 1870d99c8..0e839323c 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -1501,7 +1501,8 @@ bool Blockchain::validate_miner_transaction(const block& b, size_t cumulative_bl 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; } - CHECK_AND_ASSERT_MES((money_in_use - fee) / 5 == b.miner_tx.amount_burnt, false, "miner_transaction has incorrect amount_burnt amount"); + 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); From 2ce22c25083d6b8ff95fb2e8a62da60de708701b Mon Sep 17 00:00:00 2001 From: Some Random Crypto Guy Date: Sun, 15 Dec 2024 22:28:14 +0000 Subject: [PATCH 04/17] partial working serialisation --- .../cryptonote_boost_serialization.h | 24 ++- .../cryptonote_format_utils.cpp | 4 +- src/cryptonote_core/blockchain.cpp | 8 +- src/cryptonote_core/cryptonote_core.cpp | 3 +- src/cryptonote_core/cryptonote_tx_utils.cpp | 193 +++++------------- src/cryptonote_core/tx_verification_utils.cpp | 2 +- src/device/device_ledger.cpp | 6 +- src/multisig/multisig_tx_builder_ringct.cpp | 3 +- src/ringct/rctSigs.cpp | 171 +++++++++++++--- src/ringct/rctSigs.h | 11 +- src/ringct/rctTypes.cpp | 3 + src/ringct/rctTypes.h | 27 ++- src/serialization/json_object.cpp | 31 +++ src/serialization/json_object.h | 3 + src/wallet/wallet2.cpp | 11 +- tests/unit_tests/bulletproofs.cpp | 4 +- tests/unit_tests/ringct.cpp | 2 +- tests/unit_tests/serialization.cpp | 5 +- 18 files changed, 303 insertions(+), 208 deletions(-) diff --git a/src/cryptonote_basic/cryptonote_boost_serialization.h b/src/cryptonote_basic/cryptonote_boost_serialization.h index a3c7a16ce..41fa0e2c7 100644 --- a/src/cryptonote_basic/cryptonote_boost_serialization.h +++ b/src/cryptonote_basic/cryptonote_boost_serialization.h @@ -350,6 +350,14 @@ namespace boost a & x.D; } + template + 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 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_proofs; + } } template @@ -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_proofs; + } //-------------- 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) diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp index a88a15bce..12ce3491a 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.cpp +++ b/src/cryptonote_basic/cryptonote_format_utils.cpp @@ -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) @@ -517,7 +517,7 @@ namespace cryptonote { CHECK_AND_ASSERT_MES(tx.pruned, std::numeric_limits::max(), "get_pruned_transaction_weight does not support non pruned txes"); CHECK_AND_ASSERT_MES(tx.version >= 2, std::numeric_limits::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::max(), "Unsupported rct_signatures type in get_pruned_transaction_weight"); CHECK_AND_ASSERT_MES(!tx.vin.empty(), std::numeric_limits::max(), "empty vin"); CHECK_AND_ASSERT_MES(tx.vin[0].type() == typeid(cryptonote::txin_to_key), std::numeric_limits::max(), "empty vin"); diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 0e839323c..3e2dca563 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -1497,6 +1497,7 @@ 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: 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; @@ -3709,7 +3710,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()); @@ -3750,7 +3751,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) { @@ -3997,7 +3998,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!"); @@ -4040,6 +4041,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)) { diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index 252cddfd2..20defc2db 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -970,6 +970,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 +997,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 : diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp index 04ea0dc35..ae5ee897c 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.cpp +++ b/src/cryptonote_core/cryptonote_tx_utils.cpp @@ -116,132 +116,6 @@ namespace cryptonote return inv; } - rct::proofV SAProof_Gen(const std::vector &vout, const size_t change_index, const crypto::secret_key &x_change) { - - // Declare a return structure - rct::proofV proofV{}; - - // Sanity checks - CHECK_AND_ASSERT_THROW_MES(vout.size(), "SAProof_Gen() failed - no outputs provided"); - CHECK_AND_ASSERT_THROW_MES(vout.size()>=change_index, "SAProof_Gen() failed - invalid change_index provided"); - CHECK_AND_ASSERT_THROW_MES(x_change != rct::zero(), "SAProof_Gen() failed - invalid x_change key provided"); - - // Create a buffer for the hashable data - size_t size = vout.size() * (32+32); - std::vector buffer; - buffer.resize(size); - uint8_t *ptr = buffer.data(); - - // Iterate over the outputs - rct::keyV scalars; - rct::keyV commitments; - rct::keyV pubkeys; - for (size_t j=0; j> 1), pubkey.data, sizeof(rct::key)); - ptr += sizeof(rct::key); - } - CHECK_AND_ASSERT_THROW_MES(scalars.size() == vout.size(), "in SAProof_Gen() : incorrect number of scalars"); - CHECK_AND_ASSERT_THROW_MES(commitments.size() == vout.size(), "in SAProof_Gen() : incorrect number of commitments"); - CHECK_AND_ASSERT_THROW_MES(pubkeys.size() == vout.size(), "in SAProof_Gen() : incorrect number of pubkeys"); - - // Calculate the hash - rct::key hash; - rct::cn_fast_hash(hash, buffer.data(), buffer.size()); - rct::key c = rct::scalarmultBase(hash); - - for (size_t j=0; j &vout, const size_t change_index) { - // Sanity checks - CHECK_AND_ASSERT_THROW_MES(proofs.size() == vout.size(), "PRProof_Ver() failed - proof count does not match output count"); - CHECK_AND_ASSERT_THROW_MES(change_index < vout.size(), "PRProof_Ver() failed - invalid change index provided"); - - // Extract the proof for the change output - we don't care about the others because they're dummy proofs - const auto &proof = proofs[change_index]; - const rct::key &R = proof.R; // Commitment - const rct::key &z_x = proof.z1; // z_x value - const rct::key &z_y = proof.z2; // z_y value - - // Extract the public key of the change output - crypto::public_key pubkey = crypto::null_pkey; - CHECK_AND_ASSERT_THROW_MES(!cryptonote::get_output_public_key(vout[change_index], pubkey), "PRProof_Ver() failed - could not retrieve output public key"); - - // Convert the public key to rct format - rct::key P = rct::pk2rct(pubkey); - - // Recompute the challenge hash - size_t size = vout.size() * (32 + 32); - std::vector buffer(size); - uint8_t *ptr = buffer.data(); - - for (size_t j = 0; j < vout.size(); ++j) { - // Retrieve commitments and public keys for hashing - const rct::key &commitment = proofs[j].R; - crypto::public_key pubkey_temp; - CHECK_AND_ASSERT_THROW_MES(!cryptonote::get_output_public_key(vout[j], pubkey_temp), "PRProof_Ver() failed - could not retrieve public key"); - - // Copy data into the buffer - std::memcpy(ptr, commitment.bytes, sizeof(rct::key)); - std::memcpy(ptr + (size >> 1), pubkey_temp.data, sizeof(rct::key)); - ptr += sizeof(rct::key); - } - - // Compute the challenge hash - rct::key hash; - rct::cn_fast_hash(hash, buffer.data(), buffer.size()); - rct::key c = rct::scalarmultBase(hash); - - // Verify the proof for the change output - // Recalculate the expected commitment using the formula: z_x * G = R + c * P - rct::key expected_commitment = rct::addKeys(R, rct::scalarmultKey(c, P)); - - // Verify z_x * G matches the expected commitment - if (!rct::equalKeys(rct::scalarmultBase(z_x), expected_commitment)) { - return false; // Verification failed - } - - // Verify z_y * G matches the original commitment - if (!rct::equalKeys(rct::scalarmultBase(z_y), R)) { - return false; // Verification failed - } - - // All checks passed - return true; - } - //--------------------------------------------------------------- void classify_addresses(const std::vector &destinations, const boost::optional& change_addr, size_t &num_stdaddresses, size_t &num_subaddresses, account_public_address &single_dest_subaddress) { @@ -715,6 +589,7 @@ namespace cryptonote switch (hard_fork_version) { case HF_VERSION_BULLETPROOF_PLUS: case HF_VERSION_ENABLE_N_OUTS: + case HF_VERSION_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; @@ -982,6 +857,7 @@ namespace cryptonote uint64_t summary_outs_money = 0; //fill outputs size_t output_index = 0; + crypto::secret_key x_change = crypto::null_skey; uint8_t change_index = 0; for(const tx_destination_entry& dst_entr: destinations) { @@ -1037,9 +913,34 @@ namespace cryptonote if (hf_version >= HF_VERSION_ENABLE_N_OUTS && tx.type == cryptonote::transaction_type::TRANSFER) { - // Calculate the spend authority proof - crypto::secret_key x_change = crypto::null_skey; - tx.rct_signatures.sa_proof = SAProof_Gen(tx.vout, change_index, x_change); + 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; @@ -1292,22 +1193,24 @@ 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 + ); 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)); diff --git a/src/cryptonote_core/tx_verification_utils.cpp b/src/cryptonote_core/tx_verification_utils.cpp index e4bc74b4f..775368f55 100644 --- a/src/cryptonote_core/tx_verification_utils.cpp +++ b/src/cryptonote_core/tx_verification_utils.cpp @@ -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 diff --git a/src/device/device_ledger.cpp b/src/device/device_ledger.cpp index 009ee16ca..e85c12ede 100644 --- a/src/device/device_ledger.cpp +++ b/src/device/device_ledger.cpp @@ -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; diff --git a/src/multisig/multisig_tx_builder_ringct.cpp b/src/multisig/multisig_tx_builder_ringct.cpp index d17e993d6..7c07cb465 100644 --- a/src/multisig/multisig_tx_builder_ringct.cpp +++ b/src/multisig/multisig_tx_builder_ringct.cpp @@ -920,14 +920,13 @@ static bool set_tx_rct_signatures( rct::genC(rv.p_r, difference, 0); if (rv.type == rct::RCTTypeFullProofs) { rv.pr_proof = PRProof_Gen(difference); - //rv.sa_proof = SAProof_Gen(); } } // check balance if reconstructing the tx else { rv.p.pseudoOuts = unsigned_tx.rct_signatures.p.pseudoOuts; rv.pr_proof = unsigned_tx.rct_signatures.pr_proof; // should verify this during reconstruction - rv.sa_proof = unsigned_tx.rct_signatures.sa_proof; // should verify this during reconstruction + //rv.sa_proofs = unsigned_tx.rct_signatures.sa_proofs; // should verify this during reconstruction rv.p_r = unsigned_tx.rct_signatures.p_r; if (num_sources != rv.p.pseudoOuts.size()) return false; diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp index 9be094845..9bbdf7202 100644 --- a/src/ringct/rctSigs.cpp +++ b/src/ringct/rctSigs.cpp @@ -1098,6 +1098,101 @@ namespace rct { return index; } + std::vector SAProof_Gen(const keyV &pubkeys, const key &x_change, const size_t change_index) { + + // Declare a return structure + std::vector proofs{}; + + // Sanity checks + CHECK_AND_ASSERT_THROW_MES(pubkeys.size(), "SAProof_Gen() failed - no output pubkeys provided"); + CHECK_AND_ASSERT_THROW_MES(pubkeys.size() > change_index, "SAProof_Gen() failed - invalid change_index provided"); + CHECK_AND_ASSERT_THROW_MES(!rct::equalKeys(x_change, rct::zero()), "SAProof_Gen() failed - invalid x_change key provided"); + + // Iterate over the outputs + rct::keyV scalars; + rct::keyV commitments; + for (size_t j=0; j &proofs, const keyV &pubkeys, const size_t change_index) { + // Sanity checks + CHECK_AND_ASSERT_THROW_MES(proofs.size() == pubkeys.size(), "PRProof_Ver() failed - proof count does not match output count"); + CHECK_AND_ASSERT_THROW_MES(change_index < pubkeys.size(), "PRProof_Ver() failed - invalid change index provided"); + + // Recompute the challenge hash + keyV challenge_keys; + challenge_keys.reserve(pubkeys.size() * 2); + for (const auto &proof_entr: proofs) { + challenge_keys.push_back(proof_entr.R); + } + challenge_keys.insert(challenge_keys.end(), pubkeys.begin(), pubkeys.end()); + rct::key c = rct::hash_to_scalar(challenge_keys); + sc_reduce32(c.bytes); + + // Extract the proof for the change output - we don't care about the others because they're dummy proofs + const auto &proof = proofs[change_index]; + const rct::key &R = proof.R; // Commitment + const rct::key &z_x = proof.z1; // z_x value + const rct::key &z_y = proof.z2; // z_y value + const rct::key P = pubkeys[change_index]; + + // Verify the proof for the change output + // Recalculate the expected commitment using the formula: z_x * G = R + c * P + rct::key expected_commitment = rct::addKeys(R, rct::scalarmultKey(c, P)); + + // Verify z_x * G matches the expected commitment + if (!rct::equalKeys(rct::scalarmultBase(z_x), expected_commitment)) { + return false; // Verification failed + } + + // Verify z_y * G matches the original commitment + if (!rct::equalKeys(rct::scalarmultBase(z_y), R)) { + 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 @@ -1170,21 +1265,24 @@ 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 & destination_asset_types, - const std::vector &inamounts, - const std::vector &outamounts, - xmr_amount txnFee, - const ctkeyM & mixRing, - const keyV &amount_keys, - const std::vector & 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 & destination_asset_types, + const std::vector &inamounts, + const std::vector &outamounts, + xmr_amount txnFee, + const ctkeyM & mixRing, + const keyV &amount_keys, + const std::vector & index, + ctkeyV &outSk, + const RCTConfig &rct_config, + hw::device &hwdev, + const key &x_change, + const size_t change_index + ) { 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"); @@ -1369,24 +1467,37 @@ namespace rct { rv.p.MGs[i] = proveRctMGSimple(full_message, rv.mixRing[i], inSk[i], a[i], pseudoOuts[i], index[i], hwdev); } } + + // Check if spend authority proof is needed (only for TRANSFER TXs) + /* + if (tx_type == cryptonote::transaction_type::TRANSFER && rv.type == rct::RCTTypeFullProofs) { + rv.sa_proofs = SAProof_Gen(destinations, x_change, change_index); +#ifdef DBG + CHECK_AND_ASSERT_THROW_MES(SAProof_Ver(rv.sa_proofs, destinations, change_index), "SAProof_Ver() failed on recently created proof"); +#endif + } + */ + 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 & destination_asset_types, - const std::vector &inamounts, - const std::vector &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 & destination_asset_types, + const std::vector &inamounts, + const std::vector &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 ) { std::vector index; index.resize(inPk.size()); @@ -1397,7 +1508,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); } //RingCT protocol diff --git a/src/ringct/rctSigs.h b/src/ringct/rctSigs.h index 33c12f066..38aa1eaad 100644 --- a/src/ringct/rctSigs.h +++ b/src/ringct/rctSigs.h @@ -88,6 +88,9 @@ namespace rct { zk_proof PRProof_Gen(const rct::key &difference); bool PRProof_Ver(const rct::key &C, const zk_proof &proof); + std::vector SAProof_Gen(const keyV &pubkeys, const key &x_change, const size_t change_index); + bool SAProof_Ver(const std::vector &proofs, const keyV &pubkeys, const size_t change_index); + //proveRange and verRange //proveRange gives C, and mask such that \sumCi = C // c.f. https://eprint.iacr.org/2015/1098 section 5.1 @@ -145,7 +148,9 @@ 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 ); rctSig genRctSimple( const key & message, @@ -162,7 +167,9 @@ namespace rct { const std::vector & 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 ); bool verRct(const rctSig & rv, bool semantics); static inline bool verRct(const rctSig & rv) { return verRct(rv, true) && verRct(rv, false); } diff --git a/src/ringct/rctTypes.cpp b/src/ringct/rctTypes.cpp index c22b0524f..31a9d1a67 100644 --- a/src/ringct/rctTypes.cpp +++ b/src/ringct/rctTypes.cpp @@ -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; diff --git a/src/ringct/rctTypes.h b/src/ringct/rctTypes.h index 74783bd3e..43b3ec827 100644 --- a/src/ringct/rctTypes.h +++ b/src/ringct/rctTypes.h @@ -101,7 +101,6 @@ namespace rct { FIELD(z2) END_SERIALIZE() }; - typedef std::vector proofV; //containers For CT operations //if it's representing a private ctkey then "dest" contains the secret key of the address @@ -341,10 +340,10 @@ namespace rct { xmr_amount txnFee; // contains b key p_r; zk_proof pr_proof; // p_r - proofV sa_proof; + std::vector sa_proofs; // spend authority proofs rctSigBase() : - type(RCTTypeNull), message{}, mixRing{}, pseudoOuts{}, ecdhInfo{}, outPk{}, txnFee(0), p_r{}, pr_proof{}, sa_proof{} + type(RCTTypeNull), message{}, mixRing{}, pseudoOuts{}, ecdhInfo{}, outPk{}, txnFee(0), p_r{}, pr_proof{}, sa_proofs{} {} template class Archive> @@ -422,7 +421,22 @@ namespace rct { if (type == RCTTypeFullProofs) { FIELD(pr_proof) - FIELD(sa_proof) + /* + uint32_t nsap = sa_proofs.size(); + VARINT_FIELD(nsap) + ar.tag("sa_proofs"); + ar.begin_array(); + if (nsap > outputs) + return false; + PREPARE_CUSTOM_VECTOR_SERIALIZATION(nsap, sa_proofs); + for (size_t i = 0; i < nsap; ++i) + { + FIELDS(sa_proofs[i]) + if (nsap - i > 1) + ar.delimit_array(); + } + ar.end_array(); + */ } return ar.good(); } @@ -438,7 +452,7 @@ namespace rct { FIELD(p_r) if (type == RCTTypeFullProofs) { FIELD(pr_proof) - FIELD(sa_proof) + //FIELD(sa_proofs) } END_SERIALIZE() }; @@ -820,6 +834,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); @@ -838,6 +853,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"); @@ -856,5 +872,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 */ diff --git a/src/serialization/json_object.cpp b/src/serialization/json_object.cpp index bef0906dc..5bce34ac5 100644 --- a/src/serialization/json_object.cpp +++ b/src/serialization/json_object.cpp @@ -1173,6 +1173,10 @@ void toJsonValue(rapidjson::Writer& 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_proofs, sig.sa_proofs); + } } // 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_proofs, sa_proofs); + } } // 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& 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& dest, const cryptonote::rpc::DaemonInfo& info) { dest.StartObject(); diff --git a/src/serialization/json_object.h b/src/serialization/json_object.h index 3868ab3f8..c0022985b 100644 --- a/src/serialization/json_object.h +++ b/src/serialization/json_object.h @@ -307,6 +307,9 @@ void fromJsonValue(const rapidjson::Value& val, rct::mgSig& sig); void toJsonValue(rapidjson::Writer& dest, const rct::clsag& sig); void fromJsonValue(const rapidjson::Value& val, rct::clsag& sig); +void toJsonValue(rapidjson::Writer& dest, const rct::zk_proof& p); +void fromJsonValue(const rapidjson::Value& val, rct::zk_proof& p); + void toJsonValue(rapidjson::Writer& dest, const cryptonote::rpc::DaemonInfo& info); void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::DaemonInfo& info); diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 9d6f2009a..419ab5cfb 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -2147,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); @@ -10263,11 +10264,11 @@ void wallet2::transfer_selected_rct(std::vector 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)); diff --git a/tests/unit_tests/ringct.cpp b/tests/unit_tests/ringct.cpp index bbecd6fe5..6dc2061e8 100644 --- a/tests/unit_tests/ringct.cpp +++ b/tests/unit_tests/ringct.cpp @@ -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")); } diff --git a/tests/unit_tests/serialization.cpp b/tests/unit_tests/serialization.cpp index 823ab609b..9331ec013 100644 --- a/tests/unit_tests/serialization.cpp +++ b/tests/unit_tests/serialization.cpp @@ -608,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 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()); From 0448a6bf9aa7ac33a612831272b374b892804b00 Mon Sep 17 00:00:00 2001 From: Some Random Crypto Guy Date: Mon, 16 Dec 2024 07:48:16 +0000 Subject: [PATCH 05/17] interim checkin --- .../cryptonote_boost_serialization.h | 4 +- src/cryptonote_core/blockchain.cpp | 10 ++-- src/cryptonote_core/cryptonote_tx_utils.cpp | 10 +++- src/ringct/rctSigs.cpp | 50 +++++++++---------- src/ringct/rctSigs.h | 10 ++-- src/ringct/rctTypes.h | 3 +- 6 files changed, 49 insertions(+), 38 deletions(-) diff --git a/src/cryptonote_basic/cryptonote_boost_serialization.h b/src/cryptonote_basic/cryptonote_boost_serialization.h index 41fa0e2c7..3a894841c 100644 --- a/src/cryptonote_basic/cryptonote_boost_serialization.h +++ b/src/cryptonote_basic/cryptonote_boost_serialization.h @@ -423,7 +423,7 @@ namespace boost a & x.p_r; if (x.type == rct::RCTTypeFullProofs) { a & x.pr_proof; - //a & x.sa_proofs; + a & x.sa_proofs; } } @@ -462,7 +462,7 @@ namespace boost a & x.p_r; if (x.type == rct::RCTTypeFullProofs) { a & x.pr_proof; - //a & x.sa_proofs; + a & x.sa_proofs; } //-------------- a & x.p.rangeSigs; diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 3e2dca563..07f58295d 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -3619,10 +3619,12 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context } if (hf_version >= HF_VERSION_FULL_PROOFS) { - 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; + if (tx.type == cryptonote::transaction_type::TRANSFER) { + if (tx.rct_signatures.type != rct::RCTTypeFullProofs) { + MERROR_VER("FullProofs required for TRANSFER TXs after v" + std::to_string(HF_VERSION_FULL_PROOFS)); + tvc.m_invalid_output = true; + return false; + } } } diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp index ae5ee897c..a13d4d0a5 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.cpp +++ b/src/cryptonote_core/cryptonote_tx_utils.cpp @@ -858,6 +858,7 @@ namespace cryptonote //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) { @@ -970,6 +971,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]; @@ -1209,7 +1216,8 @@ namespace cryptonote rct_config, hwdev, rct::sk2rct(x_change), - change_index + 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 diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp index 9bbdf7202..058d7db8a 100644 --- a/src/ringct/rctSigs.cpp +++ b/src/ringct/rctSigs.cpp @@ -1098,7 +1098,7 @@ namespace rct { return index; } - std::vector SAProof_Gen(const keyV &pubkeys, const key &x_change, const size_t change_index) { + std::vector SAProof_Gen(const keyV &pubkeys, const key &x_change, const size_t change_index, const key &key_yF) { // Declare a return structure std::vector proofs{}; @@ -1126,9 +1126,10 @@ namespace rct { // Calculate the challenge hash from the commitments plus the pubkeys keyV challenge_keys; - challenge_keys.reserve(pubkeys.size() * 2); + challenge_keys.reserve(pubkeys.size() * 2 + 1); challenge_keys.insert(challenge_keys.end(), commitments.begin(), commitments.end()); challenge_keys.insert(challenge_keys.end(), pubkeys.begin(), pubkeys.end()); + challenge_keys.push_back(key_yF); rct::key c = rct::hash_to_scalar(challenge_keys); sc_reduce32(c.bytes); @@ -1144,8 +1145,8 @@ namespace rct { rct::key z_x; sc_muladd(z_x.bytes, x_val.bytes, c.bytes, scalars[j].bytes); //rct::key z_x = rct::addKeys(scalars[j], rct::scalarmultKey(c, x_val)); - rct::key z_y = scalars[j]; - proofs.push_back({commitments[j], z_x, z_y}); + //rct::key z_y = scalars[j]; + proofs.push_back({commitments[j], z_x, rct::zero()}); } // Return the proof to the caller @@ -1153,18 +1154,19 @@ namespace rct { } - bool SAProof_Ver(const std::vector &proofs, const keyV &pubkeys, const size_t change_index) { + bool SAProof_Ver(const std::vector &proofs, const keyV &pubkeys, const size_t change_index, const key &key_yF) { // Sanity checks CHECK_AND_ASSERT_THROW_MES(proofs.size() == pubkeys.size(), "PRProof_Ver() failed - proof count does not match output count"); CHECK_AND_ASSERT_THROW_MES(change_index < pubkeys.size(), "PRProof_Ver() failed - invalid change index provided"); // Recompute the challenge hash keyV challenge_keys; - challenge_keys.reserve(pubkeys.size() * 2); + challenge_keys.reserve(pubkeys.size() * 2 + 1); for (const auto &proof_entr: proofs) { challenge_keys.push_back(proof_entr.R); } challenge_keys.insert(challenge_keys.end(), pubkeys.begin(), pubkeys.end()); + challenge_keys.push_back(key_yF); rct::key c = rct::hash_to_scalar(challenge_keys); sc_reduce32(c.bytes); @@ -1172,23 +1174,17 @@ namespace rct { const auto &proof = proofs[change_index]; const rct::key &R = proof.R; // Commitment const rct::key &z_x = proof.z1; // z_x value - const rct::key &z_y = proof.z2; // z_y value const rct::key P = pubkeys[change_index]; // Verify the proof for the change output // Recalculate the expected commitment using the formula: z_x * G = R + c * P - rct::key expected_commitment = rct::addKeys(R, rct::scalarmultKey(c, P)); + rct::key expected_commitment = rct::addKeys(R, rct::scalarmultKey(P, c)); // Verify z_x * G matches the expected commitment if (!rct::equalKeys(rct::scalarmultBase(z_x), expected_commitment)) { return false; // Verification failed } - // Verify z_y * G matches the original commitment - if (!rct::equalKeys(rct::scalarmultBase(z_y), R)) { - return false; // Verification failed - } - // All checks passed return true; } @@ -1281,7 +1277,8 @@ namespace rct { const RCTConfig &rct_config, hw::device &hwdev, const key &x_change, - const size_t change_index + const size_t change_index, + const key &key_yF ) { const bool bulletproof_or_plus = rct_config.range_proof_type > RangeProofBorromean; @@ -1451,6 +1448,16 @@ namespace rct { DP(rv.p_r); if (rv.type == RCTTypeFullProofs) rv.pr_proof = PRProof_Gen(difference); + + // Check if spend authority proof is needed (only for TRANSFER TXs) + rv.sa_proofs.clear(); + if (tx_type == cryptonote::transaction_type::TRANSFER && rv.type == rct::RCTTypeFullProofs) { + rv.sa_proofs = SAProof_Gen(destinations, x_change, change_index, key_yF); + //#ifdef DBG + CHECK_AND_ASSERT_THROW_MES(SAProof_Ver(rv.sa_proofs, 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++) @@ -1468,16 +1475,6 @@ namespace rct { } } - // Check if spend authority proof is needed (only for TRANSFER TXs) - /* - if (tx_type == cryptonote::transaction_type::TRANSFER && rv.type == rct::RCTTypeFullProofs) { - rv.sa_proofs = SAProof_Gen(destinations, x_change, change_index); -#ifdef DBG - CHECK_AND_ASSERT_THROW_MES(SAProof_Ver(rv.sa_proofs, destinations, change_index), "SAProof_Ver() failed on recently created proof"); -#endif - } - */ - return rv; } @@ -1497,7 +1494,8 @@ namespace rct { const RCTConfig &rct_config, hw::device &hwdev, const key &x_change, - const size_t change_index + const size_t change_index, + const key &key_yF ) { std::vector index; index.resize(inPk.size()); @@ -1508,7 +1506,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, x_change, change_index); + 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 diff --git a/src/ringct/rctSigs.h b/src/ringct/rctSigs.h index 38aa1eaad..0c6a88b1a 100644 --- a/src/ringct/rctSigs.h +++ b/src/ringct/rctSigs.h @@ -88,8 +88,8 @@ namespace rct { zk_proof PRProof_Gen(const rct::key &difference); bool PRProof_Ver(const rct::key &C, const zk_proof &proof); - std::vector SAProof_Gen(const keyV &pubkeys, const key &x_change, const size_t change_index); - bool SAProof_Ver(const std::vector &proofs, const keyV &pubkeys, const size_t change_index); + std::vector SAProof_Gen(const keyV &pubkeys, const key &x_change, const size_t change_index, const key &key_yF); + bool SAProof_Ver(const std::vector &proofs, const keyV &pubkeys, const size_t change_index, const key &key_yF); //proveRange and verRange //proveRange gives C, and mask such that \sumCi = C @@ -150,7 +150,8 @@ namespace rct { const RCTConfig &rct_config, hw::device &hwdev, const key &x_change = rct::zero(), - const size_t change_index = 0 + const size_t change_index = 0, + const key &key_yF = rct::zero() ); rctSig genRctSimple( const key & message, @@ -169,7 +170,8 @@ namespace rct { const RCTConfig &rct_config, hw::device &hwdev, const key &x_change = rct::zero(), - const size_t change_index = 0 + 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); } diff --git a/src/ringct/rctTypes.h b/src/ringct/rctTypes.h index 43b3ec827..2b1002f76 100644 --- a/src/ringct/rctTypes.h +++ b/src/ringct/rctTypes.h @@ -421,6 +421,7 @@ namespace rct { if (type == RCTTypeFullProofs) { FIELD(pr_proof) + FIELD(sa_proofs) /* uint32_t nsap = sa_proofs.size(); VARINT_FIELD(nsap) @@ -452,7 +453,7 @@ namespace rct { FIELD(p_r) if (type == RCTTypeFullProofs) { FIELD(pr_proof) - //FIELD(sa_proofs) + FIELD(sa_proofs) } END_SERIALIZE() }; From f3522764a1198f995b48ad34489bceafb9733760 Mon Sep 17 00:00:00 2001 From: Some Random Crypto Guy Date: Mon, 16 Dec 2024 09:16:34 +0000 Subject: [PATCH 06/17] switched to single spend authority proof - the dummy proofs don't work as intended, so dropping them --- .../cryptonote_boost_serialization.h | 4 +- src/multisig/multisig_tx_builder_ringct.cpp | 2 +- src/ringct/rctSigs.cpp | 95 +++++++------------ src/ringct/rctSigs.h | 4 +- src/ringct/rctTypes.h | 24 +---- src/serialization/json_object.cpp | 4 +- 6 files changed, 44 insertions(+), 89 deletions(-) diff --git a/src/cryptonote_basic/cryptonote_boost_serialization.h b/src/cryptonote_basic/cryptonote_boost_serialization.h index 3a894841c..bcbb4c7ff 100644 --- a/src/cryptonote_basic/cryptonote_boost_serialization.h +++ b/src/cryptonote_basic/cryptonote_boost_serialization.h @@ -423,7 +423,7 @@ namespace boost a & x.p_r; if (x.type == rct::RCTTypeFullProofs) { a & x.pr_proof; - a & x.sa_proofs; + a & x.sa_proof; } } @@ -462,7 +462,7 @@ namespace boost a & x.p_r; if (x.type == rct::RCTTypeFullProofs) { a & x.pr_proof; - a & x.sa_proofs; + a & x.sa_proof; } //-------------- a & x.p.rangeSigs; diff --git a/src/multisig/multisig_tx_builder_ringct.cpp b/src/multisig/multisig_tx_builder_ringct.cpp index 7c07cb465..5b48a83e1 100644 --- a/src/multisig/multisig_tx_builder_ringct.cpp +++ b/src/multisig/multisig_tx_builder_ringct.cpp @@ -926,7 +926,7 @@ static bool set_tx_rct_signatures( else { rv.p.pseudoOuts = unsigned_tx.rct_signatures.p.pseudoOuts; rv.pr_proof = unsigned_tx.rct_signatures.pr_proof; // should verify this during reconstruction - //rv.sa_proofs = unsigned_tx.rct_signatures.sa_proofs; // should verify this during reconstruction + rv.sa_proof = unsigned_tx.rct_signatures.sa_proof; // should verify this during reconstruction rv.p_r = unsigned_tx.rct_signatures.p_r; if (num_sources != rv.p.pseudoOuts.size()) return false; diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp index 058d7db8a..3d6112e54 100644 --- a/src/ringct/rctSigs.cpp +++ b/src/ringct/rctSigs.cpp @@ -1098,90 +1098,58 @@ namespace rct { return index; } - std::vector SAProof_Gen(const keyV &pubkeys, const key &x_change, const size_t change_index, const key &key_yF) { + zk_proof SAProof_Gen(const key &P, const key &x_change, const key &key_yF) { // Declare a return structure - std::vector proofs{}; + zk_proof proof{}; + proof.z2 = rct::zero(); // Sanity checks - CHECK_AND_ASSERT_THROW_MES(pubkeys.size(), "SAProof_Gen() failed - no output pubkeys provided"); - CHECK_AND_ASSERT_THROW_MES(pubkeys.size() > change_index, "SAProof_Gen() failed - invalid change_index provided"); + 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"); - // Iterate over the outputs - rct::keyV scalars; - rct::keyV commitments; - for (size_t j=0; j &proofs, const keyV &pubkeys, const size_t change_index, const key &key_yF) { + bool SAProof_Ver(const zk_proof &proof, const key &P, const key &key_yF) { + // Sanity checks - CHECK_AND_ASSERT_THROW_MES(proofs.size() == pubkeys.size(), "PRProof_Ver() failed - proof count does not match output count"); - CHECK_AND_ASSERT_THROW_MES(change_index < pubkeys.size(), "PRProof_Ver() failed - invalid change index provided"); + CHECK_AND_ASSERT_THROW_MES(!rct::equalKeys(P, rct::zero()), "SAProof_Gen() failed - invalid public key provided"); + CHECK_AND_ASSERT_THROW_MES(!rct::equalKeys(key_yF, rct::zero()), "SAProof_Gen() failed - invalid shared secret key provided"); // Recompute the challenge hash keyV challenge_keys; - challenge_keys.reserve(pubkeys.size() * 2 + 1); - for (const auto &proof_entr: proofs) { - challenge_keys.push_back(proof_entr.R); - } - challenge_keys.insert(challenge_keys.end(), pubkeys.begin(), pubkeys.end()); + challenge_keys.reserve(3); + challenge_keys.push_back(proof.R); + challenge_keys.push_back(P); challenge_keys.push_back(key_yF); rct::key c = rct::hash_to_scalar(challenge_keys); sc_reduce32(c.bytes); - // Extract the proof for the change output - we don't care about the others because they're dummy proofs - const auto &proof = proofs[change_index]; - const rct::key &R = proof.R; // Commitment - const rct::key &z_x = proof.z1; // z_x value - const rct::key P = pubkeys[change_index]; - - // Verify the proof for the change output // Recalculate the expected commitment using the formula: z_x * G = R + c * P - rct::key expected_commitment = rct::addKeys(R, rct::scalarmultKey(P, c)); + 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(z_x), expected_commitment)) { + if (!rct::equalKeys(rct::scalarmultBase(proof.z1), expected_commitment)) { return false; // Verification failed } @@ -1446,16 +1414,19 @@ namespace rct { sc_sub(difference.bytes, sumpouts.bytes, sumout.bytes); genC(rv.p_r, difference, 0); DP(rv.p_r); - if (rv.type == RCTTypeFullProofs) + 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) - rv.sa_proofs.clear(); if (tx_type == cryptonote::transaction_type::TRANSFER && rv.type == rct::RCTTypeFullProofs) { - rv.sa_proofs = SAProof_Gen(destinations, x_change, change_index, key_yF); - //#ifdef DBG - CHECK_AND_ASSERT_THROW_MES(SAProof_Ver(rv.sa_proofs, destinations, change_index, key_yF), "SAProof_Ver() failed on recently created proof"); - //#endif + 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); diff --git a/src/ringct/rctSigs.h b/src/ringct/rctSigs.h index 0c6a88b1a..037be68ac 100644 --- a/src/ringct/rctSigs.h +++ b/src/ringct/rctSigs.h @@ -88,8 +88,8 @@ namespace rct { zk_proof PRProof_Gen(const rct::key &difference); bool PRProof_Ver(const rct::key &C, const zk_proof &proof); - std::vector SAProof_Gen(const keyV &pubkeys, const key &x_change, const size_t change_index, const key &key_yF); - bool SAProof_Ver(const std::vector &proofs, const keyV &pubkeys, const size_t change_index, const key &key_yF); + zk_proof SAProof_Gen(const keyV &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 diff --git a/src/ringct/rctTypes.h b/src/ringct/rctTypes.h index 2b1002f76..692b84d36 100644 --- a/src/ringct/rctTypes.h +++ b/src/ringct/rctTypes.h @@ -340,10 +340,10 @@ namespace rct { xmr_amount txnFee; // contains b key p_r; zk_proof pr_proof; // p_r - std::vector sa_proofs; // spend authority proofs + zk_proof sa_proof; // spend authority proof rctSigBase() : - type(RCTTypeNull), message{}, mixRing{}, pseudoOuts{}, ecdhInfo{}, outPk{}, txnFee(0), p_r{}, pr_proof{}, sa_proofs{} + type(RCTTypeNull), message{}, mixRing{}, pseudoOuts{}, ecdhInfo{}, outPk{}, txnFee(0), p_r{}, pr_proof{}, sa_proof{} {} template class Archive> @@ -421,23 +421,7 @@ namespace rct { if (type == RCTTypeFullProofs) { FIELD(pr_proof) - FIELD(sa_proofs) - /* - uint32_t nsap = sa_proofs.size(); - VARINT_FIELD(nsap) - ar.tag("sa_proofs"); - ar.begin_array(); - if (nsap > outputs) - return false; - PREPARE_CUSTOM_VECTOR_SERIALIZATION(nsap, sa_proofs); - for (size_t i = 0; i < nsap; ++i) - { - FIELDS(sa_proofs[i]) - if (nsap - i > 1) - ar.delimit_array(); - } - ar.end_array(); - */ + FIELD(sa_proof) } return ar.good(); } @@ -453,7 +437,7 @@ namespace rct { FIELD(p_r) if (type == RCTTypeFullProofs) { FIELD(pr_proof) - FIELD(sa_proofs) + FIELD(sa_proof) } END_SERIALIZE() }; diff --git a/src/serialization/json_object.cpp b/src/serialization/json_object.cpp index 5bce34ac5..6b2ab1230 100644 --- a/src/serialization/json_object.cpp +++ b/src/serialization/json_object.cpp @@ -1175,7 +1175,7 @@ void toJsonValue(rapidjson::Writer& dest, const rct::rctSig& 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_proofs, sig.sa_proofs); + INSERT_INTO_JSON_OBJECT(dest, sa_proof, sig.sa_proof); } } @@ -1216,7 +1216,7 @@ void fromJsonValue(const rapidjson::Value& val, rct::rctSig& sig) 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_proofs, sa_proofs); + GET_FROM_JSON_OBJECT(val, sig.sa_proof, sa_proof); } } From 82d706aacba12f9db3f395e63ec327de011b1cf0 Mon Sep 17 00:00:00 2001 From: Some Random Crypto Guy Date: Mon, 16 Dec 2024 09:18:47 +0000 Subject: [PATCH 07/17] bumped RC version --- README.md | 2 +- src/version.cpp.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 78fb423cd..1ffc38c8a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Salvium Zero v0.7.0rc1 +# Salvium Zero v0.7.0-rc2 Copyright (c) 2023-2024, Salvium Portions Copyright (c) 2014-2023, The Monero Project diff --git a/src/version.cpp.in b/src/version.cpp.in index 9fdaee1dd..649417768 100644 --- a/src/version.cpp.in +++ b/src/version.cpp.in @@ -1,5 +1,5 @@ #define DEF_SALVIUM_VERSION_TAG "@VERSIONTAG@" -#define DEF_SALVIUM_VERSION "0.7.0rc1" +#define DEF_SALVIUM_VERSION "0.7.0-rc2" #define DEF_MONERO_VERSION_TAG "release" #define DEF_MONERO_VERSION "0.18.3.3" #define DEF_MONERO_RELEASE_NAME "Zero" From e15dbb5db2ec3cf8817b89916e49b69c6abafafa Mon Sep 17 00:00:00 2001 From: Some Random Crypto Guy Date: Mon, 16 Dec 2024 14:07:37 +0000 Subject: [PATCH 08/17] added belt and braces to prevent CONVERT TXs from being attempted; integrated spend authority proof support into wallet; bumped version number --- README.md | 2 +- src/cryptonote_core/blockchain.cpp | 9 +++ src/ringct/rctSigs.cpp | 60 ++++---------------- src/version.cpp.in | 2 +- src/wallet/wallet2.cpp | 90 +++++++++++++++++++++++++++++- src/wallet/wallet2.h | 2 + 6 files changed, 113 insertions(+), 52 deletions(-) diff --git a/README.md b/README.md index 1ffc38c8a..226ea453a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Salvium Zero v0.7.0-rc2 +# Salvium Zero v0.7.0-rc3 Copyright (c) 2023-2024, Salvium Portions Copyright (c) 2014-2023, The Monero Project diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 07f58295d..0be78f752 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -3671,6 +3671,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; } diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp index 3d6112e54..d4021332b 100644 --- a/src/ringct/rctSigs.cpp +++ b/src/ringct/rctSigs.cpp @@ -522,33 +522,6 @@ namespace rct { return sc_isnonzero(c.bytes) == 0; } - - // Optimized function to hash a vector of keys into a scalar - rct::key my_hash_to_scalar(std::vector& keys) { - - // Create a fixed-size buffer large enough to hold all keys and a domain separator - size_t total_size = keys.size() * sizeof(rct::key) + sizeof("ZKP") - 1; - std::vector data(total_size); - - // Copy the keys into the buffer - size_t offset = 0; - for (const auto& key : keys) { - std::memcpy(data.data() + offset, key.bytes, sizeof(rct::key)); - offset += sizeof(rct::key); - } - - // Add the domain separator "ZKP" at the end of the buffer - const char* domain_separator = "ZKP"; - std::memcpy(data.data() + offset, domain_separator, sizeof("ZKP") - 1); - - // Hash the concatenated data into a fixed-size hash - rct::key hash_output; - keccak((const uint8_t *)data.data(), total_size, hash_output.bytes, sizeof(rct::key)); - sc_reduce32(hash_output.bytes); // Reduce to valid scalar - - return hash_output; - } - zk_proof PRProof_Gen(const rct::key &difference) { zk_proof proof; @@ -565,7 +538,6 @@ namespace rct { // Calculate challenge c = H_p(R) std::vector keys{proof.R, comm_diff}; rct::key c = rct::hash_to_scalar(keys); - sc_reduce32(c.bytes); // Calculate response z = r + c * difference sc_muladd(proof.z1.bytes, difference.bytes, c.bytes, r.bytes); @@ -1100,27 +1072,22 @@ namespace rct { zk_proof SAProof_Gen(const key &P, const key &x_change, const key &key_yF) { - // Declare a return structure - zk_proof proof{}; - proof.z2 = rct::zero(); - - // Sanity checks + // 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 commitments plus the pubkeys - keyV challenge_keys; - challenge_keys.reserve(3); - challenge_keys.push_back(proof.R); - challenge_keys.push_back(P); - challenge_keys.push_back(key_yF); + // 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); - sc_reduce32(c.bytes); rct::key z_x; sc_muladd(z_x.bytes, x_change.bytes, c.bytes, r.bytes); @@ -1132,18 +1099,13 @@ namespace rct { bool SAProof_Ver(const zk_proof &proof, const key &P, const key &key_yF) { - // Sanity checks - CHECK_AND_ASSERT_THROW_MES(!rct::equalKeys(P, rct::zero()), "SAProof_Gen() failed - invalid public key provided"); - CHECK_AND_ASSERT_THROW_MES(!rct::equalKeys(key_yF, rct::zero()), "SAProof_Gen() failed - invalid shared secret key provided"); + // 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; - challenge_keys.reserve(3); - challenge_keys.push_back(proof.R); - challenge_keys.push_back(P); - challenge_keys.push_back(key_yF); + keyV challenge_keys{proof.R, P, key_yF}; rct::key c = rct::hash_to_scalar(challenge_keys); - sc_reduce32(c.bytes); // 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)); diff --git a/src/version.cpp.in b/src/version.cpp.in index 649417768..41201dff1 100644 --- a/src/version.cpp.in +++ b/src/version.cpp.in @@ -1,5 +1,5 @@ #define DEF_SALVIUM_VERSION_TAG "@VERSIONTAG@" -#define DEF_SALVIUM_VERSION "0.7.0-rc2" +#define DEF_SALVIUM_VERSION "0.7.0-rc3" #define DEF_MONERO_VERSION_TAG "release" #define DEF_MONERO_VERSION "0.18.3.3" #define DEF_MONERO_RELEASE_NAME "Zero" diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 419ab5cfb..313dd7cde 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -2242,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::max() - tx_scan_info.money_transfered, error::wallet_internal_error, "Overflow in received amounts"); @@ -2481,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 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 &o_indices, const std::vector &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, size_t> *output_tracker_cache, bool ignore_callbacks) { PERF_TIMER(process_new_transaction); @@ -2784,6 +2855,15 @@ 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); @@ -2901,6 +2981,14 @@ 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) m_callback->on_money_received(height, txid, tx, td.m_amount, td.asset_type, burnt, td.m_subaddr_index, spends_one_of_ours(tx), td.m_tx.unlock_time, td.m_td_origin_idx); diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index ee90e53ba..1273d03dc 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -1191,6 +1191,8 @@ private: std::vector 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 inline void serialize(t_archive &a, const unsigned int ver) { From cef01372b11ed6d962e1ac509919da4a8739a08b Mon Sep 17 00:00:00 2001 From: Some Random Crypto Guy Date: Tue, 17 Dec 2024 20:06:54 +0000 Subject: [PATCH 09/17] updated block fast sync checksums; disabled spend authority proof due to multisig; fixed issue with duplicate keys; bumped version --- src/blocks/checkpoints.dat | Bin 12164 -> 14980 bytes src/cryptonote_core/blockchain.cpp | 3 + src/multisig/multisig_tx_builder_ringct.cpp | 86 ++++++++++++++++++-- src/ringct/rctSigs.cpp | 2 + src/ringct/rctSigs.h | 2 +- src/version.cpp.in | 2 +- src/wallet/wallet2.cpp | 6 +- 7 files changed, 92 insertions(+), 9 deletions(-) diff --git a/src/blocks/checkpoints.dat b/src/blocks/checkpoints.dat index 20cb92123f51fdce7764af796aa787032865e2ef..8ba5bc6e79341a097ef26b26e51badc223c35f8c 100644 GIT binary patch delta 2849 zcmV++3*PjEUxal5>ahWXFMrH%cvzeUk7r-~1Qd-d@aCQ95{y+ktZUX-d+-A^Gpbo$DS? z=O14*NM_V{dE9`&8LY0TFmIw&`a~W!($NhBkiZ)y?i(h-jw-TczJG^>ah4Uh(6-`? zVKrFTct>0FF9BpS+o7Ms&t6aJ-U33L*g`bXR&D7m47T z0k`2gJeyLHxqoH1_dKy=#;^L{g-69Agk|dVYL^ADW?D9Wd`HxJ)$#11hSrF(l~Sg^ zE3Jeaz+b>y3MYVt=r}=lD6YO%HRtxMocbu3uKI$nvVR*lCC}J~%)kHB7g$b@-8)v8 z%R8vWEjqbis8obQOD+r>h4_^b-*|`vqdCD*8k5xD&3_}z2I&`ooIpQ* z0X`W@;-VR4YEWL5|6|A6Tp&AU^zwUOazLgL(t>ely- zoGY3A zQKwxUqwt8NMRg7THR8q&6uv!x1 zk>7h%)d&k}zF#Bt!~!lE*~mLf*uFd&E7U!8K`0}UMnAy-9qQ5-!!R&i*%P7EI5UjR z3~ZNUv;{cyMfFok0ecE|!NJv|m3>WOupXod<4HF@=Hb`JlpSvaYUw(+qcPMdrZgnLEFHoN(DBt5dxmA2|lVadph(ebxIe`O$pH$uCo)tVH&msJUy2#@aW zIIIl^ckj7*q^`J8mnuTU!Fc zobb<~WJ4-B)PF zf)+f_{pbAFVpi+F`^QKaR-fSv>x9z?W3^F~3Kbsyy-daPHN_*1X>frE%|TzmJ&PgfjjUduG;Nx^9| zYJuO;!C{>cmCjpSX}y9edHq7=v*F`etkO4%Okwcw=)6!(EY> zndObbsMY~rW{BoqG$1IJsGOtX!iLmYy)2KY0iP7uKC*qJi4+N2wC%mN)v(X~A${Y1 zwON>6b(0G~EL*GL1%LcgdMkjvXq!3jI0?uM8F)(sEqJVC8N4eAn;&q+pUkM%lRoU! zs47n@6t1BCsau(Udik1-&>4Fp;Xv`dDY8x=u}lqffEIzX4P%NOBSgn41Z z*7FBLE2Yafvfoh4V?>r(u1EW$mV0zT_h!0XYp8H za9SK&kUV@>SAPo+(!_KSsyoFOK3~sKj?&={v6zXP!J4abgYGnMMJJF~ZeI)zVDPjl zuXwEYdwJ<#?o72TuC;QUE9WohGOC%b+E}d;uaj9E+?htmgVRUTtaYh9eUQV~reCkf znwh~=qlF6Yq_OrcHfy=8FO*T?Fsu=TzBJE*K$XRkeWS z9Utt$hO|h7DMyJ3p3_ic3K{>S#xT`9PiU|Y!CPGb~EI~gCam=FZKOo7Tx=!IFo3?yZSVh zxJlRiNPo4N?f?55R*qq0WpMJ>8Gp}(R!RsPw-h+=Vp?$SEKss)D|twO zQ%&B3bH4}^a^o1Q0ImWkAIw^F{}|yX`7#nfsmdw)k4)=T=aPxhyB8)8ju$QatHC{W z$5?JR@lFR=f4+?BXGe(uRVnseU(pKyN`@P?^jpx+hnInLTQg& delta 10 RcmZoEZHZ^xw~?_~9{?A?1ONa4 diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 0be78f752..4fe7d91df 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -1558,16 +1558,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(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(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 outputs_verified; diff --git a/src/multisig/multisig_tx_builder_ringct.cpp b/src/multisig/multisig_tx_builder_ringct.cpp index 5b48a83e1..18c309fc5 100644 --- a/src/multisig/multisig_tx_builder_ringct.cpp +++ b/src/multisig/multisig_tx_builder_ringct.cpp @@ -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,7 +829,10 @@ static bool set_tx_rct_signatures( const bool reconstruction, cryptonote::transaction& unsigned_tx, std::vector& 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 && @@ -919,15 +933,38 @@ 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 = PRProof_Gen(difference); + 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.pr_proof = unsigned_tx.rct_signatures.pr_proof; // should verify this during reconstruction - rv.sa_proof = unsigned_tx.rct_signatures.sa_proof; // should verify this during reconstruction - 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)); @@ -1172,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); @@ -1186,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 @@ -1221,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) @@ -1241,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 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 @@ -1253,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; diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp index d4021332b..702758c7c 100644 --- a/src/ringct/rctSigs.cpp +++ b/src/ringct/rctSigs.cpp @@ -1383,6 +1383,7 @@ namespace rct { #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); @@ -1390,6 +1391,7 @@ namespace rct { 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); diff --git a/src/ringct/rctSigs.h b/src/ringct/rctSigs.h index 037be68ac..d5a0e9f89 100644 --- a/src/ringct/rctSigs.h +++ b/src/ringct/rctSigs.h @@ -88,7 +88,7 @@ namespace rct { zk_proof PRProof_Gen(const rct::key &difference); bool PRProof_Ver(const rct::key &C, const zk_proof &proof); - zk_proof SAProof_Gen(const keyV &P, const key &x_change, const key &key_yF); + 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 diff --git a/src/version.cpp.in b/src/version.cpp.in index 41201dff1..d56fb6644 100644 --- a/src/version.cpp.in +++ b/src/version.cpp.in @@ -1,5 +1,5 @@ #define DEF_SALVIUM_VERSION_TAG "@VERSIONTAG@" -#define DEF_SALVIUM_VERSION "0.7.0-rc3" +#define DEF_SALVIUM_VERSION "0.7.0-rc4" #define DEF_MONERO_VERSION_TAG "release" #define DEF_MONERO_VERSION "0.18.3.3" #define DEF_MONERO_RELEASE_NAME "Zero" diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 313dd7cde..f65d38145 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -2856,6 +2856,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote 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 @@ -2863,6 +2864,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote 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) @@ -2980,7 +2982,8 @@ 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 @@ -2988,6 +2991,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote 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) From c763febe98f75c45ea4a9e17df3305235b24e48f Mon Sep 17 00:00:00 2001 From: Some Random Crypto Guy Date: Wed, 18 Dec 2024 10:10:25 +0000 Subject: [PATCH 10/17] bumped mainline version to v0.7.0 --- README.md | 2 +- src/version.cpp.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 226ea453a..21a95ec92 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Salvium Zero v0.7.0-rc3 +# Salvium Zero v0.7.0 Copyright (c) 2023-2024, Salvium Portions Copyright (c) 2014-2023, The Monero Project diff --git a/src/version.cpp.in b/src/version.cpp.in index d56fb6644..03e86deaf 100644 --- a/src/version.cpp.in +++ b/src/version.cpp.in @@ -1,5 +1,5 @@ #define DEF_SALVIUM_VERSION_TAG "@VERSIONTAG@" -#define DEF_SALVIUM_VERSION "0.7.0-rc4" +#define DEF_SALVIUM_VERSION "0.7.0" #define DEF_MONERO_VERSION_TAG "release" #define DEF_MONERO_VERSION "0.18.3.3" #define DEF_MONERO_RELEASE_NAME "Zero" From d39f2f180e498d06256766eca7625317817dc446 Mon Sep 17 00:00:00 2001 From: Some Random Crypto Guy Date: Wed, 18 Dec 2024 12:01:18 +0000 Subject: [PATCH 11/17] set fork height --- src/hardforks/hardforks.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/hardforks/hardforks.cpp b/src/hardforks/hardforks.cpp index 6ef62e4d7..7bb5f0628 100644 --- a/src/hardforks/hardforks.cpp +++ b/src/hardforks/hardforks.cpp @@ -36,7 +36,10 @@ 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 }, }; 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); From 6368aee05f31fcfa28d34c0ad457ba257eaeb40b Mon Sep 17 00:00:00 2001 From: Some Random Crypto Guy Date: Thu, 19 Dec 2024 11:31:05 +0000 Subject: [PATCH 12/17] bumped version for consensus rules hard fork --- README.md | 2 +- src/cryptonote_config.h | 2 ++ src/cryptonote_core/cryptonote_core.cpp | 10 ++++++++++ src/hardforks/hardforks.cpp | 3 +++ src/version.cpp.in | 2 +- 5 files changed, 17 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 21a95ec92..a51470d70 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Salvium Zero v0.7.0 +# Salvium Zero v0.7.1 Copyright (c) 2023-2024, Salvium Portions Copyright (c) 2014-2023, The Monero Project diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h index b9b838eda..e6744d495 100644 --- a/src/cryptonote_config.h +++ b/src/cryptonote_config.h @@ -220,6 +220,8 @@ #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 diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index 20defc2db..d10e836e6 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -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 diff --git a/src/hardforks/hardforks.cpp b/src/hardforks/hardforks.cpp index 7bb5f0628..bddf7bf2e 100644 --- a/src/hardforks/hardforks.cpp +++ b/src/hardforks/hardforks.cpp @@ -40,6 +40,9 @@ const hardfork_t mainnet_hard_forks[] = { // 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); diff --git a/src/version.cpp.in b/src/version.cpp.in index 03e86deaf..d551e9863 100644 --- a/src/version.cpp.in +++ b/src/version.cpp.in @@ -1,5 +1,5 @@ #define DEF_SALVIUM_VERSION_TAG "@VERSIONTAG@" -#define DEF_SALVIUM_VERSION "0.7.0" +#define DEF_SALVIUM_VERSION "0.7.1" #define DEF_MONERO_VERSION_TAG "release" #define DEF_MONERO_VERSION "0.18.3.3" #define DEF_MONERO_RELEASE_NAME "Zero" From 114297d7845dc091b07109892cbbc5106da46d85 Mon Sep 17 00:00:00 2001 From: Some Random Crypto Guy Date: Fri, 20 Dec 2024 09:48:00 +0000 Subject: [PATCH 13/17] fixed switch values in validation; bumped version --- README.md | 2 +- src/cryptonote_core/blockchain.cpp | 53 +++++++++++---------- src/cryptonote_core/cryptonote_tx_utils.cpp | 1 + src/version.cpp.in | 2 +- 4 files changed, 31 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index a51470d70..0ab4a8b21 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Salvium Zero v0.7.1 +# Salvium Zero v0.7.2 Copyright (c) 2023-2024, Salvium Portions Copyright (c) 2014-2023, The Monero Project diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 4fe7d91df..a9d3be1fd 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -1498,6 +1498,7 @@ bool Blockchain::validate_miner_transaction(const block& b, size_t cumulative_bl 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; @@ -3492,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)) { @@ -3507,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) { @@ -3606,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) @@ -3620,11 +3620,19 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context } } } + */ - if (hf_version >= HF_VERSION_FULL_PROOFS) { - if (tx.type == cryptonote::transaction_type::TRANSFER) { + // 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 for TRANSFER TXs after v" + std::to_string(HF_VERSION_FULL_PROOFS)); + 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; } @@ -4043,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: { @@ -4133,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; } diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp index a13d4d0a5..383dfd199 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.cpp +++ b/src/cryptonote_core/cryptonote_tx_utils.cpp @@ -590,6 +590,7 @@ namespace cryptonote 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; diff --git a/src/version.cpp.in b/src/version.cpp.in index d551e9863..168c8a235 100644 --- a/src/version.cpp.in +++ b/src/version.cpp.in @@ -1,5 +1,5 @@ #define DEF_SALVIUM_VERSION_TAG "@VERSIONTAG@" -#define DEF_SALVIUM_VERSION "0.7.1" +#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" From 0f88d91fa05792846bcfe4db72c6fb81217a9e3d Mon Sep 17 00:00:00 2001 From: Some Random Crypto Guy Date: Tue, 7 Jan 2025 16:57:19 +0000 Subject: [PATCH 14/17] bumped version --- README.md | 10 +++++----- src/cryptonote_config.h | 2 ++ src/cryptonote_core/blockchain.cpp | 20 ++++++++++++++++++++ src/hardforks/hardforks.cpp | 9 +++++++++ src/version.cpp.in | 2 +- 5 files changed, 37 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 0ab4a8b21..08ba31e05 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Salvium Zero v0.7.2 +# Salvium Zero v0.8.0-rc1 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.7.0 + git checkout v0.8.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.7.0 + git checkout v0.8.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.7.0'. 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.8.0'. If you don't care about the version and just want binaries from master, skip this step: ```bash - git checkout v0.7.0 + git checkout v0.8.0 ``` * If you are on a 64-bit system, run: diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h index e6744d495..d18fd54e6 100644 --- a/src/cryptonote_config.h +++ b/src/cryptonote_config.h @@ -222,6 +222,8 @@ #define HF_VERSION_ENFORCE_FULL_PROOFS 4 +#define HF_VERSION_SHUTDOWN_USER_TXS 6 + #define HF_VERSION_REQUIRE_VIEW_TAGS 255 #define HF_VERSION_ENABLE_CONVERT 255 #define HF_VERSION_ENABLE_ORACLE 255 diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index a9d3be1fd..964644d4e 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -3656,6 +3656,15 @@ bool Blockchain::check_tx_type_and_version(const transaction& tx, tx_verificatio const uint8_t hf_version = m_hardfork->get_current_version(); + // Reject ALL TXs except miner + protocol for v5 + if (hf_version == HF_VERSION_SHUTDOWN_USER_TXS) { + if (tx.type != cryptonote::transaction_type::MINER && tx.type != cryptonote::transaction_type::PROTOCOL) { + MERROR_VER("User TXs are not permitted for v" + std::to_string(HF_VERSION_SHUTDOWN_USER_TXS)); + tvc.m_version_mismatch = true; + return false; + } + } + // Prior to v2, only allow TX v2 if (hf_version < HF_VERSION_ENABLE_N_OUTS) { @@ -4774,6 +4783,17 @@ leave: } TIME_MEASURE_FINISH(t2); + TIME_MEASURE_START(t2point5); + + // make sure that block is allowed TXs (prevented during pre-audit period) + if (hf_version == HF_VERSION_SHUTDOWN_USER_TXS && bl.tx_hashes.size()) + { + MERROR_VER("Block with id: " << id << std::endl << "contains " << bl.tx_hashes.size() << " illicit user transactions"); + bvc.m_verifivation_failed = true; + goto leave; + } + + TIME_MEASURE_FINISH(t2point5); //check proof of work TIME_MEASURE_START(target_calculating_time); diff --git a/src/hardforks/hardforks.cpp b/src/hardforks/hardforks.cpp index bddf7bf2e..041e9dd41 100644 --- a/src/hardforks/hardforks.cpp +++ b/src/hardforks/hardforks.cpp @@ -43,6 +43,9 @@ const hardfork_t mainnet_hard_forks[] = { // 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 }, + + // version 5 starts from block 135500, which is on or around the 8th of January, 2025. Fork time finalised on 2025-01-07. No fork voting occurs for the v5 fork. + //{ 5, 135500, 0, 1736265945 }, }; 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); @@ -56,6 +59,12 @@ const hardfork_t testnet_hard_forks[] = { // version 3 starts from block 500 { 3, 500, 0, 1729518000 }, + + // version 4 starts from block 600 + { 4, 600, 0, 173626500 }, + + // version 5 starts from block 700 + { 5, 700, 0, 1736265945 }, }; 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); diff --git a/src/version.cpp.in b/src/version.cpp.in index 168c8a235..1f9073775 100644 --- a/src/version.cpp.in +++ b/src/version.cpp.in @@ -1,5 +1,5 @@ #define DEF_SALVIUM_VERSION_TAG "@VERSIONTAG@" -#define DEF_SALVIUM_VERSION "0.7.2" +#define DEF_SALVIUM_VERSION "0.8.0-rc1" #define DEF_MONERO_VERSION_TAG "release" #define DEF_MONERO_VERSION "0.18.3.3" #define DEF_MONERO_RELEASE_NAME "Zero" From b48c86afe088dae24b934b400d650f8c16994722 Mon Sep 17 00:00:00 2001 From: Some Random Crypto Guy Date: Tue, 7 Jan 2025 22:53:58 +0000 Subject: [PATCH 15/17] added user tx verification --- src/cryptonote_config.h | 2 +- src/cryptonote_core/blockchain.cpp | 10 +--------- src/cryptonote_core/cryptonote_tx_utils.cpp | 1 + src/cryptonote_core/tx_pool.cpp | 9 +++++++++ src/hardforks/hardforks.cpp | 2 +- 5 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h index d18fd54e6..c87cebec2 100644 --- a/src/cryptonote_config.h +++ b/src/cryptonote_config.h @@ -222,7 +222,7 @@ #define HF_VERSION_ENFORCE_FULL_PROOFS 4 -#define HF_VERSION_SHUTDOWN_USER_TXS 6 +#define HF_VERSION_SHUTDOWN_USER_TXS 5 #define HF_VERSION_REQUIRE_VIEW_TAGS 255 #define HF_VERSION_ENABLE_CONVERT 255 diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 964644d4e..ce5c0016c 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -1499,6 +1499,7 @@ bool Blockchain::validate_miner_transaction(const block& b, size_t cumulative_bl case HF_VERSION_ENABLE_N_OUTS: case HF_VERSION_FULL_PROOFS: case HF_VERSION_ENFORCE_FULL_PROOFS: + case HF_VERSION_SHUTDOWN_USER_TXS: 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; @@ -3656,15 +3657,6 @@ bool Blockchain::check_tx_type_and_version(const transaction& tx, tx_verificatio const uint8_t hf_version = m_hardfork->get_current_version(); - // Reject ALL TXs except miner + protocol for v5 - if (hf_version == HF_VERSION_SHUTDOWN_USER_TXS) { - if (tx.type != cryptonote::transaction_type::MINER && tx.type != cryptonote::transaction_type::PROTOCOL) { - MERROR_VER("User TXs are not permitted for v" + std::to_string(HF_VERSION_SHUTDOWN_USER_TXS)); - tvc.m_version_mismatch = true; - return false; - } - } - // Prior to v2, only allow TX v2 if (hf_version < HF_VERSION_ENABLE_N_OUTS) { diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp index 383dfd199..e9de4e231 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.cpp +++ b/src/cryptonote_core/cryptonote_tx_utils.cpp @@ -591,6 +591,7 @@ namespace cryptonote case HF_VERSION_ENABLE_N_OUTS: case HF_VERSION_FULL_PROOFS: case HF_VERSION_ENFORCE_FULL_PROOFS: + case HF_VERSION_SHUTDOWN_USER_TXS: // 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; diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index aaed85ad1..5f86824fb 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -167,6 +167,15 @@ namespace cryptonote return false; } + // Reject ALL TXs except miner + protocol for v5 + if (version == HF_VERSION_SHUTDOWN_USER_TXS) { + if (tx.type != cryptonote::transaction_type::MINER && tx.type != cryptonote::transaction_type::PROTOCOL) { + LOG_PRINT_L1("User TXs are not permitted for v" + std::to_string(HF_VERSION_SHUTDOWN_USER_TXS)); + tvc.m_verifivation_failed = true; + return false; + } + } + if(!check_inputs_types_supported(tx)) { tvc.m_verifivation_failed = true; diff --git a/src/hardforks/hardforks.cpp b/src/hardforks/hardforks.cpp index 041e9dd41..1f643e46a 100644 --- a/src/hardforks/hardforks.cpp +++ b/src/hardforks/hardforks.cpp @@ -61,7 +61,7 @@ const hardfork_t testnet_hard_forks[] = { { 3, 500, 0, 1729518000 }, // version 4 starts from block 600 - { 4, 600, 0, 173626500 }, + { 4, 600, 0, 1736265000 }, // version 5 starts from block 700 { 5, 700, 0, 1736265945 }, From 3b72dc05559c698a062872b8247e92154dbabc8f Mon Sep 17 00:00:00 2001 From: Some Random Crypto Guy Date: Tue, 7 Jan 2025 23:23:44 +0000 Subject: [PATCH 16/17] added code to skip user TXs in v5 when filling block template --- README.md | 2 +- src/cryptonote_core/tx_pool.cpp | 8 ++++++++ src/version.cpp.in | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 08ba31e05..7c702bbbe 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Salvium Zero v0.8.0-rc1 +# Salvium Zero v0.8.0-rc2 Copyright (c) 2023-2024, Salvium Portions Copyright (c) 2014-2023, The Monero Project diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index 5f86824fb..529fbdf5a 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -1662,6 +1662,14 @@ namespace cryptonote continue; } + // HERE BE DRAGONS!!! + // SRCG: skip all user TXs for HF 5 - when the node restarts, it'll discard them fully in `tx_memory_pool::validate()` + if (version == HF_VERSION_SHUTDOWN_USER_TXS) { + LOG_PRINT_L2(" User TXs forbidden by consensus for HF 5 - skipping"); + continue; + } + // LAND AHOY!!! + LOG_PRINT_L2("Considering " << sorted_it->second << ", weight " << meta.weight << ", current block weight " << total_weight << "/" << max_total_weight << ", current coinbase " << print_money(best_coinbase) << ", relay method " << (unsigned)meta.get_relay_method()); if (!meta.matches(relay_category::legacy) && !(m_mine_stem_txes && meta.get_relay_method() == relay_method::stem)) diff --git a/src/version.cpp.in b/src/version.cpp.in index 1f9073775..51b1399cc 100644 --- a/src/version.cpp.in +++ b/src/version.cpp.in @@ -1,5 +1,5 @@ #define DEF_SALVIUM_VERSION_TAG "@VERSIONTAG@" -#define DEF_SALVIUM_VERSION "0.8.0-rc1" +#define DEF_SALVIUM_VERSION "0.8.0-rc2" #define DEF_MONERO_VERSION_TAG "release" #define DEF_MONERO_VERSION "0.18.3.3" #define DEF_MONERO_RELEASE_NAME "Zero" From 3fc5ea35433973f218b82b1b0fb4bc93f4afc180 Mon Sep 17 00:00:00 2001 From: Some Random Crypto Guy Date: Wed, 8 Jan 2025 18:44:12 +0000 Subject: [PATCH 17/17] set fork height; updated fast-sync checkpoints --- README.md | 2 +- src/blocks/checkpoints.dat | Bin 14980 -> 16836 bytes src/hardforks/hardforks.cpp | 4 ++-- src/version.cpp.in | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 7c702bbbe..04cadfd9c 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Salvium Zero v0.8.0-rc2 +# Salvium Zero v0.8.0 Copyright (c) 2023-2024, Salvium Portions Copyright (c) 2014-2023, The Monero Project diff --git a/src/blocks/checkpoints.dat b/src/blocks/checkpoints.dat index 8ba5bc6e79341a097ef26b26e51badc223c35f8c..d48793c5ec67796f44bfc284094bfb5dd25e7c30 100644 GIT binary patch delta 1883 zcmV-h2c-Cfb;N@K0tW%H0)je!3iSzjO~S;I?G8~IGiZXtQSCT~)qvx8(^=_yl#Be> z2a*|oVK*O>t5YPpnkQJR_A!l)uYqL())98o?Qo z@7xvAEp+Tz%M(JE6Xhh}4T~cNAR>-|cb1}E< zBuy<(yhq(sC_rBMIuBlpRGMs`G*8#{vv`|{11%N5qOeJ{j-i2FoD(>`6loHYxG-?3 zxL*qOJd6F+kOTd%jyKC@{6{u0sKnl&p{@#cd1`cMrgDAqi?SMz3$>>x%*Ol7YP(JQ zTepavFwQA8J1MV}DeS9%o=bmJ-d?L<`*hloqX7n=E`6%EAl$Uz@i<>{fI))C5z?Ds z(?+U-T(xN(Tm1!~4RZjzXKRuGELt$j3ID^-EnoB?EoHs9A|uZ&2J536I)yb_ne0V( z3MCrVF+_0G7-k;mX5^a^<>oO^?wB>r>zuRT>*$(#uJ_$pGjLQkzONhRbgZMF`RgR=B+LN?@9m2@8e~$Pe zT1!g@8J-XR>JpcKm*g?l!Nk7}ItI_bKoT4s3ftN#$s`K&axK}pvM&6Mc?(F2ORekY z)pw<~{$_O&E$?mAPlcR+GV_Kdjh(b(_11#!eL_dV3|sgYuCJz@c~>!5B9RFy_aZPk zRFzA@gN&6&6@D)N>;q_}h_>Va#SiMbG&PG%zjZd!04r*LC>dJ&FJg_Iiy9NTE)Vfy|Z5-PZg0KnT!*Hv{~N7+AeAev79?kdNS@6wizPS7`eLm|?ZH{Z#qjn=}ac6SNp zUcLN`1&WQ!fUn}Xp$TraIR%s-f@Q3tZZ6X;n9=4X$ta*=uQCjJu+J#eix6iT+Ll$| z>i8+iXcF|9!=EDs(^n;C1?&O1GAv`U_SFTxp#l4Uayc7Hz^VJ~)2L5BIhCIYT*`^H`xy(K#44ZE>uJ$)#l7(<8|%KcB)Z99gg>ctQY> zK%h#u8S`e^z!?!9@`nGQ9$1yc@lam#PnH~rs0fvk8GyI9kO^5V0(x1#z$=?Co(G;p z0dlf`8|E9Q45asERqD$1E{clITV70o@RtmRAf6NI+&iyr=feyL?UFoUzW9Z!mU*P#RKfd#iDqo>t#bJ4 zfWhV$op$#xXIPhQ!%_s47>H)@{)aTSDW#i#*?t+8EoLZ>x#NdpY&h#cuzCu`lg5A-a5 z&Y(K1Qe=-s28^Lb!hGg01>(om?(zk-ljEkDJtsa3xQ`)*H>JhdhpLBX%04Q{5>y7K z71p#S44Skl<1f0BY;VWf6J*_01eLL4fc4^5yKUvTar=16Le7(#m9i&~PTrrSZOkm) zCft?;JCY(%n?nb!dn3t;wfI31Vc@}kHkPS?yWs^&1*eWm#NZtI?RRkeB}CVHTyhId zPlK7$9pJ?R8Fg84iIG#35_%rg1aOoBfVDxb!>2%ky*?n29 zAwNi~K`h{`c3E`Jj}@%qAc{HE-8S5-E^jzQT!zc2%$IJ-T_;~kncf98f0g!s&}ikQ zz<$LOwipnJC*$A_Ruyq^QZ}H6MT~aKtf`o6xXzCWsZD3xH>$ZE!5>eu8`R6cB|3(I z9=a>fh-v5vnZU(27HxTQ7;SrdbIVOU<|&bHZ=8d_Wixc&|k4~iRu_By(Wn$p^;F`TJDju_ymr znVmTB@fN;qUpWFF)QtX>PH=mv6CJL(*{EY5uZ@-KiKF?$Q0DT7rKC7ckgKLoCD$5I z0|GUQKdhgmxD*^b(yAX4{{cbDU0gRZHpq{tlpEwl_Ibcxj`V#7v&9r5>lbHCvK&*; V^Pr;fSSB9bpmj&az@c*Om+o#8t(^b> delta 12 TcmX@o%-B-O^on64Q