mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-15 08:23:46 +00:00
new: add filter for block logs
This commit is contained in:
parent
d3fe97ad4e
commit
432749d6a1
7 changed files with 230 additions and 11 deletions
31
accounts/abi/bind/backends/bor_simulated.go
Normal file
31
accounts/abi/bind/backends/bor_simulated.go
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
package backends
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/maticnetwork/bor/common"
|
||||||
|
"github.com/maticnetwork/bor/core/rawdb"
|
||||||
|
"github.com/maticnetwork/bor/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (fb *filterBackend) GetBorBlockReceipt(ctx context.Context, hash common.Hash) (*types.BorReceipt, error) {
|
||||||
|
number := rawdb.ReadHeaderNumber(fb.db, hash)
|
||||||
|
if number == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
receipt := rawdb.ReadRawBorReceipt(fb.db, hash, *number)
|
||||||
|
if receipt == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return receipt, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fb *filterBackend) GetBorBlockLogs(ctx context.Context, hash common.Hash) ([]*types.Log, error) {
|
||||||
|
receipt, err := fb.GetBorBlockReceipt(ctx, hash)
|
||||||
|
if err != nil || receipt == nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return receipt.Logs, nil
|
||||||
|
}
|
||||||
|
|
@ -33,14 +33,10 @@ func (b *EthAPIBackend) GetBorBlockReceipt(ctx context.Context, hash common.Hash
|
||||||
return receipt, nil
|
return receipt, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// func (b *EthAPIBackend) GetBorBlockLogs(ctx context.Context, hash common.Hash) ([][]*types.Log, error) {
|
func (b *EthAPIBackend) GetBorBlockLogs(ctx context.Context, hash common.Hash) ([]*types.Log, error) {
|
||||||
// receipts := b.eth.blockchain.GetReceiptsByHash(hash)
|
receipt := b.eth.blockchain.GetBorReceiptByHash(hash)
|
||||||
// if receipts == nil {
|
if receipt == nil {
|
||||||
// return nil, nil
|
return nil, nil
|
||||||
// }
|
}
|
||||||
// logs := make([][]*types.Log, len(receipts))
|
return receipt.Logs, nil
|
||||||
// for i, receipt := range receipts {
|
}
|
||||||
// logs[i] = receipt.Logs
|
|
||||||
// }
|
|
||||||
// return logs, nil
|
|
||||||
// }
|
|
||||||
|
|
|
||||||
35
eth/filters/bor_api.go
Normal file
35
eth/filters/bor_api.go
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
package filters
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/maticnetwork/bor/core/types"
|
||||||
|
"github.com/maticnetwork/bor/rpc"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (api *PublicFilterAPI) GetBorBlockLogs(ctx context.Context, crit FilterCriteria) ([]*types.Log, error) {
|
||||||
|
var filter *BorBlockLogsFilter
|
||||||
|
if crit.BlockHash != nil {
|
||||||
|
// Block filter requested, construct a single-shot filter
|
||||||
|
filter = NewBorBlockLogsFilter(api.backend, *crit.BlockHash, crit.Addresses, crit.Topics)
|
||||||
|
} else {
|
||||||
|
// Convert the RPC block numbers into internal representations
|
||||||
|
begin := rpc.LatestBlockNumber.Int64()
|
||||||
|
if crit.FromBlock != nil {
|
||||||
|
begin = crit.FromBlock.Int64()
|
||||||
|
}
|
||||||
|
end := rpc.LatestBlockNumber.Int64()
|
||||||
|
if crit.ToBlock != nil {
|
||||||
|
end = crit.ToBlock.Int64()
|
||||||
|
}
|
||||||
|
// Construct the range filter
|
||||||
|
filter = NewBorBlockLogsRangeFilter(api.backend, begin, end, crit.Addresses, crit.Topics)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the filter and return all the logs
|
||||||
|
logs, err := filter.Logs(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return returnLogs(logs), err
|
||||||
|
}
|
||||||
150
eth/filters/bor_filter.go
Normal file
150
eth/filters/bor_filter.go
Normal file
|
|
@ -0,0 +1,150 @@
|
||||||
|
// Copyright 2014 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package filters
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/maticnetwork/bor/common"
|
||||||
|
"github.com/maticnetwork/bor/core/types"
|
||||||
|
"github.com/maticnetwork/bor/ethdb"
|
||||||
|
"github.com/maticnetwork/bor/rpc"
|
||||||
|
)
|
||||||
|
|
||||||
|
// BorBlockLogsFilter can be used to retrieve and filter logs.
|
||||||
|
type BorBlockLogsFilter struct {
|
||||||
|
backend Backend
|
||||||
|
|
||||||
|
db ethdb.Database
|
||||||
|
addresses []common.Address
|
||||||
|
topics [][]common.Hash
|
||||||
|
|
||||||
|
block common.Hash // Block hash if filtering a single block
|
||||||
|
begin, end int64 // Range interval if filtering multiple blocks
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBorBlockLogsRangeFilter creates a new filter which uses a bloom filter on blocks to
|
||||||
|
// figure out whether a particular block is interesting or not.
|
||||||
|
func NewBorBlockLogsRangeFilter(backend Backend, begin, end int64, addresses []common.Address, topics [][]common.Hash) *BorBlockLogsFilter {
|
||||||
|
// Create a generic filter and convert it into a range filter
|
||||||
|
filter := newBorBlockLogsFilter(backend, addresses, topics)
|
||||||
|
filter.begin = begin
|
||||||
|
filter.end = end
|
||||||
|
|
||||||
|
return filter
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBorBlockLogsFilter creates a new filter which directly inspects the contents of
|
||||||
|
// a block to figure out whether it is interesting or not.
|
||||||
|
func NewBorBlockLogsFilter(backend Backend, block common.Hash, addresses []common.Address, topics [][]common.Hash) *BorBlockLogsFilter {
|
||||||
|
// Create a generic filter and convert it into a block filter
|
||||||
|
filter := newBorBlockLogsFilter(backend, addresses, topics)
|
||||||
|
filter.block = block
|
||||||
|
return filter
|
||||||
|
}
|
||||||
|
|
||||||
|
// newBorBlockLogsFilter creates a generic filter that can either filter based on a block hash,
|
||||||
|
// or based on range queries. The search criteria needs to be explicitly set.
|
||||||
|
func newBorBlockLogsFilter(backend Backend, addresses []common.Address, topics [][]common.Hash) *BorBlockLogsFilter {
|
||||||
|
return &BorBlockLogsFilter{
|
||||||
|
backend: backend,
|
||||||
|
addresses: addresses,
|
||||||
|
topics: topics,
|
||||||
|
db: backend.ChainDb(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Logs searches the blockchain for matching log entries, returning all from the
|
||||||
|
// first block that contains matches, updating the start of the filter accordingly.
|
||||||
|
func (f *BorBlockLogsFilter) Logs(ctx context.Context) ([]*types.Log, error) {
|
||||||
|
// If we're doing singleton block filtering, execute and return
|
||||||
|
if f.block != (common.Hash{}) {
|
||||||
|
receipt, err := f.backend.GetBorBlockReceipt(ctx, f.block)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if receipt == nil {
|
||||||
|
return nil, errors.New("unknown block")
|
||||||
|
}
|
||||||
|
return f.borBlockLogs(ctx, receipt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Figure out the limits of the filter range
|
||||||
|
header, _ := f.backend.HeaderByNumber(ctx, rpc.LatestBlockNumber)
|
||||||
|
if header == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
head := header.Number.Uint64()
|
||||||
|
|
||||||
|
if f.begin == -1 {
|
||||||
|
f.begin = int64(nextSprintEnd(head))
|
||||||
|
}
|
||||||
|
end := f.end
|
||||||
|
if f.end == -1 {
|
||||||
|
end = int64(head)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gather all indexed logs, and finish with non indexed ones
|
||||||
|
return f.unindexedLogs(ctx, uint64(end))
|
||||||
|
}
|
||||||
|
|
||||||
|
// unindexedLogs returns the logs matching the filter criteria based on raw block
|
||||||
|
// iteration and bloom matching.
|
||||||
|
func (f *BorBlockLogsFilter) unindexedLogs(ctx context.Context, end uint64) ([]*types.Log, error) {
|
||||||
|
var logs []*types.Log
|
||||||
|
|
||||||
|
for ; f.begin <= int64(end); f.begin = f.begin + 64 {
|
||||||
|
header, err := f.backend.HeaderByNumber(ctx, rpc.BlockNumber(f.begin))
|
||||||
|
if header == nil || err != nil {
|
||||||
|
return logs, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// get bor block receipt
|
||||||
|
receipt, err := f.backend.GetBorBlockReceipt(ctx, header.Hash())
|
||||||
|
if receipt == nil || err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// filter bor block logs
|
||||||
|
found, err := f.borBlockLogs(ctx, receipt)
|
||||||
|
if err != nil {
|
||||||
|
return logs, err
|
||||||
|
}
|
||||||
|
logs = append(logs, found...)
|
||||||
|
}
|
||||||
|
return logs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// borBlockLogs returns the logs matching the filter criteria within a single block.
|
||||||
|
func (f *BorBlockLogsFilter) borBlockLogs(ctx context.Context, receipt *types.BorReceipt) (logs []*types.Log, err error) {
|
||||||
|
if bloomFilter(receipt.Bloom, f.addresses, f.topics) {
|
||||||
|
found := filterLogs(receipt.Logs, nil, nil, f.addresses, f.topics)
|
||||||
|
logs = append(logs, found...)
|
||||||
|
}
|
||||||
|
return logs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func nextSprintEnd(n uint64) uint64 {
|
||||||
|
m := n % 64
|
||||||
|
if m == 0 {
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
return n + 64 - m
|
||||||
|
}
|
||||||
|
|
@ -36,6 +36,8 @@ type Backend interface {
|
||||||
HeaderByHash(ctx context.Context, blockHash common.Hash) (*types.Header, error)
|
HeaderByHash(ctx context.Context, blockHash common.Hash) (*types.Header, error)
|
||||||
GetReceipts(ctx context.Context, blockHash common.Hash) (types.Receipts, error)
|
GetReceipts(ctx context.Context, blockHash common.Hash) (types.Receipts, error)
|
||||||
GetLogs(ctx context.Context, blockHash common.Hash) ([][]*types.Log, error)
|
GetLogs(ctx context.Context, blockHash common.Hash) ([][]*types.Log, error)
|
||||||
|
GetBorBlockReceipt(ctx context.Context, blockHash common.Hash) (*types.BorReceipt, error)
|
||||||
|
GetBorBlockLogs(ctx context.Context, blockHash common.Hash) ([]*types.Log, error)
|
||||||
|
|
||||||
SubscribeNewTxsEvent(chan<- core.NewTxsEvent) event.Subscription
|
SubscribeNewTxsEvent(chan<- core.NewTxsEvent) event.Subscription
|
||||||
SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription
|
SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,7 @@ type Backend interface {
|
||||||
// Bor API
|
// Bor API
|
||||||
GetRootHash(ctx context.Context, starBlockNr uint64, endBlockNr uint64) (string, error)
|
GetRootHash(ctx context.Context, starBlockNr uint64, endBlockNr uint64) (string, error)
|
||||||
GetBorBlockReceipt(ctx context.Context, hash common.Hash) (*types.BorReceipt, error)
|
GetBorBlockReceipt(ctx context.Context, hash common.Hash) (*types.BorReceipt, error)
|
||||||
|
GetBorBlockLogs(ctx context.Context, hash common.Hash) ([]*types.Log, error)
|
||||||
|
|
||||||
// Transaction pool API
|
// Transaction pool API
|
||||||
SendTx(ctx context.Context, signedTx *types.Transaction) error
|
SendTx(ctx context.Context, signedTx *types.Transaction) error
|
||||||
|
|
|
||||||
|
|
@ -291,3 +291,7 @@ func (b *LesApiBackend) GetRootHash(ctx context.Context, starBlockNr uint64, end
|
||||||
func (b *LesApiBackend) GetBorBlockReceipt(ctx context.Context, hash common.Hash) (*types.BorReceipt, error) {
|
func (b *LesApiBackend) GetBorBlockReceipt(ctx context.Context, hash common.Hash) (*types.BorReceipt, error) {
|
||||||
return nil, errors.New("Not implemented")
|
return nil, errors.New("Not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *LesApiBackend) GetBorBlockLogs(ctx context.Context, hash common.Hash) ([]*types.Log, error) {
|
||||||
|
return nil, errors.New("Not implemented")
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue