txscript: Make executeOpcode take opcode and data.
This converts the executeOpcode function defined on the engine to accept an opcode and data slice instead of a parsed opcode as a step towards removing the parsed opcode struct and associated supporting code altogether. It also updates all callers accordingly.
This commit is contained in:
parent
595d379fa6
commit
ef3d06e62b
1 changed files with 14 additions and 16 deletions
|
@ -341,23 +341,21 @@ func checkMinimalDataPush(op *opcode, data []byte) error {
|
||||||
// executeOpcode peforms execution on the passed opcode. It takes into account
|
// executeOpcode peforms execution on the passed opcode. It takes into account
|
||||||
// whether or not it is hidden by conditionals, but some rules still must be
|
// whether or not it is hidden by conditionals, but some rules still must be
|
||||||
// tested in this case.
|
// tested in this case.
|
||||||
func (vm *Engine) executeOpcode(pop *parsedOpcode) error {
|
func (vm *Engine) executeOpcode(op *opcode, data []byte) error {
|
||||||
// Disabled opcodes are fail on program counter.
|
// Disabled opcodes are fail on program counter.
|
||||||
if isOpcodeDisabled(pop.opcode.value) {
|
if isOpcodeDisabled(op.value) {
|
||||||
str := fmt.Sprintf("attempt to execute disabled opcode %s",
|
str := fmt.Sprintf("attempt to execute disabled opcode %s", op.name)
|
||||||
pop.opcode.name)
|
|
||||||
return scriptError(ErrDisabledOpcode, str)
|
return scriptError(ErrDisabledOpcode, str)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always-illegal opcodes are fail on program counter.
|
// Always-illegal opcodes are fail on program counter.
|
||||||
if isOpcodeAlwaysIllegal(pop.opcode.value) {
|
if isOpcodeAlwaysIllegal(op.value) {
|
||||||
str := fmt.Sprintf("attempt to execute reserved opcode %s",
|
str := fmt.Sprintf("attempt to execute reserved opcode %s", op.name)
|
||||||
pop.opcode.name)
|
|
||||||
return scriptError(ErrReservedOpcode, str)
|
return scriptError(ErrReservedOpcode, str)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note that this includes OP_RESERVED which counts as a push operation.
|
// Note that this includes OP_RESERVED which counts as a push operation.
|
||||||
if pop.opcode.value > OP_16 {
|
if op.value > OP_16 {
|
||||||
vm.numOps++
|
vm.numOps++
|
||||||
if vm.numOps > MaxOpsPerScript {
|
if vm.numOps > MaxOpsPerScript {
|
||||||
str := fmt.Sprintf("exceeded max operation limit of %d",
|
str := fmt.Sprintf("exceeded max operation limit of %d",
|
||||||
|
@ -365,29 +363,30 @@ func (vm *Engine) executeOpcode(pop *parsedOpcode) error {
|
||||||
return scriptError(ErrTooManyOperations, str)
|
return scriptError(ErrTooManyOperations, str)
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if len(pop.data) > MaxScriptElementSize {
|
} else if len(data) > MaxScriptElementSize {
|
||||||
str := fmt.Sprintf("element size %d exceeds max allowed size %d",
|
str := fmt.Sprintf("element size %d exceeds max allowed size %d",
|
||||||
len(pop.data), MaxScriptElementSize)
|
len(data), MaxScriptElementSize)
|
||||||
return scriptError(ErrElementTooBig, str)
|
return scriptError(ErrElementTooBig, str)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nothing left to do when this is not a conditional opcode and it is
|
// Nothing left to do when this is not a conditional opcode and it is
|
||||||
// not in an executing branch.
|
// not in an executing branch.
|
||||||
if !vm.isBranchExecuting() && !isOpcodeConditional(pop.opcode.value) {
|
if !vm.isBranchExecuting() && !isOpcodeConditional(op.value) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure all executed data push opcodes use the minimal encoding when
|
// Ensure all executed data push opcodes use the minimal encoding when
|
||||||
// the minimal data verification flag is set.
|
// the minimal data verification flag is set.
|
||||||
if vm.dstack.verifyMinimalData && vm.isBranchExecuting() &&
|
if vm.dstack.verifyMinimalData && vm.isBranchExecuting() &&
|
||||||
pop.opcode.value >= 0 && pop.opcode.value <= OP_PUSHDATA4 {
|
op.value >= 0 && op.value <= OP_PUSHDATA4 {
|
||||||
|
|
||||||
if err := checkMinimalDataPush(pop.opcode, pop.data); err != nil {
|
if err := checkMinimalDataPush(op, data); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return pop.opcode.opfunc(pop, vm)
|
pop := parsedOpcode{opcode: op, data: data}
|
||||||
|
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
|
||||||
|
@ -670,8 +669,7 @@ func (vm *Engine) Step() (done bool, err error) {
|
||||||
// Execute the opcode while taking into account several things such as
|
// Execute the opcode while taking into account several things such as
|
||||||
// disabled opcodes, illegal opcodes, maximum allowed operations per script,
|
// disabled opcodes, illegal opcodes, maximum allowed operations per script,
|
||||||
// maximum script element sizes, and conditionals.
|
// maximum script element sizes, and conditionals.
|
||||||
pop := parsedOpcode{opcode: vm.tokenizer.op, data: vm.tokenizer.Data()}
|
err = vm.executeOpcode(vm.tokenizer.op, vm.tokenizer.Data())
|
||||||
err = vm.executeOpcode(&pop)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return true, err
|
return true, err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue