model

package module
v0.52.0 Latest Latest
Warning

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

Go to latest
Published: Nov 22, 2024 License: MIT Imports: 16 Imported by: 8

README

Model

codecov NPM Version Go Release

Reusing data types, domain model or Shared Kernel in DDD parlance. This uses Protobuf definitions and holds the equivalent code for both Golang and Typescript that can be used in userland code.

Protobuf

If you don’t have buf installed, follow the installation guide from buf.build.

Generating models
buf generate
Updating the model

All models are currently defined in the asset.proto file. It is a relatively small model.

If adding lots of models, might make sense to split into a new file.

The below steps are needed to successfully update and distribute the models:

  • Add model changes to .proto file.
  • Verify there are no errors by linting. Use buf lint
  • Also format the proto files using buf format -w.
  • Generate the code definition of your model. Use buf generate
  • If adding support for a new language, please update buf.gen.yaml to include the task.
  • Commit the generated code.
  • Bump up the version number in package.json
Reproducible models

On every PR and Push, Github actions runs multiple tasks, one of which runs buf generate on the CI runner and checks if there is a diff between the generated code you are submitting and what it generates. If there is a diff, the CI run fails.

This ensures bad code isn't mistakenly committed and we can safely distribute the changes to everyone

Test

For the test run the following command:

go test ./...

Documentation

Overview

Package model provides common data structures shared among blndgs projects. This file has been copied from the Bundler project. It is included in the model package to avoid introducing a cyclical dependency between the Model and Bundler projects and accommodate Bundler<->Solver communication. Any modifications made to the Bundler file should be reflected here as well to maintain consistency.

Note: In the future, this file may move here as the single source of truth.

Package model provides structures and methods for the communication between the Bundler and Solver. This file defines extensions to the UserOperation struct and methods for extracting and inserting Intent JSON from/to the CallData and Signature fields.

The CallData field in a userOperation is expected to contain either the Intent JSON or the EVM instructions but not both. The Intent JSON is expected to be appended to the signature value within the Signature field when the Calldata field contains the EVM instructions. The Signature field is expected to contain only the signature when the userOperation is unsolved.

Index

Constants

View Source
const (
	ErrNoIntentFound         userOperationError = "no Intent found"
	ErrIntentInvalidJSON     userOperationError = "invalid Intent JSON"
	ErrNoSignatureValue      userOperationError = "signature value is not found"
	ErrNoCallData            userOperationError = "no CallData found"
	ErrInvalidCallData       userOperationError = "invalid hex-encoded CallData"
	ErrInvalidSignature      userOperationError = "invalid hex-encoded signature"
	ErrInvalidUserOp         userOperationError = "ambiguous UserOperation solved state"
	ErrDoubleIntentDef       userOperationError = "intent JSON is set in both calldata and signature fields"
	ErrUnsupportedIntentType userOperationError = "unsupported intent type"
	ErrInvalidChainID        userOperationError = "invalid chain ID"
)

Define error constants

View Source
const (
	KernelSignatureLength = 69
	SimpleSignatureLength = 65
)
View Source
const (
	CrossChainMarker     uint16 = 0xFFFF
	HashPlaceholder      uint16 = 0xFFFF // Placeholder for the userOp hash that will be computed during validation
	OpTypeLength                = 2
	IntentJSONLengthSize        = 2
	HashLength                  = 32
	HashListLengthSize          = 1
	MinOpCount                  = 2
	MaxOpCount                  = 3
	PlaceholderSize             = 2
	OperationHashSize           = 32
)

Variables

