Skip to content

Commit

Permalink
Merge pull request #180 from m-Peter/implement-detailed-sync-status
Browse files Browse the repository at this point in the history
Implement a more detailed sync status for `eth_syncing`
  • Loading branch information
m-Peter authored Apr 19, 2024
2 parents 0b977af + ef80211 commit 24e36e7
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 20 deletions.
43 changes: 30 additions & 13 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ type BlockChainAPI struct {
transactions storage.TransactionIndexer
receipts storage.ReceiptIndexer
accounts storage.AccountIndexer
// Stores the height from which the indexing resumed since the last restart.
// This is needed for syncing status.
indexingResumedHeight uint64
}

func NewBlockChainAPI(
Expand All @@ -60,15 +63,17 @@ func NewBlockChainAPI(
transactions storage.TransactionIndexer,
receipts storage.ReceiptIndexer,
accounts storage.AccountIndexer,
indexingResumedHeight uint64,
) *BlockChainAPI {
return &BlockChainAPI{
logger: logger,
config: config,
evm: evm,
blocks: blocks,
transactions: transactions,
receipts: receipts,
accounts: accounts,
logger: logger,
config: config,
evm: evm,
blocks: blocks,
transactions: transactions,
receipts: receipts,
accounts: accounts,
indexingResumedHeight: indexingResumedHeight,
}
}

Expand All @@ -92,16 +97,28 @@ func (b *BlockChainAPI) BlockNumber() (hexutil.Uint64, error) {
return hexutil.Uint64(latestBlockHeight), nil
}

// Syncing returns false in case the node is currently not syncing with the network. It can be up-to-date or has not
// yet received the latest block headers from its pears. In case it is synchronizing:
// Syncing returns false in case the node is currently not syncing with the network.
// It can be up-to-date or has not yet received the latest block headers from its peers.
// In case it is synchronizing:
// - startingBlock: block number this node started to synchronize from
// - currentBlock: block number this node is currently importing
// - highestBlock: block number of the highest block header this node has received from peers
// - pulledStates: number of state entries processed until now
// - knownStates: number of known state entries that still need to be pulled
func (b *BlockChainAPI) Syncing() (interface{}, error) {
// todo maybe we should check if the node is caught up with the latest flow block
return false, nil
currentBlock, err := b.blocks.LatestEVMHeight()
if err != nil {
return nil, err
}

highestBlock, err := b.evm.GetLatestEVMHeight(context.Background())
if err != nil {
return nil, err
}

return SyncStatus{
StartingBlock: hexutil.Uint64(b.indexingResumedHeight),
CurrentBlock: hexutil.Uint64(currentBlock),
HighestBlock: hexutil.Uint64(highestBlock),
}, nil
}

// SendRawTransaction will add the signed transaction to the transaction pool.
Expand Down
6 changes: 6 additions & 0 deletions api/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,3 +201,9 @@ type Block struct {
Uncles []common.Hash `json:"uncles"`
MixHash common.Hash `json:"mixHash"`
}

type SyncStatus struct {
StartingBlock hexutil.Uint64 `json:"startingBlock"`
CurrentBlock hexutil.Uint64 `json:"currentBlock"`
HighestBlock hexutil.Uint64 `json:"highestBlock"`
}
6 changes: 6 additions & 0 deletions bootstrap/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,11 @@ func startServer(
return fmt.Errorf("failed to create EVM requester: %w", err)
}

indexingResumedHeight, err := blocks.LatestEVMHeight()
if err != nil {
return fmt.Errorf("failed to retrieve the indexing resumed height: %w", err)
}

blockchainAPI := api.NewBlockChainAPI(
logger,
cfg,
Expand All @@ -210,6 +215,7 @@ func startServer(
transactions,
receipts,
accounts,
indexingResumedHeight,
)

streamAPI := api.NewStreamAPI(
Expand Down
6 changes: 6 additions & 0 deletions services/requester/cadence/get_latest_evm_height.cdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import EVM

access(all)
fun main(): UInt64 {
return EVM.getLatestBlock().height
}
26 changes: 26 additions & 0 deletions services/requester/requester.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ var (

//go:embed cadence/get_code.cdc
getCodeScript []byte

//go:embed cadence/get_latest_evm_height.cdc
getLatestEVMHeight []byte
)

const minFlowBalance = 2
Expand Down Expand Up @@ -75,6 +78,9 @@ type Requester interface {
// GetCode returns the code stored at the given address in
// the state for the given block number.
GetCode(ctx context.Context, address common.Address, height uint64) ([]byte, error)

// GetLatestEVMHeight returns the latest EVM height of the network.
GetLatestEVMHeight(ctx context.Context) (uint64, error)
}

var _ Requester = &EVM{}
Expand Down Expand Up @@ -406,6 +412,26 @@ func (e *EVM) GetCode(
return code, nil
}

func (e *EVM) GetLatestEVMHeight(ctx context.Context) (uint64, error) {
// TODO(m-Peter): Consider adding some time-based caching, if this
// endpoint turns out to be called quite frequently.
val, err := e.client.ExecuteScriptAtLatestBlock(
ctx,
e.replaceAddresses(getLatestEVMHeight),
[]cadence.Value{},
)
if err != nil {
return 0, err
}

// sanity check, should never occur
if _, ok := val.(cadence.UInt64); !ok {
e.logger.Panic().Msg(fmt.Sprintf("failed to convert height %v to UInt64", val))
}

return val.(cadence.UInt64).ToGoValue().(uint64), nil
}

// getSignerNetworkInfo loads the signer account from network and returns key index and sequence number
func (e *EVM) getSignerNetworkInfo(ctx context.Context) (int, uint64, error) {
account, err := e.client.GetAccount(ctx, e.config.COAAddress)
Expand Down
2 changes: 1 addition & 1 deletion tests/e2e_web3js_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ func TestWeb3_E2E(t *testing.T) {
runWeb3Test(t, "setup_test")
})

t.Run("ready-only interactions", func(t *testing.T) {
t.Run("read-only interactions", func(t *testing.T) {
runWeb3Test(t, "eth_non_interactive_test")
})

Expand Down
21 changes: 15 additions & 6 deletions tests/web3js/eth_non_interactive_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,18 @@ it('get transaction', async() => {
assert.equal(rcp.gasUsed, tx.gas)
})

it('get status', async() => {
//let mining = await web3.eth.isMining() todo
let sync = await web3.eth.isSyncing()
//assert.isFalse(mining)
assert.isFalse(sync)
})
it('get mining status', async() => {
let mining = await web3.eth.isMining()
assert.isFalse(mining)
})

it('get syncing status', async() => {
let height = await web3.eth.getBlockNumber()
assert.equal(height, conf.startBlockHeight)

let syncInfo = await web3.eth.isSyncing()
// conf.startBlockHeight = 3n
assert.equal(syncInfo.startingBlock, height)
assert.equal(syncInfo.currentBlock, height)
assert.equal(syncInfo.highestBlock, height)
})

0 comments on commit 24e36e7

Please sign in to comment.