Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Factor block.check "bypass" into block.identify overrides. #1487

Merged
merged 4 commits into from
Jul 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions include/bitcoin/system/chain/block.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,18 @@ class BC_API block
bool is_malleable64() const NOEXCEPT;
bool is_malleated64() const NOEXCEPT;

/// Identity.
/// -----------------------------------------------------------------------

code identify() const NOEXCEPT;
code identify(const context& ctx) const NOEXCEPT;

/// Validation.
/// -----------------------------------------------------------------------

/// Consensus checks (no DoS guards for block sync without headers first).
code check(bool bypass=false) const NOEXCEPT;
code check(const context& ctx, bool bypass=false) const NOEXCEPT;
code check() const NOEXCEPT;
code check(const context& ctx) const NOEXCEPT;
code accept(const context& ctx, size_t subsidy_interval,
uint64_t initial_subsidy) const NOEXCEPT;
code connect(const context& ctx) const NOEXCEPT;
Expand Down
13 changes: 8 additions & 5 deletions include/bitcoin/system/chain/prevout.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,26 +33,29 @@ class BC_API prevout final
/// A height of zero is immature (unspendable) despite unspent state.
///************************************************************************
/// The confirmed chain height of the prevout (zero if not found).
/// Unused if the input owning this prevout is null (coinbase).
size_t height{ zero };

///************************************************************************
/// CONSENSUS:
/// A mtp of max_uint32 fails locktime maturity (until time overflow).
///************************************************************************
/// The median time past at height (max_uint32 if not found/confirmed).
/// Unused if the input owning this prevout is null (coinbase).
uint32_t median_time_past{ max_uint32 };

///************************************************************************
/// CONSENSUS:
/// An unspent coinbase collision is immature (unspendable) and spent
/// collision is mature (bip30). Coinbase collision precluded by bip34.
/// collision is mature (bip30). CB collision presumed precluded by bip34.
///************************************************************************
/// For coinbase tx, implies fully spent at height or not found.
/// Coinbase value stored in first input of coinbase transaction.
/// For a non-coinbase input this indicates spent at height.
/// If the input owning this prevout is null (coinbase), this implies that
/// all outputs of any duplicate txs are fully spent at height.
/// If the input owning this prevout is not null (not coinbase), this
/// indicates whether the prevout is spent at height (double spend).
bool spent{ true };

/// The output is of a coinbase transaction.
/// The previous output is of a coinbase transaction.
bool coinbase{ false };
};

Expand Down
2 changes: 1 addition & 1 deletion include/bitcoin/system/chain/witness.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ class BC_API witness
/// The (only) coinbase witness must be (arbitrary) 32-byte value (bip141).
static VCONSTEXPR bool is_reserved_pattern(const chunk_cptrs& stack) NOEXCEPT
{
return stack.size() == one && stack.front()->size() == hash_size;
return is_one(stack.size()) && stack.front()->size() == hash_size;
}

