MCPcopy
hub / github.com/btcsuite/btcd / executeOpcode

Method executeOpcode

txscript/engine.go:460–525  ·  view source on GitHub ↗

executeOpcode performs execution on the passed opcode. It takes into account whether or not it is hidden by conditionals, but some rules still must be tested in this case.

(op *opcode, data []byte)

Source from the content-addressed store, hash-verified

458// whether or not it is hidden by conditionals, but some rules still must be
459// tested in this case.
460func (vm *Engine) executeOpcode(op *opcode, data []byte) error {
461 // Disabled opcodes are fail on program counter.
462 if isOpcodeDisabled(op.value) {
463 str := fmt.Sprintf("attempt to execute disabled opcode %s", op.name)
464 return scriptError(ErrDisabledOpcode, str)
465 }
466
467 // Always-illegal opcodes are fail on program counter.
468 if isOpcodeAlwaysIllegal(op.value) {
469 str := fmt.Sprintf("attempt to execute reserved opcode %s", op.name)
470 return scriptError(ErrReservedOpcode, str)
471 }
472
473 // Note that this includes OP_RESERVED which counts as a push operation.
474 if vm.taprootCtx == nil && op.value > OP_16 {
475 vm.numOps++
476 if vm.numOps > MaxOpsPerScript {
477 str := fmt.Sprintf("exceeded max operation limit of %d",
478 MaxOpsPerScript)
479 return scriptError(ErrTooManyOperations, str)
480 }
481
482 } else if len(data) > MaxScriptElementSize {
483 str := fmt.Sprintf("element size %d exceeds max allowed size %d",
484 len(data), MaxScriptElementSize)
485 return scriptError(ErrElementTooBig, str)
486 }
487
488 // With ScriptVerifyConstScriptCode, OP_CODESEPARATOR in a non-segwit
489 // script is rejected even in an unexecuted branch. The script is
490 // non-segwit when neither a witness program nor a taproot execution
491 // context has been recorded on the engine: vm.witnessProgram is set
492 // for v0/v1 native witness spends and nested P2SH-witness spends,
493 // and vm.taprootCtx is set once the engine has recursed into the
494 // taproot script-path layer. Both nil means we are still executing
495 // a legacy script (scriptSig + scriptPubKey, or a P2SH redeem
496 // script), which is the only case the const-scriptcode rule
497 // applies to. The check is performed here, before the branch
498 // execution gate below, so it fires unconditionally on every
499 // OP_CODESEPARATOR encountered during script iteration.
500 if op.value == OP_CODESEPARATOR && vm.taprootCtx == nil &&
501 vm.witnessProgram == nil &&
502 vm.hasFlag(ScriptVerifyConstScriptCode) {
503
504 str := "OP_CODESEPARATOR used in non-segwit script"
505 return scriptError(ErrCodeSeparator, str)
506 }
507
508 // Nothing left to do when this is not a conditional opcode and it is
509 // not in an executing branch.
510 if !vm.isBranchExecuting() && !isOpcodeConditional(op.value) {
511 return nil
512 }
513
514 // Ensure all executed data push opcodes use the minimal encoding when
515 // the minimal data verification flag is set.
516 if vm.dstack.verifyMinimalData && vm.isBranchExecuting() &&
517 op.value >= 0 && op.value <= OP_PUSHDATA4 {

Callers 1

StepMethod · 0.95

Calls 7

hasFlagMethod · 0.95
isBranchExecutingMethod · 0.95
isOpcodeDisabledFunction · 0.85
scriptErrorFunction · 0.85
isOpcodeAlwaysIllegalFunction · 0.85
isOpcodeConditionalFunction · 0.85
checkMinimalDataPushFunction · 0.85

Tested by

no test coverage detected