Skip to content

Commit 52c2cdb

Browse files
committed
Implement OP_CHECKLOCKTIMEVERIFY
The code is a rebased version of that in BIP65 by Peter Todd.
1 parent c789b76 commit 52c2cdb

File tree

6 files changed

+99
-5
lines changed

6 files changed

+99
-5
lines changed

src/main.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,6 @@ static const unsigned int BLOCKFILE_CHUNK_SIZE = 0x1000000; // 16 MiB
7474
static const unsigned int UNDOFILE_CHUNK_SIZE = 0x100000; // 1 MiB
7575
/** Coinbase transaction outputs can only be spent after this number of new blocks (network rule) */
7676
static const int COINBASE_MATURITY = 100;
77-
/** Threshold for nLockTime: below this value it is interpreted as block number, otherwise as UNIX timestamp. */
78-
static const unsigned int LOCKTIME_THRESHOLD = 500000000; // Tue Nov 5 00:53:20 1985 UTC
7977
/** Maximum number of script-checking threads allowed */
8078
static const int MAX_SCRIPTCHECK_THREADS = 16;
8179
/** -par default (number of script-checking threads, 0 = auto) */

src/script/interpreter.cpp

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
332332
case OP_NOP:
333333
break;
334334

335-
case OP_NOP1: case OP_NOP2: case OP_NOP3: case OP_NOP4: case OP_NOP5:
335+
case OP_NOP2: case OP_NOP3: case OP_NOP4: case OP_NOP5:
336336
case OP_NOP6: case OP_NOP7: case OP_NOP8: case OP_NOP9: case OP_NOP10:
337337
{
338338
if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS)
@@ -909,6 +909,48 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
909909
}
910910
break;
911911

912+
case OP_CHECKLOCKTIMEVERIFY:
913+
{
914+
if (!(flags & SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY)) {
915+
// not enabled; treat as a NOP1
916+
if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
917+
return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS);
918+
}
919+
break;
920+
}
921+
922+
if (stack.size() < 1)
923+
return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
924+
925+
// Note that elsewhere numeric opcodes are limited to
926+
// operands in the range -2**31+1 to 2**31-1, however it is
927+
// legal for opcodes to produce results exceeding that
928+
// range. This limitation is implemented by CScriptNum's
929+
// default 4-byte limit.
930+
//
931+
// If we kept to that limit we'd have a year 2038 problem,
932+
// even though the nLockTime field in transactions
933+
// themselves is uint32 which only becomes meaningless
934+
// after the year 2106.
935+
//
936+
// Thus as a special case we tell CScriptNum to accept up
937+
// to 5-byte bignums, which are good until 2**32-1, the
938+
// same limit as the nLockTime field itself.
939+
const CScriptNum nLockTime(stacktop(-1), 5);
940+
941+
// In the rare event that the argument may be < 0 due to
942+
// some arithmetic being done first, you can always use
943+
// 0 MAX CHECKLOCKTIMEVERIFY.
944+
if (nLockTime < 0)
945+
return set_error(serror, SCRIPT_ERR_NEGATIVE_LOCKTIME);
946+
947+
// Actually compare the specified lock time with the transaction.
948+
if (!checker.CheckLockTime(nLockTime))
949+
return set_error(serror, SCRIPT_ERR_UNSATISFIED_LOCKTIME);
950+
951+
break;
952+
}
953+
912954
default:
913955
return set_error(serror, SCRIPT_ERR_BAD_OPCODE);
914956
}
@@ -1078,6 +1120,42 @@ bool SignatureChecker::CheckSig(const vector<unsigned char>& vchSigIn, const vec
10781120
return true;
10791121
}
10801122