View Source
var (

	// UserOpPrimitives is the primitive ABI types for each UserOperation field.
	UserOpPrimitives = []abi.ArgumentMarshaling{
		{Name: "sender", InternalType: "Sender", Type: "address"},
		{Name: "nonce", InternalType: "Nonce", Type: "uint256"},
		{Name: "initCode", InternalType: "InitCode", Type: "bytes"},
		{Name: "callData", InternalType: "CallData", Type: "bytes"},
		{Name: "callGasLimit", InternalType: "CallGasLimit", Type: "uint256"},
		{Name: "verificationGasLimit", InternalType: "VerificationGasLimit", Type: "uint256"},
		{Name: "preVerificationGas", InternalType: "PreVerificationGas", Type: "uint256"},
		{Name: "maxFeePerGas", InternalType: "MaxFeePerGas", Type: "uint256"},
		{Name: "maxPriorityFeePerGas", InternalType: "MaxPriorityFeePerGas", Type: "uint256"},
		{Name: "paymasterAndData", InternalType: "PaymasterAndData", Type: "bytes"},
		{Name: "signature", InternalType: "Signature", Type: "bytes"},
	}

	// UserOpType is the ABI type of a UserOperation.
	UserOpType, _ = abi.NewType("tuple", "op", UserOpPrimitives)

	// UserOpArr is the ABI type for an array of UserOperations.
	UserOpArr, _ = abi.NewType("tuple[]", "ops", UserOpPrimitives)
)
View Source
var (
	ErrInvalidHashListLength = errors.New("invalid hash list length")
	ErrInvalidHashListEntry  = errors.New("invalid hash list entry")
	ErrPlaceholderNotFound   = errors.New("invalid hash list with missing placeholder")
	ErrHashListInvalidValue  = errors.New("invalid hash list hash value")
	ErrMissingCrossChainData = errors.New("missing cross-chain data")
	ErrCrossChainSameChain   = errors.New("destination and source chain cannot be the same")
	ErrNoIntent              = errors.New("no intent found")
)

Error definitions

View Source
var EntrypointV06 = common.HexToAddress("0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789")
View Source
var KernelSignaturePrefixValues = map[KernelSignaturePrefix][]byte{
	Prefix0: []byte{0, 0, 0, 0},
	Prefix1: []byte{0, 0, 0, 1},
	Prefix2: []byte{0, 0, 0, 2},
}

Functions

func BuildCrossChainData added in v0.45.0

func BuildCrossChainData(intentJSON []byte, hashList []CrossChainHashListEntry) ([]byte, error)

BuildCrossChainData constructs the cross-chain data payload used in cross-chain UserOperations.

**Purpose:** This low-level utility function constructs the cross-chain data payload by combining the Intent JSON and a provided hash list. It formats the data according to the specified cross-chain data structure required by cross-chain operations.

**When to Use:** Use `BuildCrossChainData` when you have the Intent JSON and the hash list already prepared and need to construct the cross-chain data payload manually. This function does not perform any sorting or validation of the hash list entries.

**Parameters:**

  • `intentJSON`: The Intent JSON bytes.
  • `hashList`: A slice of `CrossChainHashListEntry` representing operation hashes and placeholders.

**Returns:**

  • `[]byte`: The constructed cross-chain data payload.
  • `error`: An error if building fails (e.g., if the Intent JSON exceeds the maximum allowed size).

**Cross-Chain Data Format:** The cross-chain data is structured as follows: - **OpType (2 bytes)**: A marker indicating a cross-chain operation (`0xFFFF`). - **Intent JSON Length (2 bytes)**: The length of the Intent JSON. - **Intent JSON (variable length)**: The serialized Intent JSON. - **Hash List Length (1 byte)**: The number of entries in the hash list. - **Hash List Entries (variable length)**: Each entry is either:

  • **Placeholder (2 bytes)**: `0xFFFF`, representing the current operation's hash.
  • **Operation Hash (32 bytes)**: The hash of another operation in the cross-chain set.

**Usage Notes:** - This function assumes that the hash list entries are already in the correct order. - It does not perform any sorting or validation on the hash list. - The caller is responsible for ensuring the hash list is correctly constructed.

**Related Functions:**

  • `EncodeCrossChainCallData`: A higher-level function that builds the cross-chain call data for a `UserOperation`, including sorting and constructing the hash list.

func ExtractDestinationChainID added in v0.45.0

func ExtractDestinationChainID(intent *pb.Intent) (*big.Int, error)

ExtractDestinationChainID retrieves the chain ID from the 'to' field of the intent.

func ExtractJSONFromField added in v0.14.0

func ExtractJSONFromField(fieldData string) (string, bool)

ExtractJSONFromField tries to unmarshal the provided field data into an Intent struct. If successful, it assumes the field data is a valid JSON string of the Intent.

Returns:

  • string: The JSON data if unmarshalling is successful.
  • bool: A boolean indicating if the unmarshalling was successful.

