WIP: next hard fork #5

Draft
BrannonKing wants to merge 178 commits from WIP-HF-2022 into master
Showing only changes of commit ef3d06e62b - Show all commits

View file

@ -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
} }