WIP: next hard fork #5

Draft
BrannonKing wants to merge 178 commits from WIP-HF-2022 into master
3 changed files with 90 additions and 100 deletions
Showing only changes of commit b95ba0ac95 - Show all commits

View file

@ -385,8 +385,7 @@ func (vm *Engine) executeOpcode(op *opcode, data []byte) error {
}
}
pop := parsedOpcode{opcode: op, data: data}
return op.opfunc(&pop, vm)
return op.opfunc(op, data, vm)
}
// checkValidPC returns an error if the current script position is not valid for

View file

@ -28,7 +28,7 @@ type opcode struct {
value byte
name string
length int
opfunc func(*parsedOpcode, *Engine) error
opfunc func(*opcode, []byte, *Engine) error
}
// These constants are the values of the official opcodes used on the btc wiki,
@ -611,13 +611,6 @@ var opcodeOnelineRepls = map[string]string{
"OP_16": "16",
}
// parsedOpcode represents an opcode that has been parsed and includes any
// potential data associated with it.
type parsedOpcode struct {
opcode *opcode
data []byte
}
// disasmOpcode writes a human-readable disassembly of the provided opcode and
// data into the provided buffer. The compact flag indicates the disassembly
// should print a more compact representation of data-carrying and small integer
@ -676,45 +669,42 @@ func disasmOpcode(buf *strings.Builder, op *opcode, data []byte, compact bool) {
// opcodes before executing in an initial parse step, the consensus rules
// dictate the script doesn't fail until the program counter passes over a
// disabled opcode (even when they appear in a branch that is not executed).
func opcodeDisabled(op *parsedOpcode, vm *Engine) error {
str := fmt.Sprintf("attempt to execute disabled opcode %s",
op.opcode.name)
func opcodeDisabled(op *opcode, data []byte, vm *Engine) error {
str := fmt.Sprintf("attempt to execute disabled opcode %s", op.name)
return scriptError(ErrDisabledOpcode, str)
}
// opcodeReserved is a common handler for all reserved opcodes. It returns an
// appropriate error indicating the opcode is reserved.
func opcodeReserved(op *parsedOpcode, vm *Engine) error {
str := fmt.Sprintf("attempt to execute reserved opcode %s",
op.opcode.name)
func opcodeReserved(op *opcode, data []byte, vm *Engine) error {
str := fmt.Sprintf("attempt to execute reserved opcode %s", op.name)
return scriptError(ErrReservedOpcode, str)
}
// opcodeInvalid is a common handler for all invalid opcodes. It returns an
// appropriate error indicating the opcode is invalid.
func opcodeInvalid(op *parsedOpcode, vm *Engine) error {
str := fmt.Sprintf("attempt to execute invalid opcode %s",
op.opcode.name)
func opcodeInvalid(op *opcode, data []byte, vm *Engine) error {
str := fmt.Sprintf("attempt to execute invalid opcode %s", op.name)
return scriptError(ErrReservedOpcode, str)
}
// opcodeFalse pushes an empty array to the data stack to represent false. Note
// that 0, when encoded as a number according to the numeric encoding consensus
// rules, is an empty array.
func opcodeFalse(op *parsedOpcode, vm *Engine) error {
func opcodeFalse(op *opcode, data []byte, vm *Engine) error {
vm.dstack.PushByteArray(nil)
return nil
}
// opcodePushData is a common handler for the vast majority of opcodes that push
// raw data (bytes) to the data stack.
func opcodePushData(op *parsedOpcode, vm *Engine) error {
vm.dstack.PushByteArray(op.data)
func opcodePushData(op *opcode, data []byte, vm *Engine) error {
vm.dstack.PushByteArray(data)
return nil
}
// opcode1Negate pushes -1, encoded as a number, to the data stack.
func opcode1Negate(op *parsedOpcode, vm *Engine) error {
func opcode1Negate(op *opcode, data []byte, vm *Engine) error {
vm.dstack.PushInt(scriptNum(-1))
return nil
}
@ -722,23 +712,24 @@ func opcode1Negate(op *parsedOpcode, vm *Engine) error {
// opcodeN is a common handler for the small integer data push opcodes. It
// pushes the numeric value the opcode represents (which will be from 1 to 16)
// onto the data stack.
func opcodeN(op *parsedOpcode, vm *Engine) error {
func opcodeN(op *opcode, data []byte, vm *Engine) error {
// The opcodes are all defined consecutively, so the numeric value is
// the difference.
vm.dstack.PushInt(scriptNum((op.opcode.value - (OP_1 - 1))))
vm.dstack.PushInt(scriptNum((op.value - (OP_1 - 1))))
return nil
}
// opcodeNop is a common handler for the NOP family of opcodes. As the name
// implies it generally does nothing, however, it will return an error when
// the flag to discourage use of NOPs is set for select opcodes.
func opcodeNop(op *parsedOpcode, vm *Engine) error {
switch op.opcode.value {
func opcodeNop(op *opcode, data []byte, vm *Engine) error {
switch op.value {
case OP_NOP1, OP_NOP4, OP_NOP5,
OP_NOP6, OP_NOP7, OP_NOP8, OP_NOP9, OP_NOP10:
if vm.hasFlag(ScriptDiscourageUpgradableNops) {
str := fmt.Sprintf("OP_NOP%d reserved for soft-fork "+
"upgrades", op.opcode.value-(OP_NOP1-1))
str := fmt.Sprintf("%v reserved for soft-fork "+
"upgrades", op.name)
return scriptError(ErrDiscourageUpgradableNOPs, str)
}
}
@ -801,7 +792,7 @@ func popIfBool(vm *Engine) (bool, error) {
//
// Data stack transformation: [... bool] -> [...]
// Conditional stack transformation: [...] -> [... OpCondValue]
func opcodeIf(op *parsedOpcode, vm *Engine) error {
func opcodeIf(op *opcode, data []byte, vm *Engine) error {
condVal := OpCondFalse
if vm.isBranchExecuting() {
ok, err := popIfBool(vm)
@ -835,7 +826,7 @@ func opcodeIf(op *parsedOpcode, vm *Engine) error {
//
// Data stack transformation: [... bool] -> [...]
// Conditional stack transformation: [...] -> [... OpCondValue]
func opcodeNotIf(op *parsedOpcode, vm *Engine) error {
func opcodeNotIf(op *opcode, data []byte, vm *Engine) error {
condVal := OpCondFalse
if vm.isBranchExecuting() {
ok, err := popIfBool(vm)
@ -858,10 +849,10 @@ func opcodeNotIf(op *parsedOpcode, vm *Engine) error {
// An error is returned if there has not already been a matching OP_IF.
//
// Conditional stack transformation: [... OpCondValue] -> [... !OpCondValue]
func opcodeElse(op *parsedOpcode, vm *Engine) error {
func opcodeElse(op *opcode, data []byte, vm *Engine) error {
if len(vm.condStack) == 0 {
str := fmt.Sprintf("encountered opcode %s with no matching "+
"opcode to begin conditional execution", op.opcode.name)
"opcode to begin conditional execution", op.name)
return scriptError(ErrUnbalancedConditional, str)
}
@ -884,10 +875,10 @@ func opcodeElse(op *parsedOpcode, vm *Engine) error {
// An error is returned if there has not already been a matching OP_IF.
//
// Conditional stack transformation: [... OpCondValue] -> [...]
func opcodeEndif(op *parsedOpcode, vm *Engine) error {
func opcodeEndif(op *opcode, data []byte, vm *Engine) error {
if len(vm.condStack) == 0 {
str := fmt.Sprintf("encountered opcode %s with no matching "+
"opcode to begin conditional execution", op.opcode.name)
"opcode to begin conditional execution", op.name)
return scriptError(ErrUnbalancedConditional, str)
}
@ -900,14 +891,14 @@ func opcodeEndif(op *parsedOpcode, vm *Engine) error {
// item on the stack or when that item evaluates to false. In the latter case
// where the verification fails specifically due to the top item evaluating
// to false, the returned error will use the passed error code.
func abstractVerify(op *parsedOpcode, vm *Engine, c ErrorCode) error {
func abstractVerify(op *opcode, vm *Engine, c ErrorCode) error {
verified, err := vm.dstack.PopBool()
if err != nil {
return err
}
if !verified {
str := fmt.Sprintf("%s failed", op.opcode.name)
str := fmt.Sprintf("%s failed", op.name)
return scriptError(c, str)
}
return nil
@ -915,13 +906,13 @@ func abstractVerify(op *parsedOpcode, vm *Engine, c ErrorCode) error {
// opcodeVerify examines the top item on the data stack as a boolean value and
// verifies it evaluates to true. An error is returned if it does not.
func opcodeVerify(op *parsedOpcode, vm *Engine) error {
func opcodeVerify(op *opcode, data []byte, vm *Engine) error {
return abstractVerify(op, vm, ErrVerify)
}
// opcodeReturn returns an appropriate error since it is always an error to
// return early from a script.
func opcodeReturn(op *parsedOpcode, vm *Engine) error {
func opcodeReturn(op *opcode, data []byte, vm *Engine) error {
return scriptError(ErrEarlyReturn, "script returned early")
}
@ -951,7 +942,7 @@ func verifyLockTime(txLockTime, threshold, lockTime int64) error {
// 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 {
func opcodeCheckLockTimeVerify(op *opcode, data []byte, vm *Engine) error {
// If the ScriptVerifyCheckLockTimeVerify script flag is not set, treat
// opcode as OP_NOP2 instead.
if !vm.hasFlag(ScriptVerifyCheckLockTimeVerify) {
@ -1025,7 +1016,7 @@ func opcodeCheckLockTimeVerify(op *parsedOpcode, vm *Engine) error {
// 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 {
func opcodeCheckSequenceVerify(op *opcode, data []byte, vm *Engine) error {
// If the ScriptVerifyCheckSequenceVerify script flag is not set, treat
// opcode as OP_NOP3 instead.
if !vm.hasFlag(ScriptVerifyCheckSequenceVerify) {
@ -1102,7 +1093,7 @@ func opcodeCheckSequenceVerify(op *parsedOpcode, vm *Engine) error {
//
// Main data stack transformation: [... x1 x2 x3] -> [... x1 x2]
// Alt data stack transformation: [... y1 y2 y3] -> [... y1 y2 y3 x3]
func opcodeToAltStack(op *parsedOpcode, vm *Engine) error {
func opcodeToAltStack(op *opcode, data []byte, vm *Engine) error {
so, err := vm.dstack.PopByteArray()
if err != nil {
return err
@ -1117,7 +1108,7 @@ func opcodeToAltStack(op *parsedOpcode, vm *Engine) error {
//
// Main data stack transformation: [... x1 x2 x3] -> [... x1 x2 x3 y3]
// Alt data stack transformation: [... y1 y2 y3] -> [... y1 y2]
func opcodeFromAltStack(op *parsedOpcode, vm *Engine) error {
func opcodeFromAltStack(op *opcode, data []byte, vm *Engine) error {
so, err := vm.astack.PopByteArray()
if err != nil {
return err
@ -1130,35 +1121,35 @@ func opcodeFromAltStack(op *parsedOpcode, vm *Engine) error {
// opcode2Drop removes the top 2 items from the data stack.
//
// Stack transformation: [... x1 x2 x3] -> [... x1]
func opcode2Drop(op *parsedOpcode, vm *Engine) error {
func opcode2Drop(op *opcode, data []byte, vm *Engine) error {
return vm.dstack.DropN(2)
}
// opcode2Dup duplicates the top 2 items on the data stack.
//
// Stack transformation: [... x1 x2 x3] -> [... x1 x2 x3 x2 x3]
func opcode2Dup(op *parsedOpcode, vm *Engine) error {
func opcode2Dup(op *opcode, data []byte, vm *Engine) error {
return vm.dstack.DupN(2)
}
// opcode3Dup duplicates the top 3 items on the data stack.
//
// Stack transformation: [... x1 x2 x3] -> [... x1 x2 x3 x1 x2 x3]
func opcode3Dup(op *parsedOpcode, vm *Engine) error {
func opcode3Dup(op *opcode, data []byte, vm *Engine) error {
return vm.dstack.DupN(3)
}
// opcode2Over duplicates the 2 items before the top 2 items on the data stack.
//
// Stack transformation: [... x1 x2 x3 x4] -> [... x1 x2 x3 x4 x1 x2]
func opcode2Over(op *parsedOpcode, vm *Engine) error {
func opcode2Over(op *opcode, data []byte, vm *Engine) error {
return vm.dstack.OverN(2)
}
// opcode2Rot rotates the top 6 items on the data stack to the left twice.
//
// Stack transformation: [... x1 x2 x3 x4 x5 x6] -> [... x3 x4 x5 x6 x1 x2]
func opcode2Rot(op *parsedOpcode, vm *Engine) error {
func opcode2Rot(op *opcode, data []byte, vm *Engine) error {
return vm.dstack.RotN(2)
}
@ -1166,7 +1157,7 @@ func opcode2Rot(op *parsedOpcode, vm *Engine) error {
// before them.
//
// Stack transformation: [... x1 x2 x3 x4] -> [... x3 x4 x1 x2]
func opcode2Swap(op *parsedOpcode, vm *Engine) error {
func opcode2Swap(op *opcode, data []byte, vm *Engine) error {
return vm.dstack.SwapN(2)
}
@ -1174,7 +1165,7 @@ func opcode2Swap(op *parsedOpcode, vm *Engine) error {
//
// Stack transformation (x1==0): [... x1] -> [... x1]
// Stack transformation (x1!=0): [... x1] -> [... x1 x1]
func opcodeIfDup(op *parsedOpcode, vm *Engine) error {
func opcodeIfDup(op *opcode, data []byte, vm *Engine) error {
so, err := vm.dstack.PeekByteArray(0)
if err != nil {
return err
@ -1194,7 +1185,7 @@ func opcodeIfDup(op *parsedOpcode, vm *Engine) error {
// Stack transformation: [...] -> [... <num of items on the stack>]
// Example with 2 items: [x1 x2] -> [x1 x2 2]
// Example with 3 items: [x1 x2 x3] -> [x1 x2 x3 3]
func opcodeDepth(op *parsedOpcode, vm *Engine) error {
func opcodeDepth(op *opcode, data []byte, vm *Engine) error {
vm.dstack.PushInt(scriptNum(vm.dstack.Depth()))
return nil
}
@ -1202,28 +1193,28 @@ func opcodeDepth(op *parsedOpcode, vm *Engine) error {
// opcodeDrop removes the top item from the data stack.
//
// Stack transformation: [... x1 x2 x3] -> [... x1 x2]
func opcodeDrop(op *parsedOpcode, vm *Engine) error {
func opcodeDrop(op *opcode, data []byte, vm *Engine) error {
return vm.dstack.DropN(1)
}
// opcodeDup duplicates the top item on the data stack.
//
// Stack transformation: [... x1 x2 x3] -> [... x1 x2 x3 x3]
func opcodeDup(op *parsedOpcode, vm *Engine) error {
func opcodeDup(op *opcode, data []byte, vm *Engine) error {
return vm.dstack.DupN(1)
}
// opcodeNip removes the item before the top item on the data stack.
//
// Stack transformation: [... x1 x2 x3] -> [... x1 x3]
func opcodeNip(op *parsedOpcode, vm *Engine) error {
func opcodeNip(op *opcode, data []byte, vm *Engine) error {
return vm.dstack.NipN(1)
}
// opcodeOver duplicates the item before the top item on the data stack.
//
// Stack transformation: [... x1 x2 x3] -> [... x1 x2 x3 x2]
func opcodeOver(op *parsedOpcode, vm *Engine) error {
func opcodeOver(op *opcode, data []byte, vm *Engine) error {
return vm.dstack.OverN(1)
}
@ -1233,7 +1224,7 @@ func opcodeOver(op *parsedOpcode, vm *Engine) error {
// Stack transformation: [xn ... x2 x1 x0 n] -> [xn ... x2 x1 x0 xn]
// Example with n=1: [x2 x1 x0 1] -> [x2 x1 x0 x1]
// Example with n=2: [x2 x1 x0 2] -> [x2 x1 x0 x2]
func opcodePick(op *parsedOpcode, vm *Engine) error {
func opcodePick(op *opcode, data []byte, vm *Engine) error {
val, err := vm.dstack.PopInt()
if err != nil {
return err
@ -1248,7 +1239,7 @@ func opcodePick(op *parsedOpcode, vm *Engine) error {
// Stack transformation: [xn ... x2 x1 x0 n] -> [... x2 x1 x0 xn]
// Example with n=1: [x2 x1 x0 1] -> [x2 x0 x1]
// Example with n=2: [x2 x1 x0 2] -> [x1 x0 x2]
func opcodeRoll(op *parsedOpcode, vm *Engine) error {
func opcodeRoll(op *opcode, data []byte, vm *Engine) error {
val, err := vm.dstack.PopInt()
if err != nil {
return err
@ -1260,14 +1251,14 @@ func opcodeRoll(op *parsedOpcode, vm *Engine) error {
// opcodeRot rotates the top 3 items on the data stack to the left.
//
// Stack transformation: [... x1 x2 x3] -> [... x2 x3 x1]
func opcodeRot(op *parsedOpcode, vm *Engine) error {
func opcodeRot(op *opcode, data []byte, vm *Engine) error {
return vm.dstack.RotN(1)
}
// opcodeSwap swaps the top two items on the stack.
//
// Stack transformation: [... x1 x2] -> [... x2 x1]
func opcodeSwap(op *parsedOpcode, vm *Engine) error {
func opcodeSwap(op *opcode, data []byte, vm *Engine) error {
return vm.dstack.SwapN(1)
}
@ -1275,7 +1266,7 @@ func opcodeSwap(op *parsedOpcode, vm *Engine) error {
// second-to-top item.
//
// Stack transformation: [... x1 x2] -> [... x2 x1 x2]
func opcodeTuck(op *parsedOpcode, vm *Engine) error {
func opcodeTuck(op *opcode, data []byte, vm *Engine) error {
return vm.dstack.Tuck()
}
@ -1283,7 +1274,7 @@ func opcodeTuck(op *parsedOpcode, vm *Engine) error {
// stack.
//
// Stack transformation: [... x1] -> [... x1 len(x1)]
func opcodeSize(op *parsedOpcode, vm *Engine) error {
func opcodeSize(op *opcode, data []byte, vm *Engine) error {
so, err := vm.dstack.PeekByteArray(0)
if err != nil {
return err
@ -1297,7 +1288,7 @@ func opcodeSize(op *parsedOpcode, vm *Engine) error {
// bytes, and pushes the result, encoded as a boolean, back to the stack.
//
// Stack transformation: [... x1 x2] -> [... bool]
func opcodeEqual(op *parsedOpcode, vm *Engine) error {
func opcodeEqual(op *opcode, data []byte, vm *Engine) error {
a, err := vm.dstack.PopByteArray()
if err != nil {
return err
@ -1318,8 +1309,8 @@ func opcodeEqual(op *parsedOpcode, vm *Engine) error {
// evaluates to true. An error is returned if it does not.
//
// Stack transformation: [... x1 x2] -> [... bool] -> [...]
func opcodeEqualVerify(op *parsedOpcode, vm *Engine) error {
err := opcodeEqual(op, vm)
func opcodeEqualVerify(op *opcode, data []byte, vm *Engine) error {
err := opcodeEqual(op, data, vm)
if err == nil {
err = abstractVerify(op, vm, ErrEqualVerify)
}
@ -1330,7 +1321,7 @@ func opcodeEqualVerify(op *parsedOpcode, vm *Engine) error {
// it with its incremented value (plus 1).
//
// Stack transformation: [... x1 x2] -> [... x1 x2+1]
func opcode1Add(op *parsedOpcode, vm *Engine) error {
func opcode1Add(op *opcode, data []byte, vm *Engine) error {
m, err := vm.dstack.PopInt()
if err != nil {
return err
@ -1344,7 +1335,7 @@ func opcode1Add(op *parsedOpcode, vm *Engine) error {
// it with its decremented value (minus 1).
//
// Stack transformation: [... x1 x2] -> [... x1 x2-1]
func opcode1Sub(op *parsedOpcode, vm *Engine) error {
func opcode1Sub(op *opcode, data []byte, vm *Engine) error {
m, err := vm.dstack.PopInt()
if err != nil {
return err
@ -1358,7 +1349,7 @@ func opcode1Sub(op *parsedOpcode, vm *Engine) error {
// it with its negation.
//
// Stack transformation: [... x1 x2] -> [... x1 -x2]
func opcodeNegate(op *parsedOpcode, vm *Engine) error {
func opcodeNegate(op *opcode, data []byte, vm *Engine) error {
m, err := vm.dstack.PopInt()
if err != nil {
return err
@ -1372,7 +1363,7 @@ func opcodeNegate(op *parsedOpcode, vm *Engine) error {
// it with its absolute value.
//
// Stack transformation: [... x1 x2] -> [... x1 abs(x2)]
func opcodeAbs(op *parsedOpcode, vm *Engine) error {
func opcodeAbs(op *opcode, data []byte, vm *Engine) error {
m, err := vm.dstack.PopInt()
if err != nil {
return err
@ -1397,7 +1388,7 @@ func opcodeAbs(op *parsedOpcode, vm *Engine) error {
// Stack transformation (x2==0): [... x1 0] -> [... x1 1]
// Stack transformation (x2!=0): [... x1 1] -> [... x1 0]
// Stack transformation (x2!=0): [... x1 17] -> [... x1 0]
func opcodeNot(op *parsedOpcode, vm *Engine) error {
func opcodeNot(op *opcode, data []byte, vm *Engine) error {
m, err := vm.dstack.PopInt()
if err != nil {
return err
@ -1417,7 +1408,7 @@ func opcodeNot(op *parsedOpcode, vm *Engine) error {
// Stack transformation (x2==0): [... x1 0] -> [... x1 0]
// Stack transformation (x2!=0): [... x1 1] -> [... x1 1]
// Stack transformation (x2!=0): [... x1 17] -> [... x1 1]
func opcode0NotEqual(op *parsedOpcode, vm *Engine) error {
func opcode0NotEqual(op *opcode, data []byte, vm *Engine) error {
m, err := vm.dstack.PopInt()
if err != nil {
return err
@ -1434,7 +1425,7 @@ func opcode0NotEqual(op *parsedOpcode, vm *Engine) error {
// them with their sum.
//
// Stack transformation: [... x1 x2] -> [... x1+x2]
func opcodeAdd(op *parsedOpcode, vm *Engine) error {
func opcodeAdd(op *opcode, data []byte, vm *Engine) error {
v0, err := vm.dstack.PopInt()
if err != nil {
return err
@ -1454,7 +1445,7 @@ func opcodeAdd(op *parsedOpcode, vm *Engine) error {
// entry.
//
// Stack transformation: [... x1 x2] -> [... x1-x2]
func opcodeSub(op *parsedOpcode, vm *Engine) error {
func opcodeSub(op *opcode, data []byte, vm *Engine) error {
v0, err := vm.dstack.PopInt()
if err != nil {
return err
@ -1476,7 +1467,7 @@ func opcodeSub(op *parsedOpcode, vm *Engine) error {
// Stack transformation (x1!=0, x2==0): [... 5 0] -> [... 0]
// Stack transformation (x1==0, x2!=0): [... 0 7] -> [... 0]
// Stack transformation (x1!=0, x2!=0): [... 4 8] -> [... 1]
func opcodeBoolAnd(op *parsedOpcode, vm *Engine) error {
func opcodeBoolAnd(op *opcode, data []byte, vm *Engine) error {
v0, err := vm.dstack.PopInt()
if err != nil {
return err
@ -1503,7 +1494,7 @@ func opcodeBoolAnd(op *parsedOpcode, vm *Engine) error {
// Stack transformation (x1!=0, x2==0): [... 5 0] -> [... 1]
// Stack transformation (x1==0, x2!=0): [... 0 7] -> [... 1]
// Stack transformation (x1!=0, x2!=0): [... 4 8] -> [... 1]
func opcodeBoolOr(op *parsedOpcode, vm *Engine) error {
func opcodeBoolOr(op *opcode, data []byte, vm *Engine) error {
v0, err := vm.dstack.PopInt()
if err != nil {
return err
@ -1528,7 +1519,7 @@ func opcodeBoolOr(op *parsedOpcode, vm *Engine) error {
//
// Stack transformation (x1==x2): [... 5 5] -> [... 1]
// Stack transformation (x1!=x2): [... 5 7] -> [... 0]
func opcodeNumEqual(op *parsedOpcode, vm *Engine) error {
func opcodeNumEqual(op *opcode, data []byte, vm *Engine) error {
v0, err := vm.dstack.PopInt()
if err != nil {
return err
@ -1556,8 +1547,8 @@ func opcodeNumEqual(op *parsedOpcode, vm *Engine) error {
// to true. An error is returned if it does not.
//
// Stack transformation: [... x1 x2] -> [... bool] -> [...]
func opcodeNumEqualVerify(op *parsedOpcode, vm *Engine) error {
err := opcodeNumEqual(op, vm)
func opcodeNumEqualVerify(op *opcode, data []byte, vm *Engine) error {
err := opcodeNumEqual(op, data, vm)
if err == nil {
err = abstractVerify(op, vm, ErrNumEqualVerify)
}
@ -1569,7 +1560,7 @@ func opcodeNumEqualVerify(op *parsedOpcode, vm *Engine) error {
//
// Stack transformation (x1==x2): [... 5 5] -> [... 0]
// Stack transformation (x1!=x2): [... 5 7] -> [... 1]
func opcodeNumNotEqual(op *parsedOpcode, vm *Engine) error {
func opcodeNumNotEqual(op *opcode, data []byte, vm *Engine) error {
v0, err := vm.dstack.PopInt()
if err != nil {
return err
@ -1594,7 +1585,7 @@ func opcodeNumNotEqual(op *parsedOpcode, vm *Engine) error {
// otherwise a 0.
//
// Stack transformation: [... x1 x2] -> [... bool]
func opcodeLessThan(op *parsedOpcode, vm *Engine) error {
func opcodeLessThan(op *opcode, data []byte, vm *Engine) error {
v0, err := vm.dstack.PopInt()
if err != nil {
return err
@ -1619,7 +1610,7 @@ func opcodeLessThan(op *parsedOpcode, vm *Engine) error {
// with a 1, otherwise a 0.
//
// Stack transformation: [... x1 x2] -> [... bool]
func opcodeGreaterThan(op *parsedOpcode, vm *Engine) error {
func opcodeGreaterThan(op *opcode, data []byte, vm *Engine) error {
v0, err := vm.dstack.PopInt()
if err != nil {
return err
@ -1643,7 +1634,7 @@ func opcodeGreaterThan(op *parsedOpcode, vm *Engine) error {
// replaced with a 1, otherwise a 0.
//
// Stack transformation: [... x1 x2] -> [... bool]
func opcodeLessThanOrEqual(op *parsedOpcode, vm *Engine) error {
func opcodeLessThanOrEqual(op *opcode, data []byte, vm *Engine) error {
v0, err := vm.dstack.PopInt()
if err != nil {
return err
@ -1667,7 +1658,7 @@ func opcodeLessThanOrEqual(op *parsedOpcode, vm *Engine) error {
// item, they are replaced with a 1, otherwise a 0.
//
// Stack transformation: [... x1 x2] -> [... bool]
func opcodeGreaterThanOrEqual(op *parsedOpcode, vm *Engine) error {
func opcodeGreaterThanOrEqual(op *opcode, data []byte, vm *Engine) error {
v0, err := vm.dstack.PopInt()
if err != nil {
return err
@ -1691,7 +1682,7 @@ func opcodeGreaterThanOrEqual(op *parsedOpcode, vm *Engine) error {
// them with the minimum of the two.
//
// Stack transformation: [... x1 x2] -> [... min(x1, x2)]
func opcodeMin(op *parsedOpcode, vm *Engine) error {
func opcodeMin(op *opcode, data []byte, vm *Engine) error {
v0, err := vm.dstack.PopInt()
if err != nil {
return err
@ -1715,7 +1706,7 @@ func opcodeMin(op *parsedOpcode, vm *Engine) error {
// them with the maximum of the two.
//
// Stack transformation: [... x1 x2] -> [... max(x1, x2)]
func opcodeMax(op *parsedOpcode, vm *Engine) error {
func opcodeMax(op *opcode, data []byte, vm *Engine) error {
v0, err := vm.dstack.PopInt()
if err != nil {
return err
@ -1743,7 +1734,7 @@ func opcodeMax(op *parsedOpcode, vm *Engine) error {
// the third-to-top item is the value to test.
//
// Stack transformation: [... x1 min max] -> [... bool]
func opcodeWithin(op *parsedOpcode, vm *Engine) error {
func opcodeWithin(op *opcode, data []byte, vm *Engine) error {
maxVal, err := vm.dstack.PopInt()
if err != nil {
return err
@ -1777,7 +1768,7 @@ func calcHash(buf []byte, hasher hash.Hash) []byte {
// replaces it with ripemd160(data).
//
// Stack transformation: [... x1] -> [... ripemd160(x1)]
func opcodeRipemd160(op *parsedOpcode, vm *Engine) error {
func opcodeRipemd160(op *opcode, data []byte, vm *Engine) error {
buf, err := vm.dstack.PopByteArray()
if err != nil {
return err
@ -1791,7 +1782,7 @@ func opcodeRipemd160(op *parsedOpcode, vm *Engine) error {
// with sha1(data).
//
// Stack transformation: [... x1] -> [... sha1(x1)]
func opcodeSha1(op *parsedOpcode, vm *Engine) error {
func opcodeSha1(op *opcode, data []byte, vm *Engine) error {
buf, err := vm.dstack.PopByteArray()
if err != nil {
return err
@ -1806,7 +1797,7 @@ func opcodeSha1(op *parsedOpcode, vm *Engine) error {
// it with sha256(data).
//
// Stack transformation: [... x1] -> [... sha256(x1)]
func opcodeSha256(op *parsedOpcode, vm *Engine) error {
func opcodeSha256(op *opcode, data []byte, vm *Engine) error {
buf, err := vm.dstack.PopByteArray()
if err != nil {
return err
@ -1821,7 +1812,7 @@ func opcodeSha256(op *parsedOpcode, vm *Engine) error {
// it with ripemd160(sha256(data)).
//
// Stack transformation: [... x1] -> [... ripemd160(sha256(x1))]
func opcodeHash160(op *parsedOpcode, vm *Engine) error {
func opcodeHash160(op *opcode, data []byte, vm *Engine) error {
buf, err := vm.dstack.PopByteArray()
if err != nil {
return err
@ -1836,7 +1827,7 @@ func opcodeHash160(op *parsedOpcode, vm *Engine) error {
// it with sha256(sha256(data)).
//
// Stack transformation: [... x1] -> [... sha256(sha256(x1))]
func opcodeHash256(op *parsedOpcode, vm *Engine) error {
func opcodeHash256(op *opcode, data []byte, vm *Engine) error {
buf, err := vm.dstack.PopByteArray()
if err != nil {
return err
@ -1850,7 +1841,7 @@ func opcodeHash256(op *parsedOpcode, vm *Engine) error {
// seen OP_CODESEPARATOR which is used during signature checking.
//
// This opcode does not change the contents of the data stack.
func opcodeCodeSeparator(op *parsedOpcode, vm *Engine) error {
func opcodeCodeSeparator(op *opcode, data []byte, vm *Engine) error {
vm.lastCodeSep = int(vm.tokenizer.ByteIndex())
return nil
}
@ -1869,7 +1860,7 @@ func opcodeCodeSeparator(op *parsedOpcode, vm *Engine) error {
// cryptographic methods against the provided public key.
//
// Stack transformation: [... signature pubkey] -> [... bool]
func opcodeCheckSig(op *parsedOpcode, vm *Engine) error {
func opcodeCheckSig(op *opcode, data []byte, vm *Engine) error {
pkBytes, err := vm.dstack.PopByteArray()
if err != nil {
return err
@ -1984,9 +1975,9 @@ func opcodeCheckSig(op *parsedOpcode, vm *Engine) error {
// The opcodeCheckSig function is invoked followed by opcodeVerify. See the
// documentation for each of those opcodes for more details.
//
// Stack transformation: signature pubkey] -> [... bool] -> [...]
func opcodeCheckSigVerify(op *parsedOpcode, vm *Engine) error {
err := opcodeCheckSig(op, vm)
// Stack transformation: [... signature pubkey] -> [... bool] -> [...]
func opcodeCheckSigVerify(op *opcode, data []byte, vm *Engine) error {
err := opcodeCheckSig(op, data, vm)
if err == nil {
err = abstractVerify(op, vm, ErrCheckSigVerify)
}
@ -2021,7 +2012,7 @@ type parsedSigInfo struct {
//
// Stack transformation:
// [... dummy [sig ...] numsigs [pubkey ...] numpubkeys] -> [... bool]
func opcodeCheckMultiSig(op *parsedOpcode, vm *Engine) error {
func opcodeCheckMultiSig(op *opcode, data []byte, vm *Engine) error {
numKeys, err := vm.dstack.PopInt()
if err != nil {
return err
@ -2247,8 +2238,8 @@ func opcodeCheckMultiSig(op *parsedOpcode, vm *Engine) error {
//
// Stack transformation:
// [... dummy [sig ...] numsigs [pubkey ...] numpubkeys] -> [... bool] -> [...]
func opcodeCheckMultiSigVerify(op *parsedOpcode, vm *Engine) error {
err := opcodeCheckMultiSig(op, vm)
func opcodeCheckMultiSigVerify(op *opcode, data []byte, vm *Engine) error {
err := opcodeCheckMultiSig(op, data, vm)
if err == nil {
err = abstractVerify(op, vm, ErrCheckMultiSigVerify)
}

View file

@ -23,8 +23,8 @@ func TestOpcodeDisabled(t *testing.T) {
OP_LSHIFT, OP_RSHIFT,
}
for _, opcodeVal := range tests {
pop := parsedOpcode{opcode: &opcodeArray[opcodeVal], data: nil}
err := opcodeDisabled(&pop, nil)
op := &opcodeArray[opcodeVal]
err := opcodeDisabled(op, nil, nil)
if !IsErrorCode(err, ErrDisabledOpcode) {
t.Errorf("opcodeDisabled: unexpected error - got %v, "+
"want %v", err, ErrDisabledOpcode)