func ExtractSourceChainID added in v0.45.0

func ExtractSourceChainID(intent *pb.Intent) (*big.Int, error)

ExtractSourceChainID retrieves the chain ID from the 'from' field of the intent.

func FromBigInt added in v0.18.3

func FromBigInt(i *big.Int) (*protov1.BigInt, error)

FromBigInt converts a *big.Int to a protobuf BigInt message.

func IsCrossChainData added in v0.50.0

func IsCrossChainData(data []byte, minHashListLength int, maxHashListLength int) bool

IsCrossChainData checks if the provided data represents cross-chain data.

Parameters:

  • data: The data to check.
  • minHashListLength: Minimum required length of the hash list.
  • maxHashListLength: Maximum allowed length of the hash list.

Returns:

  • bool: True if it's cross-chain data, false otherwise.

func IsCrossChainIntent added in v0.45.0

func IsCrossChainIntent(intent *pb.Intent) (bool, error)

IsCrossChainIntent checks if the given Intent represents a cross-chain intent.

Parameters:

  • intent: The Intent struct to check.

Returns:

  • bool: True if it's a cross-chain intent, false otherwise.
  • error: An error if chain IDs cannot be extracted.

func ToBigInt added in v0.18.3

func ToBigInt(b *protov1.BigInt) (*big.Int, error)

ToBigInt converts a protobuf BigInt message to a *big.Int.

Types

type BodyOfUserOps added in v0.4.0

type BodyOfUserOps struct {
	UserOps    []*UserOperation   `json:"user_ops" binding:"required,dive"`
	UserOpsExt []UserOperationExt `json:"user_ops_ext" binding:"required,dive"`
}

BodyOfUserOps represents the request body for HTTP requests sent to the Solver. It contains slices of UserOperation and UserOperationExt, representing the primary data and its extended information required for processing by the Solver.

type CrossChainData added in v0.45.0

type CrossChainData struct {
	IntentJSON []byte
	HashList   []CrossChainHashListEntry
}

CrossChainData represents the parsed components of cross-chain data.

func ParseCrossChainData added in v0.45.0

func ParseCrossChainData(data []byte) (*CrossChainData, error)

ParseCrossChainData parses the cross-chain data into a structured format.

type CrossChainHashListEntry added in v0.45.0

type CrossChainHashListEntry struct {
	IsPlaceholder bool
	OperationHash []byte
}

CrossChainHashListEntry represents an entry in the cross-chain hash list.

func BuildSortedHashList added in v0.45.0

func BuildSortedHashList(thisOpHash common.Hash, otherOpHashes []common.Hash) ([]CrossChainHashListEntry, error)

BuildSortedHashList constructs a sorted hash list for cross-chain operations.

**Purpose:** This utility function creates a hash list containing the placeholder for the current operation's hash and the hashes of other operations involved in the cross-chain set. It sorts the hash list entries in ascending order to establish a deterministic hash calculation.

**Parameters:**

  • `thisOpHash`: The hash of the current `UserOperation`.
  • `otherOpHashes`: A slice of hashes (`[]common.Hash`) representing other operations in the cross-chain set.

**Returns:**

  • `[]CrossChainHashListEntry`: The sorted hash list entries.
  • `error`: An error if the operation hashes are invalid.

**Usage Notes:** - Use this function to build the hash list when preparing cross-chain call data. - It ensures the placeholder and other operation hashes are correctly ordered.

**Example:** ```go hashList, err := BuildSortedHashList(thisOpHash, []common.Hash{otherOpHash})

if err != nil {
    // Handle error
}

crossChainData, err := BuildCrossChainData(intentJSONBytes, hashList) ```

**Related Functions:** - `EncodeCrossChainCallData`: Can utilize this function to build the hash list. - `BuildCrossChainData`: Consumes the hash list entries to construct the cross-chain data payload.

type KernelSignaturePrefix added in v0.34.0

type KernelSignaturePrefix int
const (
	Prefix0 KernelSignaturePrefix = iota
	Prefix1
	Prefix2
)

type UserOpSolvedStatus added in v0.16.0

type UserOpSolvedStatus int

UserOpSolvedStatus is an enum type that defines the possible states of a UserOperation's resolution.It indicates whether an operation is unsolved, solved, conventional, or in an unknown state.

