client

package
v2.14.0 Latest Latest
Warning

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

Go to latest
Published: Jul 29, 2024 License: MIT Imports: 21 Imported by: 0

Documentation

Index

Constants

View Source
const (
	Primary = NodeTier(iota)
	Secondary
)
View Source
const (
	NodeSelectionModeHighestHead     = "HighestHead"
	NodeSelectionModeRoundRobin      = "RoundRobin"
	NodeSelectionModeTotalDifficulty = "TotalDifficulty"
	NodeSelectionModePriorityLevel   = "PriorityLevel"
)
View Source
const QueryTimeout = 10 * time.Second

Variables

View Source
var (
	// PromMultiNodeRPCNodeStates reports current RPC node state
	PromMultiNodeRPCNodeStates = promauto.NewGaugeVec(prometheus.GaugeOpts{
		Name: "multi_node_states",
		Help: "The number of RPC nodes currently in the given state for the given chain",
	}, []string{"network", "chainId", "state"})
	// PromMultiNodeInvariantViolations reports violation of our assumptions
	PromMultiNodeInvariantViolations = promauto.NewCounterVec(prometheus.CounterOpts{
		Name: "multi_node_invariant_violations",
		Help: "The number of invariant violations",
	}, []string{"network", "chainId", "invariant"})
	ErroringNodeError = fmt.Errorf("no live nodes available")
)

Functions

func CtxAddHealthCheckFlag added in v2.14.0

func CtxAddHealthCheckFlag(ctx context.Context) context.Context

func CtxIsHeathCheckRequest added in v2.14.0

func CtxIsHeathCheckRequest(ctx context.Context) bool

func MaxTotalDifficulty added in v2.14.0

func MaxTotalDifficulty(a, b *big.Int) *big.Int

Types

type ChainConfig added in v2.11.0

type ChainConfig interface {
	NodeNoNewHeadsThreshold() time.Duration
	FinalityDepth() uint32
	FinalityTagEnabled() bool
	FinalizedBlockOffset() uint32
}

type ChainInfo added in v2.14.0

type ChainInfo struct {
	BlockNumber          int64
	FinalizedBlockNumber int64
	TotalDifficulty      *big.Int
}

ChainInfo - defines RPC's or MultiNode's view on the chain

type Head interface {
	BlockNumber() int64
	BlockDifficulty() *big.Int
	IsValid() bool
}

Head is the interface required by the NodeClient

type MultiNode

type MultiNode[
	CHAIN_ID types.ID,
	SEQ types.Sequence,
	ADDR types.Hashable,
	BLOCK_HASH types.Hashable,
	TX any,
	TX_HASH types.Hashable,
	EVENT any,
	EVENT_OPS any,
	TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH],
	FEE feetypes.Fee,
	HEAD types.Head[BLOCK_HASH],
	RPC_CLIENT RPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM],
	BATCH_ELEM any,
] interface {
	Close() error
	NodeStates() map[string]string
	SelectNodeRPC() (RPC_CLIENT, error)

	BatchCallContextAll(ctx context.Context, b []BATCH_ELEM) error
	ConfiguredChainID() CHAIN_ID
	// contains filtered or unexported methods
}

MultiNode is a generalized multi node client interface that includes methods to interact with different chains. It also handles multiple node RPC connections simultaneously.

func NewMultiNode

func NewMultiNode[
	CHAIN_ID types.ID,
	SEQ types.Sequence,
	ADDR types.Hashable,
	BLOCK_HASH types.Hashable,
	TX any,
	TX_HASH types.Hashable,
	EVENT any,
	EVENT_OPS any,
	TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH],
	FEE feetypes.Fee,
	HEAD types.Head[BLOCK_HASH],
	RPC_CLIENT RPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM],
	BATCH_ELEM any,
](
	lggr logger.Logger,
	selectionMode string,
	leaseDuration time.Duration,
	noNewHeadsThreshold time.Duration,
	nodes []Node[CHAIN_ID, HEAD, RPC_CLIENT],
	sendonlys []SendOnlyNode[CHAIN_ID, RPC_CLIENT],
	chainID CHAIN_ID,
	chainFamily string,
	classifySendTxError func(tx TX, err error) SendTxReturnCode,
	sendTxSoftTimeout time.Duration,
	deathDeclarationDelay time.Duration,
) MultiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]

type Node

