feat: Add eth_syncing RPC method

This commit adds eth_syncing RPC method which returns an object
with data about the sync status or false.
This commit is contained in:
Fridrik Asmundsson 2023-04-21 12:02:40 +00:00
parent 86723a3223
commit 2bc205ed62
16 changed files with 132 additions and 2 deletions

View File

@ -812,6 +812,7 @@ type FullNode interface {
EthGetStorageAt(ctx context.Context, address ethtypes.EthAddress, position ethtypes.EthBytes, blkParam string) (ethtypes.EthBytes, error) //perm:read EthGetStorageAt(ctx context.Context, address ethtypes.EthAddress, position ethtypes.EthBytes, blkParam string) (ethtypes.EthBytes, error) //perm:read
EthGetBalance(ctx context.Context, address ethtypes.EthAddress, blkParam string) (ethtypes.EthBigInt, error) //perm:read EthGetBalance(ctx context.Context, address ethtypes.EthAddress, blkParam string) (ethtypes.EthBigInt, error) //perm:read
EthChainId(ctx context.Context) (ethtypes.EthUint64, error) //perm:read EthChainId(ctx context.Context) (ethtypes.EthUint64, error) //perm:read
EthSyncing(ctx context.Context) (ethtypes.EthSyncingResult, error) //perm:read
NetVersion(ctx context.Context) (string, error) //perm:read NetVersion(ctx context.Context) (string, error) //perm:read
NetListening(ctx context.Context) (bool, error) //perm:read NetListening(ctx context.Context) (bool, error) //perm:read
EthProtocolVersion(ctx context.Context) (ethtypes.EthUint64, error) //perm:read EthProtocolVersion(ctx context.Context) (ethtypes.EthUint64, error) //perm:read

View File

@ -98,6 +98,7 @@ type Gateway interface {
EthGetStorageAt(ctx context.Context, address ethtypes.EthAddress, position ethtypes.EthBytes, blkParam string) (ethtypes.EthBytes, error) EthGetStorageAt(ctx context.Context, address ethtypes.EthAddress, position ethtypes.EthBytes, blkParam string) (ethtypes.EthBytes, error)
EthGetBalance(ctx context.Context, address ethtypes.EthAddress, blkParam string) (ethtypes.EthBigInt, error) EthGetBalance(ctx context.Context, address ethtypes.EthAddress, blkParam string) (ethtypes.EthBigInt, error)
EthChainId(ctx context.Context) (ethtypes.EthUint64, error) EthChainId(ctx context.Context) (ethtypes.EthUint64, error)
EthSyncing(ctx context.Context) (ethtypes.EthSyncingResult, error)
NetVersion(ctx context.Context) (string, error) NetVersion(ctx context.Context) (string, error)
NetListening(ctx context.Context) (bool, error) NetListening(ctx context.Context) (bool, error)
EthProtocolVersion(ctx context.Context) (ethtypes.EthUint64, error) EthProtocolVersion(ctx context.Context) (ethtypes.EthUint64, error)

View File

@ -21,6 +21,7 @@ func CreateEthRPCAliases(as apitypes.Aliaser) {
as.AliasMethod("eth_getStorageAt", "Filecoin.EthGetStorageAt") as.AliasMethod("eth_getStorageAt", "Filecoin.EthGetStorageAt")
as.AliasMethod("eth_getBalance", "Filecoin.EthGetBalance") as.AliasMethod("eth_getBalance", "Filecoin.EthGetBalance")
as.AliasMethod("eth_chainId", "Filecoin.EthChainId") as.AliasMethod("eth_chainId", "Filecoin.EthChainId")
as.AliasMethod("eth_syncing", "Filecoin.EthSyncing")
as.AliasMethod("eth_feeHistory", "Filecoin.EthFeeHistory") as.AliasMethod("eth_feeHistory", "Filecoin.EthFeeHistory")
as.AliasMethod("eth_protocolVersion", "Filecoin.EthProtocolVersion") as.AliasMethod("eth_protocolVersion", "Filecoin.EthProtocolVersion")
as.AliasMethod("eth_maxPriorityFeePerGas", "Filecoin.EthMaxPriorityFeePerGas") as.AliasMethod("eth_maxPriorityFeePerGas", "Filecoin.EthMaxPriorityFeePerGas")

View File

@ -1476,6 +1476,21 @@ func (mr *MockFullNodeMockRecorder) EthSubscribe(arg0, arg1 interface{}) *gomock
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthSubscribe", reflect.TypeOf((*MockFullNode)(nil).EthSubscribe), arg0, arg1) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthSubscribe", reflect.TypeOf((*MockFullNode)(nil).EthSubscribe), arg0, arg1)
} }
// EthSyncing mocks base method.
func (m *MockFullNode) EthSyncing(arg0 context.Context) (ethtypes.EthSyncingResult, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "EthSyncing", arg0)
ret0, _ := ret[0].(ethtypes.EthSyncingResult)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// EthSyncing indicates an expected call of EthSyncing.
func (mr *MockFullNodeMockRecorder) EthSyncing(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthSyncing", reflect.TypeOf((*MockFullNode)(nil).EthSyncing), arg0)
}
// EthUninstallFilter mocks base method. // EthUninstallFilter mocks base method.
func (m *MockFullNode) EthUninstallFilter(arg0 context.Context, arg1 ethtypes.EthFilterID) (bool, error) { func (m *MockFullNode) EthUninstallFilter(arg0 context.Context, arg1 ethtypes.EthFilterID) (bool, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()

View File

@ -314,6 +314,8 @@ type FullNodeMethods struct {
EthSubscribe func(p0 context.Context, p1 jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error) `perm:"read"` EthSubscribe func(p0 context.Context, p1 jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error) `perm:"read"`
EthSyncing func(p0 context.Context) (ethtypes.EthSyncingResult, error) `perm:"read"`
EthUninstallFilter func(p0 context.Context, p1 ethtypes.EthFilterID) (bool, error) `perm:"read"` EthUninstallFilter func(p0 context.Context, p1 ethtypes.EthFilterID) (bool, error) `perm:"read"`
EthUnsubscribe func(p0 context.Context, p1 ethtypes.EthSubscriptionID) (bool, error) `perm:"read"` EthUnsubscribe func(p0 context.Context, p1 ethtypes.EthSubscriptionID) (bool, error) `perm:"read"`
@ -722,6 +724,8 @@ type GatewayMethods struct {
EthSubscribe func(p0 context.Context, p1 jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error) `` EthSubscribe func(p0 context.Context, p1 jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error) ``
EthSyncing func(p0 context.Context) (ethtypes.EthSyncingResult, error) ``
EthUninstallFilter func(p0 context.Context, p1 ethtypes.EthFilterID) (bool, error) `` EthUninstallFilter func(p0 context.Context, p1 ethtypes.EthFilterID) (bool, error) ``
EthUnsubscribe func(p0 context.Context, p1 ethtypes.EthSubscriptionID) (bool, error) `` EthUnsubscribe func(p0 context.Context, p1 ethtypes.EthSubscriptionID) (bool, error) ``
@ -2422,6 +2426,17 @@ func (s *FullNodeStub) EthSubscribe(p0 context.Context, p1 jsonrpc.RawParams) (e
return *new(ethtypes.EthSubscriptionID), ErrNotSupported return *new(ethtypes.EthSubscriptionID), ErrNotSupported
} }
func (s *FullNodeStruct) EthSyncing(p0 context.Context) (ethtypes.EthSyncingResult, error) {
if s.Internal.EthSyncing == nil {
return *new(ethtypes.EthSyncingResult), ErrNotSupported
}
return s.Internal.EthSyncing(p0)
}
func (s *FullNodeStub) EthSyncing(p0 context.Context) (ethtypes.EthSyncingResult, error) {
return *new(ethtypes.EthSyncingResult), ErrNotSupported
}
func (s *FullNodeStruct) EthUninstallFilter(p0 context.Context, p1 ethtypes.EthFilterID) (bool, error) { func (s *FullNodeStruct) EthUninstallFilter(p0 context.Context, p1 ethtypes.EthFilterID) (bool, error) {
if s.Internal.EthUninstallFilter == nil { if s.Internal.EthUninstallFilter == nil {
return false, ErrNotSupported return false, ErrNotSupported
@ -4600,6 +4615,17 @@ func (s *GatewayStub) EthSubscribe(p0 context.Context, p1 jsonrpc.RawParams) (et
return *new(ethtypes.EthSubscriptionID), ErrNotSupported return *new(ethtypes.EthSubscriptionID), ErrNotSupported
} }
func (s *GatewayStruct) EthSyncing(p0 context.Context) (ethtypes.EthSyncingResult, error) {
if s.Internal.EthSyncing == nil {
return *new(ethtypes.EthSyncingResult), ErrNotSupported
}
return s.Internal.EthSyncing(p0)
}
func (s *GatewayStub) EthSyncing(p0 context.Context) (ethtypes.EthSyncingResult, error) {
return *new(ethtypes.EthSyncingResult), ErrNotSupported
}
func (s *GatewayStruct) EthUninstallFilter(p0 context.Context, p1 ethtypes.EthFilterID) (bool, error) { func (s *GatewayStruct) EthUninstallFilter(p0 context.Context, p1 ethtypes.EthFilterID) (bool, error) {
if s.Internal.EthUninstallFilter == nil { if s.Internal.EthUninstallFilter == nil {
return false, ErrNotSupported return false, ErrNotSupported

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -238,6 +238,30 @@ func (c *EthCall) UnmarshalJSON(b []byte) error {
return nil return nil
} }
type EthSyncingResult struct {
DoneSync bool
StartingBlock EthUint64
CurrentBlock EthUint64
HighestBlock EthUint64
}
func (sr EthSyncingResult) MarshalJSON() ([]byte, error) {
if sr.DoneSync {
// when done syncing, the json response should be '"result": false'
return []byte("false"), nil
}
// need to do an anonymous struct to avoid infinite recursion
return json.Marshal(&struct {
StartingBlock EthUint64 `json:"startingblock"`
CurrentBlock EthUint64 `json:"currentblock"`
HighestBlock EthUint64 `json:"highestblock"`
}{
StartingBlock: sr.StartingBlock,
CurrentBlock: sr.CurrentBlock,
HighestBlock: sr.HighestBlock})
}
const ( const (
EthAddressLength = 20 EthAddressLength = 20
EthHashLength = 32 EthHashLength = 32

View File

@ -103,6 +103,7 @@
* [EthProtocolVersion](#EthProtocolVersion) * [EthProtocolVersion](#EthProtocolVersion)
* [EthSendRawTransaction](#EthSendRawTransaction) * [EthSendRawTransaction](#EthSendRawTransaction)
* [EthSubscribe](#EthSubscribe) * [EthSubscribe](#EthSubscribe)
* [EthSyncing](#EthSyncing)
* [EthUninstallFilter](#EthUninstallFilter) * [EthUninstallFilter](#EthUninstallFilter)
* [EthUnsubscribe](#EthUnsubscribe) * [EthUnsubscribe](#EthUnsubscribe)
* [Filecoin](#Filecoin) * [Filecoin](#Filecoin)
@ -3071,6 +3072,15 @@ Inputs:
Response: `"0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e"` Response: `"0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e"`
### EthSyncing
Perms: read
Inputs: `null`
Response: `false`
### EthUninstallFilter ### EthUninstallFilter
Uninstalls a filter with given id. Uninstalls a filter with given id.

View File

@ -115,6 +115,7 @@ type TargetAPI interface {
EthGetStorageAt(ctx context.Context, address ethtypes.EthAddress, position ethtypes.EthBytes, blkParam string) (ethtypes.EthBytes, error) EthGetStorageAt(ctx context.Context, address ethtypes.EthAddress, position ethtypes.EthBytes, blkParam string) (ethtypes.EthBytes, error)
EthGetBalance(ctx context.Context, address ethtypes.EthAddress, blkParam string) (ethtypes.EthBigInt, error) EthGetBalance(ctx context.Context, address ethtypes.EthAddress, blkParam string) (ethtypes.EthBigInt, error)
EthChainId(ctx context.Context) (ethtypes.EthUint64, error) EthChainId(ctx context.Context) (ethtypes.EthUint64, error)
EthSyncing(ctx context.Context) (ethtypes.EthSyncingResult, error)
NetVersion(ctx context.Context) (string, error) NetVersion(ctx context.Context) (string, error)
NetListening(ctx context.Context) (bool, error) NetListening(ctx context.Context) (bool, error)
EthProtocolVersion(ctx context.Context) (ethtypes.EthUint64, error) EthProtocolVersion(ctx context.Context) (ethtypes.EthUint64, error)

View File

@ -252,6 +252,14 @@ func (gw *Node) EthChainId(ctx context.Context) (ethtypes.EthUint64, error) {
return gw.target.EthChainId(ctx) return gw.target.EthChainId(ctx)
} }
func (gw *Node) EthSyncing(ctx context.Context) (ethtypes.EthSyncingResult, error) {
if err := gw.limit(ctx, basicRateLimitTokens); err != nil {
return ethtypes.EthSyncingResult{}, err
}
return gw.target.EthSyncing(ctx)
}
func (gw *Node) NetVersion(ctx context.Context) (string, error) { func (gw *Node) NetVersion(ctx context.Context) (string, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil { if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return "", err return "", err

View File

@ -102,6 +102,10 @@ func (e *EthModuleDummy) EthChainId(ctx context.Context) (ethtypes.EthUint64, er
return 0, ErrModuleDisabled return 0, ErrModuleDisabled
} }
func (e *EthModuleDummy) EthSyncing(ctx context.Context) (ethtypes.EthSyncingResult, error) {
return ethtypes.EthSyncingResult{}, ErrModuleDisabled
}
func (e *EthModuleDummy) NetVersion(ctx context.Context) (string, error) { func (e *EthModuleDummy) NetVersion(ctx context.Context) (string, error) {
return "", ErrModuleDisabled return "", ErrModuleDisabled
} }

View File

@ -67,6 +67,7 @@ type EthModuleAPI interface {
EthGetBalance(ctx context.Context, address ethtypes.EthAddress, blkParam string) (ethtypes.EthBigInt, error) EthGetBalance(ctx context.Context, address ethtypes.EthAddress, blkParam string) (ethtypes.EthBigInt, error)
EthFeeHistory(ctx context.Context, p jsonrpc.RawParams) (ethtypes.EthFeeHistory, error) EthFeeHistory(ctx context.Context, p jsonrpc.RawParams) (ethtypes.EthFeeHistory, error)
EthChainId(ctx context.Context) (ethtypes.EthUint64, error) EthChainId(ctx context.Context) (ethtypes.EthUint64, error)
EthSyncing(ctx context.Context) (ethtypes.EthSyncingResult, error)
NetVersion(ctx context.Context) (string, error) NetVersion(ctx context.Context) (string, error)
NetListening(ctx context.Context) (bool, error) NetListening(ctx context.Context) (bool, error)
EthProtocolVersion(ctx context.Context) (ethtypes.EthUint64, error) EthProtocolVersion(ctx context.Context) (ethtypes.EthUint64, error)
@ -133,6 +134,7 @@ type EthModule struct {
ChainAPI ChainAPI
MpoolAPI MpoolAPI
StateAPI StateAPI
SyncAPI
} }
var _ EthModuleAPI = (*EthModule)(nil) var _ EthModuleAPI = (*EthModule)(nil)
@ -673,6 +675,42 @@ func (a *EthModule) EthChainId(ctx context.Context) (ethtypes.EthUint64, error)
return ethtypes.EthUint64(build.Eip155ChainId), nil return ethtypes.EthUint64(build.Eip155ChainId), nil
} }
func (a *EthModule) EthSyncing(ctx context.Context) (ethtypes.EthSyncingResult, error) {
state, err := a.SyncAPI.SyncState(ctx)
if err != nil {
return ethtypes.EthSyncingResult{}, fmt.Errorf("failed calling SyncState: %w", err)
}
if len(state.ActiveSyncs) == 0 {
return ethtypes.EthSyncingResult{}, errors.New("no active syncs, try again")
}
working := -1
for i, ss := range state.ActiveSyncs {
if ss.Stage == api.StageIdle {
continue
}
working = i
}
if working == -1 {
working = len(state.ActiveSyncs) - 1
}
ss := state.ActiveSyncs[working]
if ss.Base == nil || ss.Target == nil {
return ethtypes.EthSyncingResult{}, errors.New("missing syncing information, try again")
}
res := ethtypes.EthSyncingResult{
DoneSync: ss.Stage == api.StageSyncComplete,
CurrentBlock: ethtypes.EthUint64(ss.Height),
StartingBlock: ethtypes.EthUint64(ss.Base.Height()),
HighestBlock: ethtypes.EthUint64(ss.Target.Height()),
}
return res, nil
}
func (a *EthModule) EthFeeHistory(ctx context.Context, p jsonrpc.RawParams) (ethtypes.EthFeeHistory, error) { func (a *EthModule) EthFeeHistory(ctx context.Context, p jsonrpc.RawParams) (ethtypes.EthFeeHistory, error) {
params, err := jsonrpc.DecodeParams[ethtypes.EthFeeHistoryParams](p) params, err := jsonrpc.DecodeParams[ethtypes.EthFeeHistoryParams](p)
if err != nil { if err != nil {

View File

@ -18,8 +18,8 @@ import (
"github.com/filecoin-project/lotus/node/repo" "github.com/filecoin-project/lotus/node/repo"
) )
func EthModuleAPI(cfg config.FevmConfig) func(helpers.MetricsCtx, repo.LockedRepo, fx.Lifecycle, *store.ChainStore, *stmgr.StateManager, EventAPI, *messagepool.MessagePool, full.StateAPI, full.ChainAPI, full.MpoolAPI) (*full.EthModule, error) { func EthModuleAPI(cfg config.FevmConfig) func(helpers.MetricsCtx, repo.LockedRepo, fx.Lifecycle, *store.ChainStore, *stmgr.StateManager, EventAPI, *messagepool.MessagePool, full.StateAPI, full.ChainAPI, full.MpoolAPI, full.SyncAPI) (*full.EthModule, error) {
return func(mctx helpers.MetricsCtx, r repo.LockedRepo, lc fx.Lifecycle, cs *store.ChainStore, sm *stmgr.StateManager, evapi EventAPI, mp *messagepool.MessagePool, stateapi full.StateAPI, chainapi full.ChainAPI, mpoolapi full.MpoolAPI) (*full.EthModule, error) { return func(mctx helpers.MetricsCtx, r repo.LockedRepo, lc fx.Lifecycle, cs *store.ChainStore, sm *stmgr.StateManager, evapi EventAPI, mp *messagepool.MessagePool, stateapi full.StateAPI, chainapi full.ChainAPI, mpoolapi full.MpoolAPI, syncapi full.SyncAPI) (*full.EthModule, error) {
sqlitePath, err := r.SqlitePath() sqlitePath, err := r.SqlitePath()
if err != nil { if err != nil {
return nil, err return nil, err
@ -84,6 +84,7 @@ func EthModuleAPI(cfg config.FevmConfig) func(helpers.MetricsCtx, repo.LockedRep
ChainAPI: chainapi, ChainAPI: chainapi,
MpoolAPI: mpoolapi, MpoolAPI: mpoolapi,
StateAPI: stateapi, StateAPI: stateapi,
SyncAPI: syncapi,
EthTxHashManager: &ethTxHashManager, EthTxHashManager: &ethTxHashManager,
}, nil }, nil