const (
	UnsolvedUserOp          UserOpSolvedStatus = iota
	UnsolvedAggregateUserOp                    // Unsolved Cross-chain userOp that contains 1 or more cross-chain unsolved userOps
	SolvedUserOp                               // Intent Json values must be present
	// ConventionalUserOp indicates that the UserOperation does not contain Intent JSON and
	// must have a valid EVM calldata value.
	ConventionalUserOp
	UnSignedUserOp // UnSignedUserOp indicates that the UserOperation does not contain a signature value.
	// UnknownUserOp indicates that the UserOperation's state is unknown or ambiguous.
	UnknownUserOp
)

type UserOperation added in v0.4.0

type UserOperation struct {
	Sender               common.Address `json:"sender"               mapstructure:"sender"               validate:"required"`
	Nonce                *big.Int       `json:"nonce"                mapstructure:"nonce"                validate:"required"`
	InitCode             []byte         `json:"initCode"             mapstructure:"initCode"             validate:"required"`
	CallData             []byte         `json:"callData"             mapstructure:"callData"             validate:"required"`
	CallGasLimit         *big.Int       `json:"callGasLimit"         mapstructure:"callGasLimit"         validate:"required"`
	VerificationGasLimit *big.Int       `json:"verificationGasLimit" mapstructure:"verificationGasLimit" validate:"required"`
	PreVerificationGas   *big.Int       `json:"preVerificationGas"   mapstructure:"preVerificationGas"   validate:"required"`
	MaxFeePerGas         *big.Int       `json:"maxFeePerGas"         mapstructure:"maxFeePerGas"         validate:"required"`
	MaxPriorityFeePerGas *big.Int       `json:"maxPriorityFeePerGas" mapstructure:"maxPriorityFeePerGas" validate:"required"`
	PaymasterAndData     []byte         `json:"paymasterAndData"     mapstructure:"paymasterAndData"     validate:"required"`
	Signature            []byte         `json:"signature"            mapstructure:"signature"`
}

UserOperation represents an EIP-4337 style transaction for a smart contract account.

func (*UserOperation) Aggregate added in v0.47.0

func (op *UserOperation) Aggregate(embeddedOp *UserOperation) error

Aggregate combines the current UserOperation with another unsolved cross-chain UserOperation.

Preconditions:

  • Both the called UserOperation and the embeddedOp are valid unsolved userOps (Validate() returns UnsolvedUserOp).
  • Both userOps are valid cross-chain userOps.

If any precondition is not met, returns an error indicating which userOp didn't meet the precondition.

Behavior:

  • Copies the embeddedOp's packed data into the signature field of the called UserOperation.
  • If initCode is set in the embeddedOp, it is copied into the called UserOperation.
  • If the same embeddedOp is already aggregated, the operation is idempotent.
  • If a different embeddedOp is already aggregated, the existing packed
  • data is replaced with the new embeddedOp's data.

Returns:

  • error: An error if the operation fails.

func (*UserOperation) EncodeCrossChainCallData added in v0.45.0

func (op *UserOperation) EncodeCrossChainCallData(entrypoint common.Address, otherOpHash common.Hash, isSourceOp bool) ([]byte, error)

EncodeCrossChainCallData constructs the cross-chain call data payload for a `UserOperation`.

**Purpose:** This high-level function (vs the `BuildCrossChainData`) prepares the cross-chain call data by calculating the current operation's hash, building and sorting the hash list, and constructing the cross-chain data payload. It encapsulates the logic required for cross-chain operations involving two `UserOperation`s or extended for more in the future.

**When to Use:** Use `EncodeCrossChainCallData` when you need to construct the cross-chain call data for a `UserOperation` and have all the necessary parameters, including the entry point, the hash of the other operation, and the Intent JSON. This function handles the calculation of hashes, sorting of the hash list, and building the cross-chain data payload.

**Parameters:**

  • `entrypoint`: The entry point address used to calculate the `UserOperation` hash.
  • `otherOpHash`: The operation hash of the other chain's `UserOperation`.
  • `isSourceOp`: A boolean indicating if this is the source operation (`true`) or the destination operation (`false`).

