interpreter

package
v2.2.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 8, 2023 License: ISC Imports: 16 Imported by: 2

README

interpreter

ISC License GoDoc

Package interpreter implements the an interpreter for the bitcoin transaction language. There is a comprehensive test suite.

This package has intentionally been designed so it can be used as a standalone package for any projects needing to use or validate bitcoin transaction scripts.

Bitcoin Scripts

Bitcoin provides a stack-based, FORTH-like language for the scripts in the bitcoin transactions. This language is not turing complete although it is still fairly powerful. A description of the language can be found at https://wiki.bitcoinsv.io/index.php/Script

Installation and Updating

$ go get -u github.com/libsv/go-bt/bscript/interpreter

Examples

  • Standard Pay-to-pubkey-hash Script
    Demonstrates creating a script which pays to a bitcoin address. It also prints the created script hex and uses the DisasmString function to display the disassembled script.

License

Package interpreter is licensed under the copyfree ISC License.

Documentation

Overview

Package interpreter implements the bitcoin transaction script language.

A complete description of the script language used by bitcoin can be found at https://en.bitcoin.it/wiki/Script. The following only serves as a quick overview to provide information on how to use the package.

This package provides data structures and functions to parse and execute bitcoin transaction scripts.

Script Overview

Bitcoin transaction scripts are written in a stack-base, FORTH-like language.

The bitcoin script language consists of a number of opcodes which fall into several categories such pushing and popping data to and from the stack, performing basic and bitwise arithmetic, conditional branching, comparing hashes, and checking cryptographic signatures. Scripts are processed from left to right and intentionally do not provide loops.

The vast majority of Bitcoin scripts at the time of this writing are of several standard forms which consist of a spender providing a public key and a signature which proves the spender owns the associated private key. This information is used to prove the spender is authorized to perform the transaction.

One benefit of using a scripting language is added flexibility in specifying what conditions must be met in order to spend bitcoins.

Errors

Errors returned by this package are of type interpreter.Error. This allows the caller to programmatically determine the specific error by examining the ErrorCode field of the type asserted interpreter.Error while still providing rich error messages with contextual information. A convenience function named IsErrorCode is also provided to allow callers to easily check for a specific error code. See ErrorCode in the package documentation for a full list.

Index

Constants

View Source
const (
	MaxOpsBeforeGenesis                = 500
	MaxStackSizeBeforeGenesis          = 1000
	MaxScriptSizeBeforeGenesis         = 10000
	MaxScriptElementSizeBeforeGenesis  = 520
	MaxScriptNumberLengthBeforeGenesis = 4
	MaxPubKeysPerMultiSigBeforeGenesis = 20
)

Limits applied to transactions before genesis

View Source
const (
	// LockTimeThreshold is the number below which a lock time is
	// interpreted to be a block number.  Since an average of one block
	// is generated per 10 minutes, this allows blocks for about 9,512
	// years.
	LockTimeThreshold = 5e8 // Tue Nov 5 00:53:20 1985 UTC
)

Variables

This section is empty.

Functions

This section is empty.

Types

type Debugger

type Debugger interface {
	BeforeExecute(*State)
	AfterExecute(*State)
	BeforeStep(*State)
	AfterStep(*State)
	BeforeExecuteOpcode(*State)
	AfterExecuteOpcode(*State)
	BeforeScriptChange(*State)
	AfterScriptChange(*State)
	AfterSuccess(*State)
	AfterError(*State, error)

	BeforeStackPush(*State, []byte)
	AfterStackPush(*State, []byte)
	BeforeStackPop(*State)
	AfterStackPop(*State, []byte)
}

Debugger implement to enable debugging. If enabled, copies of state are provided to each of the functions on call.

Each function is called during its stage of a threads lifecycle. A high level overview of this lifecycle is:

BeforeExecute
for step
   BeforeStep
   BeforeExecuteOpcode
   for each stack push
     BeforeStackPush
     AfterStackPush
   end for
   for each stack pop
     BeforeStackPop
     AfterStackPop
   end for
   AfterExecuteOpcode
   if end of script
     BeforeScriptChange
     AfterScriptChange
   end if
   if bip16 and end of final script
     BeforeStackPush
     AfterStackPush
   end if
   AfterStep
end for
AfterExecute
if success
  AfterSuccess
end if
if error
  AfterError
end if

type DefaultOpcodeParser

type DefaultOpcodeParser struct {
	ErrorOnCheckSig bool
}

DefaultOpcodeParser is a standard parser which can be used from zero value.

func (*DefaultOpcodeParser) Parse

Parse takes a *bscript.Script and returns a []interpreter.ParsedOp

func (*DefaultOpcodeParser) Unparse

func (p *DefaultOpcodeParser) Unparse(pscr ParsedScript) (*bscript.Script, error)

Unparse reverses the action of Parse and returns the ParsedScript as a *bscript.Script

