-
Notifications
You must be signed in to change notification settings - Fork 44
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: implement bloom indexer for
eth_getLogs
(#150)
* implement get logs bloom indexer * fix lint * fix bloom handler * increase unindexedLogs batch size * increase filter max block range * remove unused hash in the bloom bits and return empty bitsets if bloom bits are pruned * add test
- Loading branch information
Showing
16 changed files
with
594 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
package indexer | ||
|
||
import ( | ||
"context" | ||
|
||
"cosmossdk.io/collections" | ||
"github.com/ethereum/go-ethereum/core/bloombits" | ||
coretypes "github.com/ethereum/go-ethereum/core/types" | ||
|
||
evmconfig "github.com/initia-labs/minievm/x/evm/config" | ||
) | ||
|
||
// doBloomIndexing triggers bloom indexing in a goroutine. If bloom indexing is already running, | ||
// it does nothing. | ||
func (e *EVMIndexerImpl) doBloomIndexing(ctx context.Context, height uint64) { | ||
if running := e.bloomIndexingRunning.Swap(true); running { | ||
return | ||
} | ||
|
||
go func(ctx context.Context, height uint64) { | ||
defer e.bloomIndexingRunning.Store(false) | ||
if err := e.bloomIndexing(ctx, height); err != nil { | ||
e.logger.Error("failed to do bloom indexing", "err", err) | ||
} | ||
|
||
e.logger.Debug("bloom indexing finished", "height", height) | ||
}(ctx, height) | ||
} | ||
|
||
// bloomIndexing generates the bloom index if the current section is complete. | ||
func (e *EVMIndexerImpl) bloomIndexing(ctx context.Context, height uint64) error { | ||
section, err := e.PeekBloomBitsNextSection(ctx) | ||
if err != nil { | ||
return err | ||
} | ||
if (height / evmconfig.SectionSize) <= section { | ||
return nil | ||
} | ||
|
||
e.logger.Info("Processing new bloom indexing section", "section", section) | ||
|
||
gen, err := bloombits.NewGenerator(uint(evmconfig.SectionSize)) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
for i := uint64(0); i < evmconfig.SectionSize; i++ { | ||
header, err := e.BlockHeaderByNumber(ctx, section*evmconfig.SectionSize+i) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if err := gen.AddBloom(uint(header.Number.Uint64()-section*evmconfig.SectionSize), header.Bloom); err != nil { | ||
return err | ||
} | ||
} | ||
|
||
// write the bloom bits to the store | ||
for i := 0; i < coretypes.BloomBitLength; i++ { | ||
bits, err := gen.Bitset(uint(i)) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if err := e.RecordBloomBits(ctx, section, uint32(i), bits); err != nil { | ||
return err | ||
} | ||
} | ||
|
||
// increment the section number; if this fails, the section will be reprocessed | ||
if err := e.NextBloomBitsSection(ctx); err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// ReadBloomBits reads the bloom bits for the given index, section and hash. | ||
func (e *EVMIndexerImpl) ReadBloomBits(ctx context.Context, section uint64, index uint32) ([]byte, error) { | ||
bloomBits, err := e.BloomBits.Get(ctx, collections.Join(section, index)) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return bloomBits, nil | ||
} | ||
|
||
// RecordBloomBits records the bloom bits for the given index, section and hash. | ||
func (e *EVMIndexerImpl) RecordBloomBits(ctx context.Context, section uint64, index uint32, bloomBits []byte) error { | ||
return e.BloomBits.Set(ctx, collections.Join(section, index), bloomBits) | ||
} | ||
|
||
// NextBloomBitsSection increments the section number. | ||
func (e *EVMIndexerImpl) NextBloomBitsSection(ctx context.Context) error { | ||
_, err := e.BloomBitsNextSection.Next(ctx) | ||
return err | ||
} | ||
|
||
// PeekBloomBitsNextSection returns the next section number to be processed. | ||
func (e *EVMIndexerImpl) PeekBloomBitsNextSection(ctx context.Context) (uint64, error) { | ||
return e.BloomBitsNextSection.Peek(ctx) | ||
} | ||
|
||
// Check if bloom indexing is running | ||
func (e *EVMIndexerImpl) IsBloomIndexingRunning() bool { | ||
return e.bloomIndexingRunning.Load() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
package indexer_test | ||
|
||
import ( | ||
"math/big" | ||
"testing" | ||
"time" | ||
|
||
"github.com/ethereum/go-ethereum/common" | ||
"github.com/ethereum/go-ethereum/common/hexutil" | ||
coretypes "github.com/ethereum/go-ethereum/core/types" | ||
evmindexer "github.com/initia-labs/minievm/indexer" | ||
|
||
"github.com/initia-labs/minievm/tests" | ||
evmconfig "github.com/initia-labs/minievm/x/evm/config" | ||
evmtypes "github.com/initia-labs/minievm/x/evm/types" | ||
|
||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func Test_BloomIndexing(t *testing.T) { | ||
app, addrs, privKeys := tests.CreateApp(t) | ||
indexer := app.EVMIndexer().(*evmindexer.EVMIndexerImpl) | ||
defer app.Close() | ||
|
||
tx, _ := tests.GenerateCreateERC20Tx(t, app, privKeys[0]) | ||
_, finalizeRes := tests.ExecuteTxs(t, app, tx) | ||
tests.CheckTxResult(t, finalizeRes.TxResults[0], true) | ||
|
||
events := finalizeRes.TxResults[0].Events | ||
createEvent := events[len(events)-3] | ||
require.Equal(t, evmtypes.EventTypeContractCreated, createEvent.GetType()) | ||
|
||
contractAddr, err := hexutil.Decode(createEvent.Attributes[0].Value) | ||
require.NoError(t, err) | ||
|
||
// mint 1_000_000 tokens to the first address | ||
tx, _ = tests.GenerateMintERC20Tx(t, app, privKeys[0], common.BytesToAddress(contractAddr), addrs[0], new(big.Int).SetUint64(1_000_000_000_000)) | ||
_, finalizeRes = tests.ExecuteTxs(t, app, tx) | ||
tests.CheckTxResult(t, finalizeRes.TxResults[0], true) | ||
|
||
for i := uint64(0); i < evmconfig.SectionSize; i++ { | ||
tests.IncreaseBlockHeight(t, app) | ||
} | ||
|
||
// wait for bloom indexing | ||
for { | ||
if indexer.IsBloomIndexingRunning() { | ||
time.Sleep(100 * time.Millisecond) | ||
} else { | ||
break | ||
} | ||
} | ||
|
||
ctx, err := app.CreateQueryContext(0, false) | ||
require.NoError(t, err) | ||
|
||
for i := uint32(0); i < coretypes.BloomBitLength; i++ { | ||
bloomBits, err := indexer.ReadBloomBits(ctx, 0, i) | ||
require.NoError(t, err) | ||
require.NotNil(t, bloomBits) | ||
} | ||
|
||
nextSection, err := indexer.PeekBloomBitsNextSection(ctx) | ||
require.NoError(t, err) | ||
require.Equal(t, uint64(1), nextSection) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.