**Returns:**

  • `[]byte`: The encoded cross-chain call data payload: Intent JSON and sorted hash list.
  • `error`: An error if encoding fails (e.g., invalid chain IDs or Intent JSON exceeds maximum size).

**Cross-Chain Data Construction Steps:** 1. **Calculate Current Operation Hash**: Computes the hash of the current `UserOperation`. 2. **Build and Sort Hash List**:

  • Create a hash list containing a placeholder for the current operation's hash and the other operation's hash.
  • Sort the hash list in ascending order based on the hash values.

3. **Construct Cross-Chain Data**:

  • Use `BuildCrossChainData` to assemble the cross-chain data payload.

**Related Functions:** - `BuildCrossChainData`: Used internally to construct the cross-chain data payload.

func (*UserOperation) ExtractEmbeddedOp added in v0.47.0

func (op *UserOperation) ExtractEmbeddedOp() (*UserOperation, error)

ExtractEmbeddedOp reverses the Aggregate operation and extracts the packed other UserOperation from the signature field.

Returns:

  • *UserOperation: The extracted UserOperation.
  • error: An error if extraction fails.

func (*UserOperation) GetDynamicGasPrice added in v0.4.0

func (op *UserOperation) GetDynamicGasPrice(basefee *big.Int) *big.Int

GetDynamicGasPrice returns the effective gas price paid by the UserOperation given a basefee. If basefee is nil, it will assume a value of 0.

func (*UserOperation) GetFactory added in v0.4.0

func (op *UserOperation) GetFactory() common.Address

GetFactory returns the address portion of InitCode if applicable. Otherwise it returns the zero address.

func (*UserOperation) GetIntent added in v0.4.0

func (op *UserOperation) GetIntent() (*pb.Intent, error)

GetIntent takes the Intent Type from the CallData or Signature field, decodes it into an Intent struct, and returns the struct.

func (*UserOperation) GetIntentJSON added in v0.4.0

func (op *UserOperation) GetIntentJSON() (string, error)

GetIntentJSON returns the Intent JSON from the CallData or signature fields, if present.

func (*UserOperation) GetMaxGasAvailable added in v0.4.0

func (op *UserOperation) GetMaxGasAvailable() *big.Int

GetMaxGasAvailable returns the max amount of gas that can be consumed by this UserOperation.

func (*UserOperation) GetMaxPrefund added in v0.4.0

func (op *UserOperation) GetMaxPrefund() *big.Int

GetMaxPrefund returns the max amount of wei required to pay for gas fees by either the sender or paymaster.

func (*UserOperation) GetPaymaster added in v0.4.0

func (op *UserOperation) GetPaymaster() common.Address

GetPaymaster returns the address portion of PaymasterAndData if applicable. Otherwise it returns the zero address.

func (*UserOperation) GetSignatureEndIdx added in v0.34.0

func (op *UserOperation) GetSignatureEndIdx() int

GetSignatureEndIdx returns the end index of the signature value in the UserOperation's Signature field. Returns either of the 3 following values:

  • KernelSignatureLength: If the signature is a kernel signature with a prefix.
  • SimpleSignatureLength: If the signature is an ECDSA signature without a prefix.
  • 0: If the signature is a kernel signature without a prefix or as a fallback

func (*UserOperation) GetSignatureValue added in v0.34.0

func (op *UserOperation) GetSignatureValue() []byte

GetSignatureValue retrieves the signature value from a UserOperation.

This function supports three use cases:

  1. No, or invalid signature value: It returns nil.

  2. If the UserOperation has a Kernel signature (identified by a specific prefix), and the length of the signature is greater than or equal to the KernelSignatureLength, it returns the signature up to the KernelSignatureLength.

  3. Treated as a fallback if the UserOperation has a sufficient length for a conventional signature, it returns the signature up to the SignatureLength.

Otherwise, it returns nil.

func (*UserOperation) GetUserOpHash added in v0.4.0

func (op *UserOperation) GetUserOpHash(entryPoint common.Address, chainID *big.Int) common.Hash

GetUserOpHash returns the hash of the userOp + entryPoint address + chainID.

func (*UserOperation) HasIntent added in v0.4.0

func (op *UserOperation) HasIntent() bool

HasIntent checks if the CallData or signature field contains a valid Intent JSON that decodes successfully into an Intent struct.

