Skip to content

Commit e980a01

Browse files
committed
Check version before internal lock.
1 parent 1cc7c18 commit e980a01

5 files changed

Lines changed: 24 additions & 7 deletions

File tree

include/bitcoin/system/chain/input.hpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,14 +118,15 @@ class BC_API input
118118
/// Requires metadata.height and median_time_past (otherwise returns true).
119119
bool is_locked(size_t height, uint32_t median_time_past) const NOEXCEPT;
120120

121-
/// Any non-zero relative locktime value locks internally-spent input.
122-
bool is_internally_locked() const NOEXCEPT;
123-
124121
protected:
125122
input(const chain::point::cptr& point, const chain::script::cptr& script,
126123
const chain::witness::cptr& witness, uint32_t sequence,
127124
bool valid) NOEXCEPT;
128125

126+
/// Any non-zero relative locktime value locks internally-spent input.
127+
friend class transaction;
128+
bool is_internal_lock() const NOEXCEPT;
129+
129130
private:
130131
typedef struct { size_t nominal; size_t witnessed; } sizes;
131132

include/bitcoin/system/chain/transaction.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,9 @@ class BC_API transaction
128128
bool is_empty() const NOEXCEPT;
129129
bool is_dusty(uint64_t minimum_output_value) const NOEXCEPT;
130130

131+
/// Requires no metadata, true if spend in own block would be locked.
132+
bool is_internal_lock(const input& in) const NOEXCEPT;
133+
131134
/// Assumes coinbase if prevout not populated (returns only legacy sigops).
132135
size_t signature_operations(bool bip16, bool bip141) const NOEXCEPT;
133136

src/chain/block.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -730,7 +730,7 @@ bool block::populate(const chain::context& ctx) const NOEXCEPT
730730
if (point != points.end())
731731
{
732732
in->prevout = point->second;
733-
in->metadata.locked = bip68 && in->is_internally_locked();
733+
in->metadata.locked = bip68 && (*tx)->is_internal_lock(*in);
734734
locked |= in->metadata.locked;
735735
}
736736
}

src/chain/input.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -416,10 +416,11 @@ bool input::is_locked(size_t height, uint32_t median_time_past) const NOEXCEPT
416416
metadata.median_time_past);
417417
}
418418

419-
bool input::is_internally_locked() const NOEXCEPT
419+
// protected (tx friend)
420+
bool input::is_internal_lock() const NOEXCEPT
420421
{
421-
// Internal spends have zero relative height/mtp.
422-
return is_locked(sequence_, {}, {}, {}, {});
422+
// Internal spends have no relative height/mtp (any metadata values work).
423+
return is_locked(metadata.height, metadata.median_time_past);
423424
}
424425

425426
bool input::reserved_hash(hash_digest& out) const NOEXCEPT

src/chain/transaction.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1151,6 +1151,18 @@ bool transaction::is_immature(size_t height) const NOEXCEPT
11511151
return !std::all_of(inputs_->begin(), inputs_->end(), mature);
11521152
}
11531153

1154+
bool transaction::is_internal_lock(const input& in) const NOEXCEPT
1155+
{
1156+
// BIP68: not applied to the sequence of the input of a coinbase.
1157+
BC_ASSERT(!is_coinbase());
1158+
1159+
// BIP68: applied to txs with a version greater than or equal to two.
1160+
if (version_ < relative_locktime_min_version)
1161+
return false;
1162+
1163+
return in.is_internal_lock();
1164+
}
1165+
11541166
bool transaction::is_locked(size_t height,
11551167
uint32_t median_time_past) const NOEXCEPT
11561168
{

0 commit comments

Comments
 (0)