core/filtermaps: removed chainView interface and limitedChainView

This commit is contained in:
Zsolt Felfoldi 2025-03-12 14:35:38 +01:00
parent 131883e903
commit 4ece8f50f8
6 changed files with 103 additions and 159 deletions

View file

@ -22,119 +22,109 @@ import (
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
) )
// chainView represents an immutable view of a chain with a block hash, a // blockchain represents the underlying blockchain of ChainView.
// block id and a set of receipts associated to each block number. Block id
// can be any unique identifier of the blocks.
// Note that id and receipts are expected to be available up to headNumber
// while the canonical block hash is only expected up to headNumber-1 so that
// it can be implemented by the block builder while the processed head hash
// is not known yet.
type chainView interface {
headNumber() uint64
getBlockHash(number uint64) common.Hash
getBlockId(number uint64) common.Hash
getReceipts(number uint64) types.Receipts
}
// equalViews returns true if the two chain views are equivalent.
func equalViews(cv1, cv2 chainView) bool {
if cv1 == nil || cv2 == nil {
return false
}
head1, head2 := cv1.headNumber(), cv2.headNumber()
return head1 == head2 && cv1.getBlockId(head1) == cv2.getBlockId(head2)
}
// matchViews returns true if the two chain views are equivalent up until the
// specified block number. If the specified number is higher than one of the
// heads then false is returned.
func matchViews(cv1, cv2 chainView, number uint64) bool {
if cv1 == nil || cv2 == nil {
return false
}
head1 := cv1.headNumber()
if head1 < number {
return false
}
head2 := cv2.headNumber()
if head2 < number {
return false
}
if number == head1 || number == head2 {
return cv1.getBlockId(number) == cv2.getBlockId(number)
}
return cv1.getBlockHash(number) == cv2.getBlockHash(number)
}
// blockchain defines functions required by the FilterMaps log indexer.
type blockchain interface { type blockchain interface {
GetHeader(hash common.Hash, number uint64) *types.Header GetHeader(hash common.Hash, number uint64) *types.Header
GetCanonicalHash(number uint64) common.Hash GetCanonicalHash(number uint64) common.Hash
GetReceiptsByHash(hash common.Hash) types.Receipts GetReceiptsByHash(hash common.Hash) types.Receipts
} }
// StoredChainView implements chainView based on a given blockchain. // ChainView represents an immutable view of a chain with a block id and a set
// of receipts associated to each block number and a block hash associated with
// all block numbers except the head block. This is because in the future
// ChainView might represent a view where the head block is currently being
// created. Block id is a unique identifier that can also be calculated for the
// head block.
// Note that the view's head does not have to be the current canonical head // Note that the view's head does not have to be the current canonical head
// of the underlying blockchain, it should only possess the block headers // of the underlying blockchain, it should only possess the block headers
// and receipts up until the expected chain view head. // and receipts up until the expected chain view head.
// Also note that this implementation uses the canonical block hash as block type ChainView struct {
// id which works as long as the log index structure is not hashed into the
// block headers. Starting from the fork that hashes the log index to the
// block the id needs to be based on a set of fields that exactly defines the
// block but does not include the log index root itself.
type StoredChainView struct {
chain blockchain chain blockchain
head uint64 headNumber uint64
hashes []common.Hash // block hashes starting backwards from headNumber until first canonical hash hashes []common.Hash // block hashes starting backwards from headNumber until first canonical hash
} }
// NewStoredChainView creates a new StoredChainView. // NewChainView creates a new ChainView.
func NewStoredChainView(chain blockchain, number uint64, hash common.Hash) *StoredChainView { func NewChainView(chain blockchain, number uint64, hash common.Hash) *ChainView {
cv := &StoredChainView{ cv := &ChainView{
chain: chain, chain: chain,
head: number, headNumber: number,
hashes: []common.Hash{hash}, hashes: []common.Hash{hash},
} }
cv.extendNonCanonical() cv.extendNonCanonical()
return cv return cv
} }
// headNumber implements chainView. // getBlockHash returns the block hash belonging to the given block number.
func (cv *StoredChainView) headNumber() uint64 { // Note that the hash of the head block is not returned because ChainView might
return cv.head // represent a view where the head block is currently being created.
} func (cv *ChainView) getBlockHash(number uint64) common.Hash {
if number >= cv.headNumber {
// getBlockHash implements chainView.
func (cv *StoredChainView) getBlockHash(number uint64) common.Hash {
if number >= cv.head {
panic("invalid block number") panic("invalid block number")
} }
return cv.blockHash(number) return cv.blockHash(number)
} }
// getBlockId implements chainView. // getBlockId returns the unique block id belonging to the given block number.
func (cv *StoredChainView) getBlockId(number uint64) common.Hash { // Note that it is currently equal to the block hash. In the future it might
if number > cv.head { // be a different id for future blocks if the log index root becomes part of
// consensus and therefore rendering the index with the new head will happen
// before the hash of that new head is available.
func (cv *ChainView) getBlockId(number uint64) common.Hash {
if number > cv.headNumber {
panic("invalid block number") panic("invalid block number")
} }
return cv.blockHash(number) return cv.blockHash(number)
} }
// getReceipts implements chainView. // getReceipts returns the set of receipts belonging to the block at the given
func (cv *StoredChainView) getReceipts(number uint64) types.Receipts { // block number.
if number > cv.head { func (cv *ChainView) getReceipts(number uint64) types.Receipts {
if number > cv.headNumber {
panic("invalid block number") panic("invalid block number")
} }
return cv.chain.GetReceiptsByHash(cv.blockHash(number)) return cv.chain.GetReceiptsByHash(cv.blockHash(number))
} }
// limitedView returns a new chain view that is a truncated version of the parent view.
func (cv *ChainView) limitedView(newHead uint64) *ChainView {
if newHead >= cv.headNumber {
return cv
}
return NewChainView(cv.chain, newHead, cv.blockHash(newHead))
}
// equalViews returns true if the two chain views are equivalent.
func equalViews(cv1, cv2 *ChainView) bool {
if cv1 == nil || cv2 == nil {
return false
}
return cv1.headNumber == cv2.headNumber && cv1.getBlockId(cv1.headNumber) == cv2.getBlockId(cv2.headNumber)
}
// matchViews returns true if the two chain views are equivalent up until the
// specified block number. If the specified number is higher than one of the
// heads then false is returned.
func matchViews(cv1, cv2 *ChainView, number uint64) bool {
if cv1 == nil || cv2 == nil {
return false
}
if cv1.headNumber < number || cv2.headNumber < number {
return false
}
if number == cv1.headNumber || number == cv2.headNumber {
return cv1.getBlockId(number) == cv2.getBlockId(number)
}
return cv1.getBlockHash(number) == cv2.getBlockHash(number)
}
// extendNonCanonical checks whether the previously known reverse list of head // extendNonCanonical checks whether the previously known reverse list of head
// hashes still ends with one that is canonical on the underlying blockchain. // hashes still ends with one that is canonical on the underlying blockchain.
// If necessary then it traverses further back on the header chain and adds // If necessary then it traverses further back on the header chain and adds
// more hashes to the list. // more hashes to the list.
func (cv *StoredChainView) extendNonCanonical() bool { func (cv *ChainView) extendNonCanonical() bool {
for { for {
hash, number := cv.hashes[len(cv.hashes)-1], cv.head-uint64(len(cv.hashes)-1) hash, number := cv.hashes[len(cv.hashes)-1], cv.headNumber-uint64(len(cv.hashes)-1)
if cv.chain.GetCanonicalHash(number) == hash { if cv.chain.GetCanonicalHash(number) == hash {
return true return true
} }
@ -152,61 +142,15 @@ func (cv *StoredChainView) extendNonCanonical() bool {
} }
// blockHash returns the given block hash without doing the head number check. // blockHash returns the given block hash without doing the head number check.
func (cv *StoredChainView) blockHash(number uint64) common.Hash { func (cv *ChainView) blockHash(number uint64) common.Hash {
if number+uint64(len(cv.hashes)) <= cv.head { if number+uint64(len(cv.hashes)) <= cv.headNumber {
hash := cv.chain.GetCanonicalHash(number) hash := cv.chain.GetCanonicalHash(number)
if !cv.extendNonCanonical() { if !cv.extendNonCanonical() {
return common.Hash{} return common.Hash{}
} }
if number+uint64(len(cv.hashes)) <= cv.head { if number+uint64(len(cv.hashes)) <= cv.headNumber {
return hash return hash
} }
} }
return cv.hashes[cv.head-number] return cv.hashes[cv.headNumber-number]
}
// limitedChainView wraps a chainView and truncates it at a given head number.
type limitedChainView struct {
parent chainView
head uint64
}
// newLimitedChainView returns a truncated view of the given parent.
func newLimitedChainView(parent chainView, headNumber uint64) chainView {
if headNumber >= parent.headNumber() {
return parent
}
return &limitedChainView{
parent: parent,
head: headNumber,
}
}
// headNumber implements chainView.
func (cv *limitedChainView) headNumber() uint64 {
return cv.head
}
// getBlockHash implements chainView.
func (cv *limitedChainView) getBlockHash(number uint64) common.Hash {
if number >= cv.head {
panic("invalid block number")
}
return cv.parent.getBlockHash(number)
}
// getBlockId implements chainView.
func (cv *limitedChainView) getBlockId(number uint64) common.Hash {
if number > cv.head {
panic("invalid block number")
}
return cv.parent.getBlockId(number)
}
// getReceipts implements chainView.
func (cv *limitedChainView) getReceipts(number uint64) types.Receipts {
if number > cv.head {
panic("invalid block number")
}
return cv.parent.getReceipts(number)
} }

View file

@ -62,7 +62,7 @@ type FilterMaps struct {
// Matcher backend can read them under indexLock read lock. // Matcher backend can read them under indexLock read lock.
indexLock sync.RWMutex indexLock sync.RWMutex
filterMapsRange filterMapsRange
indexedView chainView // always consistent with the log index indexedView *ChainView // always consistent with the log index
// also accessed by indexer and matcher backend but no locking needed. // also accessed by indexer and matcher backend but no locking needed.
filterMapCache *lru.Cache[uint32, filterMap] filterMapCache *lru.Cache[uint32, filterMap]
@ -86,12 +86,12 @@ type FilterMaps struct {
ptrHeadIndex, ptrTailIndex, ptrTailUnindexBlock uint64 ptrHeadIndex, ptrTailIndex, ptrTailUnindexBlock uint64
ptrTailUnindexMap uint32 ptrTailUnindexMap uint32
targetView chainView targetView *ChainView
matcherSyncRequest *FilterMapsMatcherBackend matcherSyncRequest *FilterMapsMatcherBackend
finalBlock, lastFinal uint64 finalBlock, lastFinal uint64
lastFinalEpoch uint32 lastFinalEpoch uint32
stop bool stop bool
TargetViewCh chan chainView TargetViewCh chan *ChainView
FinalBlockCh chan uint64 FinalBlockCh chan uint64
BlockProcessingCh chan bool BlockProcessingCh chan bool
blockProcessing bool blockProcessing bool
@ -174,7 +174,7 @@ type lastBlockOfMap struct {
} }
// NewFilterMaps creates a new FilterMaps and starts the indexer. // NewFilterMaps creates a new FilterMaps and starts the indexer.
func NewFilterMaps(db ethdb.KeyValueStore, initView chainView, params Params, history, unindexLimit uint64, noHistory bool, exportFileName string) *FilterMaps { func NewFilterMaps(db ethdb.KeyValueStore, initView *ChainView, params Params, history, unindexLimit uint64, noHistory bool, exportFileName string) *FilterMaps {
rs, initialized, err := rawdb.ReadFilterMapsRange(db) rs, initialized, err := rawdb.ReadFilterMapsRange(db)
if err != nil { if err != nil {
log.Error("Error reading log index range", "error", err) log.Error("Error reading log index range", "error", err)
@ -184,7 +184,7 @@ func NewFilterMaps(db ethdb.KeyValueStore, initView chainView, params Params, hi
db: db, db: db,
closeCh: make(chan struct{}), closeCh: make(chan struct{}),
waitIdleCh: make(chan chan bool), waitIdleCh: make(chan chan bool),
TargetViewCh: make(chan chainView), TargetViewCh: make(chan *ChainView),
FinalBlockCh: make(chan uint64), FinalBlockCh: make(chan uint64),
BlockProcessingCh: make(chan bool), BlockProcessingCh: make(chan bool),
history: history, history: history,
@ -213,7 +213,7 @@ func NewFilterMaps(db ethdb.KeyValueStore, initView chainView, params Params, hi
f.targetView = initView f.targetView = initView
if f.initialized { if f.initialized {
f.indexedView = f.initChainView(f.targetView) f.indexedView = f.initChainView(f.targetView)
f.headBlockIndexed = f.afterLastIndexedBlock == f.indexedView.headNumber()+1 f.headBlockIndexed = f.afterLastIndexedBlock == f.indexedView.headNumber+1
if !f.headBlockIndexed { if !f.headBlockIndexed {
f.headBlockDelimiter = 0 f.headBlockDelimiter = 0
} }
@ -248,7 +248,7 @@ func (f *FilterMaps) Stop() {
// on the last block of stored maps. // on the last block of stored maps.
// Note that the returned view might be shorter than the existing index if // Note that the returned view might be shorter than the existing index if
// the latest maps are not consistent with targetView. // the latest maps are not consistent with targetView.
func (f *FilterMaps) initChainView(chainView chainView) chainView { func (f *FilterMaps) initChainView(chainView *ChainView) *ChainView {
mapIndex := f.afterLastRenderedMap mapIndex := f.afterLastRenderedMap
for { for {
var ok bool var ok bool
@ -261,11 +261,11 @@ func (f *FilterMaps) initChainView(chainView chainView) chainView {
log.Error("Could not initialize indexed chain view", "error", err) log.Error("Could not initialize indexed chain view", "error", err)
break break
} }
if lastBlockNumber <= chainView.headNumber() && chainView.getBlockId(lastBlockNumber) == lastBlockId { if lastBlockNumber <= chainView.headNumber && chainView.getBlockId(lastBlockNumber) == lastBlockId {
return newLimitedChainView(chainView, lastBlockNumber) return chainView.limitedView(lastBlockNumber)
} }
} }
return newLimitedChainView(chainView, 0) return chainView.limitedView(0)
} }
// reset un-initializes the FilterMaps structure and removes all related data from // reset un-initializes the FilterMaps structure and removes all related data from
@ -298,7 +298,7 @@ func (f *FilterMaps) init() error {
for min < max { for min < max {
mid := (min + max + 1) / 2 mid := (min + max + 1) / 2
cp := checkpointList[mid-1] cp := checkpointList[mid-1]
if cp.blockNumber <= f.targetView.headNumber() && f.targetView.getBlockId(cp.blockNumber) == cp.blockId { if cp.blockNumber <= f.targetView.headNumber && f.targetView.getBlockId(cp.blockNumber) == cp.blockId {
min = mid min = mid
} else { } else {
max = mid - 1 max = mid - 1
@ -367,7 +367,7 @@ func (f *FilterMaps) removeDbWithPrefix(prefix []byte, action string) bool {
// setRange updates the indexed chain view and covered range and also adds the // setRange updates the indexed chain view and covered range and also adds the
// changes to the given batch. // changes to the given batch.
// Note that this function assumes that the index write lock is being held. // Note that this function assumes that the index write lock is being held.
func (f *FilterMaps) setRange(batch ethdb.KeyValueWriter, newView chainView, newRange filterMapsRange) { func (f *FilterMaps) setRange(batch ethdb.KeyValueWriter, newView *ChainView, newRange filterMapsRange) {
f.indexedView = newView f.indexedView = newView
f.filterMapsRange = newRange f.filterMapsRange = newRange
f.updateMatchersValidRange() f.updateMatchersValidRange()

View file

@ -132,7 +132,7 @@ func (f *FilterMaps) processSingleEvent(blocking bool) bool {
} }
// setTargetView updates the target chain view of the iterator. // setTargetView updates the target chain view of the iterator.
func (f *FilterMaps) setTargetView(targetView chainView) { func (f *FilterMaps) setTargetView(targetView *ChainView) {
if equalViews(f.targetView, targetView) { if equalViews(f.targetView, targetView) {
return return
} }
@ -170,7 +170,7 @@ func (f *FilterMaps) tryIndexHead() bool {
log.Info("Log index head rendering in progress", log.Info("Log index head rendering in progress",
"first block", f.firstIndexedBlock, "last block", f.afterLastIndexedBlock-1, "first block", f.firstIndexedBlock, "last block", f.afterLastIndexedBlock-1,
"processed", f.afterLastIndexedBlock-f.ptrHeadIndex, "processed", f.afterLastIndexedBlock-f.ptrHeadIndex,
"remaining", f.indexedView.headNumber()+1-f.afterLastIndexedBlock, "remaining", f.indexedView.headNumber+1-f.afterLastIndexedBlock,
"elapsed", common.PrettyDuration(time.Since(f.startedHeadIndexAt))) "elapsed", common.PrettyDuration(time.Since(f.startedHeadIndexAt)))
f.loggedHeadIndex = true f.loggedHeadIndex = true
f.lastLogHeadIndex = time.Now() f.lastLogHeadIndex = time.Now()
@ -323,10 +323,10 @@ func (f *FilterMaps) needTailEpoch(epoch uint32) bool {
// tailTargetBlock returns the target value for the tail block number according // tailTargetBlock returns the target value for the tail block number according
// to the log history parameter and the current index head. // to the log history parameter and the current index head.
func (f *FilterMaps) tailTargetBlock() uint64 { func (f *FilterMaps) tailTargetBlock() uint64 {
if f.history == 0 || f.indexedView.headNumber() < f.history { if f.history == 0 || f.indexedView.headNumber < f.history {
return 0 return 0
} }
return f.indexedView.headNumber() + 1 - f.history return f.indexedView.headNumber + 1 - f.history
} }
// tailPartialBlocks returns the number of rendered blocks in the partially // tailPartialBlocks returns the number of rendered blocks in the partially

View file

@ -230,7 +230,7 @@ func (ts *testSetup) setHistory(history uint64, noHistory bool) {
ts.fm.Stop() ts.fm.Stop()
} }
head := ts.chain.CurrentBlock() head := ts.chain.CurrentBlock()
ts.fm = NewFilterMaps(ts.db, NewStoredChainView(ts.chain, head.Number.Uint64(), head.Hash()), ts.params, history, 1, noHistory, "") ts.fm = NewFilterMaps(ts.db, NewChainView(ts.chain, head.Number.Uint64(), head.Hash()), ts.params, history, 1, noHistory, "")
ts.fm.testDisableSnapshots = ts.testDisableSnapshots ts.fm.testDisableSnapshots = ts.testDisableSnapshots
ts.fm.Start() ts.fm.Start()
} }
@ -414,7 +414,7 @@ func (tc *testChain) setTargetHead() {
head := tc.CurrentBlock() head := tc.CurrentBlock()
if tc.ts.fm != nil { if tc.ts.fm != nil {
if !tc.ts.fm.noHistory { if !tc.ts.fm.noHistory {
tc.ts.fm.TargetViewCh <- NewStoredChainView(tc, head.Number.Uint64(), head.Hash()) tc.ts.fm.TargetViewCh <- NewChainView(tc, head.Number.Uint64(), head.Hash())
} }
} }
} }

View file

@ -140,7 +140,7 @@ func (f *FilterMaps) lastCanonicalSnapshotBefore(afterLastMap uint32) *renderedM
var best *renderedMap var best *renderedMap
for _, blockNumber := range f.renderSnapshots.Keys() { for _, blockNumber := range f.renderSnapshots.Keys() {
if cp, _ := f.renderSnapshots.Get(blockNumber); cp != nil && blockNumber < f.afterLastIndexedBlock && if cp, _ := f.renderSnapshots.Get(blockNumber); cp != nil && blockNumber < f.afterLastIndexedBlock &&
blockNumber <= f.targetView.headNumber() && f.targetView.getBlockId(blockNumber) == cp.lastBlockId && blockNumber <= f.targetView.headNumber && f.targetView.getBlockId(blockNumber) == cp.lastBlockId &&
cp.mapIndex < afterLastMap && (best == nil || blockNumber > best.lastBlock) { cp.mapIndex < afterLastMap && (best == nil || blockNumber > best.lastBlock) {
best = cp best = cp
} }
@ -168,7 +168,7 @@ func (f *FilterMaps) lastCanonicalMapBoundaryBefore(afterLastMap uint32) (nextMa
if err != nil { if err != nil {
return 0, 0, 0, fmt.Errorf("failed to retrieve last block of reverse iterated map %d: %v", mapIndex, err) return 0, 0, 0, fmt.Errorf("failed to retrieve last block of reverse iterated map %d: %v", mapIndex, err)
} }
if lastBlock >= f.indexedView.headNumber() || lastBlock >= f.targetView.headNumber() || if lastBlock >= f.indexedView.headNumber || lastBlock >= f.targetView.headNumber ||
lastBlockId != f.targetView.getBlockId(lastBlock) { lastBlockId != f.targetView.getBlockId(lastBlock) {
// map is not full or inconsistent with targetView; roll back // map is not full or inconsistent with targetView; roll back
continue continue
@ -533,8 +533,8 @@ func (r *mapRenderer) getUpdatedRange() (filterMapsRange, error) {
lm := r.finishedMaps[r.afterLastFinished-1] lm := r.finishedMaps[r.afterLastFinished-1]
newRange.headBlockIndexed = lm.finished newRange.headBlockIndexed = lm.finished
if lm.finished { if lm.finished {
newRange.afterLastIndexedBlock = r.f.targetView.headNumber() + 1 newRange.afterLastIndexedBlock = r.f.targetView.headNumber + 1
if lm.lastBlock != r.f.targetView.headNumber() { if lm.lastBlock != r.f.targetView.headNumber {
panic("map rendering finished but last block != head block") panic("map rendering finished but last block != head block")
} }
newRange.headBlockDelimiter = lm.headDelimiter newRange.headBlockDelimiter = lm.headDelimiter
@ -608,7 +608,7 @@ func (fmr *filterMapsRange) addRenderedRange(firstRendered, afterLastRendered, a
// logIterator iterates on the linear log value index range. // logIterator iterates on the linear log value index range.
type logIterator struct { type logIterator struct {
chainView chainView chainView *ChainView
blockNumber uint64 blockNumber uint64
receipts types.Receipts receipts types.Receipts
blockStart, delimiter, finished bool blockStart, delimiter, finished bool
@ -622,8 +622,8 @@ var errUnindexedRange = errors.New("unindexed range")
// given block's first log value entry (the block delimiter), according to the // given block's first log value entry (the block delimiter), according to the
// current targetView. // current targetView.
func (f *FilterMaps) newLogIteratorFromBlockDelimiter(blockNumber uint64) (*logIterator, error) { func (f *FilterMaps) newLogIteratorFromBlockDelimiter(blockNumber uint64) (*logIterator, error) {
if blockNumber > f.targetView.headNumber() { if blockNumber > f.targetView.headNumber {
return nil, fmt.Errorf("iterator entry point %d after target chain head block %d", blockNumber, f.targetView.headNumber()) return nil, fmt.Errorf("iterator entry point %d after target chain head block %d", blockNumber, f.targetView.headNumber)
} }
if blockNumber < f.firstIndexedBlock || blockNumber >= f.afterLastIndexedBlock { if blockNumber < f.firstIndexedBlock || blockNumber >= f.afterLastIndexedBlock {
return nil, errUnindexedRange return nil, errUnindexedRange
@ -639,7 +639,7 @@ func (f *FilterMaps) newLogIteratorFromBlockDelimiter(blockNumber uint64) (*logI
} }
lvIndex-- lvIndex--
} }
finished := blockNumber == f.targetView.headNumber() finished := blockNumber == f.targetView.headNumber
return &logIterator{ return &logIterator{
chainView: f.targetView, chainView: f.targetView,
blockNumber: blockNumber, blockNumber: blockNumber,
@ -652,8 +652,8 @@ func (f *FilterMaps) newLogIteratorFromBlockDelimiter(blockNumber uint64) (*logI
// newLogIteratorFromMapBoundary creates a logIterator starting at the given // newLogIteratorFromMapBoundary creates a logIterator starting at the given
// map boundary, according to the current targetView. // map boundary, according to the current targetView.
func (f *FilterMaps) newLogIteratorFromMapBoundary(mapIndex uint32, startBlock, startLvPtr uint64) (*logIterator, error) { func (f *FilterMaps) newLogIteratorFromMapBoundary(mapIndex uint32, startBlock, startLvPtr uint64) (*logIterator, error) {
if startBlock > f.targetView.headNumber() { if startBlock > f.targetView.headNumber {
return nil, fmt.Errorf("iterator entry point %d after target chain head block %d", startBlock, f.targetView.headNumber()) return nil, fmt.Errorf("iterator entry point %d after target chain head block %d", startBlock, f.targetView.headNumber)
} }
// get block receipts // get block receipts
receipts := f.targetView.getReceipts(startBlock) receipts := f.targetView.getReceipts(startBlock)
@ -687,7 +687,7 @@ func (f *FilterMaps) newLogIteratorFromMapBoundary(mapIndex uint32, startBlock,
// updateChainView updates the iterator's chain view if it still matches the // updateChainView updates the iterator's chain view if it still matches the
// previous view at the current position. Returns true if successful. // previous view at the current position. Returns true if successful.
func (l *logIterator) updateChainView(cv chainView) bool { func (l *logIterator) updateChainView(cv *ChainView) bool {
if !matchViews(cv, l.chainView, l.blockNumber) { if !matchViews(cv, l.chainView, l.blockNumber) {
return false return false
} }
@ -744,7 +744,7 @@ func (l *logIterator) nextValid() {
} }
l.logIndex = 0 l.logIndex = 0
} }
if l.blockNumber == l.chainView.headNumber() { if l.blockNumber == l.chainView.headNumber {
l.finished = true l.finished = true
} else { } else {
l.delimiter = true l.delimiter = true

View file

@ -133,7 +133,7 @@ func (fm *FilterMapsMatcherBackend) synced() {
indexed, lastIndexed = true, fm.f.afterLastIndexedBlock-subLastIndexed-1 indexed, lastIndexed = true, fm.f.afterLastIndexedBlock-subLastIndexed-1
} }
fm.syncCh <- SyncRange{ fm.syncCh <- SyncRange{
HeadNumber: fm.f.indexedView.headNumber(), HeadNumber: fm.f.indexedView.headNumber,
Valid: fm.valid, Valid: fm.valid,
FirstValid: fm.firstValid, FirstValid: fm.firstValid,
LastValid: fm.lastValid, LastValid: fm.lastValid,
@ -159,7 +159,7 @@ func (fm *FilterMapsMatcherBackend) SyncLogIndex(ctx context.Context) (SyncRange
if fm.f.targetView == nil { if fm.f.targetView == nil {
return SyncRange{}, errors.New("canonical chain head not available") return SyncRange{}, errors.New("canonical chain head not available")
} }
return SyncRange{HeadNumber: fm.f.targetView.headNumber()}, nil return SyncRange{HeadNumber: fm.f.targetView.headNumber}, nil
} }
syncCh := make(chan SyncRange, 1) syncCh := make(chan SyncRange, 1)
fm.f.matchersLock.Lock() fm.f.matchersLock.Lock()