WIP: next hard fork #5
3 changed files with 90 additions and 100 deletions
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue