-
Notifications
You must be signed in to change notification settings - Fork 33
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
Feature/scribe chain backfill #146
Conversation
Codecov Report
@@ Coverage Diff @@
## master #146 +/- ##
===================================================
+ Coverage 51.28562% 51.41195% +0.12632%
===================================================
Files 137 138 +1
Lines 5756 5843 +87
Branches 73 73
===================================================
+ Hits 2952 3004 +52
- Misses 2511 2545 +34
- Partials 293 294 +1
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. |
// Backfill the first batch of events. | ||
latestBlock, err := simulatedChain.BlockNumber(b.GetTestContext()) | ||
Nil(b.T(), err) | ||
err = chainBackfiller.Backfill(b.GetTestContext(), latestBlock-uint64(chainConfig.ConfirmationThreshold)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
setting the endHeight of the backfiller will be the job of the ScribeBackfiller
which is the aggregator of chain backfillers. This is just to test the method that the ScribeBackfiller
is going to use for setting that end blockheight. But when actually calling it, there will be protective checks around making sure endHeight doesn't wrap around if threshold > currentBlock. This is a placeholder/duplicate of what will be done in the ScribeTest level. this is more so a proof of concept / sanity check
services/scribe/backfill/chain.go
Outdated
// from a slice of ContractBackfillers. | ||
type ChainBackfiller struct { | ||
// contracts is the list of contracts to get logs for | ||
contracts []contracts.DeployedContract |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We definitely shouldn't be using this interface here, I'd define a new one. There are Accessor methods we don't have access to here/we don't need any of these:
From #114, I'm pretty sure the only thing we need here is:
- Address
- ChainID
- StartBlock
Owner, DeployTX, and ContractHandle will all be nil here and throw an error
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually - we can probably just get this from chainConfig, right?
services/scribe/backfill/chain.go
Outdated
if err != nil { | ||
return nil, fmt.Errorf("could not create contract backfiller: %w", err) | ||
} | ||
contractBackfillers[i] = *contractBackfiller |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is safe (risks nil dereference. Let's set the type in the slice to just be []*ContractBackfiller
startHeight := c.chainConfig.Contracts[contractBackfiller.contract.Address().String()].StartBlock | ||
// call Backfill concurrently | ||
g.Go(func() error { | ||
err := contractBackfiller.Backfill(ctx, startHeight, endHeight) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still not sure about this error handling behavior here. An error on a contract in a given chain shouldn't throw an error on every contract on that chain. Maybe we need to throw this in a for-loop w/ a backoff? If you want to handle in a different pr can definitely make an issue and handle later, but definitely needs to be addressed
One thing to remember here is RPCs can be super flaky. Rate limits, data-availability issues, etc can all cause any of our networked calls (eth_getLogs
, eth_getTransactionByHash
, eth_getReceipt
) to fail so we want to design these individual loops to be resilient.
The goal here is to keep these things indexing as long as we can hit our most important gurantee- that we're not marking a range as indexed if it's not indexed
// Check that the events were written to the database. | ||
for _, contract := range contracts { | ||
// Check the storage of logs. | ||
logs, err := b.testDB.RetrieveAllLogs_Test(b.GetTestContext(), true, chainConfig.ChainID, contract.Address().String()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One minor thing here, can we rename this to UnsafeRetrieveAllLogs
, just a standard go pattern
@@ -103,11 +112,22 @@ func (s Store) RetrieveLogs(ctx context.Context, txHash common.Hash, chainID uin | |||
// RetrieveAllLogs_Test retrieves all logs in the database. This is only used for testing. | |||
// | |||
//nolint:golint, revive, stylecheck | |||
func (s Store) RetrieveAllLogs_Test(ctx context.Context) (logs []*types.Log, err error) { | |||
func (s Store) RetrieveAllLogs_Test(ctx context.Context, specific bool, chainID uint32, address string) (logs []*types.Log, err error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason address isn't a string here? Would like to try to keep the interface native
services/scribe/db/event.go
Outdated
@@ -14,13 +14,13 @@ type EventDB interface { | |||
// RetrieveLogs retrieves logs that match a tx hash and chain id | |||
RetrieveLogs(ctx context.Context, txHash common.Hash, chainID uint32) (logs []*types.Log, err error) | |||
// RetrieveAllLogs_Test retrieves all logs in the database. This is only used for testing. | |||
RetrieveAllLogs_Test(ctx context.Context) (logs []*types.Log, err error) | |||
RetrieveAllLogs_Test(ctx context.Context, specific bool, chainID uint32, address string) (logs []*types.Log, err error) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
common.Address
services/scribe/db/event.go
Outdated
@@ -14,13 +14,13 @@ type EventDB interface { | |||
// RetrieveLogs retrieves logs that match a tx hash and chain id | |||
RetrieveLogs(ctx context.Context, txHash common.Hash, chainID uint32) (logs []*types.Log, err error) | |||
// RetrieveAllLogs_Test retrieves all logs in the database. This is only used for testing. | |||
RetrieveAllLogs_Test(ctx context.Context) (logs []*types.Log, err error) | |||
RetrieveAllLogs_Test(ctx context.Context, specific bool, chainID uint32, address string) (logs []*types.Log, err error) | |||
// StoreReceipt stores a receipt | |||
StoreReceipt(ctx context.Context, receipt types.Receipt, chainID uint32) error | |||
// RetrieveReceipt retrieves a receipt by tx hash and chain id | |||
RetrieveReceipt(ctx context.Context, txHash common.Hash, chainID uint32) (receipt types.Receipt, err error) | |||
// RetrieveAllReceipts_Test retrieves all receipts in the database. This is only used for testing. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's specific here? Throw in comment
services/scribe/backfill/contract.go
Outdated
for { | ||
select { | ||
case <-ctx.Done(): | ||
return nil | ||
case log := <-logChan: | ||
// check if either attempt count has exceeded maxAttempts | ||
if storeAttempt > maxAttempts { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's ditch max attempts here
Description
Each contract backfiller belongs to a chain backfiller. The chain represents one chain and hosts our contracts on it, which we add to a config and use to create a contract backfiller for each one. The job of the chain backfiller is to aggregate the storing of logs on all of these contract backfillers to populate the same event database.