diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp index 32018c27c..22c9eb7e5 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.cpp +++ b/src/cryptonote_basic/cryptonote_format_utils.cpp @@ -1381,12 +1381,7 @@ namespace cryptonote for (const auto &o: tx.vout) { - if (hf_version >= HF_VERSION_ENFORCE_CARROT) - { - // from v10, require outputs be carrot outputs - CHECK_AND_ASSERT_MES(o.target.type() == typeid(txout_to_carrot_v1), false, "wrong variant type: " - << o.target.type().name() << ", expected txout_to_carrot_v1 in transaction id=" << get_transaction_hash(tx)); - } else if (hf_version >= HF_VERSION_CARROT) { + if (hf_version >= HF_VERSION_CARROT) { if (tx.type != cryptonote::transaction_type::PROTOCOL) { CHECK_AND_ASSERT_MES(o.target.type() == typeid(txout_to_carrot_v1), false, "wrong variant type: " << o.target.type().name() << ", expected txout_to_carrot_v1 in transaction id=" << get_transaction_hash(tx)); diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h index 9ba859ea2..74cfd456a 100644 --- a/src/cryptonote_config.h +++ b/src/cryptonote_config.h @@ -244,7 +244,6 @@ #define HF_VERSION_AUDIT2 8 #define HF_VERSION_AUDIT2_PAUSE 9 #define HF_VERSION_CARROT 10 -#define HF_VERSION_ENFORCE_CARROT 11 #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 f538e1abc..9cbd8eafa 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -1403,15 +1403,19 @@ bool Blockchain::prevalidate_protocol_transaction(const block& b, uint64_t heigh CHECK_AND_ASSERT_MES(b.protocol_tx.vin[0].type() == typeid(txin_gen), false, "coinbase protocol transaction in the block has the wrong type"); CHECK_AND_ASSERT_MES(b.protocol_tx.version > 1, false, "Invalid coinbase protocol transaction version"); - if (hf_version >= HF_VERSION_ENFORCE_CARROT) { - CHECK_AND_ASSERT_MES(b.protocol_tx.version == TRANSACTION_VERSION_CARROT, false, "protocol transaction has wrong version"); - CHECK_AND_ASSERT_MES(b.protocol_tx.type == cryptonote::transaction_type::PROTOCOL, false, "protocol transaction has wrong type"); - } else if (hf_version >= HF_VERSION_CARROT) { - CHECK_AND_ASSERT_MES(b.protocol_tx.version == 2 || b.protocol_tx.version == TRANSACTION_VERSION_CARROT, false, "protocol transaction has wrong version"); + // Work out what the HF version _was_ when the STAKE outputs were created + uint64_t stake_lock_period = get_config(m_nettype).STAKE_LOCK_PERIOD; + uint8_t hf_version_submitted = get_ideal_hard_fork_version(height - stake_lock_period - 1); + + if (hf_version >= HF_VERSION_CARROT) { + if (hf_version_submitted >= HF_VERSION_CARROT || b.protocol_tx.vout.size() == 0) { + CHECK_AND_ASSERT_MES(b.protocol_tx.version == TRANSACTION_VERSION_CARROT, false, "protocol transaction has wrong version"); + } else { + CHECK_AND_ASSERT_MES(b.protocol_tx.version == 2, false, "protocol transaction has wrong version"); + } CHECK_AND_ASSERT_MES(b.protocol_tx.type == cryptonote::transaction_type::PROTOCOL, false, "protocol transaction has wrong type"); } - // for v2 txes (ringct), we only accept empty rct signatures for protocol transactions, if (hf_version >= HF_VERSION_REJECT_SIGS_IN_COINBASE && b.protocol_tx.version >= 2) { @@ -1432,8 +1436,7 @@ bool Blockchain::prevalidate_protocol_transaction(const block& b, uint64_t heigh return false; } - CHECK_AND_ASSERT_MES(check_output_types(b.protocol_tx, hf_version), false, "protocol transaction has invalid output type(s) in block " << get_block_hash(b)); - + CHECK_AND_ASSERT_MES(check_output_types(b.protocol_tx, hf_version_submitted), false, "protocol transaction has invalid output type(s) in block " << get_block_hash(b)); return true; } //------------------------------------------------------------------ @@ -1520,7 +1523,6 @@ bool Blockchain::validate_miner_transaction(const block& b, size_t cumulative_bl case HF_VERSION_AUDIT2: case HF_VERSION_AUDIT2_PAUSE: case HF_VERSION_CARROT: - case HF_VERSION_ENFORCE_CARROT: 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; @@ -2092,6 +2094,7 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block, entry.P_change = audit_entry.first.P_change; entry.return_pubkey = audit_entry.first.return_pubkey; entry.origin_height = matured_audit_height; + entry.is_carrot = false; protocol_entries.push_back(entry); } } diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp index fdf1e37e2..7f821135e 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.cpp +++ b/src/cryptonote_core/cryptonote_tx_utils.cpp @@ -361,10 +361,13 @@ namespace cryptonote LOG_ERROR("Cannot mix Carrot and non-Carrot outputs in the same protocol transaction"); return false; } + if (carrot_found && hard_fork_version < HF_VERSION_CARROT) { + LOG_ERROR("Carrot outputs found in CryptoNote protocol transaction"); + return false; + } - if (carrot_found || hard_fork_version >= HF_VERSION_ENFORCE_CARROT) + if (carrot_found || (!noncarrot_found && hard_fork_version >= HF_VERSION_CARROT)) { - // Ensure the TX version is correct tx.version = TRANSACTION_VERSION_CARROT; try @@ -594,7 +597,6 @@ namespace cryptonote case HF_VERSION_AUDIT2: case HF_VERSION_AUDIT2_PAUSE: case HF_VERSION_CARROT: - case HF_VERSION_ENFORCE_CARROT: // 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/hardforks/hardforks.cpp b/src/hardforks/hardforks.cpp index 03359be0f..1abab57e6 100644 --- a/src/hardforks/hardforks.cpp +++ b/src/hardforks/hardforks.cpp @@ -92,9 +92,6 @@ const hardfork_t testnet_hard_forks[] = { // version 10 Carrot - including treasury mint - starts from block 1100 {10, 1100, 0, 1739780005 }, - - // version 11 Carrot and CryptoNote starts from block 1200 - {11, 1200, 0, 1756811153 }, }; 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/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 2676cc2d1..d5921e2da 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -8747,7 +8747,14 @@ bool simple_wallet::stake(const std::vector &args_) } std::vector local_args; - local_args.push_back(m_wallet->get_subaddress_as_str({m_current_subaddress_account,0})); + + carrot::AddressDeriveType derive_type; + if (m_wallet->use_fork_rules(HF_VERSION_CARROT, 0)) { + derive_type = carrot::AddressDeriveType::Carrot; + } else { + derive_type = carrot::AddressDeriveType::PreCarrot; + } + local_args.push_back(m_wallet->get_subaddress_as_str({{m_current_subaddress_account, 0}, derive_type, false})); local_args.insert(local_args.end(), args_.begin(), args_.end()); if (m_wallet->get_current_hard_fork() >= HF_VERSION_SALVIUM_ONE_PROOFS) { diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index ae098a76f..2ee540dc5 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -1590,9 +1590,10 @@ std::string wallet2::get_subaddress_as_str(const carrot::subaddress_index_extend // Build the cryptonote::account_public_address account_public_address addr{address.address_spend_pubkey, address.address_view_pubkey}; + addr.m_is_carrot = subaddr.derive_type == carrot::AddressDeriveType::Carrot; // change this code into base 58 - return cryptonote::get_account_address_as_str(m_nettype, address.is_subaddress, addr, subaddr.derive_type == carrot::AddressDeriveType::Carrot); + return cryptonote::get_account_address_as_str(m_nettype, address.is_subaddress, addr, addr.m_is_carrot); } //---------------------------------------------------------------------------------------------------- std::string wallet2::get_integrated_address_as_str(const crypto::hash8& payment_id) const @@ -10772,8 +10773,13 @@ std::vector wallet2::create_transactions_2(std::vector hwdev_lock (hwdev); hw::reset_mode rst(hwdev); - const bool do_carrot_tx_construction = use_fork_rules(HF_VERSION_CARROT); - if (do_carrot_tx_construction) + // Sanity check correct CN/Carrot address is being used + const uint8_t hf_version = get_current_hard_fork(); + for (const auto &entry: dsts) { + THROW_WALLET_EXCEPTION_IF(entry.addr.m_is_carrot && hf_version < HF_VERSION_CARROT, error::wallet_internal_error, "Carrot address supplied, but Carrot not yet active"); + THROW_WALLET_EXCEPTION_IF(!entry.addr.m_is_carrot && hf_version >= HF_VERSION_CARROT, error::wallet_internal_error, "CryptoNote address supplied, but Carrot is now active"); + } + if (hf_version >= HF_VERSION_CARROT) { const auto tx_proposals = tools::wallet::make_carrot_transaction_proposals_wallet2_transfer(*this, dsts, priority, extra, tx_type, subaddr_account, subaddr_indices, subtract_fee_from_outputs); std::vector ptx_vector;