type Node[
	CHAIN_ID types.ID,
	HEAD Head,
	RPC NodeClient[CHAIN_ID, HEAD],
] interface {
	// State returns most accurate state of the Node on the moment of call.
	// While some of the checks may be performed in the background and State may return cached value, critical, like
	// `FinalizedBlockOutOfSync`, must be executed upon every call.
	State() nodeState
	// StateAndLatest returns nodeState with the latest ChainInfo observed by Node during current lifecycle.
	StateAndLatest() (nodeState, ChainInfo)
	// HighestUserObservations - returns highest ChainInfo ever observed by underlying RPC excluding results of health check requests
	HighestUserObservations() ChainInfo
	SetPoolChainInfoProvider(PoolChainInfoProvider)
	// Name is a unique identifier for this node.
	Name() string
	String() string
	RPC() RPC
	SubscribersCount() int32
	// UnsubscribeAllExceptAliveLoop - closes all subscriptions except the aliveLoop subscription
	UnsubscribeAllExceptAliveLoop()
	ConfiguredChainID() CHAIN_ID
	Order() int32
	Start(context.Context) error
	Close() error
}

func NewNode

func NewNode[
	CHAIN_ID types.ID,
	HEAD Head,
	RPC NodeClient[CHAIN_ID, HEAD],
](
	nodeCfg NodeConfig,
	chainCfg ChainConfig,
	lggr logger.Logger,
	wsuri url.URL,
	httpuri *url.URL,
	name string,
	id int32,
	chainID CHAIN_ID,
	nodeOrder int32,
	rpc RPC,
	chainFamily string,
) Node[CHAIN_ID, HEAD, RPC]

type NodeClient

type NodeClient[
	CHAIN_ID types.ID,
	HEAD Head,
] interface {
	DialHTTP() error
	// DisconnectAll - cancels all inflight requests, terminates all subscriptions and resets latest ChainInfo.
	DisconnectAll()
	Close()
	ClientVersion(context.Context) (string, error)
	SubscribersCount() int32
	SetAliveLoopSub(types.Subscription)
	UnsubscribeAllExceptAliveLoop()
	IsSyncing(ctx context.Context) (bool, error)
	LatestFinalizedBlock(ctx context.Context) (HEAD, error)
	// GetInterceptedChainInfo - returns latest and highest observed by application layer ChainInfo.
	// latest ChainInfo is the most recent value received within a NodeClient's current lifecycle between Dial and DisconnectAll.
	// highestUserObservations ChainInfo is the highest ChainInfo observed excluding health checks calls.
	// Its values must not be reset.
	// The results of corresponding calls, to get the most recent head and the latest finalized head, must be
	// intercepted and reflected in ChainInfo before being returned to a caller. Otherwise, MultiNode is not able to
	// provide repeatable read guarantee.
	// DisconnectAll must reset latest ChainInfo to default value.
	// Ensure implementation does not have a race condition when values are reset before request completion and as
	// a result latest ChainInfo contains information from the previous cycle.
	GetInterceptedChainInfo() (latest, highestUserObservations ChainInfo)
	// contains filtered or unexported methods
}

NodeClient includes all the necessary RPC methods required by a node.

type NodeConfig

type NodeConfig interface {
	PollFailureThreshold() uint32
	PollInterval() time.Duration
	SelectionMode() string
	SyncThreshold() uint32
	NodeIsSyncingEnabled() bool
	FinalizedBlockPollInterval() time.Duration
	EnforceRepeatableRead() bool
	DeathDeclarationDelay() time.Duration
}

type NodeSelector

type NodeSelector[
	CHAIN_ID types.ID,
	HEAD Head,
	RPC NodeClient[CHAIN_ID, HEAD],
] interface {
	// Select returns a Node, or nil if none can be selected.
	// Implementation must be thread-safe.
	Select() Node[CHAIN_ID, HEAD, RPC]
	// Name returns the strategy name, e.g. "HighestHead" or "RoundRobin"
	Name() string
}

func NewHighestHeadNodeSelector

func NewHighestHeadNodeSelector[
	CHAIN_ID types.ID,
	HEAD Head,
	RPC NodeClient[CHAIN_ID, HEAD],
](nodes []Node[CHAIN_ID, HEAD, RPC]) NodeSelector[CHAIN_ID, HEAD, RPC]

func NewPriorityLevelNodeSelector

func NewPriorityLevelNodeSelector[
	CHAIN_ID types.ID,
	HEAD Head,
	RPC NodeClient[CHAIN_ID, HEAD],
](nodes []Node[CHAIN_ID, HEAD, RPC]) NodeSelector[CHAIN_ID, HEAD, RPC]

func NewRoundRobinSelector

func NewRoundRobinSelector[
	CHAIN_ID types.ID,
	HEAD Head,
	RPC NodeClient[CHAIN_ID, HEAD],
](nodes []Node[CHAIN_ID, HEAD, RPC]) NodeSelector[CHAIN_ID, HEAD, RPC]

func NewTotalDifficultyNodeSelector

func NewTotalDifficultyNodeSelector[
	CHAIN_ID types.ID,
	HEAD Head,
	RPC NodeClient[CHAIN_ID, HEAD],
](nodes []Node[CHAIN_ID, HEAD, RPC]) NodeSelector[CHAIN_ID, HEAD, RPC]

