Skip to content

Commit 9cfb25b

Browse files
committed
[blockchain] add ValidateBlock() to fullsync check
1 parent 7c868d1 commit 9cfb25b

File tree

7 files changed

+72
-18
lines changed

7 files changed

+72
-18
lines changed

blockchain/block/block.go

+3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
package block
77

88
import (
9+
"context"
910
"time"
1011

1112
"github.com/ethereum/go-ethereum/core/types"
@@ -20,6 +21,8 @@ import (
2021
"github.com/iotexproject/iotex-core/v2/pkg/log"
2122
)
2223

24+
type BlockValidator func(context.Context, *Block) error
25+
2326
// Block defines the struct of block
2427
type Block struct {
2528
Header

blockchain/blockchain.go

+6
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,12 @@ func NewBlockchain(cfg Config, g genesis.Genesis, dao blockdao.BlockDAO, bbf Blo
206206
if chain.dao == nil {
207207
log.L().Panic("blockdao is nil")
208208
}
209+
chain.dao.SetBlockValidator(func(ctx context.Context, blk *block.Block) error {
210+
if chain.blockValidator == nil {
211+
return nil
212+
}
213+
return chain.blockValidator.Validate(ctx, blk)
214+
})
209215
chain.lifecycle.Add(chain.dao)
210216
chain.lifecycle.Add(chain.pubSubManager)
211217

blockchain/blockdao/blockdao.go

+12-1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ type (
4242
BlockStore
4343
GetBlob(hash.Hash256) (*types.BlobTxSidecar, string, error)
4444
GetBlobsByHeight(uint64) ([]*types.BlobTxSidecar, []string, error)
45+
SetBlockValidator(block.BlockValidator)
4546
}
4647

4748
BlockStore interface {
@@ -65,6 +66,7 @@ type (
6566
blockStore BlockStore
6667
blobStore BlobStore
6768
indexers []BlockIndexer
69+
validator block.BlockValidator
6870
timerFactory *prometheustimer.TimerFactory
6971
lifecycle lifecycle.Lifecycle
7072
headerCache cache.LRUCache
@@ -126,6 +128,10 @@ func NewBlockDAOWithIndexersAndCache(blkStore BlockStore, indexers []BlockIndexe
126128
return blockDAO
127129
}
128130

131+
func (dao *blockDAO) SetBlockValidator(v block.BlockValidator) {
132+
dao.validator = v
133+
}
134+
129135
// Start starts block DAO and initiates the top height if it doesn't exist
130136
func (dao *blockDAO) Start(ctx context.Context) error {
131137
err := dao.lifecycle.OnStart(ctx)
@@ -142,8 +148,13 @@ func (dao *blockDAO) Start(ctx context.Context) error {
142148
}
143149

144150
func (dao *blockDAO) checkIndexers(ctx context.Context) error {
145-
checker := NewBlockIndexerChecker(dao)
151+
var checker *BlockIndexerChecker
146152
for i, indexer := range dao.indexers {
153+
if _, ok := indexer.(BlockIndexerStateDBWriter); ok {
154+
checker = NewBlockIndexerChecker(dao, dao.validator)
155+
} else {
156+
checker = NewBlockIndexerChecker(dao, nil)
157+
}
147158
if err := checker.CheckIndexer(ctx, indexer, 0, func(height uint64) {
148159
if height%5000 == 0 {
149160
log.L().Info(

blockchain/blockdao/blockindexer.go

+30-14
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,25 @@ type (
3434
StartHeight() uint64
3535
}
3636

37+
BlockIndexerStateDBWriter interface {
38+
BlockIndexer
39+
// StateDBWriter indicates this indexer writes to state DB
40+
StateDBWriter()
41+
}
42+
3743
// BlockIndexerChecker defines a checker of block indexer
3844
BlockIndexerChecker struct {
39-
dao BlockDAO
45+
dao BlockDAO
46+
validator block.BlockValidator
4047
}
4148
)
4249

4350
// NewBlockIndexerChecker creates a new block indexer checker
44-
func NewBlockIndexerChecker(dao BlockDAO) *BlockIndexerChecker {
45-
return &BlockIndexerChecker{dao: dao}
51+
func NewBlockIndexerChecker(dao BlockDAO, v block.BlockValidator) *BlockIndexerChecker {
52+
return &BlockIndexerChecker{
53+
dao: dao,
54+
validator: v,
55+
}
4656
}
4757

4858
// CheckIndexer checks a block indexer against block dao
@@ -115,18 +125,24 @@ func (bic *BlockIndexerChecker) CheckIndexer(ctx context.Context, indexer BlockI
115125
bcCtx.Tip.Hash = g.Hash()
116126
bcCtx.Tip.Timestamp = time.Unix(g.Timestamp, 0)
117127
}
128+
checkCtx := protocol.WithFeatureCtx(protocol.WithBlockCtx(
129+
protocol.WithBlockchainCtx(ctx, bcCtx),
130+
protocol.BlockCtx{
131+
BlockHeight: i,
132+
BlockTimeStamp: blk.Timestamp(),
133+
Producer: producer,
134+
GasLimit: g.BlockGasLimitByHeight(i),
135+
BaseFee: blk.BaseFee(),
136+
ExcessBlobGas: blk.ExcessBlobGas(),
137+
},
138+
))
139+
if bic.validator != nil {
140+
if err := bic.validator(checkCtx, blk); err != nil {
141+
return err
142+
}
143+
}
118144
for {
119-
if err = indexer.PutBlock(protocol.WithFeatureCtx(protocol.WithBlockCtx(
120-
protocol.WithBlockchainCtx(ctx, bcCtx),
121-
protocol.BlockCtx{
122-
BlockHeight: i,
123-
BlockTimeStamp: blk.Timestamp(),
124-
Producer: producer,
125-
GasLimit: g.BlockGasLimitByHeight(i),
126-
BaseFee: blk.BaseFee(),
127-
ExcessBlobGas: blk.ExcessBlobGas(),
128-
},
129-
)), blk); err == nil {
145+
if err = indexer.PutBlock(checkCtx, blk); err == nil {
130146
break
131147
}
132148
if i < g.HawaiiBlockHeight && errors.Cause(err) == block.ErrDeltaStateMismatch {

blockchain/blockdao/blockindexer_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ func TestCheckIndexer(t *testing.T) {
4949
ctrl := gomock.NewController(t)
5050
defer ctrl.Finish()
5151
mockDao := mock_blockdao.NewMockBlockDAO(ctrl)
52-
checker := NewBlockIndexerChecker(mockDao)
52+
checker := NewBlockIndexerChecker(mockDao, nil)
5353
indexer := mock_blockdao.NewMockBlockIndexer(ctrl)
5454

5555
putBlocks := make([]*block.Block, 0)
@@ -121,7 +121,7 @@ func TestCheckIndexerWithStart(t *testing.T) {
121121
ctrl := gomock.NewController(t)
122122
defer ctrl.Finish()
123123
mockDao := mock_blockdao.NewMockBlockDAO(ctrl)
124-
checker := NewBlockIndexerChecker(mockDao)
124+
checker := NewBlockIndexerChecker(mockDao, nil)
125125
indexer := mock_blockdao.NewMockBlockIndexerWithStart(ctrl)
126126

127127
putBlocks := make([]*block.Block, 0)
@@ -179,7 +179,7 @@ func TestBlockIndexerChecker_CheckIndexer(t *testing.T) {
179179
ctx := context.Background()
180180
store := mock_blockdao.NewMockBlockDAO(ctrl)
181181
dao := &blockDAO{blockStore: store}
182-
bic := NewBlockIndexerChecker(dao)
182+
bic := NewBlockIndexerChecker(dao, nil)
183183
indexer := mock_blockdao.NewMockBlockIndexer(ctrl)
184184

185185
t.Run("WithoutBlockchainContext", func(t *testing.T) {

blockindex/sync_indexers.go

+6
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ import (
1212
"github.com/iotexproject/iotex-core/v2/blockchain/blockdao"
1313
)
1414

15+
var (
16+
_ blockdao.BlockIndexerStateDBWriter = (*SyncIndexers)(nil)
17+
)
18+
1519
// SyncIndexers is a special index that includes multiple indexes,
1620
// which stay in sync when blocks are added.
1721
type SyncIndexers struct {
@@ -26,6 +30,8 @@ func NewSyncIndexers(indexers ...blockdao.BlockIndexer) *SyncIndexers {
2630
return &SyncIndexers{indexers: indexers}
2731
}
2832

33+
func (ig *SyncIndexers) StateDBWriter() {}
34+
2935
// Start starts the indexer group
3036
func (ig *SyncIndexers) Start(ctx context.Context) error {
3137
for _, indexer := range ig.indexers {

test/mock/mock_blockdao/mock_blockdao.go

+12
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)