Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ship-3971] Poll for headers when using http rpc #1537

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

davidcauchi
Copy link
Contributor

@davidcauchi davidcauchi commented Jan 8, 2025

  • Poll for headers when using http rpc

Below is a summarization created by an LLM (gpt-4-0125-preview). Be mindful of hallucinations and verify accuracy.

Why

The changes introduce polling for headers as an alternative to subscription-based updates in environments where subscriptions are not supported, such as over HTTP. This ensures that the EVMClient functionality remains robust across different network configurations and client capabilities.

What

  • lib/.changeset/v1.50.21.md
    • Added a changeset document describing the new feature allowing EVMClient to poll for headers when set up with an HTTP RPC.
  • lib/blockchain/blockchain.go
    • Added an InitializeHeaderSubscription method in the EVMClient interface to abstract the initialization of header updates, whether by subscription or polling.
  • lib/blockchain/ethereum.go
    • Modified newEVMClient to initialize header subscription or polling depending on the client's capabilities.
    • Added logic in WaitForFinalizedTx to start polling for new headers if subscriptions are not supported.
    • Implemented InitializeHeaderSubscription to decide between subscribing to new headers or starting a polling loop based on client support.
    • Added startPollingHeaders method to begin polling for new headers at regular intervals if subscriptions are not supported.
  • EthereumMultinodeClient
    • Implemented InitializeHeaderSubscription to initialize header subscription or polling for multinode clients.

@cl-sonarqube-production
Copy link

Copy link

@joaoluisam joaoluisam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

go func() {
defer e.subscriptionWg.Done()
// Initialize lastHeaderNumber dynamically
lastHeaderNumber := latestHeader.Number.Uint64() - 1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why -1? in the first run we could could just execute e.receiveHeader(latestHeader) after fetching last header.
won't doing -1 always result in the latest block being fetched 2x in every subsequent run?

e.l.Error().Err(err).Uint64("BlockNumber", blockNum).Msg("Error fetching header during range processing")
continue
}
lastHeaderNumber = header.Number.Uint64()
Copy link
Contributor

@Tofel Tofel Jan 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need it? maybe to be safe we could run lastHeaderNumber = latestHeader.Number.Uint64() after the for loop? like in my comment above


// Process headers from (lastHeaderNumber + 1) to latestHeader.Number
// We may need to add a rate limiter, if we run into issues.
for blockNum := lastHeaderNumber + 1; blockNum <= latestHeader.Number.Uint64(); blockNum++ {
Copy link
Contributor

@Tofel Tofel Jan 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will that work? in :1292 you have set lastHeaderNumber to latestHeader and here you are iterating from latestHeader+1 to latestHeader, so this for loop shouldn't run even once...

maybe better just iterate like this:

blocksToFetch := latestHeader.Number.Uint64() - lastHeaderNumber
for blockNum := 0; blockNum < blocksToFetch; blockNum++ {
    header, err := e.HeaderByNumber(context.Background(), big.NewInt(int64(blockNum)))
    if err != nil {
        e.l.Error().Err(err).Uint64("BlockNumber", blockNum).Msg("Error fetching header during range processing")
	continue
    }
    if err := e.receiveHeader(header); err != nil {
        e.l.Error().Err(err).Uint64("BlockNumber", blockNum).Msg("Error processing header")
        continue
    }
}

lastHeaderNumber = latestHeader.Number.Uint64()

I would also use < as condition, because the last block would have already been fetched and added in lines :1293-1295?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants