Documentation
¶
Overview ¶
Package scparser provides a Neo3 VM opcode parser and parsing utilities.
It's designed for applications that don't need full VM implementation, but stil require some way to analyze bytecode.
Index ¶
- Constants
- Variables
- func GetAppCallNoArgsFromContext(ctx *Context) (util.Uint160, string, callflag.CallFlag, error)
- func GetBigIntFromInstr(instr Instruction) (*big.Int, error)
- func GetBoolFromInstr(instr Instruction) (bool, error)
- func GetBytesFromInstr(instr Instruction) ([]byte, error)
- func GetInt64FromInstr(instr Instruction) (int64, error)
- func GetListOfEFromContext[E any](ctx *Context, getEFromInstr GetEFromInstr[E], maxLen ...int) ([]E, error)
- func GetListOfEFromPushedItems[E any](items []PushedItem, getEFromInstr GetEFromInstr[E]) ([]E, error)
- func GetPublicKeyFromInstr(instr Instruction) (*keys.PublicKey, error)
- func GetSignatureFromInstr(instr Instruction) ([]byte, error)
- func GetStringFromInstr(instr Instruction) (string, error)
- func GetTryParams(op opcode.Opcode, p []byte) ([]byte, []byte)
- func GetUTF8StringFromInstr(instr Instruction) (string, error)
- func GetUint160FromInstr(instr Instruction) (util.Uint160, error)
- func GetUint256FromInstr(instr Instruction) (util.Uint256, error)
- func IsMultiSigContract(script []byte) bool
- func IsScriptCorrect(script []byte, methods bitfield.Field) error
- func IsSignatureContract(script []byte) bool
- func IsStandardContract(script []byte) bool
- func ParseMultiSigContract(script []byte) (int, [][]byte, bool)
- func ParseSignatureContract(script []byte) ([]byte, bool)
- type Context
- func (c *Context) CalcJumpOffset(parameter []byte) (int, int, error)
- func (c *Context) CurrInstr() (int, opcode.Opcode)
- func (c *Context) IP() int
- func (c *Context) Jump(pos int)
- func (c *Context) LenInstr() int
- func (c *Context) Next() (opcode.Opcode, []byte, error)
- func (c *Context) NextIP() int
- func (c *Context) NextInstr() (int, opcode.Opcode)
- type GetEFromInstr
- type Instruction
- type MapPair
- type PushedItem
- func GetAppCallFromContext(ctx *Context) (util.Uint160, string, callflag.CallFlag, []PushedItem, error)
- func GetAppCallFromContextNonStrict(ctx *Context) (util.Uint160, string, callflag.CallFlag, []PushedItem, error)
- func GetListFromContext(ctx *Context, maxLen ...int) ([]PushedItem, error)
- func GetListFromContextNonStrict(ctx *Context, maxLen ...int) ([]PushedItem, error)
- func ParseAppCall(script []byte) (util.Uint160, string, callflag.CallFlag, []PushedItem, error)
- func ParseAppCallNonStrict(script []byte) (util.Uint160, string, callflag.CallFlag, []PushedItem, error)
- func ParseSomething(script []byte, strict bool) ([]PushedItem, error)
Constants ¶
const (
// MaxMultisigKeys is the maximum number of keys allowed for correct multisig contract.
MaxMultisigKeys = 1024
)
Variables ¶
var ( // ErrNestedInstruction is returned on attempt to parse non-nested // type from Array/Struct/Map. ErrNestedInstruction = errors.New("unexpected Array/Struct/Map stackitem") // ErrEmptyInstruction is returned on an attempt to retrieve some value from // the instruction placeholder got after non-strict mode of script parsing. ErrEmptyInstruction = errors.New("instruction is empty") )
Functions ¶
func GetAppCallNoArgsFromContext ¶ added in v0.117.0
GetAppCallNoArgsFromContext parses a contract call (which is effectively an opcode.SYSCALL instruction with interopnames.SystemContractCall parameter) assuming the arguments of the contract call (usually followed by opcode.PACK opcode) are already parsed. It returns the calling contract hash, method name and callflags.
func GetBigIntFromInstr ¶ added in v0.117.0
func GetBigIntFromInstr(instr Instruction) (*big.Int, error)
GetBigIntFromInstr returns *big.Int value emitted by the specified instruction. It works with static integer values only; for the rest of cases (result of SYSCALL, custom integer operations, etc.) parse the script manually. It returns ErrEmptyInstruction on attempt to convert an empty instruction got after non-strict script parsing.
func GetBoolFromInstr ¶ added in v0.117.0
func GetBoolFromInstr(instr Instruction) (bool, error)
GetBoolFromInstr returns the boolean value emitted by the specified instruction. It works with static bool values only; for the rest of cases (result of SYSCALL, custom bool operations, etc.) parse the script manually. It returns ErrEmptyInstruction on attempt to convert an empty instruction got after non-strict script parsing.
func GetBytesFromInstr ¶ added in v0.117.0
func GetBytesFromInstr(instr Instruction) ([]byte, error)
GetBytesFromInstr returns bytes value emitted by the specified PUSHDATA* instruction. It works with static byte values only; for the rest of cases (result of SYSCALL, custom bytes operations, etc.) parse the script manually. It returns ErrEmptyInstruction on attempt to convert an empty instruction got after non-strict script parsing.
func GetInt64FromInstr ¶ added in v0.117.0
func GetInt64FromInstr(instr Instruction) (int64, error)
GetInt64FromInstr returns int64 value (ensuring bounds) emitted by the specified instruction. It works with static integer values only; for the rest of cases (result of SYSCALL, custom integer operations, etc.) parse the script manually. It returns ErrEmptyInstruction on attempt to convert an empty instruction got after non-strict script parsing.
func GetListOfEFromContext ¶ added in v0.117.0
func GetListOfEFromContext[E any](ctx *Context, getEFromInstr GetEFromInstr[E], maxLen ...int) ([]E, error)
GetListOfEFromContext is an implementation of GetListFromContext that works with uniformly typed elements. It accepts GetEFromInstr delegate to retrieve a single list element from the Instruction (hence, only non-nested PushedItem types are supported; use a custom parser for the list of nested types). It returns ErrEmptyInstruction on attempt to convert an empty instruction got after non-strict script parsing.
func GetListOfEFromPushedItems ¶ added in v0.117.0
func GetListOfEFromPushedItems[E any](items []PushedItem, getEFromInstr GetEFromInstr[E]) ([]E, error)
GetListOfEFromPushedItems returns the list of uniformly typed elements parsed from the provided list of PushedItem. It accepts GetEFromInstr delegate to retrieve a single list element from the Instruction (hence, only non-nested PushedItem types are supported; use a custom parser for the list of nested types). It returns ErrEmptyInstruction on attempt to convert an empty instruction got after non-strict script parsing.
func GetPublicKeyFromInstr ¶ added in v0.117.0
func GetPublicKeyFromInstr(instr Instruction) (*keys.PublicKey, error)
GetPublicKeyFromInstr returns the secp256r1 public key bytes emitted by the specified instruction. It works with static values only; for the rest of cases (result of SYSCALL, custom bytes operations, etc.) parse the script manually. It returns nil in case if instruction is empty. It returns ErrEmptyInstruction on attempt to convert an empty instruction got after non-strict script parsing.
func GetSignatureFromInstr ¶ added in v0.117.0
func GetSignatureFromInstr(instr Instruction) ([]byte, error)
GetSignatureFromInstr returns the standard signature bytes emitted by the specified instruction. It works with static values only; for the rest of cases (result of SYSCALL, custom bytes operations, etc.) parse the script manually. It returns ErrEmptyInstruction on attempt to convert an empty instruction got after non-strict script parsing.
func GetStringFromInstr ¶ added in v0.117.0
func GetStringFromInstr(instr Instruction) (string, error)
GetStringFromInstr returns the string value emitted by the specified instruction. It works with static string values only; for the rest of cases (result of SYSCALL, custom string operations, etc.) parse the script manually. It returns ErrEmptyInstruction on attempt to convert an empty instruction got after non-strict script parsing.
func GetTryParams ¶
GetTryParams splits opcode.TRY and opcode.TRYL instruction parameter into offsets for catch and finally blocks.
func GetUTF8StringFromInstr ¶ added in v0.117.0
func GetUTF8StringFromInstr(instr Instruction) (string, error)
GetUTF8StringFromInstr returns the string value emitted by the specified instruction. It checks that the result is a valid UTF-8 string. It works with static string values only; for the rest of cases (result of SYSCALL, custom string operations, etc.) parse the script manually. It returns ErrEmptyInstruction on attempt to convert an empty instruction got after non-strict script parsing.
func GetUint160FromInstr ¶ added in v0.117.0
func GetUint160FromInstr(instr Instruction) (util.Uint160, error)
GetUint160FromInstr returns the util.Uint160 value emitted by the specified instruction. It works with static hash values only; for the rest of cases (result of SYSCALL, custom bytes operations, etc.) parse the script manually. It returns ErrEmptyInstruction on attempt to convert an empty instruction got after non-strict script parsing.
func GetUint256FromInstr ¶ added in v0.117.0
func GetUint256FromInstr(instr Instruction) (util.Uint256, error)
GetUint256FromInstr returns the util.Uint256 value emitted by the specified instruction. It works with static hash values only; for the rest of cases (result of SYSCALL, custom bytes operations, etc.) parse the script manually. It returns ErrEmptyInstruction on attempt to convert an empty instruction got after non-strict script parsing.
func IsMultiSigContract ¶
IsMultiSigContract checks whether the passed script is a multi-signature contract.
func IsScriptCorrect ¶
IsScriptCorrect checks the script for errors and mask provided for correctness wrt instruction boundaries. Normally, it returns nil, but it can return some specific error if there is any.
func IsSignatureContract ¶
IsSignatureContract checks whether the passed script is a signature check contract.
func IsStandardContract ¶
IsStandardContract checks whether the passed script is a signature or multi-signature contract.
func ParseMultiSigContract ¶
ParseMultiSigContract returns the number of signatures and a list of public keys from the verification script of the contract.
func ParseSignatureContract ¶
ParseSignatureContract parses a simple signature contract and returns a public key.
Types ¶
type Context ¶
type Context struct {
// contains filtered or unexported fields
}
Context represents bytecode parser context.
func NewContext ¶
NewContext creates a new parsing context for the given program with the given initial offset.
func (*Context) CalcJumpOffset ¶
CalcJumpOffset returns an absolute (wrt bytecode loaded into Context) and a relative (wrt current Context.IP) offset of JMP/CALL/TRY instructions (and their long forms). 1 or 4 byte parameters are accepted.
func (*Context) Jump ¶
Jump unconditionally moves the next instruction pointer to the specified location.
func (*Context) Next ¶
Next returns the next instruction to execute with its parameter if any. The parameter is not copied and shouldn't be written to. After its invocation, the instruction pointer points to the instruction returned.
type GetEFromInstr ¶ added in v0.117.0
type GetEFromInstr[E any] func(Instruction) (E, error)
GetEFromInstr is a delegate that returns an element emitted by the specified Instruction and the error. GetInt64FromInstr, GetBigIntFromInstr, GetStringFromInstr, GetUTF8StringFromInstr, GetBoolFromInstr, GetUint160FromInstr,GetUint256FromInstr, GetSignatureFromInstr, GetPublicKeyFromInstr are suitable implementations. You may also use a custom implementation.
type Instruction ¶ added in v0.117.0
Instruction represents a single VM instruction (opcode.Opcode with an optional parameter). You may safely modify the content of Param since a copy of the original script buffer is created during script parsing.
type MapPair ¶ added in v0.117.0
type MapPair struct {
Key Instruction
Value PushedItem
}
MapPair represents a key-value pair in a Map stackitem. Key is always represented as a single Instruction and can only emit stackitem.Boolean, stackitem.Integer or stackitem.ByteString on stack. Value is a PushedItem that may emit as primitive as complex stackitems.
type PushedItem ¶ added in v0.117.0
type PushedItem struct {
Instruction
List []PushedItem
Map []MapPair
}
PushedItem represents a container for VM instruction (opcode with corresponding parameter) potentially emitting stackitem to stack. If instruction execution results in some nested stackitem emission (Array, Map or Struct), then List/Map is filled in with the content of this stakitem (see the GetListFromContext documentation for the list of VM opcodes corresponding to such instructions).
func GetAppCallFromContext ¶ added in v0.117.0
func GetAppCallFromContext(ctx *Context) (util.Uint160, string, callflag.CallFlag, []PushedItem, error)
GetAppCallFromContext parses a contract call (which is effectively an opcode.SYSCALL instruction with interopnames.SystemContractCall parameter) along with the set of arguments. It returns the calling contract hash, method name, callflags and arguments. It stops parsing after the first System.Contract.Call occurrence, so check context's IP against the script length if you need to ensure there are no additional opcodes after SYSCALL.
func GetAppCallFromContextNonStrict ¶ added in v0.117.0
func GetAppCallFromContextNonStrict(ctx *Context) (util.Uint160, string, callflag.CallFlag, []PushedItem, error)
GetAppCallFromContextNonStrict is similar to GetAppCallFromContext except that it does not check PACK/PACKSTRUCT/PACKMAP arguments against the stack length. Missing elements (if any) will be filled with empty PushedItem.
func GetListFromContext ¶ added in v0.117.0
func GetListFromContext(ctx *Context, maxLen ...int) ([]PushedItem, error)
GetListFromContext parses a list of elements from the VM context starting from the beginning and ending with the first opcode.SYSCALL or opcode.RET occurrence or the program end. It modifies the given context, so save the current context's IP before calling GetListFromContext to be able to reset the context state afterwards. [vm.MaxStackSize] is used as the default list length constraint if maxLen is not specified. It works with nested Array/Struct/Map items produced by opcode.NEWARRAY0, opcode.NEWSTRUCT0, opcode.PACK, opcode.PACKSTRUCT, opcode.PACKMAP. Optional opcode.SWAP, opcode.REVERSE3 opcode.REVERSE4, opcode.REVERSEN, opcode.REVERSEITEMS instructions are supported. It does not support any other opcode.SYSCALL instructions except System.Contract.Call. Once finished, it resets ctx state to the instruction corresponding to System.Contract.Call's callflag argument (if there's any). It does not check if there are additional opcodes after the first opcode.RET occurrence, so check the context's IP against the script length if you need to ensure that. It returns an unwrapped list of elements in the direct order (no additional reverse due to stack operations order is required).
func GetListFromContextNonStrict ¶ added in v0.117.0
func GetListFromContextNonStrict(ctx *Context, maxLen ...int) ([]PushedItem, error)
GetListFromContextNonStrict works exactly like GetListFromContext except that it does not check PACK/PACKSTRUCT/PACKMAP arguments against the stack length. Missing elements (if any) will be filled with empty PushedItem.
func ParseAppCall ¶ added in v0.117.0
ParseAppCall works similar to GetAppCallFromContext except that it creates the parsing context by itself. It stops parsing after the first System.Contract.Call occurrence, so use GetAppCallFromContext if you need to ensure there are no additional opcodes after SYSCALL.
func ParseAppCallNonStrict ¶ added in v0.117.0
func ParseAppCallNonStrict(script []byte) (util.Uint160, string, callflag.CallFlag, []PushedItem, error)
ParseAppCallNonStrict is similar to ParseAppCall except that it does not check PACK/PACKSTRUCT/PACKMAP arguments against the stack length. Missing elements (if any) will be filled with empty PushedItem.
func ParseSomething ¶ added in v0.117.0
func ParseSomething(script []byte, strict bool) ([]PushedItem, error)
ParseSomething works similar to GetListFromContext except that it creates the parsing context by itself, does not perform list unwrapping in the end and returns an error on System.Contract.Call occurrence. If strict is set to false, it will not check any PACK/PACKSTRUCT/PACKMAP arguments against the stack length. Missing elements (if any) will be filled with empty PushedItem.
func (PushedItem) IsEmpty ¶ added in v0.117.0
func (i PushedItem) IsEmpty() bool
IsEmpty denotes whether this instruction is a stub used to fill in the gaps in non-strict mode of script parsing. Such empty instructions may be produced by GetListFromContext and similar methods.
func (PushedItem) IsList ¶ added in v0.117.0
func (i PushedItem) IsList() bool
IsList denotes whether the underlying PushedItem is a list (pushes stackitem.Array or stackitem.Struct on stack).
func (PushedItem) IsMap ¶ added in v0.117.0
func (i PushedItem) IsMap() bool
IsMap denotes whether the underlying PushedItem is a map (pushes stackitem.Map on stack).
func (PushedItem) IsNested ¶ added in v0.117.0
func (i PushedItem) IsNested() bool
IsNested denotes whether execution of this instruction results in emission of some nested stackitem (Array, Struct or Map). See the GetListFromContext documentation for the list of VM opcodes corresponding to such instructions.
func (PushedItem) IsNull ¶ added in v0.117.0
func (i PushedItem) IsNull() bool
IsNull returns true if the underlying instruction pushes stackitem.Null on stack.