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

Feature/scribe chain backfill #146

Merged
merged 7 commits into from
Aug 29, 2022
Merged

Conversation

CryptoMaxPlanck
Copy link
Contributor

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.

- chain backfiller type
- chain backfiller tests
- alter testing functions
@github-actions github-actions bot added the go Pull requests that update Go code label Aug 28, 2022
@codecov
Copy link

codecov bot commented Aug 28, 2022

Codecov Report

Merging #146 (0409f3d) into master (49cac98) will increase coverage by 0.12633%.
The diff coverage is 37.93103%.

@@                 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     
Impacted Files Coverage Δ
services/scribe/db/datastore/sql/base/log.go 0.00000% <0.00000%> (ø)
services/scribe/db/datastore/sql/base/receipt.go 0.00000% <0.00000%> (ø)
...rvices/scribe/db/datastore/sql/base/transaction.go 0.00000% <0.00000%> (ø)
services/scribe/backfill/chain.go 75.00000% <75.00000%> (ø)
services/scribe/backfill/contract.go 64.55696% <90.00000%> (+7.81937%) ⬆️
services/scribe/db/datastore/sql/base/model.go 100.00000% <100.00000%> (ø)
agents/indexer/domain.go 67.27273% <0.00000%> (+3.63636%) ⬆️

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))
Copy link
Contributor Author

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

// from a slice of ContractBackfillers.
type ChainBackfiller struct {
// contracts is the list of contracts to get logs for
contracts []contracts.DeployedContract
Copy link
Contributor

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:
image
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

Copy link
Contributor

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?

if err != nil {
return nil, fmt.Errorf("could not create contract backfiller: %w", err)
}
contractBackfillers[i] = *contractBackfiller
Copy link
Contributor

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)
Copy link
Contributor

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())
Copy link
Contributor

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) {
Copy link
Contributor

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

@@ -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)
Copy link
Contributor

Choose a reason for hiding this comment

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

common.Address

@@ -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.
Copy link
Contributor

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

for {
select {
case <-ctx.Done():
return nil
case log := <-logChan:
// check if either attempt count has exceeded maxAttempts
if storeAttempt > maxAttempts {
Copy link
Contributor

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

@trajan0x trajan0x merged commit ebfc61a into master Aug 29, 2022
@trajan0x trajan0x deleted the feature/scribe_chain_backfill branch August 29, 2022 01:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
go Pull requests that update Go code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants