txscript: Implement CheckSequenceVerify (BIP0112)
This commit is contained in:
parent
fdfa07b0be
commit
a6bf1d9850
9 changed files with 293 additions and 37 deletions
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2015 The btcsuite developers
|
// Copyright (c) 2015-2016 The btcsuite developers
|
||||||
// Use of this source code is governed by an ISC
|
// Use of this source code is governed by an ISC
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
@ -8,7 +8,6 @@ const (
|
||||||
// LockTimeThreshold is the number below which a lock time is
|
// LockTimeThreshold is the number below which a lock time is
|
||||||
// interpreted to be a block number. Since an average of one block
|
// interpreted to be a block number. Since an average of one block
|
||||||
// is generated per 10 minutes, this allows blocks for about 9,512
|
// is generated per 10 minutes, this allows blocks for about 9,512
|
||||||
// years. However, if the field is interpreted as a timestamp, given
|
// years.
|
||||||
// the lock time is a uint32, the max is sometime around 2106.
|
LockTimeThreshold = 5e8 // Tue Nov 5 00:53:20 1985 UTC
|
||||||
LockTimeThreshold uint32 = 5e8 // Tue Nov 5 00:53:20 1985 UTC
|
|
||||||
)
|
)
|
||||||
|
|
|
@ -191,5 +191,59 @@
|
||||||
[[["b1dbc81696c8a9c0fccd0693ab66d7c368dbc38c0def4e800685560ddd1b2132", 0, "DUP HASH160 0x14 0x4b3bd7eba3bc0284fd3007be7f3be275e94f5826 EQUALVERIFY CHECKSIG"]],
|
[[["b1dbc81696c8a9c0fccd0693ab66d7c368dbc38c0def4e800685560ddd1b2132", 0, "DUP HASH160 0x14 0x4b3bd7eba3bc0284fd3007be7f3be275e94f5826 EQUALVERIFY CHECKSIG"]],
|
||||||
"010000000132211bdd0d568506804eef0d8cc3db68c3d766ab9306cdfcc0a9c89616c8dbb1000000006c493045022100c7bb0faea0522e74ff220c20c022d2cb6033f8d167fb89e75a50e237a35fd6d202203064713491b1f8ad5f79e623d0219ad32510bfaa1009ab30cbee77b59317d6e30001210237af13eb2d84e4545af287b919c2282019c9691cc509e78e196a9d8274ed1be0ffffffff0100000000000000001976a914f1b3ed2eda9a2ebe5a9374f692877cdf87c0f95b88ac00000000", "P2SH,DERSIG"],
|
"010000000132211bdd0d568506804eef0d8cc3db68c3d766ab9306cdfcc0a9c89616c8dbb1000000006c493045022100c7bb0faea0522e74ff220c20c022d2cb6033f8d167fb89e75a50e237a35fd6d202203064713491b1f8ad5f79e623d0219ad32510bfaa1009ab30cbee77b59317d6e30001210237af13eb2d84e4545af287b919c2282019c9691cc509e78e196a9d8274ed1be0ffffffff0100000000000000001976a914f1b3ed2eda9a2ebe5a9374f692877cdf87c0f95b88ac00000000", "P2SH,DERSIG"],
|
||||||
|
|
||||||
|
["CHECKSEQUENCEVERIFY tests"],
|
||||||
|
|
||||||
|
["By-height locks, with argument just beyond txin.nSequence"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "1 NOP3 1"]],
|
||||||
|
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 NOP3 1"]],
|
||||||
|
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000feff40000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
|
||||||
|
["By-time locks, with argument just beyond txin.nSequence (but within numerical boundries)"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194305 NOP3 1"]],
|
||||||
|
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 NOP3 1"]],
|
||||||
|
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000feff40000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
|
||||||
|
["Argument missing"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "NOP3 1"]],
|
||||||
|
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
|
||||||
|
["Argument negative with by-blockheight txin.nSequence=0"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "-1 NOP3 1"]],
|
||||||
|
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
|
||||||
|
["Argument negative with by-blocktime txin.nSequence=CTxIn::SEQUENCE_UNITS_THRESHOD"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "-1 NOP3 1"]],
|
||||||
|
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
|
||||||
|
["Argument/tx height/time mismatch, both versions"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 NOP3 1"]],
|
||||||
|
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "65535 NOP3 1"]],
|
||||||
|
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 NOP3 1"]],
|
||||||
|
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 NOP3 1"]],
|
||||||
|
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
|
||||||
|
["6 byte non-minimally-encoded arguments are invalid even if their contents are valid"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x06 0x000000000000 NOP3 1"]],
|
||||||
|
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffff00000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
|
||||||
|
["Failure due to failing CHECKSEQUENCEVERIFY in scriptSig"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "1"]],
|
||||||
|
"02000000010001000000000000000000000000000000000000000000000000000000000000000000000251b2000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
|
||||||
|
["Failure due to failing CHECKSEQUENCEVERIFY in redeemScript"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7c17aff532f22beb54069942f9bf567a66133eaf EQUAL"]],
|
||||||
|
"0200000001000100000000000000000000000000000000000000000000000000000000000000000000030251b2000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
|
||||||
|
["Failure due to insufficient tx.nVersion (<2)"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 NOP3 1"]],
|
||||||
|
"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 NOP3 1"]],
|
||||||
|
"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
|
||||||
["Make diffs cleaner by leaving a comment here without comma at the end"]
|
["Make diffs cleaner by leaving a comment here without comma at the end"]
|
||||||
]
|
]
|
||||||
|
|
|
@ -233,5 +233,89 @@
|
||||||
[[["b1dbc81696c8a9c0fccd0693ab66d7c368dbc38c0def4e800685560ddd1b2132", 0, "DUP HASH160 0x14 0x4b3bd7eba3bc0284fd3007be7f3be275e94f5826 EQUALVERIFY CHECKSIG"]],
|
[[["b1dbc81696c8a9c0fccd0693ab66d7c368dbc38c0def4e800685560ddd1b2132", 0, "DUP HASH160 0x14 0x4b3bd7eba3bc0284fd3007be7f3be275e94f5826 EQUALVERIFY CHECKSIG"]],
|
||||||
"010000000132211bdd0d568506804eef0d8cc3db68c3d766ab9306cdfcc0a9c89616c8dbb1000000006c493045022100c7bb0faea0522e74ff220c20c022d2cb6033f8d167fb89e75a50e237a35fd6d202203064713491b1f8ad5f79e623d0219ad32510bfaa1009ab30cbee77b59317d6e30001210237af13eb2d84e4545af287b919c2282019c9691cc509e78e196a9d8274ed1be0ffffffff0100000000000000001976a914f1b3ed2eda9a2ebe5a9374f692877cdf87c0f95b88ac00000000", "P2SH"],
|
"010000000132211bdd0d568506804eef0d8cc3db68c3d766ab9306cdfcc0a9c89616c8dbb1000000006c493045022100c7bb0faea0522e74ff220c20c022d2cb6033f8d167fb89e75a50e237a35fd6d202203064713491b1f8ad5f79e623d0219ad32510bfaa1009ab30cbee77b59317d6e30001210237af13eb2d84e4545af287b919c2282019c9691cc509e78e196a9d8274ed1be0ffffffff0100000000000000001976a914f1b3ed2eda9a2ebe5a9374f692877cdf87c0f95b88ac00000000", "P2SH"],
|
||||||
|
|
||||||
|
["CHECKSEQUENCEVERIFY tests"],
|
||||||
|
|
||||||
|
["By-height locks, with argument == 0 and == txin.nSequence"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 NOP3 1"]],
|
||||||
|
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "65535 NOP3 1"]],
|
||||||
|
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffff00000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "65535 NOP3 1"]],
|
||||||
|
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 NOP3 1"]],
|
||||||
|
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
|
||||||
|
["By-time locks, with argument == 0 and == txin.nSequence"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 NOP3 1"]],
|
||||||
|
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 NOP3 1"]],
|
||||||
|
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffff40000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 NOP3 1"]],
|
||||||
|
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 NOP3 1"]],
|
||||||
|
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
|
||||||
|
["Upper sequence with upper sequence is fine"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 NOP3 1"]],
|
||||||
|
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000800100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 NOP3 1"]],
|
||||||
|
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000800100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 NOP3 1"]],
|
||||||
|
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000feffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 NOP3 1"]],
|
||||||
|
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000feffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 NOP3 1"]],
|
||||||
|
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 NOP3 1"]],
|
||||||
|
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
|
||||||
|
["Argument 2^31 with various nSequence"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 NOP3 1"]],
|
||||||
|
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 NOP3 1"]],
|
||||||
|
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 NOP3 1"]],
|
||||||
|
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
|
||||||
|
["Argument 2^32-1 with various nSequence"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 NOP3 1"]],
|
||||||
|
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 NOP3 1"]],
|
||||||
|
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 NOP3 1"]],
|
||||||
|
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
|
||||||
|
["Argument 3<<31 with various nSequence"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "6442450944 NOP3 1"]],
|
||||||
|
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "6442450944 NOP3 1"]],
|
||||||
|
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "6442450944 NOP3 1"]],
|
||||||
|
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
|
||||||
|
["5 byte non-minimally-encoded operandss are valid"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x05 0x0000000000 NOP3 1"]],
|
||||||
|
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
|
||||||
|
["The argument can be calculated rather than created directly by a PUSHDATA"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194303 1ADD NOP3 1"]],
|
||||||
|
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 1SUB NOP3 1"]],
|
||||||
|
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffff00000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
|
||||||
|
["An ADD producing a 5-byte result that sets CTxIn::SEQUENCE_LOCKTIME_DISABLED_FLAG"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483647 65536 NOP3 1"]],
|
||||||
|
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483647 4259840 ADD NOP3 1"]],
|
||||||
|
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
|
||||||
|
["Valid CHECKSEQUENCEVERIFY in scriptSig"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "1"]],
|
||||||
|
"02000000010001000000000000000000000000000000000000000000000000000000000000000000000251b2010000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
|
||||||
|
["Valid CHECKSEQUENCEVERIFY in redeemScript"],
|
||||||
|
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7c17aff532f22beb54069942f9bf567a66133eaf EQUAL"]],
|
||||||
|
"0200000001000100000000000000000000000000000000000000000000000000000000000000000000030251b2010000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
|
||||||
|
|
||||||
["Make diffs cleaner by leaving a comment here without comma at the end"]
|
["Make diffs cleaner by leaving a comment here without comma at the end"]
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2013-2015 The btcsuite developers
|
// Copyright (c) 2013-2016 The btcsuite developers
|
||||||
// Use of this source code is governed by an ISC
|
// Use of this source code is governed by an ISC
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
@ -38,6 +38,11 @@ const (
|
||||||
// This is BIP0065.
|
// This is BIP0065.
|
||||||
ScriptVerifyCheckLockTimeVerify
|
ScriptVerifyCheckLockTimeVerify
|
||||||
|
|
||||||
|
// ScriptVerifyCheckSequenceVerify defines whether to allow execution
|
||||||
|
// pathways of a script to be restricted based on the age of the output
|
||||||
|
// being spent. This is BIP0112.
|
||||||
|
ScriptVerifyCheckSequenceVerify
|
||||||
|
|
||||||
// ScriptVerifyCleanStack defines that the stack must contain only
|
// ScriptVerifyCleanStack defines that the stack must contain only
|
||||||
// one stack element after evaluation and that the element must be
|
// one stack element after evaluation and that the element must be
|
||||||
// true if interpreted as a boolean. This is rule 6 of BIP0062.
|
// true if interpreted as a boolean. This is rule 6 of BIP0062.
|
||||||
|
|
|
@ -216,6 +216,7 @@ const (
|
||||||
OP_NOP2 = 0xb1 // 177
|
OP_NOP2 = 0xb1 // 177
|
||||||
OP_CHECKLOCKTIMEVERIFY = 0xb1 // 177 - AKA OP_NOP2
|
OP_CHECKLOCKTIMEVERIFY = 0xb1 // 177 - AKA OP_NOP2
|
||||||
OP_NOP3 = 0xb2 // 178
|
OP_NOP3 = 0xb2 // 178
|
||||||
|
OP_CHECKSEQUENCEVERIFY = 0xb2 // 178 - AKA OP_NOP3
|
||||||
OP_NOP4 = 0xb3 // 179
|
OP_NOP4 = 0xb3 // 179
|
||||||
OP_NOP5 = 0xb4 // 180
|
OP_NOP5 = 0xb4 // 180
|
||||||
OP_NOP6 = 0xb5 // 181
|
OP_NOP6 = 0xb5 // 181
|
||||||
|
@ -417,6 +418,7 @@ var opcodeArray = [256]opcode{
|
||||||
OP_VERIFY: {OP_VERIFY, "OP_VERIFY", 1, opcodeVerify},
|
OP_VERIFY: {OP_VERIFY, "OP_VERIFY", 1, opcodeVerify},
|
||||||
OP_RETURN: {OP_RETURN, "OP_RETURN", 1, opcodeReturn},
|
OP_RETURN: {OP_RETURN, "OP_RETURN", 1, opcodeReturn},
|
||||||
OP_CHECKLOCKTIMEVERIFY: {OP_CHECKLOCKTIMEVERIFY, "OP_CHECKLOCKTIMEVERIFY", 1, opcodeCheckLockTimeVerify},
|
OP_CHECKLOCKTIMEVERIFY: {OP_CHECKLOCKTIMEVERIFY, "OP_CHECKLOCKTIMEVERIFY", 1, opcodeCheckLockTimeVerify},
|
||||||
|
OP_CHECKSEQUENCEVERIFY: {OP_CHECKSEQUENCEVERIFY, "OP_CHECKSEQUENCEVERIFY", 1, opcodeCheckSequenceVerify},
|
||||||
|
|
||||||
// Stack opcodes.
|
// Stack opcodes.
|
||||||
OP_TOALTSTACK: {OP_TOALTSTACK, "OP_TOALTSTACK", 1, opcodeToAltStack},
|
OP_TOALTSTACK: {OP_TOALTSTACK, "OP_TOALTSTACK", 1, opcodeToAltStack},
|
||||||
|
@ -499,7 +501,6 @@ var opcodeArray = [256]opcode{
|
||||||
|
|
||||||
// Reserved opcodes.
|
// Reserved opcodes.
|
||||||
OP_NOP1: {OP_NOP1, "OP_NOP1", 1, opcodeNop},
|
OP_NOP1: {OP_NOP1, "OP_NOP1", 1, opcodeNop},
|
||||||
OP_NOP3: {OP_NOP3, "OP_NOP3", 1, opcodeNop},
|
|
||||||
OP_NOP4: {OP_NOP4, "OP_NOP4", 1, opcodeNop},
|
OP_NOP4: {OP_NOP4, "OP_NOP4", 1, opcodeNop},
|
||||||
OP_NOP5: {OP_NOP5, "OP_NOP5", 1, opcodeNop},
|
OP_NOP5: {OP_NOP5, "OP_NOP5", 1, opcodeNop},
|
||||||
OP_NOP6: {OP_NOP6, "OP_NOP6", 1, opcodeNop},
|
OP_NOP6: {OP_NOP6, "OP_NOP6", 1, opcodeNop},
|
||||||
|
@ -876,7 +877,7 @@ func opcodeN(op *parsedOpcode, vm *Engine) error {
|
||||||
// the flag to discourage use of NOPs is set for select opcodes.
|
// the flag to discourage use of NOPs is set for select opcodes.
|
||||||
func opcodeNop(op *parsedOpcode, vm *Engine) error {
|
func opcodeNop(op *parsedOpcode, vm *Engine) error {
|
||||||
switch op.opcode.value {
|
switch op.opcode.value {
|
||||||
case OP_NOP1, OP_NOP3, OP_NOP4, OP_NOP5,
|
case OP_NOP1, OP_NOP4, OP_NOP5,
|
||||||
OP_NOP6, OP_NOP7, OP_NOP8, OP_NOP9, OP_NOP10:
|
OP_NOP6, OP_NOP7, OP_NOP8, OP_NOP9, OP_NOP10:
|
||||||
if vm.hasFlag(ScriptDiscourageUpgradableNops) {
|
if vm.hasFlag(ScriptDiscourageUpgradableNops) {
|
||||||
return fmt.Errorf("OP_NOP%d reserved for soft-fork "+
|
return fmt.Errorf("OP_NOP%d reserved for soft-fork "+
|
||||||
|
@ -1009,6 +1010,25 @@ func opcodeReturn(op *parsedOpcode, vm *Engine) error {
|
||||||
return ErrStackEarlyReturn
|
return ErrStackEarlyReturn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// verifyLockTime is a helper function used to validate locktimes.
|
||||||
|
func verifyLockTime(txLockTime, threshold, lockTime int64) error {
|
||||||
|
// The lockTimes in both the script and transaction must be of the same
|
||||||
|
// type.
|
||||||
|
if !((txLockTime < threshold && lockTime < threshold) ||
|
||||||
|
(txLockTime >= threshold && lockTime >= threshold)) {
|
||||||
|
return fmt.Errorf("mismatched locktime types -- tx locktime %d, stack "+
|
||||||
|
"locktime %d", txLockTime, lockTime)
|
||||||
|
}
|
||||||
|
|
||||||
|
if lockTime > txLockTime {
|
||||||
|
str := "locktime requirement not satisfied -- locktime is " +
|
||||||
|
"greater than the transaction locktime: %d > %d"
|
||||||
|
return fmt.Errorf(str, lockTime, txLockTime)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// opcodeCheckLockTimeVerify compares the top item on the data stack to the
|
// opcodeCheckLockTimeVerify compares the top item on the data stack to the
|
||||||
// LockTime field of the transaction containing the script signature
|
// LockTime field of the transaction containing the script signature
|
||||||
// validating if the transaction outputs are spendable yet. If flag
|
// validating if the transaction outputs are spendable yet. If flag
|
||||||
|
@ -1043,8 +1063,9 @@ func opcodeCheckLockTimeVerify(op *parsedOpcode, vm *Engine) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// In the rare event that the argument may be < 0 due to some arithmetic
|
// In the rare event that the argument needs to be < 0 due to some
|
||||||
// being done first, you can always use 0 OP_MAX OP_CHECKLOCKTIMEVERIFY.
|
// arithmetic being done first, you can always use
|
||||||
|
// 0 OP_MAX OP_CHECKLOCKTIMEVERIFY.
|
||||||
if lockTime < 0 {
|
if lockTime < 0 {
|
||||||
return fmt.Errorf("negative locktime: %d", lockTime)
|
return fmt.Errorf("negative locktime: %d", lockTime)
|
||||||
}
|
}
|
||||||
|
@ -1053,19 +1074,10 @@ func opcodeCheckLockTimeVerify(op *parsedOpcode, vm *Engine) error {
|
||||||
// which the transaction is finalized or a timestamp depending on if the
|
// which the transaction is finalized or a timestamp depending on if the
|
||||||
// value is before the txscript.LockTimeThreshold. When it is under the
|
// value is before the txscript.LockTimeThreshold. When it is under the
|
||||||
// threshold it is a block height.
|
// threshold it is a block height.
|
||||||
//
|
err = verifyLockTime(int64(vm.tx.LockTime), LockTimeThreshold,
|
||||||
// The lockTimes in both the script and transaction must be of the same
|
int64(lockTime))
|
||||||
// type.
|
if err != nil {
|
||||||
if !((vm.tx.LockTime < LockTimeThreshold && int64(lockTime) < int64(LockTimeThreshold)) ||
|
return err
|
||||||
(vm.tx.LockTime >= LockTimeThreshold && int64(lockTime) >= int64(LockTimeThreshold))) {
|
|
||||||
return fmt.Errorf("mismatched locktime types -- tx locktime %d, stack "+
|
|
||||||
"locktime %d", vm.tx.LockTime, lockTime)
|
|
||||||
}
|
|
||||||
|
|
||||||
if int64(lockTime) > int64(vm.tx.LockTime) {
|
|
||||||
str := "locktime requirement not satisfied -- locktime is " +
|
|
||||||
"greater than the transaction locktime: %d > %d"
|
|
||||||
return fmt.Errorf(str, lockTime, vm.tx.LockTime)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The lock time feature can also be disabled, thereby bypassing
|
// The lock time feature can also be disabled, thereby bypassing
|
||||||
|
@ -1089,6 +1101,84 @@ func opcodeCheckLockTimeVerify(op *parsedOpcode, vm *Engine) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// opcodeCheckSequenceVerify compares the top item on the data stack to the
|
||||||
|
// LockTime field of the transaction containing the script signature
|
||||||
|
// validating if the transaction outputs are spendable yet. If flag
|
||||||
|
// ScriptVerifyCheckSequenceVerify is not set, the code continues as if OP_NOP3
|
||||||
|
// were executed.
|
||||||
|
func opcodeCheckSequenceVerify(op *parsedOpcode, vm *Engine) error {
|
||||||
|
// If the ScriptVerifyCheckSequenceVerify script flag is not set, treat
|
||||||
|
// opcode as OP_NOP3 instead.
|
||||||
|
if !vm.hasFlag(ScriptVerifyCheckSequenceVerify) {
|
||||||
|
if vm.hasFlag(ScriptDiscourageUpgradableNops) {
|
||||||
|
return errors.New("OP_NOP3 reserved for soft-fork " +
|
||||||
|
"upgrades")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if vm.tx.Version < 2 {
|
||||||
|
return fmt.Errorf("invalid transaction version: %d",
|
||||||
|
vm.tx.Version)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The current transaction sequence is a uint32 resulting in a maximum
|
||||||
|
// sequence of 2^32-1. However, scriptNums are signed and therefore a
|
||||||
|
// standard 4-byte scriptNum would only support up to a maximum of
|
||||||
|
// 2^31-1. Thus, a 5-byte scriptNum is used here since it will support
|
||||||
|
// up to 2^39-1 which allows sequences beyond the current sequence
|
||||||
|
// limit.
|
||||||
|
//
|
||||||
|
// PeekByteArray is used here instead of PeekInt because we do not want
|
||||||
|
// to be limited to a 4-byte integer for reasons specified above.
|
||||||
|
so, err := vm.dstack.PeekByteArray(0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
stackSequence, err := makeScriptNum(so, vm.dstack.verifyMinimalData, 5)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// In the rare event that the argument needs to be < 0 due to some
|
||||||
|
// arithmetic being done first, you can always use
|
||||||
|
// 0 OP_MAX OP_CHECKSEQUENCEVERIFY.
|
||||||
|
if stackSequence < 0 {
|
||||||
|
return fmt.Errorf("negative sequence: %d", stackSequence)
|
||||||
|
}
|
||||||
|
|
||||||
|
sequence := int64(stackSequence)
|
||||||
|
|
||||||
|
// To provide for future soft-fork extensibility, if the
|
||||||
|
// operand has the disabled lock-time flag set,
|
||||||
|
// CHECKSEQUENCEVERIFY behaves as a NOP.
|
||||||
|
if sequence&int64(wire.SequenceLockTimeDisabled) != 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sequence numbers with their most significant bit set are not
|
||||||
|
// consensus constrained. Testing that the transaction's sequence
|
||||||
|
// number does not have this bit set prevents using this property
|
||||||
|
// to get around a CHECKSEQUENCEVERIFY check.
|
||||||
|
txSequence := int64(vm.tx.TxIn[vm.txIdx].Sequence)
|
||||||
|
if txSequence&int64(wire.SequenceLockTimeDisabled) != 0 {
|
||||||
|
return fmt.Errorf("transaction sequence has sequence "+
|
||||||
|
"locktime disabled bit set: 0x%x", txSequence)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mask off non-consensus bits before doing comparisons.
|
||||||
|
lockTimeMask := int64(wire.SequenceLockTimeIsSeconds |
|
||||||
|
wire.SequenceLockTimeMask)
|
||||||
|
err = verifyLockTime(txSequence&lockTimeMask,
|
||||||
|
wire.SequenceLockTimeIsSeconds,
|
||||||
|
sequence&lockTimeMask)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// opcodeToAltStack removes the top item from the main data stack and pushes it
|
// opcodeToAltStack removes the top item from the main data stack and pushes it
|
||||||
// onto the alternate data stack.
|
// onto the alternate data stack.
|
||||||
//
|
//
|
||||||
|
@ -2201,4 +2291,5 @@ func init() {
|
||||||
OpcodeByName["OP_FALSE"] = OP_FALSE
|
OpcodeByName["OP_FALSE"] = OP_FALSE
|
||||||
OpcodeByName["OP_TRUE"] = OP_TRUE
|
OpcodeByName["OP_TRUE"] = OP_TRUE
|
||||||
OpcodeByName["OP_NOP2"] = OP_CHECKLOCKTIMEVERIFY
|
OpcodeByName["OP_NOP2"] = OP_CHECKLOCKTIMEVERIFY
|
||||||
|
OpcodeByName["OP_NOP3"] = OP_CHECKSEQUENCEVERIFY
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2013-2015 The btcsuite developers
|
// Copyright (c) 2013-2016 The btcsuite developers
|
||||||
// Use of this source code is governed by an ISC
|
// Use of this source code is governed by an ISC
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
@ -109,10 +109,14 @@ func TestOpcodeDisasm(t *testing.T) {
|
||||||
|
|
||||||
// OP_NOP1 through OP_NOP10.
|
// OP_NOP1 through OP_NOP10.
|
||||||
case opcodeVal >= 0xb0 && opcodeVal <= 0xb9:
|
case opcodeVal >= 0xb0 && opcodeVal <= 0xb9:
|
||||||
// OP_NOP2 is an alias of OP_CHECKLOCKTIMEVERIFY
|
switch opcodeVal {
|
||||||
if opcodeVal == 0xb1 {
|
case 0xb1:
|
||||||
|
// OP_NOP2 is an alias of OP_CHECKLOCKTIMEVERIFY
|
||||||
expectedStr = "OP_CHECKLOCKTIMEVERIFY"
|
expectedStr = "OP_CHECKLOCKTIMEVERIFY"
|
||||||
} else {
|
case 0xb2:
|
||||||
|
// OP_NOP3 is an alias of OP_CHECKSEQUENCEVERIFY
|
||||||
|
expectedStr = "OP_CHECKSEQUENCEVERIFY"
|
||||||
|
default:
|
||||||
val := byte(opcodeVal - (0xb0 - 1))
|
val := byte(opcodeVal - (0xb0 - 1))
|
||||||
expectedStr = "OP_NOP" + strconv.Itoa(int(val))
|
expectedStr = "OP_NOP" + strconv.Itoa(int(val))
|
||||||
}
|
}
|
||||||
|
@ -171,10 +175,14 @@ func TestOpcodeDisasm(t *testing.T) {
|
||||||
|
|
||||||
// OP_NOP1 through OP_NOP10.
|
// OP_NOP1 through OP_NOP10.
|
||||||
case opcodeVal >= 0xb0 && opcodeVal <= 0xb9:
|
case opcodeVal >= 0xb0 && opcodeVal <= 0xb9:
|
||||||
// OP_NOP2 is an alias of OP_CHECKLOCKTIMEVERIFY
|
switch opcodeVal {
|
||||||
if opcodeVal == 0xb1 {
|
case 0xb1:
|
||||||
|
// OP_NOP2 is an alias of OP_CHECKLOCKTIMEVERIFY
|
||||||
expectedStr = "OP_CHECKLOCKTIMEVERIFY"
|
expectedStr = "OP_CHECKLOCKTIMEVERIFY"
|
||||||
} else {
|
case 0xb2:
|
||||||
|
// OP_NOP3 is an alias of OP_CHECKSEQUENCEVERIFY
|
||||||
|
expectedStr = "OP_CHECKSEQUENCEVERIFY"
|
||||||
|
default:
|
||||||
val := byte(opcodeVal - (0xb0 - 1))
|
val := byte(opcodeVal - (0xb0 - 1))
|
||||||
expectedStr = "OP_NOP" + strconv.Itoa(int(val))
|
expectedStr = "OP_NOP" + strconv.Itoa(int(val))
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,6 +128,8 @@ func parseScriptFlags(flagStr string) (ScriptFlags, error) {
|
||||||
// Nothing.
|
// Nothing.
|
||||||
case "CHECKLOCKTIMEVERIFY":
|
case "CHECKLOCKTIMEVERIFY":
|
||||||
flags |= ScriptVerifyCheckLockTimeVerify
|
flags |= ScriptVerifyCheckLockTimeVerify
|
||||||
|
case "CHECKSEQUENCEVERIFY":
|
||||||
|
flags |= ScriptVerifyCheckSequenceVerify
|
||||||
case "CLEANSTACK":
|
case "CLEANSTACK":
|
||||||
flags |= ScriptVerifyCleanStack
|
flags |= ScriptVerifyCleanStack
|
||||||
case "DERSIG":
|
case "DERSIG":
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2013-2015 The btcsuite developers
|
// Copyright (c) 2013-2016 The btcsuite developers
|
||||||
// Use of this source code is governed by an ISC
|
// Use of this source code is governed by an ISC
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@ const (
|
||||||
ScriptDiscourageUpgradableNops |
|
ScriptDiscourageUpgradableNops |
|
||||||
ScriptVerifyCleanStack |
|
ScriptVerifyCleanStack |
|
||||||
ScriptVerifyCheckLockTimeVerify |
|
ScriptVerifyCheckLockTimeVerify |
|
||||||
|
ScriptVerifyCheckSequenceVerify |
|
||||||
ScriptVerifyLowS
|
ScriptVerifyLowS
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -24,14 +24,26 @@ const (
|
||||||
// MaxPrevOutIndex is the maximum index the index field of a previous
|
// MaxPrevOutIndex is the maximum index the index field of a previous
|
||||||
// outpoint can be.
|
// outpoint can be.
|
||||||
MaxPrevOutIndex uint32 = 0xffffffff
|
MaxPrevOutIndex uint32 = 0xffffffff
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
// SequenceLockTimeDisabled is a flag that if set on a transaction
|
||||||
// defaultTxInOutAlloc is the default size used for the backing array
|
// input's sequence number, the sequence number will not be interpreted
|
||||||
// for transaction inputs and outputs. The array will dynamically grow
|
// as a relative locktime.
|
||||||
// as needed, but this figure is intended to provide enough space for
|
SequenceLockTimeDisabled = 1 << 31
|
||||||
// the number of inputs and outputs in a typical transaction without
|
|
||||||
// needing to grow the backing array multiple times.
|
// SequenceLockTimeIsSeconds is a flag that if set on a transaction
|
||||||
|
// input's sequence number, the relative locktime has units of 512
|
||||||
|
// seconds.
|
||||||
|
SequenceLockTimeIsSeconds = 1 << 22
|
||||||
|
|
||||||
|
// SequenceLockTimeMask is a mask that extracts the relative locktime
|
||||||
|
// when masked against the transaction input sequence number.
|
||||||
|
SequenceLockTimeMask = 0x0000ffff
|
||||||
|
|
||||||
|
// defaultTxInOutAlloc is the default size used for the backing array for
|
||||||
|
// transaction inputs and outputs. The array will dynamically grow as needed,
|
||||||
|
// but this figure is intended to provide enough space for the number of
|
||||||
|
// inputs and outputs in a typical transaction without needing to grow the
|
||||||
|
// backing array multiple times.
|
||||||
defaultTxInOutAlloc = 15
|
defaultTxInOutAlloc = 15
|
||||||
|
|
||||||
// minTxInPayload is the minimum payload size for a transaction input.
|
// minTxInPayload is the minimum payload size for a transaction input.
|
||||||
|
|
Loading…
Reference in a new issue