Documentation ¶
Index ¶
- Constants
- Variables
- func CtxAddHealthCheckFlag(ctx context.Context) context.Context
- func CtxIsHeathCheckRequest(ctx context.Context) bool
- func MaxTotalDifficulty(a, b *big.Int) *big.Int
- type ChainConfig
- type ChainInfo
- type Head
- type MultiNode
- type Node
- type NodeClient
- type NodeConfig
- type NodeSelector
- 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[CHAIN_ID types.ID, HEAD Head, RPC NodeClient[CHAIN_ID, HEAD]](nodes []Node[CHAIN_ID, HEAD, RPC]) NodeSelector[CHAIN_ID, HEAD, RPC]
- 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[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 Poller
- type PoolChainInfoProvider
- type RPC
- type SendOnlyNode
- type SendTxReturnCode
Constants ¶
const ( Primary = NodeTier(iota) Secondary )
const ( NodeSelectionModeHighestHead = "HighestHead" NodeSelectionModeRoundRobin = "RoundRobin" NodeSelectionModeTotalDifficulty = "TotalDifficulty" NodeSelectionModePriorityLevel = "PriorityLevel" )
const QueryTimeout = 10 * time.Second
Variables ¶
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 CtxIsHeathCheckRequest ¶ added in v2.14.0
Types ¶
type ChainConfig ¶ added in v2.11.0
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 }
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 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 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]) 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