type NodeTier

type NodeTier int

func (NodeTier) String

func (n NodeTier) String() string

type Poller added in v2.12.0

type Poller[T any] struct {
	services.StateMachine
	// contains filtered or unexported fields
}

Poller is a component that polls a function at a given interval and delivers the result to a channel. It is used by multinode to poll for new heads and implements the Subscription interface.

func NewPoller added in v2.12.0

func NewPoller[
	T any,
](pollingInterval time.Duration, pollingFunc func(ctx context.Context) (T, error), pollingTimeout time.Duration, logger logger.Logger) (Poller[T], <-chan T)

NewPoller creates a new Poller instance and returns a channel to receive the polled data

func (*Poller[T]) Err added in v2.12.0

func (p *Poller[T]) Err() <-chan error

func (*Poller[T]) Start added in v2.12.0

func (p *Poller[T]) Start() error

func (*Poller[T]) Unsubscribe added in v2.12.0

func (p *Poller[T]) Unsubscribe()

Unsubscribe cancels the sending of events to the data channel

type PoolChainInfoProvider added in v2.14.0

type PoolChainInfoProvider interface {
	// LatestChainInfo - returns number of live nodes available in the pool, so we can prevent the last alive node in a pool from being
	// moved to out-of-sync state. It is better to have one out-of-sync node than no nodes at all.
	// Returns highest latest ChainInfo within the alive nodes. E.g. most recent block number and highest block number
	// observed by Node A are 10 and 15; Node B - 12 and 14. This method will return 12.
	LatestChainInfo() (int, ChainInfo)
	// HighestUserObservations - returns highest ChainInfo ever observed by any user of MultiNode.
	HighestUserObservations() ChainInfo
}

PoolChainInfoProvider - provides aggregation of nodes pool ChainInfo

type RPC

type RPC[
	CHAIN_ID types.ID,
	SEQ types.Sequence,
	ADDR types.Hashable,
	BLOCK_HASH types.Hashable,
	TX any,
	TX_HASH types.Hashable,
	EVENT any,
	EVENT_OPS any,
	TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH],
	FEE feetypes.Fee,
	HEAD types.Head[BLOCK_HASH],
	BATCH_ELEM any,
] interface {
	NodeClient[
		CHAIN_ID,
		HEAD,
	]
	// contains filtered or unexported methods
}

RPC includes all the necessary methods for a multi-node client to interact directly with any RPC endpoint.

type SendOnlyNode

type SendOnlyNode[
	CHAIN_ID types.ID,
	RPC sendOnlyClient[CHAIN_ID],
] interface {
	// Start may attempt to connect to the node, but should only return error for misconfiguration - never for temporary errors.
	Start(context.Context) error
	Close() error

	ConfiguredChainID() CHAIN_ID
	RPC() RPC

	String() string
	// State returns nodeState
	State() nodeState
	// Name is a unique identifier for this node.
	Name() string
}

SendOnlyNode represents one node used as a sendonly

func NewSendOnlyNode

func NewSendOnlyNode[
	CHAIN_ID types.ID,
	RPC sendOnlyClient[CHAIN_ID],
](
	lggr logger.Logger,
	httpuri url.URL,
	name string,
	chainID CHAIN_ID,
	rpc RPC,
) SendOnlyNode[CHAIN_ID, RPC]

NewSendOnlyNode returns a new sendonly node

type SendTxReturnCode

type SendTxReturnCode int
const (
	Successful              SendTxReturnCode = iota + 1
	Fatal                                    // Unrecoverable error. Most likely the attempt should be thrown away.
	Retryable                                // The error returned by the RPC indicates that if we retry with the same attempt, the tx will eventually go through.
	Underpriced                              // Attempt was underpriced. New estimation is needed with bumped gas price.
	Unknown                                  // Tx failed with an error response that is not recognized by the client.
	Unsupported                              // Attempt failed with an error response that is not supported by the client for the given chain.
	TransactionAlreadyKnown                  // The transaction that was sent has already been received by the RPC.
	InsufficientFunds                        // Tx was rejected due to insufficient funds.
	ExceedsMaxFee                            // Attempt's fee was higher than the node's limit and got rejected.
	FeeOutOfValidRange                       // This error is returned when we use a fee price suggested from an RPC, but the network rejects the attempt due to an invalid range(mostly used by L2 chains). Retry by requesting a new suggested fee price.
	TerminallyStuck                          // The error returned when a transaction is or could get terminally stuck in the mempool without any chance of inclusion.

)

SendTxReturnCode is a generalized client error that dictates what should be the next action, depending on the RPC error response.

func (SendTxReturnCode) String added in v2.12.0

func (c SendTxReturnCode) String() string

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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