mirror of
https://github.com/btcsuite/btcd.git
synced 2024-11-19 01:40:07 +01:00
txscript: Implement CheckLockTimeVerify (BIP0065)
See https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki for more information. This commit mimics Bitcoin Core commit bc60b2b4b401f0adff5b8b9678903ff8feb5867b and includes additional tests from Bitcoin Core commit cb54d17355864fa08826d6511a0d7692b21ef2c9
This commit is contained in:
parent
0f57a41ed8
commit
4c3ad4987b
@ -114,6 +114,78 @@
|
||||
[[["a955032f4d6b0c9bfe8cad8f00a8933790b9c1dc28c82e0f48e75b35da0e4944", 0, "IF CODESEPARATOR ENDIF 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 CHECKSIGVERIFY CODESEPARATOR 1"]],
|
||||
"010000000144490eda355be7480f2ec828dcc1b9903793a8008fad8cfe9b0c6b4d2f0355a9000000004a483045022100fa4a74ba9fd59c59f46c3960cf90cbe0d2b743c471d24a3d5d6db6002af5eebb02204d70ec490fd0f7055a7c45f86514336e3a7f03503dacecabb247fc23f15c83510100ffffffff010000000000000000016a00000000", "P2SH"],
|
||||
|
||||
["CHECKLOCKTIMEVERIFY tests"],
|
||||
|
||||
["By-height locks, with argument just beyond tx nLockTime"],
|
||||
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "1 NOP2 1"]],
|
||||
"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"],
|
||||
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "499999999 NOP2 1"]],
|
||||
"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000fe64cd1d", "P2SH,CHECKLOCKTIMEVERIFY"],
|
||||
|
||||
["By-time locks, with argument just beyond tx nLockTime (but within numerical boundaries)"],
|
||||
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "500000001 NOP2 1"]],
|
||||
"01000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000065cd1d", "P2SH,CHECKLOCKTIMEVERIFY"],
|
||||
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 NOP2 1"]],
|
||||
"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000feffffff", "P2SH,CHECKLOCKTIMEVERIFY"],
|
||||
|
||||
["Argument missing"],
|
||||
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "NOP2 1"]],
|
||||
"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"],
|
||||
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "1"]],
|
||||
"010000000100010000000000000000000000000000000000000000000000000000000000000000000001b1010000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"],
|
||||
|
||||
["Argument negative with by-blockheight nLockTime=0"],
|
||||
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "-1 NOP2 1"]],
|
||||
"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"],
|
||||
|
||||
["Argument negative with by-blocktime nLockTime=500,000,000"],
|
||||
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "-1 NOP2 1"]],
|
||||
"01000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000065cd1d", "P2SH,CHECKLOCKTIMEVERIFY"],
|
||||
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "1"]],
|
||||
"010000000100010000000000000000000000000000000000000000000000000000000000000000000004005194b1010000000100000000000000000002000000", "P2SH,CHECKLOCKTIMEVERIFY"],
|
||||
|
||||
["Input locked"],
|
||||
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 NOP2 1"]],
|
||||
"010000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"],
|
||||
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0"]],
|
||||
"01000000010001000000000000000000000000000000000000000000000000000000000000000000000251b1ffffffff0100000000000000000002000000", "P2SH,CHECKLOCKTIMEVERIFY"],
|
||||
|
||||
["Another input being unlocked isn't sufficient; the CHECKLOCKTIMEVERIFY-using input must be unlocked"],
|
||||
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 NOP2 1"] ,
|
||||
["0000000000000000000000000000000000000000000000000000000000000200", 1, "1"]],
|
||||
"010000000200010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00020000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"],
|
||||
|
||||
["Argument/tx height/time mismatch, both versions"],
|
||||
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 NOP2 1"]],
|
||||
"01000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000065cd1d", "P2SH,CHECKLOCKTIMEVERIFY"],
|
||||
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0"]],
|
||||
"01000000010001000000000000000000000000000000000000000000000000000000000000000000000251b100000000010000000000000000000065cd1d", "P2SH,CHECKLOCKTIMEVERIFY"],
|
||||
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "499999999 NOP2 1"]],
|
||||
"01000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000065cd1d", "P2SH,CHECKLOCKTIMEVERIFY"],
|
||||
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "500000000 NOP2 1"]],
|
||||
"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"],
|
||||
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "500000000 NOP2 1"]],
|
||||
"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ff64cd1d", "P2SH,CHECKLOCKTIMEVERIFY"],
|
||||
|
||||
["Argument 2^32 with nLockTime=2^32-1"],
|
||||
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967296 NOP2 1"]],
|
||||
"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ffffffff", "P2SH,CHECKLOCKTIMEVERIFY"],
|
||||
|
||||
["Same, but with nLockTime=2^31-1"],
|
||||
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 NOP2 1"]],
|
||||
"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ffffff7f", "P2SH,CHECKLOCKTIMEVERIFY"],
|
||||
|
||||
["6 byte non-minimally-encoded arguments are invalid even if their contents are valid"],
|
||||
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x06 0x000000000000 NOP2 1"]],
|
||||
"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"],
|
||||
|
||||
["Failure due to failing CHECKLOCKTIMEVERIFY in scriptSig"],
|
||||
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "1"]],
|
||||
"01000000010001000000000000000000000000000000000000000000000000000000000000000000000251b1000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"],
|
||||
|
||||
["Failure due to failing CHECKLOCKTIMEVERIFY in redeemScript"],
|
||||
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xc5b93064159b3b2d6ab506a41b1f50463771b988 EQUAL"]],
|
||||
"0100000001000100000000000000000000000000000000000000000000000000000000000000000000030251b1000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"],
|
||||
|
||||
["Make diffs cleaner by leaving a comment here without comma at the end"]
|
||||
]
|
||||
|
@ -187,5 +187,47 @@
|
||||
"0100000002dbb33bdf185b17f758af243c5d3c6e164cc873f6bb9f40c0677d6e0f8ee5afce000000006b4830450221009627444320dc5ef8d7f68f35010b4c050a6ed0d96b67a84db99fda9c9de58b1e02203e4b4aaa019e012e65d69b487fdf8719df72f488fa91506a80c49a33929f1fd50121022b78b756e2258af13779c1a1f37ea6800259716ca4b7f0b87610e0bf3ab52a01ffffffffdbb33bdf185b17f758af243c5d3c6e164cc873f6bb9f40c0677d6e0f8ee5afce010000009300483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303ffffffff01a0860100000000001976a9149bc0bbdd3024da4d0c38ed1aecf5c68dd1d3fa1288ac00000000", "P2SH"],
|
||||
|
||||
|
||||
["CHECKLOCKTIMEVERIFY tests"],
|
||||
|
||||
["By-height locks, with argument == 0 and == tx nLockTime"],
|
||||
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 NOP2 1"]],
|
||||
"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"],
|
||||
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "499999999 NOP2 1"]],
|
||||
"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ff64cd1d", "P2SH,CHECKLOCKTIMEVERIFY"],
|
||||
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 NOP2 1"]],
|
||||
"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ff64cd1d", "P2SH,CHECKLOCKTIMEVERIFY"],
|
||||
|
||||
["By-time locks, with argument just beyond tx nLockTime (but within numerical boundaries)"],
|
||||
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "500000000 NOP2 1"]],
|
||||
"01000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000065cd1d", "P2SH,CHECKLOCKTIMEVERIFY"],
|
||||
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 NOP2 1"]],
|
||||
"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ffffffff", "P2SH,CHECKLOCKTIMEVERIFY"],
|
||||
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "500000000 NOP2 1"]],
|
||||
"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ffffffff", "P2SH,CHECKLOCKTIMEVERIFY"],
|
||||
|
||||
["Any non-maxint nSequence is fine"],
|
||||
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 NOP2 1"]],
|
||||
"010000000100010000000000000000000000000000000000000000000000000000000000000000000000feffffff0100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"],
|
||||
|
||||
["The argument can be calculated rather than created directly by a PUSHDATA"],
|
||||
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "499999999 1ADD NOP2 1"]],
|
||||
"01000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000065cd1d", "P2SH,CHECKLOCKTIMEVERIFY"],
|
||||
|
||||
["Perhaps even by an ADD producing a 5-byte result that is out of bounds for other opcodes"],
|
||||
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483647 2147483647 ADD NOP2 1"]],
|
||||
"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000feffffff", "P2SH,CHECKLOCKTIMEVERIFY"],
|
||||
|
||||
["5 byte non-minimally-encoded arguments are valid"],
|
||||
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x05 0x0000000000 NOP2 1"]],
|
||||
"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"],
|
||||
|
||||
["Valid CHECKLOCKTIMEVERIFY in scriptSig"],
|
||||
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "1"]],
|
||||
"01000000010001000000000000000000000000000000000000000000000000000000000000000000000251b1000000000100000000000000000001000000", "P2SH,CHECKLOCKTIMEVERIFY"],
|
||||
|
||||
["Valid CHECKLOCKTIMEVERIFY in redeemScript"],
|
||||
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xc5b93064159b3b2d6ab506a41b1f50463771b988 EQUAL"]],
|
||||
"0100000001000100000000000000000000000000000000000000000000000000000000000000000000030251b1000000000100000000000000000001000000", "P2SH,CHECKLOCKTIMEVERIFY"],
|
||||
|
||||
["Make diffs cleaner by leaving a comment here without comma at the end"]
|
||||
]
|
||||
|
@ -33,6 +33,11 @@ const (
|
||||
// executed.
|
||||
ScriptDiscourageUpgradableNops
|
||||
|
||||
// ScriptVerifyCheckLockTimeVerify defines whether to verify that
|
||||
// a transaction output is spendable based on the locktime.
|
||||
// This is BIP0065.
|
||||
ScriptVerifyCheckLockTimeVerify
|
||||
|
||||
// ScriptVerifyCleanStack defines that the stack must contain only
|
||||
// one stack element after evaluation and that the element must be
|
||||
// true if interpreted as a boolean. This is rule 6 of BIP0062.
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"bytes"
|
||||
"crypto/sha1"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"hash"
|
||||
|
||||
@ -212,6 +213,7 @@ const (
|
||||
OP_CHECKMULTISIGVERIFY = 0xaf // 175
|
||||
OP_NOP1 = 0xb0 // 176
|
||||
OP_NOP2 = 0xb1 // 177
|
||||
OP_CHECKLOCKTIMEVERIFY = 0xb1 // 177 - AKA OP_NOP2
|
||||
OP_NOP3 = 0xb2 // 178
|
||||
OP_NOP4 = 0xb3 // 179
|
||||
OP_NOP5 = 0xb4 // 180
|
||||
@ -403,16 +405,17 @@ var opcodeArray = [256]opcode{
|
||||
OP_16: {OP_16, "OP_16", 1, opcodeN},
|
||||
|
||||
// Control opcodes.
|
||||
OP_NOP: {OP_NOP, "OP_NOP", 1, opcodeNop},
|
||||
OP_VER: {OP_VER, "OP_VER", 1, opcodeReserved},
|
||||
OP_IF: {OP_IF, "OP_IF", 1, opcodeIf},
|
||||
OP_NOTIF: {OP_NOTIF, "OP_NOTIF", 1, opcodeNotIf},
|
||||
OP_VERIF: {OP_VERIF, "OP_VERIF", 1, opcodeReserved},
|
||||
OP_VERNOTIF: {OP_VERNOTIF, "OP_VERNOTIF", 1, opcodeReserved},
|
||||
OP_ELSE: {OP_ELSE, "OP_ELSE", 1, opcodeElse},
|
||||
OP_ENDIF: {OP_ENDIF, "OP_ENDIF", 1, opcodeEndif},
|
||||
OP_VERIFY: {OP_VERIFY, "OP_VERIFY", 1, opcodeVerify},
|
||||
OP_RETURN: {OP_RETURN, "OP_RETURN", 1, opcodeReturn},
|
||||
OP_NOP: {OP_NOP, "OP_NOP", 1, opcodeNop},
|
||||
OP_VER: {OP_VER, "OP_VER", 1, opcodeReserved},
|
||||
OP_IF: {OP_IF, "OP_IF", 1, opcodeIf},
|
||||
OP_NOTIF: {OP_NOTIF, "OP_NOTIF", 1, opcodeNotIf},
|
||||
OP_VERIF: {OP_VERIF, "OP_VERIF", 1, opcodeReserved},
|
||||
OP_VERNOTIF: {OP_VERNOTIF, "OP_VERNOTIF", 1, opcodeReserved},
|
||||
OP_ELSE: {OP_ELSE, "OP_ELSE", 1, opcodeElse},
|
||||
OP_ENDIF: {OP_ENDIF, "OP_ENDIF", 1, opcodeEndif},
|
||||
OP_VERIFY: {OP_VERIFY, "OP_VERIFY", 1, opcodeVerify},
|
||||
OP_RETURN: {OP_RETURN, "OP_RETURN", 1, opcodeReturn},
|
||||
OP_CHECKLOCKTIMEVERIFY: {OP_CHECKLOCKTIMEVERIFY, "OP_CHECKLOCKTIMEVERIFY", 1, opcodeCheckLockTimeVerify},
|
||||
|
||||
// Stack opcodes.
|
||||
OP_TOALTSTACK: {OP_TOALTSTACK, "OP_TOALTSTACK", 1, opcodeToAltStack},
|
||||
@ -495,7 +498,6 @@ var opcodeArray = [256]opcode{
|
||||
|
||||
// Reserved opcodes.
|
||||
OP_NOP1: {OP_NOP1, "OP_NOP1", 1, opcodeNop},
|
||||
OP_NOP2: {OP_NOP2, "OP_NOP2", 1, opcodeNop},
|
||||
OP_NOP3: {OP_NOP3, "OP_NOP3", 1, opcodeNop},
|
||||
OP_NOP4: {OP_NOP4, "OP_NOP4", 1, opcodeNop},
|
||||
OP_NOP5: {OP_NOP5, "OP_NOP5", 1, opcodeNop},
|
||||
@ -873,7 +875,7 @@ func opcodeN(op *parsedOpcode, vm *Engine) error {
|
||||
// the flag to discourage use of NOPs is set for select opcodes.
|
||||
func opcodeNop(op *parsedOpcode, vm *Engine) error {
|
||||
switch op.opcode.value {
|
||||
case OP_NOP1, OP_NOP2, OP_NOP3, OP_NOP4, OP_NOP5,
|
||||
case OP_NOP1, OP_NOP3, OP_NOP4, OP_NOP5,
|
||||
OP_NOP6, OP_NOP7, OP_NOP8, OP_NOP9, OP_NOP10:
|
||||
if vm.hasFlag(ScriptDiscourageUpgradableNops) {
|
||||
return fmt.Errorf("OP_NOP%d reserved for soft-fork "+
|
||||
@ -1006,6 +1008,86 @@ func opcodeReturn(op *parsedOpcode, vm *Engine) error {
|
||||
return ErrStackEarlyReturn
|
||||
}
|
||||
|
||||
// opcodeCheckLockTimeVerify 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
|
||||
// ScriptVerifyCheckLockTimeVerify is not set, the code continues as if OP_NOP2
|
||||
// were executed.
|
||||
func opcodeCheckLockTimeVerify(op *parsedOpcode, vm *Engine) error {
|
||||
// If the ScriptVerifyCheckLockTimeVerify script flag is not set, treat
|
||||
// opcode as OP_NOP2 instead.
|
||||
if !vm.hasFlag(ScriptVerifyCheckLockTimeVerify) {
|
||||
if vm.hasFlag(ScriptDiscourageUpgradableNops) {
|
||||
return errors.New("OP_NOP2 reserved for soft-fork " +
|
||||
"upgrades")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// The current transaction locktime is a uint32 resulting in a maximum
|
||||
// locktime of 2^32-1 (the year 2106). However, scriptNums are signed
|
||||
// and therefore a standard 4-byte scriptNum would only support up to a
|
||||
// maximum of 2^31-1 (the year 2038). Thus, a 5-byte scriptNum is used
|
||||
// here since it will support up to 2^39-1 which allows dates beyond the
|
||||
// current locktime 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
|
||||
}
|
||||
lockTime, err := makeScriptNum(so, vm.dstack.verifyMinimalData, 5)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// In the rare event that the argument may be < 0 due to some arithmetic
|
||||
// being done first, you can always use 0 OP_MAX OP_CHECKLOCKTIMEVERIFY.
|
||||
if lockTime < 0 {
|
||||
return fmt.Errorf("negative locktime: %d", lockTime)
|
||||
}
|
||||
|
||||
// The lock time field of a transaction is either a block height at
|
||||
// which the transaction is finalized or a timestamp depending on if the
|
||||
// value is before the txscript.LockTimeThreshold. When it is under the
|
||||
// threshold it is a block height.
|
||||
//
|
||||
// The lockTimes in both the script and transaction must be of the same
|
||||
// type.
|
||||
if !((vm.tx.LockTime < LockTimeThreshold && int64(lockTime) < int64(LockTimeThreshold)) ||
|
||||
(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
|
||||
// OP_CHECKLOCKTIMEVERIFY, if every transaction input has been finalized by
|
||||
// setting its sequence to the maximum value (wire.MaxTxInSequenceNum). This
|
||||
// condition would result in the transaction being allowed into the blockchain
|
||||
// making the opcode ineffective.
|
||||
//
|
||||
// This condition is prevented by enforcing that the input being used by
|
||||
// the opcode is unlocked (its sequence number is less than the max
|
||||
// value). This is sufficient to prove correctness without having to
|
||||
// check every input.
|
||||
//
|
||||
// NOTE: This implies that even if the transaction is not finalized due to
|
||||
// another input being unlocked, the opcode execution will still fail when the
|
||||
// input being used by the opcode is locked.
|
||||
if vm.tx.TxIn[vm.txIdx].Sequence == wire.MaxTxInSequenceNum {
|
||||
return errors.New("transaction input is finalized")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// opcodeToAltStack removes the top item from the main data stack and pushes it
|
||||
// onto the alternate data stack.
|
||||
//
|
||||
@ -2109,11 +2191,13 @@ var OpcodeByName = make(map[string]byte)
|
||||
|
||||
func init() {
|
||||
// Initialize the opcode name to value map using the contents of the
|
||||
// opcode array. Also add entries for "OP_FALSE" and "OP_TRUE" since
|
||||
// they are aliases for "OP_0" and "OP_1", respectively.
|
||||
// opcode array. Also add entries for "OP_FALSE", "OP_TRUE", and
|
||||
// "OP_NOP2" since they are aliases for "OP_0", "OP_1",
|
||||
// and "OP_CHECKLOCKTIMEVERIFY" respectively.
|
||||
for _, op := range opcodeArray {
|
||||
OpcodeByName[op.name] = op.value
|
||||
}
|
||||
OpcodeByName["OP_FALSE"] = OP_FALSE
|
||||
OpcodeByName["OP_TRUE"] = OP_TRUE
|
||||
OpcodeByName["OP_NOP2"] = OP_CHECKLOCKTIMEVERIFY
|
||||
}
|
||||
|
@ -109,8 +109,13 @@ func TestOpcodeDisasm(t *testing.T) {
|
||||
|
||||
// OP_NOP1 through OP_NOP10.
|
||||
case opcodeVal >= 0xb0 && opcodeVal <= 0xb9:
|
||||
val := byte(opcodeVal - (0xb0 - 1))
|
||||
expectedStr = "OP_NOP" + strconv.Itoa(int(val))
|
||||
// OP_NOP2 is an alias of OP_CHECKLOCKTIMEVERIFY
|
||||
if opcodeVal == 0xb1 {
|
||||
expectedStr = "OP_CHECKLOCKTIMEVERIFY"
|
||||
} else {
|
||||
val := byte(opcodeVal - (0xb0 - 1))
|
||||
expectedStr = "OP_NOP" + strconv.Itoa(int(val))
|
||||
}
|
||||
|
||||
// OP_UNKNOWN#.
|
||||
case opcodeVal >= 0xba && opcodeVal <= 0xf8 || opcodeVal == 0xfc:
|
||||
@ -166,8 +171,13 @@ func TestOpcodeDisasm(t *testing.T) {
|
||||
|
||||
// OP_NOP1 through OP_NOP10.
|
||||
case opcodeVal >= 0xb0 && opcodeVal <= 0xb9:
|
||||
val := byte(opcodeVal - (0xb0 - 1))
|
||||
expectedStr = "OP_NOP" + strconv.Itoa(int(val))
|
||||
// OP_NOP2 is an alias of OP_CHECKLOCKTIMEVERIFY
|
||||
if opcodeVal == 0xb1 {
|
||||
expectedStr = "OP_CHECKLOCKTIMEVERIFY"
|
||||
} else {
|
||||
val := byte(opcodeVal - (0xb0 - 1))
|
||||
expectedStr = "OP_NOP" + strconv.Itoa(int(val))
|
||||
}
|
||||
|
||||
// OP_UNKNOWN#.
|
||||
case opcodeVal >= 0xba && opcodeVal <= 0xf8 || opcodeVal == 0xfc:
|
||||
|
@ -124,6 +124,8 @@ func parseScriptFlags(flagStr string) (ScriptFlags, error) {
|
||||
switch flag {
|
||||
case "":
|
||||
// Nothing.
|
||||
case "CHECKLOCKTIMEVERIFY":
|
||||
flags |= ScriptVerifyCheckLockTimeVerify
|
||||
case "CLEANSTACK":
|
||||
flags |= ScriptVerifyCleanStack
|
||||
case "DERSIG":
|
||||
|
@ -31,6 +31,7 @@ const (
|
||||
ScriptStrictMultiSig |
|
||||
ScriptDiscourageUpgradableNops |
|
||||
ScriptVerifyCleanStack |
|
||||
ScriptVerifyCheckLockTimeVerify |
|
||||
ScriptVerifyLowS
|
||||
)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user