From 2c9d4feb9fd3c7b65d50d115a1f8047eb7b90f2a Mon Sep 17 00:00:00 2001 From: spongeboi Date: Sun, 8 Sep 2024 18:31:38 -0700 Subject: [PATCH] wip: initial ethwal filter index --- filter.go | 156 ++++++++++++++++++ filter_index.go | 125 ++++++++++++++ filter_index_file.go | 60 +++++++ filter_reader.go | 55 ++++++ filter_test.go | 137 +++++++++++++++ filter_writer.go | 57 +++++++ go.mod | 15 +- go.sum | 46 +++++- .../506becdbf545c0be/0e764d3026f1cb12 | Bin 0 -> 104 bytes .../8b55e7dee2bff29b/b44aa92229ef7cdc | Bin 0 -> 27678 bytes .../7562562c68b24600/3997ae8eecbc76f9 | Bin 0 -> 82 bytes .../506becdbf545c0be/0e764d3026f1cb12 | Bin 0 -> 53962 bytes storage/storage.go | 2 + writer.go | 11 ++ writer_no_gap.go | 4 + 15 files changed, 657 insertions(+), 11 deletions(-) create mode 100644 filter.go create mode 100644 filter_index.go create mode 100644 filter_index_file.go create mode 100644 filter_reader.go create mode 100644 filter_test.go create mode 100644 filter_writer.go create mode 100644 indexes/spongeboi_erc_20_transfers_idx/9fb35e9e445a60fe/c1938b1a0a4c7cb1/506becdbf545c0be/0e764d3026f1cb12 create mode 100644 indexes/transfer_weth/19d3a297b0891a0a/e0939e4fd85a4e8a/8b55e7dee2bff29b/b44aa92229ef7cdc create mode 100644 indexes/transfer_weth/7fac973e17278470/9ae2bed6c6eefe3f/7562562c68b24600/3997ae8eecbc76f9 create mode 100644 indexes/transfer_weth/9fb35e9e445a60fe/c1938b1a0a4c7cb1/506becdbf545c0be/0e764d3026f1cb12 diff --git a/filter.go b/filter.go new file mode 100644 index 0000000..e723f98 --- /dev/null +++ b/filter.go @@ -0,0 +1,156 @@ +package ethwal + +import ( + "context" + "fmt" + + "github.com/0xsequence/ethwal/storage" + "github.com/RoaringBitmap/roaring/v2/roaring64" +) + +type Filter interface { + Eval() FilterIterator +} + +type FilterIterator interface { + HasNext() bool + Next() (uint64, uint16) + Bitmap() *roaring64.Bitmap +} + +type FilterBuilder interface { + And(filters ...Filter) Filter + Or(filters ...Filter) Filter + Eq(index string, key string) Filter +} + +func NewIndexesFilterBuilder[T any](indexes Indexes[T], fs storage.FS) (FilterBuilder, error) { + indexMap := make(map[IndexName]Index[T]) + for name, indexFunc := range indexes { + idx := &index[T]{ + name: name.Normalize(), + indexFunc: indexFunc, + fs: fs, + } + indexMap[name] = idx + } + return &chainLensFilterBuilder[T]{ + indexes: indexMap, + }, nil +} + +type chainLensFilterBuilder[T any] struct { + indexes map[IndexName]Index[T] +} + +type chainLensFilter struct { + resultSet *roaring64.Bitmap +} + +func (c *chainLensFilter) Eval() FilterIterator { + if c.resultSet == nil { + c.resultSet = roaring64.New() + } + + return newFilterIterator(c.resultSet.Clone()) +} + +func (c *chainLensFilterBuilder[T]) And(filters ...Filter) Filter { + var bmap *roaring64.Bitmap + for _, filter := range filters { + if filter == nil { + continue + } + if _, ok := filter.(*noOpFilter); ok { + continue + } + iter := filter.Eval() + if bmap == nil { + bmap = iter.Bitmap().Clone() + fmt.Println("first bmap", bmap.GetCardinality()) + } else { + fmt.Println("iter", iter.Bitmap().GetCardinality()) + bmap.And(iter.Bitmap()) + } + } + return &chainLensFilter{ + resultSet: bmap, + } +} + +func (c *chainLensFilterBuilder[T]) Or(filters ...Filter) Filter { + var bmap *roaring64.Bitmap + for _, filter := range filters { + if filter == nil { + continue + } + if _, ok := filter.(*noOpFilter); ok { + continue + } + iter := filter.Eval() + if bmap == nil { + bmap = iter.Bitmap().Clone() + } else { + bmap.Or(iter.Bitmap()) + } + } + + return &chainLensFilter{ + resultSet: bmap, + } +} + +func (c *chainLensFilterBuilder[T]) Eq(index string, key string) Filter { + // fetch the index and store it in the result set + index_ := IndexName(index).Normalize() + idx, ok := c.indexes[index_] + if !ok { + return &noOpFilter{} + } + + // TODO: what should the context be? + bitmap, err := idx.Fetch(context.Background(), key) + if err != nil { + return &noOpFilter{} + } + + return &chainLensFilter{ + resultSet: bitmap, + } +} + +type noOpFilter struct{} + +func (n *noOpFilter) Eval() FilterIterator { + bmap := roaring64.New() + return &filterIterator{ + iter: bmap.Iterator(), + bitmap: bmap, + } +} + +type filterIterator struct { + iter roaring64.IntPeekable64 + bitmap *roaring64.Bitmap +} + +func newFilterIterator(bmap *roaring64.Bitmap) FilterIterator { + return &filterIterator{ + iter: bmap.Iterator(), + bitmap: bmap, + } +} + +func (f *filterIterator) HasNext() bool { + return f.iter.HasNext() +} + +func (f *filterIterator) Next() (uint64, uint16) { + // TODO: how to handle if there's no next? + val := f.iter.Next() + return IndexCompoundID(val).Split() +} + +func (f *filterIterator) Bitmap() *roaring64.Bitmap { + return f.bitmap +} diff --git a/filter_index.go b/filter_index.go new file mode 100644 index 0000000..c65dd0b --- /dev/null +++ b/filter_index.go @@ -0,0 +1,125 @@ +package ethwal + +import ( + "context" + "crypto/sha256" + "fmt" + "strings" + + "github.com/0xsequence/ethwal/storage" + "github.com/RoaringBitmap/roaring/v2/roaring64" +) + +type IndexFunction[T any] func(block Block[T]) (toIndex bool, indexValues []string, positions []uint16, err error) + +type IndexCompoundID uint64 + +func NewIndexCompoundID(blockNum uint64, dataIndex uint16) IndexCompoundID { + return IndexCompoundID(uint64(blockNum<<16 | uint64(dataIndex))) +} + +func (i IndexCompoundID) BlockNumber() uint64 { + return (uint64(i) & 0xFFFFFFFFFFFF0000) >> 16 +} + +func (i IndexCompoundID) DataIndex() uint16 { + return uint16(i) & 0xFFFF +} + +func (i IndexCompoundID) Split() (uint64, uint16) { + return i.BlockNumber(), i.DataIndex() +} + +type IndexName string + +func (i IndexName) Normalize() IndexName { + return IndexName(strings.ToLower(string(i))) +} + +type Indexes[T any] map[IndexName]IndexFunction[T] + +type Index[T any] interface { + Fetch(ctx context.Context, key string) (*roaring64.Bitmap, error) + Store(ctx context.Context, block Block[T]) error + Name() IndexName +} + +type index[T any] struct { + name IndexName + indexFunc IndexFunction[T] + fs storage.FS +} + +var _ Index[any] = (*index[any])(nil) + +func (i *index[T]) Fetch(ctx context.Context, indexValue string) (*roaring64.Bitmap, error) { + file, err := newIndexFile(i.fs, i.name, indexValue) + if err != nil { + return nil, fmt.Errorf("failed to open index file: %w", err) + } + bmap, err := file.Read(ctx) + if err != nil { + return nil, err + } + + return bmap, nil +} + +func (i *index[T]) Store(ctx context.Context, block Block[T]) error { + toIndex, indexValues, indexPositions, err := i.indexFunc(block) + if err != nil { + return fmt.Errorf("failed to index block: %w", err) + } + if !toIndex { + return nil + } + + indexValueMap := make(map[string][]IndexCompoundID) + for i, indexValue := range indexValues { + if _, ok := indexValueMap[indexValue]; !ok { + indexValueMap[indexValue] = make([]IndexCompoundID, 0) + } + indexValueMap[indexValue] = append(indexValueMap[indexValue], NewIndexCompoundID(block.Number, indexPositions[i])) + } + + for indexValue, indexIDs := range indexValueMap { + file, err := newIndexFile(i.fs, i.name, indexValue) + if err != nil { + return fmt.Errorf("failed to open or create index file: %w", err) + } + bmap, err := file.Read(ctx) + if err != nil { + return err + } + for _, indexID := range indexIDs { + bmap.Add(uint64(indexID)) + } + err = file.Write(ctx, bmap) + if err != nil { + return err + } + } + + return nil +} + +func (i *index[T]) Name() IndexName { + return i.name +} + +func indexPath(index string, indexValue string) string { + h := sha256.New() + h.Write([]byte(indexValue)) + hashed := h.Sum(nil) + hashString := fmt.Sprintf("%x", hashed) + dividedLen := int(len(hashString) / 4) + indexValues := make([]string, 4) + for i := 0; i < 4; i++ { + if i == 3 { + indexValues[i] = hashString[i*dividedLen:] + continue + } + indexValues[i] = hashString[i*dividedLen : (i+1)*dividedLen] + } + return fmt.Sprintf("%s/%s/%s/%s/%s", index, indexValues[0], indexValues[1], indexValues[2], indexValues[3]) +} diff --git a/filter_index_file.go b/filter_index_file.go new file mode 100644 index 0000000..a7e979a --- /dev/null +++ b/filter_index_file.go @@ -0,0 +1,60 @@ +package ethwal + +import ( + "context" + "fmt" + + "github.com/0xsequence/ethwal/storage" + "github.com/RoaringBitmap/roaring/v2/roaring64" +) + +type indexFile struct { + fs storage.FS + path string +} + +func newIndexFile(fs storage.FS, indexName IndexName, key string) (*indexFile, error) { + path := indexPath(string(indexName), key) + return &indexFile{fs: fs, path: path}, nil +} + +func (i *indexFile) Read(ctx context.Context) (*roaring64.Bitmap, error) { + file, err := i.fs.Open(ctx, i.path, nil) + if err != nil { + // TODO: decide if we should report an error or just create a new roaring bitmap... + // with this approach we are not reporting an error if the file does not exist + // and we just write the new bitmap when write is called... + // return nil, fmt.Errorf("failed to open index file: %w", err) + return roaring64.New(), nil + } + defer file.Close() + var buf []byte = make([]byte, file.Size) + _, err = file.Read(buf) + if err != nil { + return nil, fmt.Errorf("failed to read index file: %w", err) + } + bmap := roaring64.New() + err = bmap.UnmarshalBinary(buf) + + if err != nil { + return nil, fmt.Errorf("failed to unmarshal bitmap: %w", err) + } + return bmap, nil +} + +func (i *indexFile) Write(ctx context.Context, bmap *roaring64.Bitmap) error { + file, err := i.fs.Create(ctx, i.path, nil) + if err != nil { + return fmt.Errorf("failed to open index file: %w", err) + } + defer file.Close() + data, err := bmap.ToBytes() + if err != nil { + return fmt.Errorf("failed to marshal bitmap: %w", err) + } + _, err = file.Write(data) + if err != nil { + return fmt.Errorf("failed to write bitmap: %w", err) + } + return nil +} diff --git a/filter_reader.go b/filter_reader.go new file mode 100644 index 0000000..b172261 --- /dev/null +++ b/filter_reader.go @@ -0,0 +1,55 @@ +package ethwal + +import ( + "context" + "io" +) + +type chainLensReader[T any] struct { + reader Reader[T] + filter Filter + iterator FilterIterator +} + +var _ Reader[any] = (*chainLensReader[any])(nil) + +func NewChainLensReader[T any](reader Reader[T], filter Filter) (Reader[T], error) { + return &chainLensReader[T]{ + reader: reader, + filter: filter, + iterator: filter.Eval(), + }, nil +} + +func (c *chainLensReader[T]) FilesNum() int { + return c.reader.FilesNum() +} + +func (c *chainLensReader[T]) Seek(ctx context.Context, blockNum uint64) error { + // TODO: how should seek function? + return c.reader.Seek(ctx, blockNum) +} + +func (c *chainLensReader[T]) BlockNum() uint64 { + // TODO: INCOMPLETE + return c.reader.BlockNum() +} + +func (c *chainLensReader[T]) Read(ctx context.Context) (Block[T], error) { + if !c.iterator.HasNext() { + return Block[T]{}, io.EOF + } + + // TODO: decide about the index what to do?? + blockNum, _ := c.iterator.Next() + err := c.reader.Seek(ctx, blockNum) + if err != nil { + return Block[T]{}, err + } + + return c.reader.Read(ctx) +} + +func (c *chainLensReader[T]) Close() error { + return c.reader.Close() +} diff --git a/filter_test.go b/filter_test.go new file mode 100644 index 0000000..a5d7010 --- /dev/null +++ b/filter_test.go @@ -0,0 +1,137 @@ +package ethwal + +import ( + "context" + "fmt" + "testing" + + "github.com/0xsequence/ethkit/go-ethereum/common" + "github.com/0xsequence/ethkit/go-ethereum/core/types" + "github.com/0xsequence/ethwal/storage/local" + "github.com/stretchr/testify/require" +) + +func Test_FilterWriter(t *testing.T) { + fs := local.NewLocalFS("./indexes/") + // fs.Create(context.Background(), "lmao_testing", nil) + reader, err := NewReader[[]types.Log](Options{ + Dataset: Dataset{ + Path: "../indexer-data/ethwal/137/ethlog/v1/", + }, + NewDecompressor: NewZSTDDecompressor, + NewDecoder: NewCBORDecoder, + }) + require.NoError(t, err) + + writer, err := NewWriter[[]types.Log](Options{ + Dataset: Dataset{ + Path: "../indexer-data/ethwal/137/ethlog/v8/", + }, + NewDecompressor: NewZSTDDecompressor, + NewDecoder: NewCBORDecoder, + }) + require.NoError(t, err) + spongeboiIndexValues := map[string]struct{}{} + transferWethIndexValues := map[string]struct{}{} + indexes := Indexes[[]types.Log]{ + "spongeboi_erc_20_transfers_idx": func(block Block[[]types.Log]) (toIndex bool, indexValues []string, pos []uint16, err error) { + pos = []uint16{} + toIndex = false + indexValues = []string{} + err = nil + for i, log := range block.Data { + // if log.Address.String() == addy.String() { + if len(log.Topics) == 3 && log.Topics[0].String() == "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" && + (log.Topics[1].String() == "0x000000000000000000000000d4bbf5d234cc95441a8af0a317d8874ee425e74d" || log.Topics[2].String() == "0x000000000000000000000000d4bbf5d234cc95441a8af0a317d8874ee425e74d") { + toIndex = true + indexValue := string(log.Topics[0].Hex()) + indexValues = append(indexValues, indexValue) + pos = append(pos, uint16(i)) + spongeboiIndexValues[indexValue] = struct{}{} + // fmt.Println("spongeboi indexValue", indexValue) + } + } + return + }, + "transfer_weth": func(block Block[[]types.Log]) (toIndex bool, indexValues []string, pos []uint16, err error) { + pos = []uint16{} + toIndex = false + indexValues = []string{} + err = nil + addy := common.HexToAddress("0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619") + for i, log := range block.Data { + if log.Address.String() == addy.String() { + toIndex = true + indexValue := string(log.Topics[0].Hex()) + pos = append(pos, uint16(i)) + indexValues = append(indexValues, indexValue) + transferWethIndexValues[indexValue] = struct{}{} + // fmt.Println("transfer_weth indexValue", indexValue) + } + } + return + }, + } + + // filterBuilder, err := NewIndexesFilterBuilder(indexes, fs) + // require.NoError(t, err) + + chainLensWriter, err := NewChainLensWriter(writer, indexes, fs) + require.NoError(t, err) + + for { + block, err := reader.Read(context.Background()) + // fmt.Println("reading block", block.Number) + if err != nil { + break + } + + chainLensWriter.Write(context.Background(), block) + } + + chainLensWriter.Close(context.Background()) + + for indexValue := range spongeboiIndexValues { + fmt.Println("spongeboi indexValue", indexValue) + } + for indexValue := range transferWethIndexValues { + fmt.Println("transfer_weth indexValue", indexValue) + } +} + +func Test_Filter(t *testing.T) { + fs := local.NewLocalFS("./indexes/") + // fs.Create(context.Background(), "lmao_testing", nil) + // reader, err := NewReader[[]types.Log](Options{ + // Dataset: Dataset{ + // Path: "../indexer-data/ethwal/137/ethlog/v1/", + // }, + // NewDecompressor: NewZSTDDecompressor, + // NewDecoder: NewCBORDecoder, + // }) + // require.NoError(t, err) + indexes := Indexes[[]types.Log]{ + "spongeboi_erc_20_transfers_idx": func(block Block[[]types.Log]) (toIndex bool, indexValues []string, pos []uint16, err error) { + return + }, + "transfer_weth": func(block Block[[]types.Log]) (toIndex bool, indexValues []string, pos []uint16, err error) { + return + }, + } + fb, err := NewIndexesFilterBuilder(indexes, fs) + require.NoError(t, err) + + spongeboiTxnFilter := fb.Eq("spongeboi_erc_20_transfers_idx", "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef") + wethTransferFilter := fb.Eq("transfer_weth", "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef") + f := fb.And(spongeboiTxnFilter, wethTransferFilter) + // chainLensReader, err := NewChainLensReader(reader, f) + iter := f.Eval() + bmap := iter.Bitmap() + fmt.Println("bmap len", bmap.GetCardinality()) + for itere := bmap.Iterator(); itere.HasNext(); { + fmt.Println(IndexCompoundID(itere.Next()).Split()) + } +} + +// topic hash for TxExcuted in sequence: 0x5c4eeb02dabf8976016ab414d617f9a162936dcace3cdef8c69ef6e262ad5ae7 +// topic hash for Transfer in weth: 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef diff --git a/filter_writer.go b/filter_writer.go new file mode 100644 index 0000000..ef51fe3 --- /dev/null +++ b/filter_writer.go @@ -0,0 +1,57 @@ +package ethwal + +import ( + "context" + + "github.com/0xsequence/ethwal/storage" +) + +type chainLensWriter[T any] struct { + writer Writer[T] + indexes map[IndexName]Index[T] +} + +var _ Writer[any] = (*chainLensWriter[any])(nil) + +func NewChainLensWriter[T any](writer Writer[T], indexes Indexes[T], fs storage.FS) (Writer[T], error) { + indexMap := make(map[IndexName]Index[T]) + for name, indexFunc := range indexes { + idx := &index[T]{ + name: name.Normalize(), + indexFunc: indexFunc, + fs: fs, + } + indexMap[name] = idx + } + cl := &chainLensWriter[T]{indexes: indexMap} + writer.SetCallback(cl.callback) + cl.writer = writer + return cl, nil +} + +func (c *chainLensWriter[T]) Write(ctx context.Context, block Block[T]) error { + // fmt.Println("chainLensWriter Write called", block.Number) + return c.writer.Write(ctx, block) +} + +func (c *chainLensWriter[T]) Close(ctx context.Context) error { + return c.writer.Close(ctx) +} + +func (c *chainLensWriter[T]) BlockNum() uint64 { + return c.writer.BlockNum() +} + +func (c *chainLensWriter[T]) RollFile(ctx context.Context) error { + return c.writer.RollFile(ctx) +} + +func (c *chainLensWriter[T]) SetCallback(cb func(Block[T])) { +} + +func (c *chainLensWriter[T]) callback(block Block[T]) { + for _, index := range c.indexes { + // TODO: what should the context be? + index.Store(context.Background(), block) + } +} diff --git a/go.mod b/go.mod index 84721fb..2589295 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( cloud.google.com/go/storage v1.41.0 github.com/0xsequence/ethkit v1.26.1 github.com/DataDog/zstd v1.5.5 + github.com/RoaringBitmap/roaring/v2 v2.3.4 github.com/Shopify/go-storage v1.3.2 github.com/c2h5oh/datasize v0.0.0-20231215233829-aa82cc1e6500 github.com/fatih/structs v1.1.0 @@ -21,8 +22,15 @@ require ( cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect cloud.google.com/go/compute/metadata v0.3.0 // indirect cloud.google.com/go/iam v1.1.8 // indirect + github.com/bits-and-blooms/bitset v1.12.0 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect + github.com/consensys/bavard v0.1.13 // indirect + github.com/consensys/gnark-crypto v0.12.1 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect + github.com/crate-crypto/go-kzg-4844 v1.0.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect + github.com/ethereum/c-kzg-4844/bindings/go v0.0.0-20230126171313-363c7d7593b4 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect @@ -33,11 +41,12 @@ require ( github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect github.com/googleapis/gax-go/v2 v2.12.4 // indirect github.com/holiman/uint256 v1.2.4 // indirect - github.com/kr/pretty v0.3.1 // indirect + github.com/mmcloughlin/addchain v0.4.0 // indirect + github.com/mschoch/smat v0.2.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/stretchr/objx v0.5.2 // indirect - github.com/tidwall/btree v1.7.0 // indirect + github.com/supranational/blst v0.3.11-0.20230124161941-ca03e11a3ff2 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 // indirect go.opencensus.io v0.24.0 // indirect @@ -58,6 +67,6 @@ require ( google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8 // indirect google.golang.org/grpc v1.63.2 // indirect google.golang.org/protobuf v1.34.1 // indirect - gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + rsc.io/tmplfunc v0.0.3 // indirect ) diff --git a/go.sum b/go.sum index 3ac3cba..485ef6b 100644 --- a/go.sum +++ b/go.sum @@ -16,23 +16,43 @@ github.com/0xsequence/ethkit v1.26.1/go.mod h1:mot9svDfrz13RcDeK6sZnqHvbGac9kzXR github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= +github.com/RoaringBitmap/roaring/v2 v2.3.4 h1:gGEh3lC5rrrvp9NoZeIAUJ/QvvvJ2qiNNWn+9gbHsDk= +github.com/RoaringBitmap/roaring/v2 v2.3.4/go.mod h1:qhgqItwt5rQY0Nj4zw9nMhXv4Pkq2D8dA8RPJAfyU08= github.com/Shopify/go-storage v1.3.2 h1:POQkNXLEMLV3ra/YUYxqh0jD+/8R7bbLvJHyvo4jqd0= github.com/Shopify/go-storage v1.3.2/go.mod h1:+TaY1ck1poxnIMR9d20JcfBKuT6dhtaz8yAojOr8ID8= +github.com/bits-and-blooms/bitset v1.12.0 h1:U/q1fAF7xXRhFCrhROzIfffYnu+dlS38vCZtmFVPHmA= +github.com/bits-and-blooms/bitset v1.12.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/btcsuite/btcd v0.23.4 h1:IzV6qqkfwbItOS/sg/aDfPDsjPP8twrCOE2R93hxMlQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= +github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/c2h5oh/datasize v0.0.0-20231215233829-aa82cc1e6500 h1:6lhrsTEnloDPXyeZBvSYvQf8u86jbKehZPVDDlkgDl4= github.com/c2h5oh/datasize v0.0.0-20231215233829-aa82cc1e6500/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= +github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= +github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= +github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/crate-crypto/go-kzg-4844 v1.0.0 h1:TsSgHwrkTKecKJ4kadtHi4b3xHW5dCFUDFnUp1TsawI= +github.com/crate-crypto/go-kzg-4844 v1.0.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 h1:HbphB4TFFXpv7MNrT52FGrrgVXF1owhMVTHFZIlnvd4= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/ethereum/c-kzg-4844/bindings/go v0.0.0-20230126171313-363c7d7593b4 h1:B2mpK+MNqgPqk2/KNi1LbqwtZDy5F7iy0mynQiBr8VA= +github.com/ethereum/c-kzg-4844/bindings/go v0.0.0-20230126171313-363c7d7593b4/go.mod h1:y4GA2JbAUama1S4QwYjC2hefgGLU8Ul0GMtL/ADMF1c= github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= @@ -72,6 +92,7 @@ github.com/google/martian/v3 v3.3.3 h1:DIhPTQrbPkgs2yJYdXU/eNACCG5DVQjySNRNlflZ9 github.com/google/martian/v3 v3.3.3/go.mod h1:iEPrYcgCF7jA9OtScMFQyAlZZ4YXTKEtJ1E6RWzmBA0= github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= +github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -81,18 +102,22 @@ github.com/googleapis/gax-go/v2 v2.12.4 h1:9gWcmF85Wvq4ryPFvGFaOgPIs1AQX0d0bcbGw github.com/googleapis/gax-go/v2 v2.12.4/go.mod h1:KYEYLorsnIGDi/rPC8b5TdlB9kbKoFubselGIoBMCwI= github.com/holiman/uint256 v1.2.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU= github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= +github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= +github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= +github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= +github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= +github.com/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM= +github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= @@ -102,13 +127,14 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/tidwall/btree v1.7.0 h1:L1fkJH/AuEh5zBnnBbmTwQ5Lt+bRJ5A8EWecslvo9iI= -github.com/tidwall/btree v1.7.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY= +github.com/supranational/blst v0.3.11-0.20230124161941-ca03e11a3ff2 h1:wh1wzwAhZBNiZO37uWS/nDaKiIwHz4mDo4pnA+fqTO0= +github.com/supranational/blst v0.3.11-0.20230124161941-ca03e11a3ff2/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/urfave/cli/v2 v2.27.2 h1:6e0H+AkS+zDckwPCUrZkKX38mRaau4nL2uipkJpbkcI= github.com/urfave/cli/v2 v2.27.2/go.mod h1:g0+79LmHHATl7DAcHO99smiR/T7uGLw84w8Y42x+4eM= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= @@ -207,8 +233,12 @@ google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHh gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= +rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= diff --git a/indexes/spongeboi_erc_20_transfers_idx/9fb35e9e445a60fe/c1938b1a0a4c7cb1/506becdbf545c0be/0e764d3026f1cb12 b/indexes/spongeboi_erc_20_transfers_idx/9fb35e9e445a60fe/c1938b1a0a4c7cb1/506becdbf545c0be/0e764d3026f1cb12 new file mode 100644 index 0000000000000000000000000000000000000000..119bb8f6708e4dd10beb4479e9394e6cacc1e6f2 GIT binary patch literal 104 zcmZQ#fB;Em1_mnw1_nkT_p2%+g8-0bW#nMYgo?8P`OD8TFuVrh_dxs&i2KhoFf0XP g3!t185ZeH;9S}PJu@eygVsK_CVtCE4fN28*0PB$vcK`qY literal 0 HcmV?d00001 diff --git a/indexes/transfer_weth/19d3a297b0891a0a/e0939e4fd85a4e8a/8b55e7dee2bff29b/b44aa92229ef7cdc b/indexes/transfer_weth/19d3a297b0891a0a/e0939e4fd85a4e8a/8b55e7dee2bff29b/b44aa92229ef7cdc new file mode 100644 index 0000000000000000000000000000000000000000..1c0b310e3778f37e469198843ecc7b9b86a65072 GIT binary patch literal 27678 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 M4^Op|)3@gT2bwZ((f|Me literal 0 HcmV?d00001 diff --git a/indexes/transfer_weth/7fac973e17278470/9ae2bed6c6eefe3f/7562562c68b24600/3997ae8eecbc76f9 b/indexes/transfer_weth/7fac973e17278470/9ae2bed6c6eefe3f/7562562c68b24600/3997ae8eecbc76f9 new file mode 100644 index 0000000000000000000000000000000000000000..4e39be358b830a0319e6cce1bc8962eef6104bf6 GIT binary patch literal 82 zcmZQ#fB;Em1_mnw1_mY|w@j6RVJQ$x0NGMN9K@i-kO`FsQVc3*7#N3_}b903DkMivR!s literal 0 HcmV?d00001 diff --git a/indexes/transfer_weth/9fb35e9e445a60fe/c1938b1a0a4c7cb1/506becdbf545c0be/0e764d3026f1cb12 b/indexes/transfer_weth/9fb35e9e445a60fe/c1938b1a0a4c7cb1/506becdbf545c0be/0e764d3026f1cb12 new file mode 100644 index 0000000000000000000000000000000000000000..fed7f25af160fe57306eb7fef0084169e3057490 GIT binary patch literal 53962 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 aP+qh-hJWVcU38AJIx?xB#3F@N%>MwEtcl?O literal 0 HcmV?d00001 diff --git a/storage/storage.go b/storage/storage.go index e6e9fb0..ff7a0f0 100644 --- a/storage/storage.go +++ b/storage/storage.go @@ -6,6 +6,8 @@ type FS storage.FS type Walker storage.Walker +type File storage.File + var NewPrefixWrapper = storage.NewPrefixWrapper var NewCacheWrapper = storage.NewCacheWrapper diff --git a/writer.go b/writer.go index 1e9c40a..a0f3fca 100644 --- a/writer.go +++ b/writer.go @@ -17,6 +17,7 @@ type Writer[T any] interface { BlockNum() uint64 RollFile(ctx context.Context) error Close(ctx context.Context) error + SetCallback(func(Block[T])) } type writer[T any] struct { @@ -35,6 +36,8 @@ type writer[T any] struct { encoder Encoder + callback func(Block[T]) + mu sync.Mutex } @@ -111,6 +114,10 @@ func (w *writer[T]) Write(ctx context.Context, b Block[T]) error { return fmt.Errorf("failed to encode file data: %w", err) } + if w.callback != nil { + w.callback(b) + } + w.lastBlockNum = b.Number w.options.FileRollPolicy.onBlockProcessed(w.lastBlockNum) return nil @@ -155,6 +162,10 @@ func (w *writer[T]) Close(ctx context.Context) error { return nil } +func (w *writer[T]) SetCallback(cb func(Block[T])) { + w.callback = cb +} + func (w *writer[T]) isReadyToWrite() bool { return w.encoder != nil } diff --git a/writer_no_gap.go b/writer_no_gap.go index e16a62d..1b4fc28 100644 --- a/writer_no_gap.go +++ b/writer_no_gap.go @@ -46,3 +46,7 @@ func (n *noGapWriter[T]) BlockNum() uint64 { func (n *noGapWriter[T]) Close(ctx context.Context) error { return n.w.Close(ctx) } + +func (n *noGapWriter[T]) SetCallback(cb func(Block[T])) { + n.w.SetCallback(cb) +}