Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

txscript: Implement CheckLockTimeVerify (BIP0065) #459

Merged
merged 1 commit into from
Oct 14, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions txscript/data/tx_invalid.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
]
42 changes: 42 additions & 0 deletions txscript/data/tx_valid.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
]
5 changes: 5 additions & 0 deletions txscript/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
112 changes: 98 additions & 14 deletions txscript/opcode.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"bytes"
"crypto/sha1"
"encoding/binary"
"errors"
"fmt"
"hash"

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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},
Expand Down Expand Up @@ -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},
Expand Down Expand Up @@ -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 "+
Expand Down Expand Up @@ -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.
//
Expand Down Expand Up @@ -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
}
18 changes: 14 additions & 4 deletions txscript/opcode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand Down
Loading