mirror of
https://github.com/bitcoin/bips.git
synced 2025-03-18 05:42:12 +01:00
Merge pull request #333 from btcdrak/112update
Update BIP112 reference example
This commit is contained in:
commit
30fb3ae942
@ -229,117 +229,109 @@ The 2-way pegged sidechain requires a new REORGPROOFVERIFY opcode, the semantics
|
||||
Refer to the reference implementation, reproduced below, for the precise
|
||||
semantics and detailed rationale for those semantics.
|
||||
|
||||
|
||||
/* If this flag set, CTxIn::nSequence is NOT interpreted as a
|
||||
* relative lock-time. */
|
||||
static const uint32_t SEQUENCE_LOCKTIME_DISABLE_FLAG = (1 << 31);
|
||||
|
||||
/* If CTxIn::nSequence encodes a relative lock-time and this flag
|
||||
* is set, the relative lock-time has units of 512 seconds,
|
||||
* otherwise it specifies blocks with a granularity of 1. */
|
||||
static const uint32_t SEQUENCE_LOCKTIME_TYPE_FLAG = (1 << 22);
|
||||
|
||||
/* If CTxIn::nSequence encodes a relative lock-time, this mask is
|
||||
* applied to extract that lock-time from the sequence field. */
|
||||
static const uint32_t SEQUENCE_LOCKTIME_MASK = 0x0000ffff;
|
||||
<pre>
|
||||
/* Below flags apply in the context of BIP 68 */
|
||||
/* If this flag set, CTxIn::nSequence is NOT interpreted as a
|
||||
* relative lock-time. */
|
||||
static const uint32_t SEQUENCE_LOCKTIME_DISABLE_FLAG = (1 << 31);
|
||||
|
||||
/* If CTxIn::nSequence encodes a relative lock-time and this flag
|
||||
* is set, the relative lock-time has units of 512 seconds,
|
||||
* otherwise it specifies blocks with a granularity of 1. */
|
||||
static const uint32_t SEQUENCE_LOCKTIME_TYPE_FLAG = (1 << 22);
|
||||
|
||||
/* If CTxIn::nSequence encodes a relative lock-time, this mask is
|
||||
* applied to extract that lock-time from the sequence field. */
|
||||
static const uint32_t SEQUENCE_LOCKTIME_MASK = 0x0000ffff;
|
||||
|
||||
case OP_NOP3:
|
||||
{
|
||||
if (!(flags & SCRIPT_VERIFY_CHECKSEQUENCEVERIFY)) {
|
||||
// not enabled; treat as a NOP3
|
||||
if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
|
||||
return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS);
|
||||
}
|
||||
break;
|
||||
case OP_NOP3:
|
||||
{
|
||||
if (!(flags & SCRIPT_VERIFY_CHECKSEQUENCEVERIFY)) {
|
||||
// not enabled; treat as a NOP3
|
||||
if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
|
||||
return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS);
|
||||
}
|
||||
|
||||
if (stack.size() < 1)
|
||||
return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
|
||||
|
||||
// Note that elsewhere numeric opcodes are limited to
|
||||
// operands in the range -2**31+1 to 2**31-1, however it is
|
||||
// legal for opcodes to produce results exceeding that
|
||||
// range. This limitation is implemented by CScriptNum's
|
||||
// default 4-byte limit.
|
||||
//
|
||||
// Thus as a special case we tell CScriptNum to accept up
|
||||
// to 5-byte bignums, which are good until 2**39-1, well
|
||||
// beyond the 2**32-1 limit of the nSequence field itself.
|
||||
const CScriptNum nSequence(stacktop(-1), fRequireMinimal, 5);
|
||||
|
||||
// In the rare event that the argument may be < 0 due to
|
||||
// some arithmetic being done first, you can always use
|
||||
// 0 MAX CHECKSEQUENCEVERIFY.
|
||||
if (nSequence < 0)
|
||||
return set_error(serror, SCRIPT_ERR_NEGATIVE_LOCKTIME);
|
||||
|
||||
// To provide for future soft-fork extensibility, if the
|
||||
// operand has the disabled lock-time flag set,
|
||||
// CHECKSEQUENCEVERIFY behaves as a NOP.
|
||||
if ((nSequence & CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG) != 0)
|
||||
break;
|
||||
|
||||
// Compare the specified sequence number with the input.
|
||||
if (!checker.CheckSequence(nSequence))
|
||||
return set_error(serror, SCRIPT_ERR_UNSATISFIED_LOCKTIME);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
bool TransactionSignatureChecker::CheckSequence(const CScriptNum& nSequence) const
|
||||
{
|
||||
// Relative lock times are supported by comparing the passed
|
||||
// in operand to the sequence number of the input.
|
||||
const int64_t txToSequence = (int64_t)txTo->vin[nIn].nSequence;
|
||||
|
||||
// Fail if the transaction's version number is not set high
|
||||
// enough to trigger BIP 68 rules.
|
||||
if (static_cast<uint32_t>(txTo->nVersion) < 2)
|
||||
return false;
|
||||
|
||||
// Sequence numbers with their most significant bit set are not
|
||||
// defined by BIP68. Testing that the transaction's sequence
|
||||
// number do not have this bit set prevents using this property
|
||||
// to get around a CHECKSEQUENCEVERIFY check.
|
||||
if (txToSequence & CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG)
|
||||
return false;
|
||||
|
||||
// Mask off any bits that do not have BIP68 consensus-enforced meaning
|
||||
// before doing the integer comparisons of ::VerifySequence.
|
||||
const uint32_t nLockTimeMask = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG
|
||||
| CTxIn::SEQUENCE_LOCKTIME_MASK;
|
||||
|
||||
if (!::VerifySequence(txToSequence & nLockTimeMask,
|
||||
CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG,
|
||||
nSequence & nLockTimeMask))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool VerifySequence(int64_t txToSequence, int64_t nThreshold, const CScriptNum& nSequence)
|
||||
{
|
||||
// There are two kinds of nLockTime: lock-by-blockheight
|
||||
// and lock-by-blocktime, distinguished by whether
|
||||
// nSequence < nThreshold (CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG).
|
||||
//
|
||||
// We want to compare apples to apples, so fail the script
|
||||
// unless the type of nSequence being tested is the same as
|
||||
// the nSequence in the transaction.
|
||||
if (!(
|
||||
(txToSequence < nThreshold && nSequence < nThreshold) ||
|
||||
(txToSequence >= nThreshold && nSequence >= nThreshold)
|
||||
))
|
||||
return false;
|
||||
|
||||
// Now that we know we're comparing apples-to-apples, the
|
||||
// comparison is a simple numeric one.
|
||||
if (nSequence > txToSequence)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (stack.size() < 1)
|
||||
return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
|
||||
|
||||
// Note that elsewhere numeric opcodes are limited to
|
||||
// operands in the range -2**31+1 to 2**31-1, however it is
|
||||
// legal for opcodes to produce results exceeding that
|
||||
// range. This limitation is implemented by CScriptNum's
|
||||
// default 4-byte limit.
|
||||
//
|
||||
// Thus as a special case we tell CScriptNum to accept up
|
||||
// to 5-byte bignums, which are good until 2**39-1, well
|
||||
// beyond the 2**32-1 limit of the nSequence field itself.
|
||||
const CScriptNum nSequence(stacktop(-1), fRequireMinimal, 5);
|
||||
|
||||
// In the rare event that the argument may be < 0 due to
|
||||
// some arithmetic being done first, you can always use
|
||||
// 0 MAX CHECKSEQUENCEVERIFY.
|
||||
if (nSequence < 0)
|
||||
return set_error(serror, SCRIPT_ERR_NEGATIVE_LOCKTIME);
|
||||
|
||||
// To provide for future soft-fork extensibility, if the
|
||||
// operand has the disabled lock-time flag set,
|
||||
// CHECKSEQUENCEVERIFY behaves as a NOP.
|
||||
if ((nSequence & CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG) != 0)
|
||||
break;
|
||||
|
||||
// Compare the specified sequence number with the input.
|
||||
if (!checker.CheckSequence(nSequence))
|
||||
return set_error(serror, SCRIPT_ERR_UNSATISFIED_LOCKTIME);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
bool TransactionSignatureChecker::CheckSequence(const CScriptNum& nSequence) const
|
||||
{
|
||||
// Relative lock times are supported by comparing the passed
|
||||
// in operand to the sequence number of the input.
|
||||
const int64_t txToSequence = (int64_t)txTo->vin[nIn].nSequence;
|
||||
|
||||
// Fail if the transaction's version number is not set high
|
||||
// enough to trigger BIP 68 rules.
|
||||
if (static_cast<uint32_t>(txTo->nVersion) < 2)
|
||||
return false;
|
||||
|
||||
// Sequence numbers with their most significant bit set are not
|
||||
// consensus constrained. Testing that the transaction's sequence
|
||||
// number do not have this bit set prevents using this property
|
||||
// to get around a CHECKSEQUENCEVERIFY check.
|
||||
if (txToSequence & CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG)
|
||||
return false;
|
||||
|
||||
// Mask off any bits that do not have consensus-enforced meaning
|
||||
// before doing the integer comparisons
|
||||
const uint32_t nLockTimeMask = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | CTxIn::SEQUENCE_LOCKTIME_MASK;
|
||||
const int64_t txToSequenceMasked = txToSequence & nLockTimeMask;
|
||||
const CScriptNum nSequenceMasked = nSequence & nLockTimeMask;
|
||||
|
||||
// There are two kinds of nSequence: lock-by-blockheight
|
||||
// and lock-by-blocktime, distinguished by whether
|
||||
// nSequenceMasked < CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG.
|
||||
//
|
||||
// We want to compare apples to apples, so fail the script
|
||||
// unless the type of nSequenceMasked being tested is the same as
|
||||
// the nSequenceMasked in the transaction.
|
||||
if (!(
|
||||
(txToSequenceMasked < CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG && nSequenceMasked < CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG) ||
|
||||
(txToSequenceMasked >= CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG && nSequenceMasked >= CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG)
|
||||
))
|
||||
return false;
|
||||
|
||||
// Now that we know we're comparing apples-to-apples, the
|
||||
// comparison is a simple numeric one.
|
||||
if (nSequenceMasked > txToSequenceMasked)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
</pre>
|
||||
|
||||
==Reference Implementation==
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user