Skip to content

Commit

Permalink
Merge pull request #1576 from evoskuil/master
Browse files Browse the repository at this point in the history
Change block.populate() to bool (locked), set in.metadata.locked.
  • Loading branch information
evoskuil authored Jan 4, 2025
2 parents a96803c + 7161382 commit 55e26ff
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 15 deletions.
4 changes: 2 additions & 2 deletions include/bitcoin/system/chain/block.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,8 @@ class BC_API block
code connect(const context& ctx) const NOEXCEPT;
code confirm(const context& ctx) const NOEXCEPT;

/// Populate previous outputs (only, no metadata) internal to the block.
size_t populate() const NOEXCEPT;
/// Populate previous outputs (and metadata.locked) internal to the block.
bool populate() const NOEXCEPT;

protected:
block(const chain::header::cptr& header,
Expand Down
3 changes: 3 additions & 0 deletions include/bitcoin/system/chain/input.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@ class BC_API input
/// Requires metadata.height and median_time_past (otherwise returns true).
bool is_locked(size_t height, uint32_t median_time_past) const NOEXCEPT;

/// Any non-zero relative locktime value locks internally-spent input.
bool is_internally_locked() const NOEXCEPT;

protected:
input(const chain::point::cptr& point, const chain::script::cptr& script,
const chain::witness::cptr& witness, uint32_t sequence,
Expand Down
24 changes: 16 additions & 8 deletions include/bitcoin/system/chain/prevout.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ class BC_API prevout final
/// CONSENSUS:
/// A height of zero is immature (unspendable) despite unspent state.
///************************************************************************

union
{
/// The confirmed chain height of the prevout (zero if not found).
/// Unused if the input owning this prevout is null (coinbase).
/// database: unused as validation precedes prevout block association.
size_t height;

/// database: populated with a database identifier for the parent tx.
Expand All @@ -47,25 +47,33 @@ class BC_API prevout final
/// 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).
/// database: unused as validation precedes prevout block association.
uint32_t median_time_past{ max_uint32 };
union
{
/// The median time past at height (max_uint32 if not found/confirmed).
/// Unused if the input owning this prevout is null (coinbase).
/// database: unused as validation precedes prevout block association.
uint32_t median_time_past{ max_uint32 };

/// Populated by block.populate() call as internal spends do not
/// require prevout block association for relative locktime checks.
/// So median_time_past is not required as locked is determined here.
bool locked;
};

///************************************************************************
/// CONSENSUS:
/// An unspent coinbase collision is immature (unspendable) and spent
/// collision is mature (bip30). CB collision presumed precluded by bip34.
///************************************************************************
/// If the input owning this prevout is null (coinbase), this implies that
/// If 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).
/// database: unused as validation precedes potential spend block assocs.
/// database: unused as validation precedes prevout block association.
bool spent{ true };

/// The previous output is of a coinbase transaction.
/// database: populated as does not require prevout block association.
/// database: populated, does not require prevout block association.
bool coinbase{ false };
};

Expand Down
11 changes: 6 additions & 5 deletions src/chain/block.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -688,7 +688,7 @@ bool block::is_unspent_coinbase_collision() const NOEXCEPT
}

// Search is not ordered, forward references are caught by block.check.
size_t block::populate() const NOEXCEPT
bool block::populate() const NOEXCEPT
{
std::unordered_map<point, output::cptr> points{};
uint32_t index{};
Expand All @@ -699,22 +699,23 @@ size_t block::populate() const NOEXCEPT
points.emplace(std::pair{ point{ (*tx)->hash(false), index++ },
out });

// Populate input prevouts from hash table and obtain count.
size_t count{};
// Populate input prevouts from hash table and obtain locked state.
bool locked{};
for (auto tx = txs_->begin(); tx != txs_->end(); ++tx)
{
for (const auto& in: *(*tx)->inputs_ptr())
{
const auto point = points.find(in->point());
if (point != points.end())
{
++count;
in->prevout = point->second;
in->metadata.locked = in->is_internally_locked();
locked |= in->metadata.locked;
}
}
}

return count;
return !locked;
}

// Delegated.
Expand Down
6 changes: 6 additions & 0 deletions src/chain/input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,12 @@ bool input::is_locked(size_t height, uint32_t median_time_past) const NOEXCEPT
metadata.median_time_past);
}

bool input::is_internally_locked() const NOEXCEPT
{
// Internal spends have zero relative height/mtp.
return is_locked(sequence_, {}, {}, {}, {});
}

bool input::reserved_hash(hash_digest& out) const NOEXCEPT
{
if (!witness::is_reserved_pattern(get_witness().stack()))
Expand Down

0 comments on commit 55e26ff

Please sign in to comment.