bool extract_sigop_script(script& out_script,
Expand Down
6 changes: 3 additions & 3 deletions include/bitcoin/system/funclets.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ constexpr Type to_bits(Type bytes) noexcept

constexpr uint8_t to_byte(char value) noexcept
{
static_assert(sizeof(char) == 1u);
static_assert(is_one(sizeof(char)));
return static_cast<uint8_t>(value);
}

Expand All @@ -147,8 +147,8 @@ constexpr Type to_int(bool value) noexcept
template <typename Type>
constexpr bool to_bool(Type value) noexcept
{
static_assert(static_cast<Type>(true) == 1);
static_assert(static_cast<Type>(false) == 0);
static_assert(is_one(static_cast<Type>(true)));
static_assert(is_zero(static_cast<Type>(false)));
return is_nonzero(value);
}

Expand Down
2 changes: 1 addition & 1 deletion include/bitcoin/system/impl/chain/operation.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ VCONSTEXPR opcode operation::minimal_opcode_from_data(
{
const auto size = data.size();

if (size == one)
if (is_one(size))
{
const auto value = data.front();

Expand Down
2 changes: 1 addition & 1 deletion include/bitcoin/system/impl/machine/interpreter.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ op_dup2() NOEXCEPT
if (state::stack_size() < 2)
return error::op_dup2;

// [0,1,2,3] => 1, [0,1,2,3] => 0,1,[0,1,2,3]
// [0,1,2,3] => 1,[0,1,2,3] => 0,1,[0,1,2,3]
state::push_variant(state::peek_(1));
state::push_variant(state::peek_(1));
return error::op_success;
Expand Down
2 changes: 1 addition & 1 deletion include/bitcoin/system/impl/machine/program.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,7 @@ template <typename Stack>
INLINE bool program<Stack>::
is_stack_clean() const NOEXCEPT
{
return stack_size() == one;
return is_one(stack_size());
}

// Alternate stack.
Expand Down
4 changes: 2 additions & 2 deletions include/bitcoin/system/impl/math/bytes.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ template <typename Integer, if_integer<Integer>>
constexpr bool is_negated(Integer value) NOEXCEPT
{
// Guard precludes zero appearing negated: ((0 % 8) + 1) == 1.
return is_nonzero(value) && add1(bit_width(value) % byte_bits) == one;
};
return is_nonzero(value) && is_one(add1(bit_width(value) % byte_bits));
}

template <typename Integer, if_integer<Integer>>
constexpr Integer to_negated(Integer value) NOEXCEPT
Expand Down
12 changes: 6 additions & 6 deletions include/bitcoin/system/intrinsics/haves.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,12 +174,12 @@ template <typename Integral, size_t Lanes,
if_not_greater<safe_multiply(sizeof(Integral), Lanes),
sizeof(xint512_t)> = true>
using to_extended =
iif<capacity<uint8_t, Integral, Lanes> == one, uint8_t,
iif<capacity<uint16_t, Integral, Lanes> == one, uint16_t,
iif<capacity<uint32_t, Integral, Lanes> == one, uint32_t,
iif<capacity<uint64_t, Integral, Lanes> == one, uint64_t,
iif<capacity<xint128_t, Integral, Lanes> == one, xint128_t,
iif<capacity<xint256_t, Integral, Lanes> == one, xint256_t,
iif<is_one(capacity<uint8_t, Integral, Lanes>), uint8_t,
iif<is_one(capacity<uint16_t, Integral, Lanes>), uint16_t,
iif<is_one(capacity<uint32_t, Integral, Lanes>), uint32_t,
iif<is_one(capacity<uint64_t, Integral, Lanes>), uint64_t,
iif<is_one(capacity<xint128_t, Integral, Lanes>), xint128_t,
iif<is_one(capacity<xint256_t, Integral, Lanes>), xint256_t,
xint512_t>>>>>>;

/// Runtime time availability of extended integer intrinsics, as a template
Expand Down
2 changes: 1 addition & 1 deletion include/bitcoin/system/stream/streams.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ namespace stream
using copy = make_stream<copy_sink<data_slab>>;

/// A fast output stream that copies data to a data_slab.
using fast = system:: ostream<>;
using fast = system::ostream<>;

/// A std::output stream that inserts data to a container.
template <typename Container>
Expand Down
72 changes: 37 additions & 35 deletions src/chain/block.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -682,10 +682,8 @@ void block::populate() const NOEXCEPT
// DO invoke on coinbase.
code block::check_transactions() const NOEXCEPT
{
code ec;

for (const auto& tx: *txs_)
if ((ec = tx->check()))
if (const auto ec = tx->check())
return ec;

return error::block_success;
Expand All @@ -694,10 +692,8 @@ code block::check_transactions() const NOEXCEPT
// DO invoke on coinbase.
code block::check_transactions(const context& ctx) const NOEXCEPT
{
code ec;

for (const auto& tx: *txs_)
if ((ec = tx->check(ctx)))
if (const auto ec = tx->check(ctx))
return ec;

return error::block_success;
Expand All @@ -706,11 +702,9 @@ code block::check_transactions(const context& ctx) const NOEXCEPT
// Do NOT invoke on coinbase.
code block::accept_transactions(const context& ctx) const NOEXCEPT
{
code ec;

if (!is_empty())
for (auto tx = std::next(txs_->begin()); tx != txs_->end(); ++tx)
if ((ec = (*tx)->accept(ctx)))
if (const auto ec = (*tx)->accept(ctx))
return ec;

return error::block_success;
Expand All @@ -719,11 +713,9 @@ code block::accept_transactions(const context& ctx) const NOEXCEPT
// Do NOT invoke on coinbase.
code block::connect_transactions(const context& ctx) const NOEXCEPT
{
code ec;

if (!is_empty())
for (auto tx = std::next(txs_->begin()); tx != txs_->end(); ++tx)
if ((ec = (*tx)->connect(ctx)))
if (const auto ec = (*tx)->connect(ctx))
return ec;

return error::block_success;
Expand All @@ -732,35 +724,49 @@ code block::connect_transactions(const context& ctx) const NOEXCEPT
// Do NOT invoke on coinbase.
code block::confirm_transactions(const context& ctx) const NOEXCEPT
{
code ec;

if (!is_empty())
for (auto tx = std::next(txs_->begin()); tx != txs_->end(); ++tx)
if ((ec = (*tx)->confirm(ctx)))
if (const auto ec = (*tx)->confirm(ctx))
return ec;

return error::block_success;
}

// Validation.
// Identity.
// ----------------------------------------------------------------------------
// The block header is checked/accepted independently.
// invalid_transaction_commitment, invalid_witness_commitment, block_malleated
// codes specifically indicate lack of block hash tx identification (identity).

// context free.
// Node relies on error::block_malleated.
// Node relies on error::invalid_transaction_commitment.
// TODO: use of get_hash() in is_forward_reference makes this thread unsafe.
code block::check(bool bypass) const NOEXCEPT
code block::identify() const NOEXCEPT
{
// type32 malleated is a subset of is_internal_double_spend.
// type64 malleated is a subset of first_not_coinbase.
if (bypass && is_malleated())
// type32 malleated is a subset of is_internal_double_spend.
if (is_malleated())
return error::block_malleated;
if (is_invalid_merkle_root())
return error::invalid_transaction_commitment;
if (bypass)
return error::block_success;

return error::block_success;
}

code block::identify(const context& ctx) const NOEXCEPT
{
const auto bip141 = ctx.is_enabled(bip141_rule);

if (bip141 && is_invalid_witness_commitment())
return error::invalid_witness_commitment;

return error::block_success;
}

// Validation.
// ----------------------------------------------------------------------------
// In the case of validation failure
// The block header is checked/accepted independently.

// TODO: use of get_hash() in is_forward_reference makes this thread unsafe.
code block::check() const NOEXCEPT
{
// empty_block is subset of first_not_coinbase.
//if (is_empty())
// return error::empty_block;
Expand All @@ -774,6 +780,8 @@ code block::check(bool bypass) const NOEXCEPT
return error::forward_reference;
if (is_internal_double_spend())
return error::block_internal_double_spend;
if (is_invalid_merkle_root())
return error::invalid_transaction_commitment;

return check_transactions();
}
Expand All @@ -783,18 +791,10 @@ code block::check(bool bypass) const NOEXCEPT
// timestamp
// median_time_past

// context required.
// Node relies on error::invalid_witness_commitment.
// TODO: use of get_hash() in is_hash_limit_exceeded makes this thread unsafe.
code block::check(const context& ctx, bool bypass) const NOEXCEPT
code block::check(const context& ctx) const NOEXCEPT
{
const auto bip141 = ctx.is_enabled(bip141_rule);

if (bip141 && is_invalid_witness_commitment())
return error::invalid_witness_commitment;
if (bypass)
return error::block_success;

const auto bip34 = ctx.is_enabled(bip34_rule);
const auto bip50 = ctx.is_enabled(bip50_rule);

Expand All @@ -804,6 +804,8 @@ code block::check(const context& ctx, bool bypass) const NOEXCEPT
return error::coinbase_height_mismatch;
if (bip50 && is_hash_limit_exceeded())
return error::temporary_hash_limit;
if (bip141 && is_invalid_witness_commitment())
return error::invalid_witness_commitment;

return check_transactions(ctx);
}
Expand Down
4 changes: 2 additions & 2 deletions src/chain/operation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -292,13 +292,13 @@ operation operation::from_string(const std::string& mnemonic) NOEXCEPT
// Data encoding uses single token with one or two parts.
const auto parts = split_push_token(mnemonic);

if (parts.size() == 1)
if (parts.size() == one)
{
// Extract operation using nominal data size decoding.
if ((valid = decode_base16(chunk, parts.front())))
code = nominal_opcode_from_data(chunk);
}
else if (parts.size() == 2)
else if (parts.size() == two)
{
// Extract operation using explicit data size decoding.

Expand Down
2 changes: 1 addition & 1 deletion src/chain/transaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1016,7 +1016,7 @@ bool transaction::create_endorsement(endorsement& out, const ec_secret& secret,

bool transaction::is_coinbase() const NOEXCEPT
{
return inputs_->size() == one && inputs_->front()->point().is_null();
return is_one(inputs_->size()) && inputs_->front()->point().is_null();
}

bool transaction::is_internal_double_spend() const NOEXCEPT
Expand Down
6 changes: 3 additions & 3 deletions src/config/printer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ static std::string format_setting(const parameter& value,
auto required = value.required();

// In terms of formatting we also treat multivalued as not required.
auto optional = value.args_limit() == 1;
auto optional = is_one(value.args_limit());

std::string formatter;
if (required)
Expand Down Expand Up @@ -308,10 +308,10 @@ std::string printer::format_usage_parameters() NOEXCEPT
const auto option = parameter.position() == parameter::not_positional;

// In terms of formatting we also treat multivalued as not required.
const auto optional = parameter.args_limit() == 1;
const auto optional = is_one(parameter.args_limit());

// This will capture only options set to zero_tokens().
const auto toggle = parameter.args_limit() == 0;
const auto toggle = is_zero(parameter.args_limit());

// A toggle with a short name gets mashed up in group.
const auto is_short = parameter.short_name() != parameter::no_short_name;
Expand Down
2 changes: 1 addition & 1 deletion src/wallet/points_value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ void points_value::greedy(points_value& out, const points_value& unspent,
return;

// Optimization for simple case not requiring search.
if (unspent.points.size() == 1)
if (is_one(unspent.points.size()))
{
out.points.push_back(unspent.points.front());
return;
Expand Down
2 changes: 1 addition & 1 deletion test/hash/hash.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ constexpr auto merkle_hash(const auto& expected) noexcept
};

Algorithm::merkle_hash(digests);
return (digests.size() == one) && (digests.front() == expected);
return is_one(digests.size()) && (digests.front() == expected);
};

// constexpr test helper for merkle_hash with four hashes.
Expand Down
2 changes: 1 addition & 1 deletion test/math/addition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ static_assert(subtract<int64_t>(pos_int32, min_int32) == (int64_t)pos_int32 - (i
BC_POP_WARNING()

// Unsigned underflow (signed underflow fails constexpr evaluation).
static_assert(subtract(min_uint32, max_uint32) == one);
static_assert(is_one(subtract(min_uint32, max_uint32)));
static_assert(is_subtract_overflow(min_uint32, max_uint32));

// TODO: value tests for default and explicit typing.
Expand Down
2 changes: 1 addition & 1 deletion test/types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ static_assert(is_same_type<argument<one, base, derived>, derived>);
// ----------------------------------------------------------------------------

// This are design limitations, and not a matter of C++ specification.
static_assert(sizeof(char) == one);
static_assert(is_one(sizeof(char)));
static_assert(
is_same_size<size_t, uint32_t> ||
is_same_size<size_t, uint64_t>);
Expand Down
Loading