Enable txindex=1 as default #37

Closed
kodxana wants to merge 211 commits from master 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(op, data, vm)
return op.opfunc(&pop, vm)
} }
// checkValidPC returns an error if the current script position is not valid for // checkValidPC returns an error if the current script position is not valid for

View file

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

View file

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