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: | diff --git a/README.md b/README.md index 226ea453a..04cadfd9c 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Salvium Zero v0.7.0-rc3 +# Salvium Zero v0.8.0 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 b9b838eda..c87cebec2 100644 --- a/src/cryptonote_config.h +++ b/src/cryptonote_config.h @@ -220,6 +220,10 @@ #define HF_VERSION_FULL_PROOFS 3 +#define HF_VERSION_ENFORCE_FULL_PROOFS 4 + +#define HF_VERSION_SHUTDOWN_USER_TXS 5 + #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 4fe7d91df..ce5c0016c 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -1498,6 +1498,8 @@ 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: + 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; @@ -3492,9 +3494,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 +3509,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 +3608,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 +3621,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 +4052,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 +4153,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; } @@ -4771,6 +4775,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/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/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp index a13d4d0a5..e9de4e231 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.cpp +++ b/src/cryptonote_core/cryptonote_tx_utils.cpp @@ -590,6 +590,8 @@ namespace cryptonote case HF_VERSION_BULLETPROOF_PLUS: 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..529fbdf5a 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; @@ -1653,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/hardforks/hardforks.cpp b/src/hardforks/hardforks.cpp index 6ef62e4d7..e17c01eec 100644 --- a/src/hardforks/hardforks.cpp +++ b/src/hardforks/hardforks.cpp @@ -36,7 +36,16 @@ const hardfork_t mainnet_hard_forks[] = { { 1, 1, 0, 1341378000 }, // version 2 starts from block 89800, which is on or around the 4th of November, 2024. Fork time finalised on 2024-10-21. No fork voting occurs for the v2 fork. - { 2, 89800, 0, 1729518000 }, + { 2, 89800, 0, 1729518000 }, + + // version 3 starts from block 121100, which is on or around the 19th of December, 2024. Fork time finalised on 2024-12-18. No fork voting occurs for the v3 fork. + { 3, 121100, 0, 1734516900 }, + + // version 4 starts from block 121100, which is on or around the 20th of December, 2024. Fork time finalised on 2024-12-19. No fork voting occurs for the v4 fork. + { 4, 121800, 0, 1734607000 }, + + // version 5 starts from block 136100, which is on or around the 9th of January, 2025. Fork time finalised on 2025-01-08. No fork voting occurs for the v5 fork. + { 5, 136100, 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); @@ -50,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, 1736265000 }, + + // 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 d56fb6644..a5dd9d5ad 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.8.0" #define DEF_MONERO_VERSION_TAG "release" #define DEF_MONERO_VERSION "0.18.3.3" #define DEF_MONERO_RELEASE_NAME "Zero"