Skip to content

Commit 8371e36

Browse files
committed
impl factory StateReaderAt
1 parent 315b4f6 commit 8371e36

File tree

7 files changed

+57
-33
lines changed

7 files changed

+57
-33
lines changed

consensus/scheme/rolldpos/chainmanager.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ type (
6262
}
6363
// StateReaderFactory is the factory interface of state reader
6464
StateReaderFactory interface {
65-
StateReaderAt(hash.Hash256) (protocol.StateReader, error)
65+
StateReaderAt(uint64, hash.Hash256) (protocol.StateReader, error)
6666
}
6767

6868
// BlockBuilderFactory is the factory interface of block builder
@@ -220,7 +220,7 @@ func (fc *forkChain) TipHash() hash.Hash256 {
220220
}
221221

222222
func (cm *chainManager) StateReader() (protocol.StateReader, error) {
223-
return cm.srf.StateReaderAt(cm.bc.TipHash())
223+
return cm.srf.StateReaderAt(cm.bc.TipHeight(), cm.bc.TipHash())
224224
}
225225

226226
// StateReader returns the state reader
@@ -285,7 +285,7 @@ func (cm *chainManager) Fork(hash hash.Hash256) (ForkChain, error) {
285285
return nil, errors.Errorf("block %x not found when fork", hash)
286286
}
287287
}
288-
sr, err := cm.srf.StateReaderAt(hash)
288+
sr, err := cm.srf.StateReaderAt(head.Height(), hash)
289289
if err != nil {
290290
return nil, errors.Wrapf(err, "failed to create state reader at %d, hash %x", head.Height(), head.HashBlock())
291291
}

