@@ -13,6 +13,7 @@ import (
1313 "github.com/ethereum/go-ethereum/core/types"
1414 "github.com/ethereum/go-ethereum/ethclient"
1515 "github.com/fatih/color"
16+ "github.com/rocket-pool/smartnode/bindings/rocketpool"
1617 "github.com/rocket-pool/smartnode/shared/services/config"
1718 "github.com/rocket-pool/smartnode/shared/types/api"
1819 cfgtypes "github.com/rocket-pool/smartnode/shared/types/config"
@@ -30,6 +31,23 @@ type ExecutionClientManager struct {
3031 primaryReady bool
3132 fallbackReady bool
3233 ignoreSyncCheck bool
34+
35+ // static, when non-nil, satisfies every public method of this manager
36+ // directly from the provided client instead of dialling a live EC.
37+ // It is set by NewStaticExecutionClientManager and used when the daemon
38+ // is running in --network-state mode.
39+ static rocketpool.ExecutionClient
40+ }
41+
42+ // NewStaticExecutionClientManager returns an ExecutionClientManager whose
43+ // public methods all delegate to the provided ExecutionClient. No network
44+ // connections are established.
45+ func NewStaticExecutionClientManager (static rocketpool.ExecutionClient ) * ExecutionClientManager {
46+ return & ExecutionClientManager {
47+ static : static ,
48+ primaryReady : true ,
49+ fallbackReady : false ,
50+ }
3351}
3452
3553// This is a signature for a wrapped ethclient.Client function
@@ -100,6 +118,9 @@ func NewExecutionClientManager(cfg *config.RocketPoolConfig) (*ExecutionClientMa
100118// CodeAt returns the code of the given account. This is needed to differentiate
101119// between contract internal errors and the local chain being out of sync.
102120func (p * ExecutionClientManager ) CodeAt (ctx context.Context , contract common.Address , blockNumber * big.Int ) ([]byte , error ) {
121+ if p .static != nil {
122+ return p .static .CodeAt (ctx , contract , blockNumber )
123+ }
103124 result , err := p .runFunction (func (client * ethClient ) (interface {}, error ) {
104125 return client .CodeAt (ctx , contract , blockNumber )
105126 })
@@ -112,6 +133,9 @@ func (p *ExecutionClientManager) CodeAt(ctx context.Context, contract common.Add
112133// CallContract executes an Ethereum contract call with the specified data as the
113134// input.
114135func (p * ExecutionClientManager ) CallContract (ctx context.Context , call ethereum.CallMsg , blockNumber * big.Int ) ([]byte , error ) {
136+ if p .static != nil {
137+ return p .static .CallContract (ctx , call , blockNumber )
138+ }
115139 result , err := p .runFunction (func (client * ethClient ) (interface {}, error ) {
116140 return client .CallContract (ctx , call , blockNumber )
117141 })
@@ -127,6 +151,9 @@ func (p *ExecutionClientManager) CallContract(ctx context.Context, call ethereum
127151
128152// HeaderByHash returns the block header with the given hash.
129153func (p * ExecutionClientManager ) HeaderByHash (ctx context.Context , hash common.Hash ) (* types.Header , error ) {
154+ if p .static != nil {
155+ return p .static .HeaderByHash (ctx , hash )
156+ }
130157 result , err := p .runFunction (func (client * ethClient ) (interface {}, error ) {
131158 return client .HeaderByHash (ctx , hash )
132159 })
@@ -139,6 +166,9 @@ func (p *ExecutionClientManager) HeaderByHash(ctx context.Context, hash common.H
139166// HeaderByNumber returns a block header from the current canonical chain. If number is
140167// nil, the latest known header is returned.
141168func (p * ExecutionClientManager ) HeaderByNumber (ctx context.Context , number * big.Int ) (* types.Header , error ) {
169+ if p .static != nil {
170+ return p .static .HeaderByNumber (ctx , number )
171+ }
142172 result , err := p .runFunction (func (client * ethClient ) (interface {}, error ) {
143173 return client .HeaderByNumber (ctx , number )
144174 })
@@ -150,6 +180,9 @@ func (p *ExecutionClientManager) HeaderByNumber(ctx context.Context, number *big
150180
151181// PendingCodeAt returns the code of the given account in the pending state.
152182func (p * ExecutionClientManager ) PendingCodeAt (ctx context.Context , account common.Address ) ([]byte , error ) {
183+ if p .static != nil {
184+ return p .static .PendingCodeAt (ctx , account )
185+ }
153186 result , err := p .runFunction (func (client * ethClient ) (interface {}, error ) {
154187 return client .PendingCodeAt (ctx , account )
155188 })
@@ -161,6 +194,9 @@ func (p *ExecutionClientManager) PendingCodeAt(ctx context.Context, account comm
161194
162195// PendingNonceAt retrieves the current pending nonce associated with an account.
163196func (p * ExecutionClientManager ) PendingNonceAt (ctx context.Context , account common.Address ) (uint64 , error ) {
197+ if p .static != nil {
198+ return p .static .PendingNonceAt (ctx , account )
199+ }
164200 result , err := p .runFunction (func (client * ethClient ) (interface {}, error ) {
165201 return client .PendingNonceAt (ctx , account )
166202 })
@@ -173,6 +209,9 @@ func (p *ExecutionClientManager) PendingNonceAt(ctx context.Context, account com
173209// SuggestGasPrice retrieves the currently suggested gas price to allow a timely
174210// execution of a transaction.
175211func (p * ExecutionClientManager ) SuggestGasPrice (ctx context.Context ) (* big.Int , error ) {
212+ if p .static != nil {
213+ return p .static .SuggestGasPrice (ctx )
214+ }
176215 result , err := p .runFunction (func (client * ethClient ) (interface {}, error ) {
177216 return client .SuggestGasPrice (ctx )
178217 })
@@ -185,6 +224,9 @@ func (p *ExecutionClientManager) SuggestGasPrice(ctx context.Context) (*big.Int,
185224// SuggestGasTipCap retrieves the currently suggested 1559 priority fee to allow
186225// a timely execution of a transaction.
187226func (p * ExecutionClientManager ) SuggestGasTipCap (ctx context.Context ) (* big.Int , error ) {
227+ if p .static != nil {
228+ return p .static .SuggestGasTipCap (ctx )
229+ }
188230 result , err := p .runFunction (func (client * ethClient ) (interface {}, error ) {
189231 return client .SuggestGasTipCap (ctx )
190232 })
@@ -200,6 +242,9 @@ func (p *ExecutionClientManager) SuggestGasTipCap(ctx context.Context) (*big.Int
200242// transactions may be added or removed by miners, but it should provide a basis
201243// for setting a reasonable default.
202244func (p * ExecutionClientManager ) EstimateGas (ctx context.Context , call ethereum.CallMsg ) (gas uint64 , err error ) {
245+ if p .static != nil {
246+ return p .static .EstimateGas (ctx , call )
247+ }
203248 result , err := p .runFunction (func (client * ethClient ) (interface {}, error ) {
204249 return client .EstimateGas (ctx , call )
205250 })
@@ -211,6 +256,9 @@ func (p *ExecutionClientManager) EstimateGas(ctx context.Context, call ethereum.
211256
212257// SendTransaction injects the transaction into the pending pool for execution.
213258func (p * ExecutionClientManager ) SendTransaction (ctx context.Context , tx * types.Transaction ) error {
259+ if p .static != nil {
260+ return p .static .SendTransaction (ctx , tx )
261+ }
214262 _ , err := p .runFunction (func (client * ethClient ) (interface {}, error ) {
215263 return nil , client .SendTransaction (ctx , tx )
216264 })
@@ -226,6 +274,9 @@ func (p *ExecutionClientManager) SendTransaction(ctx context.Context, tx *types.
226274//
227275// TODO(karalabe): Deprecate when the subscription one can return past data too.
228276func (p * ExecutionClientManager ) FilterLogs (ctx context.Context , query ethereum.FilterQuery ) ([]types.Log , error ) {
277+ if p .static != nil {
278+ return p .static .FilterLogs (ctx , query )
279+ }
229280 result , err := p .runFunction (func (client * ethClient ) (interface {}, error ) {
230281 return client .FilterLogs (ctx , query )
231282 })
@@ -238,6 +289,9 @@ func (p *ExecutionClientManager) FilterLogs(ctx context.Context, query ethereum.
238289// SubscribeFilterLogs creates a background log filtering operation, returning
239290// a subscription immediately, which can be used to stream the found events.
240291func (p * ExecutionClientManager ) SubscribeFilterLogs (ctx context.Context , query ethereum.FilterQuery , ch chan <- types.Log ) (ethereum.Subscription , error ) {
292+ if p .static != nil {
293+ return p .static .SubscribeFilterLogs (ctx , query , ch )
294+ }
241295 result , err := p .runFunction (func (client * ethClient ) (interface {}, error ) {
242296 return client .SubscribeFilterLogs (ctx , query , ch )
243297 })
@@ -254,6 +308,9 @@ func (p *ExecutionClientManager) SubscribeFilterLogs(ctx context.Context, query
254308// TransactionReceipt returns the receipt of a transaction by transaction hash.
255309// Note that the receipt is not available for pending transactions.
256310func (p * ExecutionClientManager ) TransactionReceipt (ctx context.Context , txHash common.Hash ) (* types.Receipt , error ) {
311+ if p .static != nil {
312+ return p .static .TransactionReceipt (ctx , txHash )
313+ }
257314 result , err := p .runFunction (func (client * ethClient ) (interface {}, error ) {
258315 return client .TransactionReceipt (ctx , txHash )
259316 })
@@ -269,6 +326,9 @@ func (p *ExecutionClientManager) TransactionReceipt(ctx context.Context, txHash
269326
270327// BlockNumber returns the most recent block number
271328func (p * ExecutionClientManager ) BlockNumber (ctx context.Context ) (uint64 , error ) {
329+ if p .static != nil {
330+ return p .static .BlockNumber (ctx )
331+ }
272332 result , err := p .runFunction (func (client * ethClient ) (interface {}, error ) {
273333 return client .BlockNumber (ctx )
274334 })
@@ -281,6 +341,9 @@ func (p *ExecutionClientManager) BlockNumber(ctx context.Context) (uint64, error
281341// BalanceAt returns the wei balance of the given account.
282342// The block number can be nil, in which case the balance is taken from the latest known block.
283343func (p * ExecutionClientManager ) BalanceAt (ctx context.Context , account common.Address , blockNumber * big.Int ) (* big.Int , error ) {
344+ if p .static != nil {
345+ return p .static .BalanceAt (ctx , account , blockNumber )
346+ }
284347 result , err := p .runFunction (func (client * ethClient ) (interface {}, error ) {
285348 return client .BalanceAt (ctx , account , blockNumber )
286349 })
@@ -292,6 +355,9 @@ func (p *ExecutionClientManager) BalanceAt(ctx context.Context, account common.A
292355
293356// TransactionByHash returns the transaction with the given hash.
294357func (p * ExecutionClientManager ) TransactionByHash (ctx context.Context , hash common.Hash ) (tx * types.Transaction , isPending bool , err error ) {
358+ if p .static != nil {
359+ return p .static .TransactionByHash (ctx , hash )
360+ }
295361 result , err := p .runFunction (func (client * ethClient ) (interface {}, error ) {
296362 tx , isPending , err := client .TransactionByHash (ctx , hash )
297363 result := []interface {}{tx , isPending }
@@ -311,6 +377,9 @@ func (p *ExecutionClientManager) TransactionByHash(ctx context.Context, hash com
311377// NonceAt returns the account nonce of the given account.
312378// The block number can be nil, in which case the nonce is taken from the latest known block.
313379func (p * ExecutionClientManager ) NonceAt (ctx context.Context , account common.Address , blockNumber * big.Int ) (uint64 , error ) {
380+ if p .static != nil {
381+ return p .static .NonceAt (ctx , account , blockNumber )
382+ }
314383 result , err := p .runFunction (func (client * ethClient ) (interface {}, error ) {
315384 return client .NonceAt (ctx , account , blockNumber )
316385 })
@@ -323,6 +392,9 @@ func (p *ExecutionClientManager) NonceAt(ctx context.Context, account common.Add
323392// SyncProgress retrieves the current progress of the sync algorithm. If there's
324393// no sync currently running, it returns nil.
325394func (p * ExecutionClientManager ) SyncProgress (ctx context.Context ) (* ethereum.SyncProgress , error ) {
395+ if p .static != nil {
396+ return p .static .SyncProgress (ctx )
397+ }
326398 result , err := p .runFunction (func (client * ethClient ) (interface {}, error ) {
327399 return client .SyncProgress (ctx )
328400 })
@@ -333,6 +405,9 @@ func (p *ExecutionClientManager) SyncProgress(ctx context.Context) (*ethereum.Sy
333405}
334406
335407func (p * ExecutionClientManager ) LatestBlockTime (ctx context.Context ) (time.Time , error ) {
408+ if p .static != nil {
409+ return p .static .LatestBlockTime (ctx )
410+ }
336411 result , err := p .runFunction (func (client * ethClient ) (interface {}, error ) {
337412 return client .LatestBlockTime (ctx )
338413 })
@@ -344,6 +419,9 @@ func (p *ExecutionClientManager) LatestBlockTime(ctx context.Context) (time.Time
344419
345420// BlockNumber returns the most recent block number
346421func (p * ExecutionClientManager ) ChainID (ctx context.Context ) (* big.Int , error ) {
422+ if p .static != nil {
423+ return p .static .ChainID (ctx )
424+ }
347425 result , err := p .runFunction (func (client * ethClient ) (interface {}, error ) {
348426 return client .ChainID (ctx )
349427 })
@@ -359,6 +437,19 @@ func (p *ExecutionClientManager) ChainID(ctx context.Context) (*big.Int, error)
359437
360438func (p * ExecutionClientManager ) CheckStatus (cfg * config.RocketPoolConfig ) * api.ClientManagerStatus {
361439
440+ // In static mode we have no real clients to probe; report the synthetic
441+ // "primary is working and synced" status.
442+ if p .static != nil {
443+ return & api.ClientManagerStatus {
444+ FallbackEnabled : false ,
445+ PrimaryClientStatus : api.ClientStatus {
446+ IsWorking : true ,
447+ IsSynced : true ,
448+ SyncProgress : 1 ,
449+ },
450+ }
451+ }
452+
362453 status := & api.ClientManagerStatus {
363454 FallbackEnabled : p .fallbackEc != nil ,
364455 }
0 commit comments