func (*UserOperation) HasSignature added in v0.13.0

func (op *UserOperation) HasSignature() bool

HasSignature checks if the signature field contains a fixed length ECDSA hex-encoded signature value either a conventional (65 bytes) or a kernel with or without Intent.

func (*UserOperation) HasSignatureExact added in v0.34.0

func (op *UserOperation) HasSignatureExact() bool

HasSignatureExact checks for an exact match of the signature length and the signature field contains a fixed length hex-encoded signature value either a conventional or a kernel without Intent.

func (*UserOperation) IsCrossChainIntent added in v0.45.0

func (op *UserOperation) IsCrossChainIntent() (bool, error)

IsCrossChainIntent checks if the UserOperation represents a cross-chain intent.

func (*UserOperation) IsCrossChainOperation added in v0.45.0

func (op *UserOperation) IsCrossChainOperation() bool

IsCrossChainOperation checks if the UserOperation is a cross-chain operation.

func (*UserOperation) MarshalJSON added in v0.4.0

func (op *UserOperation) MarshalJSON() ([]byte, error)

MarshalJSON returns a JSON encoding of the UserOperation.

func (*UserOperation) Pack added in v0.4.0

func (op *UserOperation) Pack() []byte

Pack returns a standard message of the userOp. This cannot be used to generate a userOpHash.

func (*UserOperation) PackForSignature added in v0.4.0

func (op *UserOperation) PackForSignature() []byte

PackForSignature returns a minimal message of the userOp. This can be used to generate a userOpHash.

func (*UserOperation) SetEVMInstructions added in v0.6.0

func (op *UserOperation) SetEVMInstructions(callDataValue []byte) error

SetEVMInstructions sets the EVM instructions in the CallData field of the UserOperation.

If the operation is unsolved, it moves the Intent JSON to the Signature field if present, and then sets the provided EVM instructions in the CallData field.

func (*UserOperation) SetIntent added in v0.4.0

func (op *UserOperation) SetIntent(intentJSON string) error

SetIntent sets the Intent JSON in the appropriate field of the UserOperation based on the operation's solution state.

If the UserOperation is unsolved, the Intent JSON is set in the CallData field. If the UserOperation is solved, the Intent JSON is appended to the Signature field.

func (*UserOperation) String added in v0.7.0

func (op *UserOperation) String() string

String returns a string representation of the UserOperation.

func (*UserOperation) ToMap added in v0.4.0

func (op *UserOperation) ToMap() (map[string]any, error)

ToMap returns the current UserOp struct as a map type.

func (*UserOperation) UnmarshalJSON added in v0.6.0

func (op *UserOperation) UnmarshalJSON(data []byte) error

UnmarshalJSON does the reverse of the provided bundler custom JSON marshaler for a UserOperation.

func (*UserOperation) Validate added in v0.16.0

func (op *UserOperation) Validate() (UserOpSolvedStatus, error)

Validate checks the status of the UserOperation and returns its UserOpSolvedStatus. It determines if the operation is conventional, unsolved, or solved based on the presence and content of CallData and Signature.

Returns:

  • UserOpSolvedStatus: The solved status of the UserOperation.
  • error: An error if there's an issue with the operation's state or contents.

type UserOperationExt added in v0.4.0

type UserOperationExt struct {
	OriginalHashValue string              `json:"original_hash_value" mapstructure:"original_hash_value" validate:"required"`
	ProcessingStatus  pb.ProcessingStatus `json:"processing_status" mapstructure:"processing_status" validate:"required"`
}

UserOperationExt extends the UserOperation with additional information necessary for processing by the Solver.This includes the original hash value of the UserOperation and its processing status.The sequence of UserOperationExt instances must correspond to the sequence in the UserOps slice.

func (*UserOperationExt) MarshalJSON added in v0.27.0

func (u *UserOperationExt) MarshalJSON() ([]byte, error)

func (*UserOperationExt) UnmarshalJSON added in v0.24.0

func (u *UserOperationExt) UnmarshalJSON(data []byte) error

UnmarshalJSON makes sure we can support using strings instead of arbitrary numbers for the proto processing

Directories

Path Synopsis
gen

Jump to

Keyboard shortcuts

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