Skip to content

Commit 5279ff9

Browse files
committed
cryptonote_core: ban large miner tx extras after v17 and simplify output order checking
1 parent a5ed445 commit 5279ff9

File tree

3 files changed

+36
-18
lines changed

3 files changed

+36
-18
lines changed

src/cryptonote_core/blockchain.cpp

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1333,11 +1333,12 @@ bool Blockchain::prevalidate_miner_transaction(const block& b, uint64_t height,
13331333

13341334
CHECK_AND_ASSERT_MES(check_output_types(b.miner_tx, hf_version), false, "miner transaction has invalid output type(s) in block " << get_block_hash(b));
13351335

1336-
// from carrot or v18, require output pubkeys be sorted in strictly increasing lexicographical order
1337-
const bool tx_is_carrot = !b.miner_tx.vout.empty() && b.miner_tx.vout.at(0).target.type() == typeid(txout_to_carrot_v1);
1338-
const bool should_enforce_sorted_outputs = hf_version > HF_VERSION_FCMP_PLUS_PLUS || tx_is_carrot;
1339-
if (should_enforce_sorted_outputs) {
1340-
CHECK_AND_ASSERT_MES(are_transaction_output_pubkeys_sorted(b.miner_tx), false, "miner transaction outputs are not sorted in block " << get_block_hash(b));
1336+
CHECK_AND_ASSERT_MES(check_transaction_output_pubkeys_order(b.miner_tx, hf_version),
1337+
false, "FCMP++ miner transaction has unsorted outputs in block " << get_block_hash(b));
1338+
1339+
// from v17, require tx.extra size be within limit
1340+
if (hf_version >= HF_VERSION_REJECT_LARGE_EXTRA) {
1341+
CHECK_AND_ASSERT_MES(b.miner_tx.extra.size() <= MAX_TX_EXTRA_SIZE, "false", "miner transaction extra too big");
13411342
}
13421343

13431344
return true;
@@ -3414,16 +3415,6 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context
34143415
return false;
34153416
}
34163417

3417-
// from carrot or v18, require output pubkeys be sorted in strictly increasing lexicographical order
3418-
const bool tx_is_carrot = !tx.vout.empty() && tx.vout.at(0).target.type() == typeid(txout_to_carrot_v1);
3419-
const bool should_enforce_sorted_outputs = hf_version > HF_VERSION_FCMP_PLUS_PLUS || tx_is_carrot;
3420-
if (should_enforce_sorted_outputs) {
3421-
if (!are_transaction_output_pubkeys_sorted(tx)) {
3422-
tvc.m_invalid_output = true;
3423-
return false;
3424-
}
3425-
}
3426-
34273418
return true;
34283419
}
34293420
//------------------------------------------------------------------

src/cryptonote_core/tx_verification_utils.cpp

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
#include <boost/iterator/transform_iterator.hpp>
3030

31+
#include "carrot_impl/format_utils.h"
3132
#include "cryptonote_basic/cryptonote_format_utils.h"
3233
#include "cryptonote_core/blockchain.h"
3334
#include "cryptonote_core/cryptonote_core.h"
@@ -284,6 +285,14 @@ static bool ver_non_input_consensus_templated(TxForwardIt tx_begin,
284285
return false;
285286
}
286287

288+
// Rule 10
289+
if (!check_transaction_output_pubkeys_order(tx, hf_version))
290+
{
291+
tvc.m_verifivation_failed = true;
292+
tvc.m_invalid_output = true;
293+
return false;
294+
}
295+
287296
// Rule 5
288297
if (!core::check_tx_semantic(tx, tvc, hf_version))
289298
return false;
@@ -564,10 +573,10 @@ uint64_t get_transaction_weight_limit(const uint8_t hf_version)
564573
return get_min_block_weight(hf_version) - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE;
565574
}
566575

567-
bool are_transaction_output_pubkeys_sorted(const transaction_prefix &tx_prefix)
576+
bool are_transaction_output_pubkeys_sorted(const std::vector<tx_out> &vout)
568577
{
569578
crypto::public_key last_output_pubkey = crypto::null_pkey;
570-
for (const tx_out &o : tx_prefix.vout) {
579+
for (const tx_out &o : vout) {
571580
crypto::public_key output_pubkey;
572581
if (!get_output_public_key(o, output_pubkey)) {
573582
return false;
@@ -581,6 +590,13 @@ bool are_transaction_output_pubkeys_sorted(const transaction_prefix &tx_prefix)
581590
return true;
582591
}
583592

593+
bool check_transaction_output_pubkeys_order(const transaction_prefix &tx_prefix, const std::uint8_t hf_version)
594+
{
595+
if (hf_version > HF_VERSION_FCMP_PLUS_PLUS || carrot::is_carrot_transaction_v1(tx_prefix))
596+
return are_transaction_output_pubkeys_sorted(tx_prefix.vout);
597+
return true;
598+
}
599+
584600
size_t get_minimum_transaction_version(uint8_t hf_version, bool has_unmixable_ring)
585601
{
586602
if (hf_version >= HF_VERSION_REJECT_UNMIXABLE_V1)

src/cryptonote_core/tx_verification_utils.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,17 @@ uint64_t get_transaction_weight_limit(uint8_t hf_version);
7878
/**
7979
* @brief Check whether transaction's output pubkeys are sorted in strictly increasing lexicographical order
8080
*/
81-
bool are_transaction_output_pubkeys_sorted(const transaction_prefix &tx_prefix);
81+
bool are_transaction_output_pubkeys_sorted(const std::vector<tx_out> &vout);
82+
83+
/**
84+
* @brief Check whether transaction's output pubkeys are sorted, iff required by fork rule
85+
* @param tx_prefix
86+
* @param hf_version hard fork version
87+
* @see are_transaction_output_pubkeys_sorted()
88+
*
89+
* Output pubkeys must be sorted after FCMP++ grace period or if a Carrot tx during FCMP++ grace period.
90+
*/
91+
bool check_transaction_output_pubkeys_order(const transaction_prefix &tx_prefix, std::uint8_t hf_version);
8292

8393
/**
8494
* @brief Get the minimum allowed transaction version
@@ -189,6 +199,7 @@ bool batch_ver_fcmp_pp_consensus
189199
* 7. Passes ver_mixed_rct_semantics() [Uses batch RingCT verification when applicable]
190200
* 8. Check unlock time is 0 from hardfork v17
191201
* 9. Check extra size <= MAX_TX_EXTRA_SIZE from hardfork v17
202+
* 10. Passes check_transaction_output_pubkeys_order()
192203
*
193204
* For pool_supplement input:
194205
* We assume the structure of the pool supplement is already correct: for each value entry, the

0 commit comments

Comments
 (0)