1123+
bool SignatureChecker::CheckLockTime(const CScriptNum& nLockTime) const
1124+
{
1125+
// There are two times of nLockTime: lock-by-blockheight
1126+
// and lock-by-blocktime, distinguished by whether
1127+
// nLockTime < LOCKTIME_THRESHOLD.
1128+
//
1129+
// We want to compare apples to apples, so fail the script
1130+
// unless the type of nLockTime being tested is the same as
1131+
// the nLockTime in the transaction.
1132+
if (!(
1133+
(txTo.nLockTime < LOCKTIME_THRESHOLD && nLockTime < LOCKTIME_THRESHOLD) ||
1134+
(txTo.nLockTime >= LOCKTIME_THRESHOLD && nLockTime >= LOCKTIME_THRESHOLD)
1135+
))
1136+
return false;
1137+
1138+
// Now that we know we're comparing apples-to-apples, the
1139+
// comparison is a simple numeric one.
1140+
if (nLockTime > (int64_t)txTo.nLockTime)
1141+
return false;
1142+
1143+
// Finally the nLockTime feature can be disabled and thus
1144+
// CHECKLOCKTIMEVERIFY bypassed if every txin has been
1145+
// finalized by setting nSequence to maxint. The
1146+
// transaction would be allowed into the blockchain, making
1147+
// the opcode ineffective.
1148+
//
1149+
// Testing if this vin is not final is sufficient to
1150+
// prevent this condition. Alternatively we could test all
1151+
// inputs, but testing just this input minimizes the data
1152+
// required to prove correct CHECKLOCKTIMEVERIFY execution.
1153+
if (txTo.vin[nIn].IsFinal())
1154+
return false;
1155+
1156+
return true;
1157+
}
1158+
10811159
bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror)
10821160
{
10831161
set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR);

src/script/interpreter.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,19 @@
77
#define BITCOIN_SCRIPT_INTERPRETER_H
88

99
#include "script_error.h"
10+
#include "script.h"
1011

1112
#include <vector>
1213
#include <stdint.h>
1314
#include <string>
1415

1516
class CPubKey;
16-
class CScript;
1717
class CTransaction;
1818
class uint256;
1919

20+
/** Threshold for nLockTime: below this value it is interpreted as block number, otherwise as UNIX timestamp. */
21+
static const unsigned int LOCKTIME_THRESHOLD = 500000000; // Tue Nov 5 00:53:20 1985 UTC
22+
2023
/** Signature hash types/flags */
2124
enum
2225
{
@@ -67,8 +70,9 @@ enum
6770
// discouraged NOPs fails the script. This verification flag will never be
6871
// a mandatory flag applied to scripts in a block. NOPs that are not
6972
// executed, e.g. within an unexecuted IF ENDIF block, are *not* rejected.
70-
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS = (1U << 7)
73+
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS = (1U << 7),
7174

75+
SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY = (1U << 8)
7276
};
7377

7478
uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
@@ -80,6 +84,10 @@ class BaseSignatureChecker
8084
{
8185
return false;
8286
}
87+
virtual bool CheckLockTime(const CScriptNum& nLockTime) const
88+
{
89+
return false;
90+
}
8391

8492
virtual ~BaseSignatureChecker() {}
8593
};
@@ -96,6 +104,7 @@ class SignatureChecker : public BaseSignatureChecker
96104
public:
97105
SignatureChecker(const CTransaction& txToIn, unsigned int nInIn) : txTo(txToIn), nIn(nInIn) {}
98106
bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode) const;
107+
bool CheckLockTime(const CScriptNum& nLockTime) const;
99108
};
100109

101110
bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* error = NULL);

src/script/script.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ enum opcodetype
148148

149149
// expansion
150150
OP_NOP1 = 0xb0,
151+
OP_CHECKLOCKTIMEVERIFY = OP_NOP1,
151152
OP_NOP2 = 0xb1,
152153
OP_NOP3 = 0xb2,
153154
OP_NOP4 = 0xb3,

src/script/script_error.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ const char* ScriptErrorString(const ScriptError serror)
4747
return "OP_RETURN was encountered";
4848
case SCRIPT_ERR_UNBALANCED_CONDITIONAL:
4949
return "Invalid OP_IF construction";
50+
case SCRIPT_ERR_NEGATIVE_LOCKTIME:
51+
return "Negative locktime";
52+
case SCRIPT_ERR_UNSATISFIED_LOCKTIME:
53+
return "Locktime requirement not satisfied";
5054
case SCRIPT_ERR_SIG_HASHTYPE:
5155
return "Signature hash type missing or not understood";
5256
case SCRIPT_ERR_SIG_DER:

src/script/script_error.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ typedef enum ScriptError_t
3535
SCRIPT_ERR_INVALID_ALTSTACK_OPERATION,
3636
SCRIPT_ERR_UNBALANCED_CONDITIONAL,
3737

38+
/* OP_CHECKLOCKTIMEVERIFY */
39+
SCRIPT_ERR_NEGATIVE_LOCKTIME,
40+
SCRIPT_ERR_UNSATISFIED_LOCKTIME,
41+
3842
/* BIP62 */
3943
SCRIPT_ERR_SIG_HASHTYPE,
4044
SCRIPT_ERR_SIG_DER,

0 commit comments

Comments
 (0)