Skip to content

Commit 85965bd

Browse files
authored
Merge pull request #2337 from CortexFoundation/dev
safe chain view update
2 parents ba1de0c + 24042a7 commit 85965bd

81 files changed

Lines changed: 8891 additions & 8544 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

core/filtermaps/chain_view.go

Lines changed: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -58,55 +58,83 @@ func NewChainView(chain blockchain, number uint64, hash common.Hash) *ChainView
5858
return cv
5959
}
6060

61-
// getBlockHash returns the block hash belonging to the given block number.
61+
// HeadNumber returns the head block number of the chain view.
62+
func (cv *ChainView) HeadNumber() uint64 {
63+
return cv.headNumber
64+
}
65+
66+
// BlockHash returns the block hash belonging to the given block number.
6267
// Note that the hash of the head block is not returned because ChainView might
6368
// represent a view where the head block is currently being created.
64-
func (cv *ChainView) getBlockHash(number uint64) common.Hash {
65-
if number >= cv.headNumber {
69+
func (cv *ChainView) BlockHash(number uint64) common.Hash {
70+
cv.lock.Lock()
71+
defer cv.lock.Unlock()
72+
73+
if number > cv.headNumber {
6674
panic("invalid block number")
6775
}
6876
return cv.blockHash(number)
6977
}
7078

71-
// getBlockId returns the unique block id belonging to the given block number.
79+
// BlockId returns the unique block id belonging to the given block number.
7280
// Note that it is currently equal to the block hash. In the future it might
7381
// be a different id for future blocks if the log index root becomes part of
7482
// consensus and therefore rendering the index with the new head will happen
7583
// before the hash of that new head is available.
76-
func (cv *ChainView) getBlockId(number uint64) common.Hash {
84+
func (cv *ChainView) BlockId(number uint64) common.Hash {
85+
cv.lock.Lock()
86+
defer cv.lock.Unlock()
87+
7788
if number > cv.headNumber {
7889
panic("invalid block number")
7990
}
8091
return cv.blockHash(number)
8192
}
8293

83-
// getReceipts returns the set of receipts belonging to the block at the given
94+
// Header returns the block header at the given block number.
95+
func (cv *ChainView) Header(number uint64) *types.Header {
96+
return cv.chain.GetHeader(cv.BlockHash(number), number)
97+
}
98+
99+
// Receipts returns the set of receipts belonging to the block at the given
84100
// block number.
85-
func (cv *ChainView) getReceipts(number uint64) types.Receipts {
86-
if number > cv.headNumber {
87-
panic("invalid block number")
88-
}
89-
blockHash := cv.blockHash(number)
101+
func (cv *ChainView) Receipts(number uint64) types.Receipts {
102+
blockHash := cv.BlockHash(number)
90103
if blockHash == (common.Hash{}) {
91104
log.Error("Chain view: block hash unavailable", "number", number, "head", cv.headNumber)
92105
}
93106
return cv.chain.GetReceiptsByHash(blockHash)
94107
}
95108

109+
// SharedRange returns the block range shared by two chain views.
110+
func (cv *ChainView) SharedRange(cv2 *ChainView) common.Range[uint64] {
111+
cv.lock.Lock()
112+
defer cv.lock.Unlock()
113+
114+
if cv == nil || cv2 == nil || !cv.extendNonCanonical() || !cv2.extendNonCanonical() {
115+
return common.Range[uint64]{}
116+
}
117+
var sharedLen uint64
118+
for n := min(cv.headNumber+1-uint64(len(cv.hashes)), cv2.headNumber+1-uint64(len(cv2.hashes))); n <= cv.headNumber && n <= cv2.headNumber && cv.blockHash(n) == cv2.blockHash(n); n++ {
119+
sharedLen = n + 1
120+
}
121+
return common.NewRange(0, sharedLen)
122+
}
123+
96124
// limitedView returns a new chain view that is a truncated version of the parent view.
97125
func (cv *ChainView) limitedView(newHead uint64) *ChainView {
98126
if newHead >= cv.headNumber {
99127
return cv
100128
}
101-
return NewChainView(cv.chain, newHead, cv.blockHash(newHead))
129+
return NewChainView(cv.chain, newHead, cv.BlockHash(newHead))
102130
}
103131

104132
// equalViews returns true if the two chain views are equivalent.
105133
func equalViews(cv1, cv2 *ChainView) bool {
106134
if cv1 == nil || cv2 == nil {
107135
return false
108136
}
109-
return cv1.headNumber == cv2.headNumber && cv1.getBlockId(cv1.headNumber) == cv2.getBlockId(cv2.headNumber)
137+
return cv1.headNumber == cv2.headNumber && cv1.BlockId(cv1.headNumber) == cv2.BlockId(cv2.headNumber)
110138
}
111139

112140
// matchViews returns true if the two chain views are equivalent up until the
@@ -120,9 +148,9 @@ func matchViews(cv1, cv2 *ChainView, number uint64) bool {
120148
return false
121149
}
122150
if number == cv1.headNumber || number == cv2.headNumber {
123-
return cv1.getBlockId(number) == cv2.getBlockId(number)
151+
return cv1.BlockId(number) == cv2.BlockId(number)
124152
}
125-
return cv1.getBlockHash(number) == cv2.getBlockHash(number)
153+
return cv1.BlockHash(number) == cv2.BlockHash(number)
126154
}
127155

128156
// extendNonCanonical checks whether the previously known reverse list of head
@@ -150,9 +178,6 @@ func (cv *ChainView) extendNonCanonical() bool {
150178

151179
// blockHash returns the given block hash without doing the head number check.
152180
func (cv *ChainView) blockHash(number uint64) common.Hash {
153-
cv.lock.Lock()
154-
defer cv.lock.Unlock()
155-
156181
if number+uint64(len(cv.hashes)) <= cv.headNumber {
157182
hash := cv.chain.GetCanonicalHash(number)
158183
if !cv.extendNonCanonical() {

core/filtermaps/filtermaps.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ func NewFilterMaps(db ctxcdb.KeyValueStore, initView *ChainView, historyCutoff,
262262
f.targetView = initView
263263
if f.indexedRange.initialized {
264264
f.indexedView = f.initChainView(f.targetView)
265-
f.indexedRange.headIndexed = f.indexedRange.blocks.AfterLast() == f.indexedView.headNumber+1
265+
f.indexedRange.headIndexed = f.indexedRange.blocks.AfterLast() == f.indexedView.HeadNumber()+1
266266
if !f.indexedRange.headIndexed {
267267
f.indexedRange.headDelimiter = 0
268268
}
@@ -313,7 +313,7 @@ func (f *FilterMaps) initChainView(chainView *ChainView) *ChainView {
313313
log.Error("Could not initialize indexed chain view", "error", err)
314314
break
315315
}
316-
if lastBlockNumber <= chainView.headNumber && chainView.getBlockId(lastBlockNumber) == lastBlockId {
316+
if lastBlockNumber <= chainView.HeadNumber() && chainView.BlockId(lastBlockNumber) == lastBlockId {
317317
return chainView.limitedView(lastBlockNumber)
318318
}
319319
}
@@ -370,7 +370,7 @@ func (f *FilterMaps) init() error {
370370
for min < max {
371371
mid := (min + max + 1) / 2
372372
cp := checkpointList[mid-1]
373-
if cp.BlockNumber <= f.targetView.headNumber && f.targetView.getBlockId(cp.BlockNumber) == cp.BlockId {
373+
if cp.BlockNumber <= f.targetView.HeadNumber() && f.targetView.BlockId(cp.BlockNumber) == cp.BlockId {
374374
min = mid
375375
} else {
376376
max = mid - 1
@@ -512,7 +512,7 @@ func (f *FilterMaps) getLogByLvIndex(lvIndex uint64) (*types.Log, error) {
512512
}
513513
}
514514
// get block receipts
515-
receipts := f.indexedView.getReceipts(firstBlockNumber)
515+
receipts := f.indexedView.Receipts(firstBlockNumber)
516516
if receipts == nil {
517517
return nil, fmt.Errorf("failed to retrieve receipts for block %d containing searched log value index %d: %v", firstBlockNumber, lvIndex, err)
518518
}

core/filtermaps/indexer.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ func (f *FilterMaps) indexerLoop() {
4444

4545
for !f.stop {
4646
if !f.indexedRange.initialized {
47-
if f.targetView.headNumber == 0 {
47+
if f.targetView.HeadNumber() == 0 {
4848
// initialize when chain head is available
4949
f.processSingleEvent(true)
5050
continue
@@ -249,7 +249,7 @@ func (f *FilterMaps) tryIndexHead() error {
249249
log.Info("Log index head rendering in progress",
250250
"first block", f.indexedRange.blocks.First(), "last block", f.indexedRange.blocks.Last(),
251251
"processed", f.indexedRange.blocks.AfterLast()-f.ptrHeadIndex,
252-
"remaining", f.indexedView.headNumber-f.indexedRange.blocks.Last(),
252+
"remaining", f.indexedView.HeadNumber()-f.indexedRange.blocks.Last(),
253253
"elapsed", common.PrettyDuration(time.Since(f.startedHeadIndexAt)))
254254
f.loggedHeadIndex = true
255255
f.lastLogHeadIndex = time.Now()
@@ -418,10 +418,10 @@ func (f *FilterMaps) needTailEpoch(epoch uint32) bool {
418418
// tailTargetBlock returns the target value for the tail block number according
419419
// to the log history parameter and the current index head.
420420
func (f *FilterMaps) tailTargetBlock() uint64 {
421-
if f.history == 0 || f.indexedView.headNumber < f.history {
421+
if f.history == 0 || f.indexedView.HeadNumber() < f.history {
422422
return 0
423423
}
424-
return f.indexedView.headNumber + 1 - f.history
424+
return f.indexedView.HeadNumber() + 1 - f.history
425425
}
426426

427427
// tailPartialBlocks returns the number of rendered blocks in the partially

core/filtermaps/map_renderer.go

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,8 @@ func (f *FilterMaps) lastCanonicalSnapshotOfMap(mapIndex uint32) *renderedMap {
143143
var best *renderedMap
144144
for _, blockNumber := range f.renderSnapshots.Keys() {
145145
if cp, _ := f.renderSnapshots.Get(blockNumber); cp != nil && blockNumber < f.indexedRange.blocks.AfterLast() &&
146-
blockNumber <= f.indexedView.headNumber && f.indexedView.getBlockId(blockNumber) == cp.lastBlockId &&
147-
blockNumber <= f.targetView.headNumber && f.targetView.getBlockId(blockNumber) == cp.lastBlockId &&
146+
blockNumber <= f.indexedView.HeadNumber() && f.indexedView.BlockId(blockNumber) == cp.lastBlockId &&
147+
blockNumber <= f.targetView.HeadNumber() && f.targetView.BlockId(blockNumber) == cp.lastBlockId &&
148148
cp.mapIndex == mapIndex && (best == nil || blockNumber > best.lastBlock) {
149149
best = cp
150150
}
@@ -173,7 +173,7 @@ func (f *FilterMaps) lastCanonicalMapBoundaryBefore(renderBefore uint32) (nextMa
173173
return 0, 0, 0, fmt.Errorf("failed to retrieve last block of reverse iterated map %d: %v", mapIndex, err)
174174
}
175175
if (f.indexedRange.headIndexed && mapIndex >= f.indexedRange.maps.Last()) ||
176-
lastBlock >= f.targetView.headNumber || lastBlockId != f.targetView.getBlockId(lastBlock) {
176+
lastBlock >= f.targetView.HeadNumber() || lastBlockId != f.targetView.BlockId(lastBlock) {
177177
continue // map is not full or inconsistent with targetView; roll back
178178
}
179179
lvPtr, err := f.getBlockLvPointer(lastBlock)
@@ -247,7 +247,7 @@ func (f *FilterMaps) loadHeadSnapshot() error {
247247
filterMap: fm,
248248
mapIndex: f.indexedRange.maps.Last(),
249249
lastBlock: f.indexedRange.blocks.Last(),
250-
lastBlockId: f.indexedView.getBlockId(f.indexedRange.blocks.Last()),
250+
lastBlockId: f.indexedView.BlockId(f.indexedRange.blocks.Last()),
251251
blockLvPtrs: lvPtrs,
252252
finished: true,
253253
headDelimiter: f.indexedRange.headDelimiter,
@@ -264,7 +264,7 @@ func (r *mapRenderer) makeSnapshot() {
264264
filterMap: r.currentMap.filterMap.fastCopy(),
265265
mapIndex: r.currentMap.mapIndex,
266266
lastBlock: r.currentMap.lastBlock,
267-
lastBlockId: r.iterator.chainView.getBlockId(r.currentMap.lastBlock),
267+
lastBlockId: r.iterator.chainView.BlockId(r.currentMap.lastBlock),
268268
blockLvPtrs: r.currentMap.blockLvPtrs,
269269
finished: true,
270270
headDelimiter: r.iterator.lvIndex,
@@ -370,7 +370,7 @@ func (r *mapRenderer) renderCurrentMap(stopCb func() bool) (bool, error) {
370370
r.currentMap.finished = true
371371
r.currentMap.headDelimiter = r.iterator.lvIndex
372372
}
373-
r.currentMap.lastBlockId = r.f.targetView.getBlockId(r.currentMap.lastBlock)
373+
r.currentMap.lastBlockId = r.f.targetView.BlockId(r.currentMap.lastBlock)
374374
totalTime += time.Since(start)
375375
mapRenderTimer.Update(totalTime)
376376
mapLogValueMeter.Mark(logValuesProcessed)
@@ -566,8 +566,8 @@ func (r *mapRenderer) getUpdatedRange() (filterMapsRange, error) {
566566
lm := r.finishedMaps[r.finished.Last()]
567567
newRange.headIndexed = lm.finished
568568
if lm.finished {
569-
newRange.blocks.SetLast(r.f.targetView.headNumber)
570-
if lm.lastBlock != r.f.targetView.headNumber {
569+
newRange.blocks.SetLast(r.f.targetView.HeadNumber())
570+
if lm.lastBlock != r.f.targetView.HeadNumber() {
571571
panic("map rendering finished but last block != head block")
572572
}
573573
newRange.headDelimiter = lm.headDelimiter
@@ -665,13 +665,13 @@ var errUnindexedRange = errors.New("unindexed range")
665665
// given block's first log value entry (the block delimiter), according to the
666666
// current targetView.
667667
func (f *FilterMaps) newLogIteratorFromBlockDelimiter(blockNumber, lvIndex uint64) (*logIterator, error) {
668-
if blockNumber > f.targetView.headNumber {
669-
return nil, fmt.Errorf("iterator entry point %d after target chain head block %d", blockNumber, f.targetView.headNumber)
668+
if blockNumber > f.targetView.HeadNumber() {
669+
return nil, fmt.Errorf("iterator entry point %d after target chain head block %d", blockNumber, f.targetView.HeadNumber())
670670
}
671671
if !f.indexedRange.blocks.Includes(blockNumber) {
672672
return nil, errUnindexedRange
673673
}
674-
finished := blockNumber == f.targetView.headNumber
674+
finished := blockNumber == f.targetView.HeadNumber()
675675
l := &logIterator{
676676
chainView: f.targetView,
677677
params: &f.Params,
@@ -687,11 +687,11 @@ func (f *FilterMaps) newLogIteratorFromBlockDelimiter(blockNumber, lvIndex uint6
687687
// newLogIteratorFromMapBoundary creates a logIterator starting at the given
688688
// map boundary, according to the current targetView.
689689
func (f *FilterMaps) newLogIteratorFromMapBoundary(mapIndex uint32, startBlock, startLvPtr uint64) (*logIterator, error) {
690-
if startBlock > f.targetView.headNumber {
691-
return nil, fmt.Errorf("iterator entry point %d after target chain head block %d", startBlock, f.targetView.headNumber)
690+
if startBlock > f.targetView.HeadNumber() {
691+
return nil, fmt.Errorf("iterator entry point %d after target chain head block %d", startBlock, f.targetView.HeadNumber())
692692
}
693693
// get block receipts
694-
receipts := f.targetView.getReceipts(startBlock)
694+
receipts := f.targetView.Receipts(startBlock)
695695
if receipts == nil {
696696
return nil, fmt.Errorf("receipts not found for start block %d", startBlock)
697697
}
@@ -758,7 +758,7 @@ func (l *logIterator) next() error {
758758
if l.delimiter {
759759
l.delimiter = false
760760
l.blockNumber++
761-
l.receipts = l.chainView.getReceipts(l.blockNumber)
761+
l.receipts = l.chainView.Receipts(l.blockNumber)
762762
if l.receipts == nil {
763763
return fmt.Errorf("receipts not found for block %d", l.blockNumber)
764764
}
@@ -795,7 +795,7 @@ func (l *logIterator) enforceValidState() {
795795
}
796796
l.logIndex = 0
797797
}
798-
if l.blockNumber == l.chainView.headNumber {
798+
if l.blockNumber == l.chainView.HeadNumber() {
799799
l.finished = true
800800
} else {
801801
l.delimiter = true

core/filtermaps/matcher.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ type MatcherBackend interface {
5757
// all states of the chain since the previous SyncLogIndex or the creation of
5858
// the matcher backend.
5959
type SyncRange struct {
60-
HeadNumber uint64
60+
IndexedView *ChainView
6161
// block range where the index has not changed since the last matcher sync
6262
// and therefore the set of matches found in this region is guaranteed to
6363
// be valid and complete.

core/filtermaps/matcher_backend.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ func (fm *FilterMapsMatcherBackend) synced() {
128128
indexedBlocks.SetAfterLast(indexedBlocks.Last()) // remove partially indexed last block
129129
}
130130
fm.syncCh <- SyncRange{
131-
HeadNumber: fm.f.targetView.headNumber,
131+
IndexedView: fm.f.indexedView,
132132
ValidBlocks: fm.validBlocks,
133133
IndexedBlocks: indexedBlocks,
134134
}
@@ -154,15 +154,15 @@ func (fm *FilterMapsMatcherBackend) SyncLogIndex(ctx context.Context) (SyncRange
154154
case <-ctx.Done():
155155
return SyncRange{}, ctx.Err()
156156
case <-fm.f.disabledCh:
157-
return SyncRange{HeadNumber: fm.f.targetView.headNumber}, nil
157+
return SyncRange{IndexedView: fm.f.indexedView}, nil
158158
}
159159
select {
160160
case vr := <-syncCh:
161161
return vr, nil
162162
case <-ctx.Done():
163163
return SyncRange{}, ctx.Err()
164164
case <-fm.f.disabledCh:
165-
return SyncRange{HeadNumber: fm.f.targetView.headNumber}, nil
165+
return SyncRange{IndexedView: fm.f.indexedView}, nil
166166
}
167167
}
168168

ctxc/api_backend.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
"github.com/CortexFoundation/CortexTheseus/consensus"
2929
"github.com/CortexFoundation/CortexTheseus/core"
3030
"github.com/CortexFoundation/CortexTheseus/core/bloombits"
31+
"github.com/CortexFoundation/CortexTheseus/core/filtermaps"
3132
"github.com/CortexFoundation/CortexTheseus/core/rawdb"
3233
"github.com/CortexFoundation/CortexTheseus/core/state"
3334
"github.com/CortexFoundation/CortexTheseus/core/txpool"
@@ -353,6 +354,17 @@ func (b *CortexAPIBackend) ServiceFilter(ctx context.Context, session *bloombits
353354
go session.Multiplex(bloomRetrievalBatch, bloomRetrievalWait, b.ctxc.bloomRequests)
354355
}
355356
}
357+
func (b *CortexAPIBackend) CurrentView() *filtermaps.ChainView {
358+
head := b.ctxc.blockchain.CurrentBlock()
359+
if head == nil {
360+
return nil
361+
}
362+
return filtermaps.NewChainView(b.ctxc.blockchain, head.Number().Uint64(), head.Hash())
363+
}
364+
365+
func (b *CortexAPIBackend) NewMatcherBackend() filtermaps.MatcherBackend {
366+
return b.ctxc.filterMaps.NewMatcherBackend()
367+
}
356368

357369
func (b *CortexAPIBackend) Engine() consensus.Engine {
358370
return b.ctxc.engine

ctxc/filters/filter_system.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
"github.com/CortexFoundation/CortexTheseus/common/lru"
3030
"github.com/CortexFoundation/CortexTheseus/core"
3131
"github.com/CortexFoundation/CortexTheseus/core/bloombits"
32+
"github.com/CortexFoundation/CortexTheseus/core/filtermaps"
3233
"github.com/CortexFoundation/CortexTheseus/core/rawdb"
3334
"github.com/CortexFoundation/CortexTheseus/core/types"
3435
"github.com/CortexFoundation/CortexTheseus/ctxcdb"
@@ -69,6 +70,8 @@ type Backend interface {
6970

7071
BloomStatus() (uint64, uint64)
7172
ServiceFilter(ctx context.Context, session *bloombits.MatcherSession)
73+
74+
CurrentView() *filtermaps.ChainView
7275
}
7376

7477
// FilterSystem holds resources shared by all filters.

0 commit comments

Comments
 (0)