consensus/scheme/rolldpos/rolldpos_test.go

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,12 @@ func TestNewRollDPoS(t *testing.T) {
7575
delegatesByEpoch := func(uint64, []byte) ([]string, error) { return nil, nil }
7676
t.Run("normal", func(t *testing.T) {
7777
sk := identityset.PrivateKey(0)
78+
chain := mock_blockchain.NewMockBlockchain(ctrl)
79+
chain.EXPECT().ChainID().Return(uint32(1)).AnyTimes()
7880
r, err := NewRollDPoSBuilder().
7981
SetConfig(builderCfg).
8082
SetPriKey(sk).
81-
SetChainManager(NewChainManager(mock_blockchain.NewMockBlockchain(ctrl), mock_factory.NewMockFactory(ctrl), &dummyBlockBuildFactory{})).
83+
SetChainManager(NewChainManager(chain, mock_factory.NewMockFactory(ctrl), &dummyBlockBuildFactory{})).
8284
SetBroadcast(func(_ proto.Message) error {
8385
return nil
8486
}).
@@ -91,10 +93,12 @@ func TestNewRollDPoS(t *testing.T) {
9193
})
9294
t.Run("mock-clock", func(t *testing.T) {
9395
sk := identityset.PrivateKey(0)
96+
chain := mock_blockchain.NewMockBlockchain(ctrl)
97+
chain.EXPECT().ChainID().Return(uint32(1)).AnyTimes()
9498
r, err := NewRollDPoSBuilder().
9599
SetConfig(builderCfg).
96100
SetPriKey(sk).
97-
SetChainManager(NewChainManager(mock_blockchain.NewMockBlockchain(ctrl), mock_factory.NewMockFactory(ctrl), &dummyBlockBuildFactory{})).
101+
SetChainManager(NewChainManager(chain, mock_factory.NewMockFactory(ctrl), &dummyBlockBuildFactory{})).
98102
SetBroadcast(func(_ proto.Message) error {
99103
return nil
100104
}).
@@ -111,10 +115,12 @@ func TestNewRollDPoS(t *testing.T) {
111115

112116
t.Run("root chain API", func(t *testing.T) {
113117
sk := identityset.PrivateKey(0)
118+
chain := mock_blockchain.NewMockBlockchain(ctrl)
119+
chain.EXPECT().ChainID().Return(uint32(1)).AnyTimes()
114120
r, err := NewRollDPoSBuilder().
115121
SetConfig(builderCfg).
116122
SetPriKey(sk).
117-
SetChainManager(NewChainManager(mock_blockchain.NewMockBlockchain(ctrl), mock_factory.NewMockFactory(ctrl), &dummyBlockBuildFactory{})).
123+
SetChainManager(NewChainManager(chain, mock_factory.NewMockFactory(ctrl), &dummyBlockBuildFactory{})).
118124
SetBroadcast(func(_ proto.Message) error {
119125
return nil
120126
}).
@@ -220,7 +226,7 @@ func TestValidateBlockFooter(t *testing.T) {
220226
builderCfg.Consensus.ConsensusDBPath = ""
221227
bc.EXPECT().Genesis().Return(g).AnyTimes()
222228
sf := mock_factory.NewMockFactory(ctrl)
223-
sf.EXPECT().StateReaderAt(gomock.Any()).Return(nil, nil).AnyTimes()
229+
sf.EXPECT().StateReaderAt(gomock.Any(), gomock.Any()).Return(nil, nil).AnyTimes()
224230
rp := rolldpos.NewProtocol(
225231
g.NumCandidateDelegates,
226232
g.NumDelegates,
@@ -291,9 +297,11 @@ func TestRollDPoS_Metrics(t *testing.T) {
291297
blockHeight := uint64(8)
292298
footer := &block.Footer{}
293299
bc := mock_blockchain.NewMockBlockchain(ctrl)
294-
bc.EXPECT().TipHeight().Return(blockHeight).Times(1)
295-
bc.EXPECT().TipHash().Return(hash.ZeroHash256).Times(1)
296-
bc.EXPECT().BlockFooterByHeight(blockHeight).Return(footer, nil).Times(2)
300+
bc.EXPECT().TipHeight().Return(blockHeight).AnyTimes()
301+
bc.EXPECT().TipHash().Return(hash.ZeroHash256).AnyTimes()
302+
bc.EXPECT().BlockFooterByHeight(blockHeight).Return(footer, nil).AnyTimes()
303+
bc.EXPECT().ChainID().Return(uint32(1)).AnyTimes()
304+
bc.EXPECT().BlockHeaderByHeight(blockHeight).Return(&block.Header{}, nil).AnyTimes()
297305

298306
sk1 := identityset.PrivateKey(1)
299307
cfg := DefaultConfig
@@ -453,7 +461,7 @@ func TestRollDPoSConsensus(t *testing.T) {
453461
ctx := context.Background()
454462
bc.ProducerPrivKey = hex.EncodeToString(chainAddrs[i].priKey.Bytes())
455463
registry := protocol.NewRegistry()
456-
sf, err := factory.NewFactory(factoryCfg, db.NewMemKVStore(), factory.RegistryOption(registry))
464+
sf, err := factory.NewStateDB(factoryCfg, db.NewMemKVStore(), factory.RegistryStateDBOption(registry))
457465
require.NoError(t, err)
458466
require.NoError(t, sf.Start(genesis.WithGenesisContext(
459467
protocol.WithRegistry(ctx, registry),
@@ -486,11 +494,11 @@ func TestRollDPoSConsensus(t *testing.T) {
486494
peers: make(map[net.Addr]*RollDPoS),
487495
}
488496
p2ps = append(p2ps, p2p)
489-
497+
minter := factory.NewMinter(sf, actPool)
490498
consensus, err := NewRollDPoSBuilder().
491499
SetPriKey(chainAddrs[i].priKey).
492500
SetConfig(builderCfg).
493-
SetChainManager(NewChainManager(chain, sf, &dummyBlockBuildFactory{})).
501+
SetChainManager(NewChainManager(chain, sf, minter)).
494502
SetBroadcast(p2p.Broadcast).
495503
SetDelegatesByEpochFunc(delegatesByEpochFunc).
496504
SetProposersByEpochFunc(delegatesByEpochFunc).

consensus/scheme/rolldpos/rolldposctx_test.go

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212

1313
"github.com/facebookgo/clock"
1414
"github.com/iotexproject/go-pkgs/crypto"
15+
"github.com/iotexproject/go-pkgs/hash"
1516
"github.com/iotexproject/iotex-proto/golang/iotextypes"
1617
"github.com/pkg/errors"
1718
"github.com/stretchr/testify/require"
@@ -25,6 +26,7 @@ import (
2526
"github.com/iotexproject/iotex-core/v2/db"
2627
"github.com/iotexproject/iotex-core/v2/endorsement"
2728
"github.com/iotexproject/iotex-core/v2/state"
29+
"github.com/iotexproject/iotex-core/v2/state/factory"
2830
"github.com/iotexproject/iotex-core/v2/test/identityset"
2931
)
3032

@@ -159,7 +161,7 @@ func TestCheckVoteEndorser(t *testing.T) {
159161
func TestCheckBlockProposer(t *testing.T) {
160162
require := require.New(t)
161163
g := genesis.TestDefault()
162-
b, sf, _, rp, pp := makeChain(t)
164+
b, sf, ap, rp, pp := makeChain(t)
163165
c := clock.New()
164166
g.Blockchain.BlockInterval = time.Second * 20
165167
delegatesByEpochFunc := func(epochnum uint64, _ []byte) ([]string, error) {
@@ -203,7 +205,7 @@ func TestCheckBlockProposer(t *testing.T) {
203205
true,
204206
time.Second,
205207
true,
206-
NewChainManager(b, sf, &dummyBlockBuildFactory{}),
208+
NewChainManager(b, sf, factory.NewMinter(sf, ap)),
207209
block.NewDeserializer(0),
208210
rp,
209211
nil,
@@ -215,7 +217,8 @@ func TestCheckBlockProposer(t *testing.T) {
215217
)
216218
require.NoError(err)
217219
require.NotNil(rctx)
218-
block := getBlockforctx(t, 0, false)
220+
prevHash := b.TipHash()
221+
block := getBlockforctx(t, 0, false, prevHash)
219222
en := endorsement.NewEndorsement(time.Unix(1596329600, 0), identityset.PrivateKey(10).PublicKey(), nil)
220223
bp := newBlockProposal(&block, []*endorsement.Endorsement{en})
221224

@@ -240,20 +243,20 @@ func TestCheckBlockProposer(t *testing.T) {
240243
require.Error(rctx.CheckBlockProposer(51, bp, en))
241244

242245
// case 6:invalid block signature
243-
block = getBlockforctx(t, 1, false)
246+
block = getBlockforctx(t, 1, false, prevHash)
244247
en = endorsement.NewEndorsement(time.Unix(1596329600, 0), identityset.PrivateKey(1).PublicKey(), nil)
245248
bp = newBlockProposal(&block, []*endorsement.Endorsement{en})
246249
require.Error(rctx.CheckBlockProposer(51, bp, en))
247250

248251
// case 7:invalid endorsement for the vote when call AddVoteEndorsement
249-
block = getBlockforctx(t, 1, true)
252+
block = getBlockforctx(t, 1, true, prevHash)
250253
en = endorsement.NewEndorsement(time.Unix(1596329600, 0), identityset.PrivateKey(1).PublicKey(), nil)
251254
en2 := endorsement.NewEndorsement(time.Unix(1596329600, 0), identityset.PrivateKey(7).PublicKey(), nil)
252255
bp = newBlockProposal(&block, []*endorsement.Endorsement{en2, en})
253256
require.Error(rctx.CheckBlockProposer(51, bp, en2))
254257

255258
// case 8:Insufficient endorsements
256-
block = getBlockforctx(t, 1, true)
259+
block = getBlockforctx(t, 1, true, prevHash)
257260
hash := block.HashBlock()
258261
vote := NewConsensusVote(hash[:], COMMIT)
259262
ens, err := endorsement.Endorse(vote, time.Unix(1562382592, 0), identityset.PrivateKey(7))
@@ -263,7 +266,7 @@ func TestCheckBlockProposer(t *testing.T) {
263266
require.Error(rctx.CheckBlockProposer(51, bp, ens[0]))
264267

265268
// case 9:normal
266-
block = getBlockforctx(t, 1, true)
269+
block = getBlockforctx(t, 1, true, prevHash)
267270
bp = newBlockProposal(&block, []*endorsement.Endorsement{en})
268271
require.NoError(rctx.CheckBlockProposer(51, bp, en))
269272
}
@@ -349,14 +352,14 @@ func TestNotProducingMultipleBlocks(t *testing.T) {
349352
require.Equal(height1, height2)
350353
}
351354

352-
func getBlockforctx(t *testing.T, i int, sign bool) block.Block {
355+
func getBlockforctx(t *testing.T, i int, sign bool, prevHash hash.Hash256) block.Block {
353356
require := require.New(t)
354357
ts := &timestamppb.Timestamp{Seconds: 1596329600, Nanos: 10}
355358
hcore := &iotextypes.BlockHeaderCore{
356359
Version: 1,
357360
Height: 51,
358361
Timestamp: ts,
359-
PrevBlockHash: []byte(""),
362+
PrevBlockHash: prevHash[:],
360363
TxRoot: []byte(""),
361364
DeltaStateDigest: []byte(""),
362365
ReceiptRoot: []byte(""),

consensus/scheme/rolldpos/roundcalculator_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ func makeChain(t *testing.T) (blockchain.Blockchain, factory.Factory, actpool.Ac
180180
factoryCfg := factory.GenerateConfig(cfg, g)
181181
db1, err := db.CreateKVStore(db.DefaultConfig, cfg.TrieDBPath)
182182
require.NoError(err)
183-
sf, err := factory.NewFactory(factoryCfg, db1, factory.RegistryOption(registry))
183+
sf, err := factory.NewStateDB(factoryCfg, db1, factory.RegistryStateDBOption(registry))
184184
require.NoError(err)
185185
ap, err := actpool.NewActPool(g, sf, actpool.DefaultConfig)
186186
require.NoError(err)

state/factory/factory.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ type (
8888
PutBlock(context.Context, *block.Block) error
8989
WorkingSet(context.Context) (protocol.StateManager, error)
9090
WorkingSetAtHeight(context.Context, uint64, ...*action.SealedEnvelope) (protocol.StateManager, error)
91-
StateReaderAt(hash.Hash256) (protocol.StateReader, error)
91+
StateReaderAt(blkHeight uint64, blkHash hash.Hash256) (protocol.StateReader, error)
9292
}
9393

9494
// factory implements StateFactory interface, tracks changes to account/contract and batch-commits to DB
@@ -580,8 +580,8 @@ func (sf *factory) ReadView(name string) (protocol.View, error) {
580580
}
581581

582582
// StateReaderAt returns a state reader at a specific height
583-
func (sf *factory) StateReaderAt(hash.Hash256) (protocol.StateReader, error) {
584-
panic("implement me")
583+
func (sf *factory) StateReaderAt(blkHeight uint64, blkHash hash.Hash256) (protocol.StateReader, error) {
584+
return nil, errors.New("StateReaderAt is not supported in archive mode")
585585
}
586586

587587
//======================================

state/factory/statedb.go

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -423,9 +423,22 @@ func (sdb *stateDB) ReadView(name string) (protocol.View, error) {
423423
}
424424

425425
// StateReaderAt returns a state reader at a specific height
426-
func (sdb *stateDB) StateReaderAt(hash.Hash256) (protocol.StateReader, error) {
427-
// TODO: implement this
428-
panic("implement me")
426+
func (sdb *stateDB) StateReaderAt(blkHeight uint64, blkHash hash.Hash256) (protocol.StateReader, error) {
427+
sdb.mutex.RLock()
428+
curHeight := sdb.currentChainHeight
429+
sdb.mutex.RUnlock()
430+
if blkHeight == curHeight {
431+
return sdb, nil
432+
} else if blkHeight < curHeight {
433+
return nil, errors.Errorf("cannot read state at height %d, current height is %d", blkHeight, curHeight)
434+
}
435+
if data, ok := sdb.workingsets.Get(blkHash); ok {
436+
if ws, ok := data.(*workingSet); ok {
437+
return ws, nil
438+
}
439+
return nil, errors.New("type assertion failed to be WorkingSet")
440+
}
441+
return nil, errors.Errorf("failed to get workingset at %x", blkHash)
429442
}
430443

431444
//======================================

test/mock/mock_factory/mock_factory.go

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)