From c820967cbaaa644347b940d1e40a3f579a55efbe Mon Sep 17 00:00:00 2001 From: Some Random Crypto Guy Date: Tue, 17 Mar 2026 13:34:27 +0000 Subject: [PATCH] fixed issues with ROLLUP circulating supply changes; fixed BURN SAL for HF11+; bumped RC version --- src/blockchain_db/lmdb/db_lmdb.cpp | 176 +++++++++++++++++--------- src/carrot_impl/tx_proposal_utils.cpp | 1 + src/cryptonote_core/blockchain.cpp | 25 ++-- src/simplewallet/simplewallet.cpp | 10 +- src/version.cpp.in | 2 +- src/wallet/wallet2.cpp | 2 +- 6 files changed, 143 insertions(+), 73 deletions(-) diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index 5f84ef2d4..d43342276 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -1501,38 +1501,55 @@ uint64_t BlockchainLMDB::add_transaction_data(const crypto::hash& blk_hash, cons tx.type == cryptonote::transaction_type::STAKE || tx.type == cryptonote::transaction_type::AUDIT || tx.type == cryptonote::transaction_type::TRANSFER || - tx.type == cryptonote::transaction_type::CREATE_TOKEN) + tx.type == cryptonote::transaction_type::CREATE_TOKEN || + tx.type == cryptonote::transaction_type::ROLLUP) { - // Get the current tally value for the source currency type - MDB_val_copy source_idx(cryptonote::asset_id_from_type(tx.source_asset_type)); - boost::multiprecision::int128_t source_tally = 0; - result = read_circulating_supply_data(m_cur_circ_supply_tally, source_idx, source_tally); - boost::multiprecision::int128_t final_source_tally = source_tally - tx.amount_burnt - tx.rct_signatures.txnFee; - if (result) - throw0(DB_ERROR(lmdb_error("Failed to get circulating supply tally when adding db transaction: ", result).c_str())); - // Sanity check - prevent underflow - if (source_tally < final_source_tally) - throw0(DB_ERROR("numeric underflow detected when processing C/B/S/A/T for db transaction")); - write_circulating_supply_data(m_cur_circ_supply_tally, source_idx, final_source_tally); - LOG_PRINT_L1("tx ID " << tx_id << "\n\tTally before burn = " << source_tally.str() << "\n\tTally after burn = " << final_source_tally.str()); + bool is_token = cryptonote::is_asset_type_token(tx.source_asset_type); + if (!is_token) { + // Get the current tally value for the source currency type + MDB_val_copy source_idx(cryptonote::asset_id_from_type(tx.source_asset_type)); + boost::multiprecision::int128_t source_tally = 0; + result = read_circulating_supply_data(m_cur_circ_supply_tally, source_idx, source_tally); + boost::multiprecision::int128_t final_source_tally = source_tally - tx.amount_burnt - tx.rct_signatures.txnFee; + if (tx.version >= TRANSACTION_VERSION_ENABLE_TOKENS) { + if (tx.source_asset_type != "SAL1") { + // this must be a SAL BURN TX, so fee is paid for by ROLLUP + final_source_tally = final_source_tally + tx.rct_signatures.txnFee; + } + } + if (result) + throw0(DB_ERROR(lmdb_error("Failed to get circulating supply tally when adding db transaction: ", result).c_str())); + // Sanity check - prevent underflow + if (source_tally < final_source_tally) + throw0(DB_ERROR("numeric underflow detected when processing C/B/S/A/T for db transaction")); + write_circulating_supply_data(m_cur_circ_supply_tally, source_idx, final_source_tally); + LOG_PRINT_L1("tx ID " << tx_id << "\n\tTally before burn = " << source_tally.str() << "\n\tTally after burn = " << final_source_tally.str()); - MDB_val_copy burn_idx(cryptonote::asset_id_from_type("BURN")); - boost::multiprecision::int128_t burn_tally = 0; - result = read_circulating_supply_data(m_cur_circ_supply_tally, burn_idx, burn_tally); - if (result && /*(m_height>0 ||*/ result != MDB_NOTFOUND/*)*/) - throw0(DB_ERROR(lmdb_error("Failed to get circulating supply tally when adding db transaction: ", result).c_str())); - boost::multiprecision::int128_t final_burn_tally = burn_tally + tx.amount_burnt + tx.rct_signatures.txnFee; - // Sanity check - prevent underflow - if (burn_tally > final_burn_tally) - throw0(DB_ERROR("burn overflow detected when adding tx for db transaction")); - write_circulating_supply_data(m_cur_circ_supply_tally, burn_idx, final_burn_tally); + MDB_val_copy burn_idx(cryptonote::asset_id_from_type("BURN")); + boost::multiprecision::int128_t burn_tally = 0; + result = read_circulating_supply_data(m_cur_circ_supply_tally, burn_idx, burn_tally); + if (result && /*(m_height>0 ||*/ result != MDB_NOTFOUND/*)*/) + throw0(DB_ERROR(lmdb_error("Failed to get circulating supply tally when adding db transaction: ", result).c_str())); + boost::multiprecision::int128_t final_burn_tally = burn_tally + tx.amount_burnt + tx.rct_signatures.txnFee; + if (tx.version >= TRANSACTION_VERSION_ENABLE_TOKENS) { + if (tx.source_asset_type != "SAL1") { + // this must be a SAL BURN TX, so fee is paid for by ROLLUP + final_burn_tally = final_burn_tally - tx.rct_signatures.txnFee; + } + } + // Sanity check - prevent underflow + if (burn_tally > final_burn_tally) + throw0(DB_ERROR("burn overflow detected when adding tx for db transaction")); + write_circulating_supply_data(m_cur_circ_supply_tally, burn_idx, final_burn_tally); + } } if (tx.type == cryptonote::transaction_type::PROTOCOL) { // Iterate over all of the outputs for a PROTOCOL_TX since they're all MINTED std::map minted_amounts; + std::map burned_amounts; for (const auto& out: tx.vout) { // Fetch the amount and output_asset_type for this output @@ -1541,6 +1558,11 @@ uint64_t BlockchainLMDB::add_transaction_data(const crypto::hash& blk_hash, cons if (!ok) throw0(DB_ERROR("failed to get output asset type (needed to update the circulating supply data for the PROTOCOL_TX)")); minted_amounts[cryptonote::asset_id_from_type(asset_type)] += out.amount; + + if (asset_type == "SAL" || asset_type == "SAL1") { + uint32_t burned_asset_id = cryptonote::asset_id_from_type("BURN"); + burned_amounts[burned_asset_id] += out.amount; + } } // Now update the overall tally entries @@ -1567,23 +1589,23 @@ uint64_t BlockchainLMDB::add_transaction_data(const crypto::hash& blk_hash, cons write_circulating_supply_data(m_cur_circ_supply_tally, source_idx, final_source_tally); // Log can be changed - not burning here LOG_PRINT_L1("tx ID " << tx_id << "\n\tAsset Type = " << cryptonote::asset_type_from_id(asset.first) << "\n\tTally before burn =" << source_tally.str() << "\n\tTally after burn =" << final_source_tally.str()); - - MDB_val_copy burn_idx(cryptonote::asset_id_from_type("BURN")); + } + + // Update burned asset tallies (subtract what was burned, BUT NOT for tokens which are being created!) + // HERE BE DRAGONS!!! + // SRCG: there should only ever be one entry in this vector!!! + for (const auto& asset: burned_amounts) { + MDB_val_copy burn_idx(asset.first); boost::multiprecision::int128_t burn_tally = 0; result = read_circulating_supply_data(m_cur_circ_supply_tally, burn_idx, burn_tally); if (result && result != MDB_NOTFOUND) throw0(DB_ERROR(lmdb_error("Failed to get circulating supply tally when adding db transaction: ", result).c_str())); - uint64_t burn_amount = 0; - if (asset.first == 0x53414C00 || asset.first == 0x53414C31 || asset.first == 0x4255524E) { //BURN SAL and SAL1 // check - burn_amount = asset.second; - } else { - burn_amount = asset.second / 200; - } - if (burn_tally < burn_amount) + if (burn_tally < asset.second) throw0(DB_ERROR("add_transaction_data() - burn underflow")); - boost::multiprecision::int128_t final_burn_tally = burn_tally - burn_amount; + boost::multiprecision::int128_t final_burn_tally = burn_tally - asset.second; write_circulating_supply_data(m_cur_circ_supply_tally, burn_idx, final_burn_tally); } + // LAND AHOY!!! } // Is there a rollup_tx to add? @@ -1898,37 +1920,60 @@ void BlockchainLMDB::remove_transaction_data(const crypto::hash& tx_hash, const write_circulating_supply_data(m_cur_circ_supply_tally, burn_idx, final_burn_tally); } - if (tx.type == cryptonote::transaction_type::BURN || tx.type == cryptonote::transaction_type::CONVERT || tx.type == cryptonote::transaction_type::STAKE || tx.type == cryptonote::transaction_type::AUDIT || tx.type == cryptonote::transaction_type::TRANSFER) { + if (tx.type == cryptonote::transaction_type::BURN || + tx.type == cryptonote::transaction_type::CONVERT || + tx.type == cryptonote::transaction_type::STAKE || + tx.type == cryptonote::transaction_type::AUDIT || + tx.type == cryptonote::transaction_type::TRANSFER || + tx.type == cryptonote::transaction_type::CREATE_TOKEN || + tx.type == cryptonote::transaction_type::ROLLUP) + { - // Get the current tally value for the source currency type - MDB_val_copy source_idx(cryptonote::asset_id_from_type(tx.source_asset_type)); - boost::multiprecision::int128_t source_tally = 0; - result = read_circulating_supply_data(m_cur_circ_supply_tally, source_idx, source_tally); - boost::multiprecision::int128_t final_source_tally = source_tally + tx.amount_burnt + tx.rct_signatures.txnFee; - if (result) - throw0(DB_ERROR(lmdb_error("Failed to get circulating supply tally when removing db transaction: ", result).c_str())); - // Sanity check - prevent overflow - if (source_tally > final_source_tally) - throw0(DB_ERROR("numeric overflow detected when processing C/B/S/A/T for db transaction")); - write_circulating_supply_data(m_cur_circ_supply_tally, source_idx, final_source_tally); - LOG_PRINT_L1("tx ID " << tip->data.tx_id << "\n\tTally before remint =" << source_tally.str() << "\n\tTally after remint =" << final_source_tally.str()); - - MDB_val_copy burn_idx(cryptonote::asset_id_from_type("BURN")); - boost::multiprecision::int128_t burn_tally = 0; - result = read_circulating_supply_data(m_cur_circ_supply_tally, burn_idx, burn_tally); - if (result && /*(m_height>0 ||*/ result != MDB_NOTFOUND/*)*/) - throw0(DB_ERROR(lmdb_error("Failed to get circulating supply tally when adding db transaction: ", result).c_str())); - boost::multiprecision::int128_t final_burn_tally = burn_tally - tx.amount_burnt - tx.rct_signatures.txnFee; - // Sanity check - prevent underflow - if (burn_tally < (tx.amount_burnt + tx.rct_signatures.txnFee)) - throw0(DB_ERROR("burn underflow detected when removing tx for db transaction")); - write_circulating_supply_data(m_cur_circ_supply_tally, burn_idx, final_burn_tally); - } + bool is_token = cryptonote::is_asset_type_token(tx.source_asset_type); + if (!is_token) { + // Get the current tally value for the source currency type + MDB_val_copy source_idx(cryptonote::asset_id_from_type(tx.source_asset_type)); + boost::multiprecision::int128_t source_tally = 0; + result = read_circulating_supply_data(m_cur_circ_supply_tally, source_idx, source_tally); + boost::multiprecision::int128_t final_source_tally = source_tally + tx.amount_burnt + tx.rct_signatures.txnFee; + if (tx.version >= TRANSACTION_VERSION_ENABLE_TOKENS) { + if (tx.source_asset_type != "SAL1") { + // this must be a SAL BURN TX, so fee is paid for by ROLLUP + final_source_tally = final_source_tally - tx.rct_signatures.txnFee; + } + } + if (result) + throw0(DB_ERROR(lmdb_error("Failed to get circulating supply tally when removing db transaction: ", result).c_str())); + // Sanity check - prevent overflow + if (source_tally > final_source_tally) + throw0(DB_ERROR("numeric overflow detected when processing C/B/S/A/T for db transaction")); + write_circulating_supply_data(m_cur_circ_supply_tally, source_idx, final_source_tally); + LOG_PRINT_L1("tx ID " << tip->data.tx_id << "\n\tTally before remint =" << source_tally.str() << "\n\tTally after remint =" << final_source_tally.str()); + MDB_val_copy burn_idx(cryptonote::asset_id_from_type("BURN")); + boost::multiprecision::int128_t burn_tally = 0; + result = read_circulating_supply_data(m_cur_circ_supply_tally, burn_idx, burn_tally); + if (result && /*(m_height>0 ||*/ result != MDB_NOTFOUND/*)*/) + throw0(DB_ERROR(lmdb_error("Failed to get circulating supply tally when adding db transaction: ", result).c_str())); + boost::multiprecision::int128_t final_burn_tally = burn_tally - tx.amount_burnt - tx.rct_signatures.txnFee; + if (tx.version >= TRANSACTION_VERSION_ENABLE_TOKENS) { + if (tx.source_asset_type != "SAL1") { + // this must be a SAL BURN TX, so fee is paid for by ROLLUP + final_burn_tally = final_burn_tally + tx.rct_signatures.txnFee; + } + } + // Sanity check - prevent underflow + if (burn_tally < (tx.amount_burnt + tx.rct_signatures.txnFee)) + throw0(DB_ERROR("burn underflow detected when removing tx for db transaction")); + write_circulating_supply_data(m_cur_circ_supply_tally, burn_idx, final_burn_tally); + } + } + if (tx.type == cryptonote::transaction_type::PROTOCOL) { // Iterate over all of the outputs for a PROTOCOL_TX since they're all MINTED std::map minted_amounts; + std::map burned_amounts; for (const auto& out: tx.vout) { // Fetch the amount and output_asset_type for this output @@ -1937,6 +1982,11 @@ void BlockchainLMDB::remove_transaction_data(const crypto::hash& tx_hash, const if (!ok) throw0(DB_ERROR("failed to get output asset type (needed to update the circulating supply data for the PROTOCOL_TX)")); minted_amounts[cryptonote::asset_id_from_type(asset_type)] += out.amount; + + if (asset_type == "SAL" || asset_type == "SAL1") { + uint32_t burned_asset_id = cryptonote::asset_id_from_type("BURN"); + burned_amounts[burned_asset_id] += out.amount; + } } // Now update the overall tally entries @@ -1955,8 +2005,13 @@ void BlockchainLMDB::remove_transaction_data(const crypto::hash& tx_hash, const boost::multiprecision::int128_t final_source_tally = source_tally - asset.second; write_circulating_supply_data(m_cur_circ_supply_tally, source_idx, final_source_tally); LOG_PRINT_L1("tx ID " << tip->data.tx_id << "\n\tAsset Type = " << cryptonote::asset_type_from_id(asset.first) << "\n\tTally before undoing mint =" << source_tally.str() << "\n\tTally after undoing mint =" << final_source_tally.str()); - - MDB_val_copy burn_idx(cryptonote::asset_id_from_type("BURN")); + } + + // Update burned asset tallies (add what was burned, BUT NOT for tokens which were being created!) + // HERE BE DRAGONS!!! + // SRCG: there should only ever be one entry in this vector!!! + for (const auto& asset: burned_amounts) { + MDB_val_copy burn_idx(asset.first); boost::multiprecision::int128_t burn_tally = 0; result = read_circulating_supply_data(m_cur_circ_supply_tally, burn_idx, burn_tally); if (result) @@ -1966,6 +2021,7 @@ void BlockchainLMDB::remove_transaction_data(const crypto::hash& tx_hash, const boost::multiprecision::int128_t final_burn_tally = burn_tally + asset.second; write_circulating_supply_data(m_cur_circ_supply_tally, burn_idx, final_burn_tally); } + // LAND AHOY!!! } remove_tx_outputs(tip->data.tx_id, tx); diff --git a/src/carrot_impl/tx_proposal_utils.cpp b/src/carrot_impl/tx_proposal_utils.cpp index 98f778145..8c21aeb33 100644 --- a/src/carrot_impl/tx_proposal_utils.cpp +++ b/src/carrot_impl/tx_proposal_utils.cpp @@ -217,6 +217,7 @@ void make_carrot_transaction_proposal_v1(const std::vector= HF_VERSION_CARROT) { - if (tx.source_asset_type != "SAL1" || tx.destination_asset_type != "SAL1") { - MERROR_VER("Invalid destination/source asset type - provided destination asset: " << tx.destination_asset_type << ", expected SAL1" << ", provided source asset: " << tx.source_asset_type << ", expected SAL1"); - tvc.m_verifivation_failed = true; - return false; + if (tx.type == cryptonote::transaction_type::BURN) { + if (tx.source_asset_type != "SAL1" || tx.destination_asset_type != "BURN") { + MERROR_VER("Invalid source/dest asset type for BURN - provided destination asset: " << tx.destination_asset_type << ", expected BURN" << ", provided source asset: " << tx.source_asset_type << ", expected SAL1"); + tvc.m_verifivation_failed = true; + return false; + } + } else { + if (tx.source_asset_type != "SAL1" || tx.destination_asset_type != "SAL1") { + MERROR_VER("Invalid destination/source asset type - provided destination asset: " << tx.destination_asset_type << ", expected SAL1" << ", provided source asset: " << tx.source_asset_type << ", expected SAL1"); + tvc.m_verifivation_failed = true; + return false; + } } - // } } else if (hf_version >= HF_VERSION_SALVIUM_ONE_PROOFS) { // protocol and miner txs don't have source and destination asset types if (tx.type == cryptonote::transaction_type::PROTOCOL || tx.type == cryptonote::transaction_type::MINER) { @@ -3960,8 +3967,8 @@ bool Blockchain::check_tx_asset_types(const transaction& tx, tx_verification_con } else if (tx.type == cryptonote::transaction_type::AUDIT) { CHECK_AND_ASSERT_MES(tx.source_asset_type == "SAL" && tx.destination_asset_type == "SAL", false, "wrong source/destination asset type: provided source asset " << tx.source_asset_type << " expected SAL and provided destination asset " << tx.destination_asset_type << " expected SAL"); } else if (tx.type == cryptonote::transaction_type::BURN) { - if (tx.source_asset_type != "SAL1" || tx.destination_asset_type != "BURN") { - MERROR_VER("Invalid source/dest asset type for BURN - provided source asset: " << tx.source_asset_type << ", and destination asset: " << tx.destination_asset_type << ", expected SAL1 and BURN respectively"); + if ((tx.source_asset_type != "SAL" && tx.source_asset_type != "SAL1") || tx.destination_asset_type != "BURN") { + MERROR_VER("Invalid source/dest asset type for BURN - provided source asset: " << tx.source_asset_type << ", and destination asset: " << tx.destination_asset_type << ", expected SAL/SAL1 and BURN respectively"); tvc.m_verifivation_failed = true; return false; } diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index c042f3bb9..28fa69def 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -8755,9 +8755,15 @@ bool simple_wallet::burn(const std::vector &args_) return true; } + uint8_t hf_version = m_wallet->get_current_hard_fork(); + if (hf_version >= HF_VERSION_CARROT && hf_version < HF_VERSION_ENABLE_TOKENS) { + fail_msg_writer() << tr("BURN command is disabled until hard fork ") << HF_VERSION_ENABLE_TOKENS; + return true; + } + std::vector local_args; carrot::AddressDeriveType derive_type; - if (m_wallet->use_fork_rules(HF_VERSION_CARROT, 0)) { + if (hf_version >= HF_VERSION_CARROT) { derive_type = carrot::AddressDeriveType::Carrot; } else { derive_type = carrot::AddressDeriveType::PreCarrot; @@ -8776,7 +8782,7 @@ bool simple_wallet::burn(const std::vector &args_) asset_type = strLastArg; local_args.pop_back(); - if (m_wallet->get_current_hard_fork() >= HF_VERSION_ENABLE_TOKENS) { + if (hf_version >= HF_VERSION_ENABLE_TOKENS) { transfer_main(Burn, asset_type, asset_type, local_args, false); } else { transfer_main(Burn, asset_type, "BURN", local_args, false); diff --git a/src/version.cpp.in b/src/version.cpp.in index c9a9bac51..36245dc56 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 "1.1.0-rc4" +#define DEF_SALVIUM_VERSION "1.1.0-rc5" #define DEF_MONERO_VERSION_TAG "release" #define DEF_MONERO_VERSION "0.18.4.0" #define DEF_MONERO_RELEASE_NAME "One" diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 17f55be48..ad846f13b 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -11089,7 +11089,7 @@ std::vector wallet2::create_transactions_2(std::vector= HF_VERSION_ENABLE_TOKENS && tx_type == cryptonote::transaction_type::BURN) { - THROW_WALLET_EXCEPTION_IF(source_asset != "SAL" && source_asset != "SAL1", error::wallet_internal_error, "Only SAL and SAL1 may be burnt"); + THROW_WALLET_EXCEPTION_IF(source_asset != "SAL" && source_asset != "SAL1", error::wallet_internal_error, "Only SAL/SAL1 may be burnt"); THROW_WALLET_EXCEPTION_IF(dsts.size() != 1, error::wallet_internal_error, "Only 1 destination permitted for BURN"); dsts[0].asset_type = source_asset; }