type Engine

type Engine interface {
	Execute(opts ...ExecutionOptionFunc) error
}

Engine is the virtual machine that executes scripts.

func NewEngine

func NewEngine() Engine

NewEngine returns a new script engine for the provided locking script (of a previous transaction out), transaction, and input index. The flags modify the behaviour of the script engine according to the description provided by each flag.

type ExecutionOptionFunc

type ExecutionOptionFunc func(p *execOpts)

ExecutionOptionFunc for setting execution options.

func WithAfterGenesis

func WithAfterGenesis() ExecutionOptionFunc

WithAfterGenesis configure the execution to operate in an after-genesis context.

func WithDebugger

func WithDebugger(debugger Debugger) ExecutionOptionFunc

WithDebugger enable execution debugging with the provided configured debugger. It is important to note that when this setting is applied, it enables thread state cloning, at every configured debug step.

func WithFlags

func WithFlags(flags scriptflag.Flag) ExecutionOptionFunc

WithFlags configure the execution with the provided flags.

func WithForkID

func WithForkID() ExecutionOptionFunc

WithForkID configure the execution to allow a tx with a fork id.

func WithP2SH

func WithP2SH() ExecutionOptionFunc

WithP2SH configure the execution to allow a P2SH output.

func WithScripts

func WithScripts(lockingScript *bscript.Script, unlockingScript *bscript.Script) ExecutionOptionFunc

WithScripts configure the execution to run again a set of *bscript.Script.

func WithState

func WithState(state *State) ExecutionOptionFunc

WithState inject the provided state into the execution thread. This assumes that the state is correct for the scripts provided.

NOTE: This is highly experimental and is unstable when used with unintended states, and likely still when used in a happy path scenario. Therefore, it is recommended to only be used for debugging purposes.

The safest recommended *interpreter.State records for a given script can be are those which can be captured during `debugger.BeforeStep` and `debugger.AfterStep`.

func WithTx

func WithTx(tx *bt.Tx, inputIdx int, prevOutput *bt.Output) ExecutionOptionFunc

WithTx configure the execution to run again a tx.

type OpcodeParser

type OpcodeParser interface {
	Parse(*bscript.Script) (ParsedScript, error)
	Unparse(ParsedScript) (*bscript.Script, error)
}

OpcodeParser parses *bscript.Script into a ParsedScript, and unparsing back

type ParsedOpcode

type ParsedOpcode struct {
	Data []byte
	// contains filtered or unexported fields
}

ParsedOpcode is a parsed opcode.

func (*ParsedOpcode) AlwaysIllegal

func (o *ParsedOpcode) AlwaysIllegal() bool

AlwaysIllegal returns true if the op is always illegal.

func (*ParsedOpcode) IsConditional

func (o *ParsedOpcode) IsConditional() bool

IsConditional returns true if the op is a conditional.

func (*ParsedOpcode) IsDisabled

func (o *ParsedOpcode) IsDisabled() bool

IsDisabled returns true if the op is disabled.

func (ParsedOpcode) Length

func (o ParsedOpcode) Length() int

Length returns the data length of the opcode.

func (ParsedOpcode) Name

func (o ParsedOpcode) Name() string

Name returns the human readable name for the current opcode.

func (*ParsedOpcode) RequiresTx

func (o *ParsedOpcode) RequiresTx() bool

RequiresTx returns true if the op is checksig.

func (ParsedOpcode) Value

func (o ParsedOpcode) Value() byte

Value returns the byte value of the opcode.

type ParsedScript

type ParsedScript []ParsedOpcode

ParsedScript is a slice of ParsedOp

func (ParsedScript) IsPushOnly

func (p ParsedScript) IsPushOnly() bool

IsPushOnly returns true if the ParsedScript only contains push commands

type State

type State struct {
	DataStack            [][]byte
	AltStack             [][]byte
	ElseStack            [][]byte
	CondStack            []int
	SavedFirstStack      [][]byte
	Scripts              []ParsedScript
	ScriptIdx            int
	OpcodeIdx            int
	LastCodeSeparatorIdx int
	NumOps               int
	Flags                scriptflag.Flag
	IsFinished           bool
	Genesis              struct {
		AfterGenesis bool
		EarlyReturn  bool
	}
}

State a snapshot of a threads state during execution.

func (*State) Opcode

func (s *State) Opcode() ParsedOpcode

Opcode the current interpreter.ParsedOpcode from the threads program counter.

func (*State) RemainingScript

func (s *State) RemainingScript() ParsedScript

RemainingScript the remaining script to be executed.

type StateHandler

type StateHandler interface {
	State() *State
	SetState(state *State)
}

StateHandler interfaces getting and applying state.

Directories

Path Synopsis
Package debug comment
Package debug comment
Package errs comment
Package errs comment
Package scriptflag comment
Package scriptflag comment

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL