mirror of
https://github.com/bitcoin/bips.git
synced 2025-03-04 11:08:05 +01:00
Add type field to CHECKLOCKTIMEVERIFY (BIP65)
Allows for future upgrades, e.g. relative CLTV.
This commit is contained in:
parent
2ea19daaa0
commit
400f79095d
1 changed files with 59 additions and 27 deletions
|
@ -16,11 +16,12 @@ some point in the future.
|
|||
|
||||
==Summary==
|
||||
|
||||
CHECKLOCKTIMEVERIFY redefines the existing NOP2 opcode. When executed it
|
||||
compares the top item on the stack to the nLockTime field of the transaction
|
||||
containing the scriptSig. If that top stack item is greater than the transaction
|
||||
nLockTime the script fails immediately, otherwise script evaluation continues
|
||||
as though a NOP was executed.
|
||||
CHECKLOCKTIMEVERIFY redefines the existing NOP2 opcode. When executed with the
|
||||
top item of the stack set to 1 it compares the second from top item on the
|
||||
stack to the nLockTime field of the transaction containing the scriptSig. If
|
||||
that stack item is greater than the transaction nLockTime the script fails
|
||||
immediately, otherwise script evaluation continues as though a NOP was
|
||||
executed.
|
||||
|
||||
The nLockTime field in a transaction prevents the transaction from being mined
|
||||
until either a certain block height, or block time, has been reached. By
|
||||
|
@ -64,7 +65,7 @@ However with CHECKLOCKTIMEVERIFY the funds can be stored in scriptPubKeys of
|
|||
the form:
|
||||
|
||||
IF
|
||||
<now + 3 months> CHECKLOCKTIMEVERIFY DROP
|
||||
<now + 3 months> 1 CHECKLOCKTIMEVERIFY DROP
|
||||
<Lenny's pubkey> CHECKSIGVERIFY
|
||||
1
|
||||
ELSE
|
||||
|
@ -113,7 +114,7 @@ scriptPubKeys of the following form are used instead:
|
|||
IF
|
||||
<service pubkey> CHECKSIGVERIFY
|
||||
ELSE
|
||||
<expiry time> CHECKLOCKTIMEVERIFY DROP
|
||||
<expiry time> 1 CHECKLOCKTIMEVERIFY DROP
|
||||
ENDIF
|
||||
<user pubkey> CHECKSIG
|
||||
|
||||
|
@ -149,7 +150,7 @@ scriptPubKeys of the following form:
|
|||
HASH160 <Hash160(encryption key)> EQUALVERIFY
|
||||
<publisher pubkey> CHECKSIG
|
||||
ELSE
|
||||
<expiry time> CHECKLOCKTIMEVERIFY DROP
|
||||
<expiry time> 1 CHECKLOCKTIMEVERIFY DROP
|
||||
<buyer pubkey> CHECKSIG
|
||||
ENDIF
|
||||
|
||||
|
@ -188,17 +189,38 @@ transaction output ''can'' be spent.
|
|||
Refer to the reference implementation, reproduced below, for the precise
|
||||
semantics and detailed rationale for those semantics.
|
||||
|
||||
case OP_NOP2:
|
||||
{
|
||||
// CHECKLOCKTIMEVERIFY
|
||||
//
|
||||
// (nLockTime -- nLockTime )
|
||||
|
||||
if (!(flags & SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY))
|
||||
break; // not enabled; treat as a NOP
|
||||
case OP_CHECKLOCKTIMEVERIFY:
|
||||
{
|
||||
if (!(flags & SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY)) {
|
||||
// not enabled; treat as a NOP2
|
||||
if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
|
||||
return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (stack.size() < 1)
|
||||
return false;
|
||||
return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
|
||||
|
||||
// Type of locktime to verify. Currently the only type
|
||||
// defined is 1, which is to verify the nLockTime
|
||||
// absolutely. If the type is not recognised, the opcode is
|
||||
// treated as a NOP to allow for upgrades in the future.
|
||||
//
|
||||
// That said, for simplicity sake, we *do* require the
|
||||
// argument to be a (possibly minimal) number within the
|
||||
// numerical limits.
|
||||
const CScriptNum nType(stacktop(-1), fRequireMinimal);
|
||||
if (nType != 1)
|
||||
break;
|
||||
|
||||
// Only if the type is recognised do we require the stack
|
||||
// to have the second argument. The alternative, requiring
|
||||
// the stack to always have both arguments, would prohibit
|
||||
// future CLTV upgrades that don't need two arguments.
|
||||
if (stack.size() < 2)
|
||||
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
|
||||
|
@ -214,14 +236,24 @@ semantics and detailed rationale for those semantics.
|
|||
// Thus as a special case we tell CScriptNum to accept up
|
||||
// to 5-byte bignums, which are good until 2**32-1, the
|
||||
// same limit as the nLockTime field itself.
|
||||
const CScriptNum nLockTime(stacktop(-1), 5);
|
||||
const CScriptNum nLockTime(stacktop(-2), 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 CHECKLOCKTIMEVERIFY.
|
||||
// 0 MAX 1 CHECKLOCKTIMEVERIFY.
|
||||
if (nLockTime < 0)
|
||||
return false;
|
||||
return set_error(serror, SCRIPT_ERR_NEGATIVE_LOCKTIME);
|
||||
|
||||
// Actually compare the specified lock time with the transaction.
|
||||
if (!checker.CheckLockTime(nLockTime))
|
||||
return set_error(serror, SCRIPT_ERR_UNSATISFIED_LOCKTIME);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
bool TransactionSignatureChecker::CheckLockTime(const CScriptNum& nLockTime) const
|
||||
{
|
||||
// There are two times of nLockTime: lock-by-blockheight
|
||||
// and lock-by-blocktime, distinguished by whether
|
||||
// nLockTime < LOCKTIME_THRESHOLD.
|
||||
|
@ -230,14 +262,14 @@ semantics and detailed rationale for those semantics.
|
|||
// unless the type of nLockTime being tested is the same as
|
||||
// the nLockTime in the transaction.
|
||||
if (!(
|
||||
(txTo.nLockTime < LOCKTIME_THRESHOLD && nLockTime < LOCKTIME_THRESHOLD) ||
|
||||
(txTo.nLockTime >= LOCKTIME_THRESHOLD && nLockTime >= LOCKTIME_THRESHOLD)
|
||||
(txTo->nLockTime < LOCKTIME_THRESHOLD && nLockTime < LOCKTIME_THRESHOLD) ||
|
||||
(txTo->nLockTime >= LOCKTIME_THRESHOLD && nLockTime >= LOCKTIME_THRESHOLD)
|
||||
))
|
||||
return false;
|
||||
|
||||
// Now that we know we're comparing apples-to-apples, the
|
||||
// comparison is a simple numeric one.
|
||||
if (nLockTime > (int64_t)txTo.nLockTime)
|
||||
if (nLockTime > (int64_t)txTo->nLockTime)
|
||||
return false;
|
||||
|
||||
// Finally the nLockTime feature can be disabled and thus
|
||||
|
@ -250,14 +282,14 @@ semantics and detailed rationale for those semantics.
|
|||
// prevent this condition. Alternatively we could test all
|
||||
// inputs, but testing just this input minimizes the data
|
||||
// required to prove correct CHECKLOCKTIMEVERIFY execution.
|
||||
if (txTo.vin[nIn].IsFinal())
|
||||
if (txTo->vin[nIn].IsFinal())
|
||||
return false;
|
||||
|
||||
break;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
https://github.com/petertodd/bitcoin/commit/ab0f54f38e08ee1e50ff72f801680ee84d0f1bf4
|
||||
|
||||
https://github.com/petertodd/bitcoin/commit/dc17027f2c37b97ce5b40154a64f18c16a72ee18
|
||||
|
||||
|
||||
==Upgrade and Testing Plan==
|
||||
|
|
Loading…
Add table
Reference in a new issue