Skip to content

read states from uncommitted state readers #4609

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
175 changes: 175 additions & 0 deletions state/factory/factory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1203,6 +1203,181 @@ func TestDeleteAndPutSameKey(t *testing.T) {
})
}

func TestMintBlocksWithTransfers(t *testing.T) {
require := require.New(t)
testStateDBPath, err := testutil.PathOfTempFile(_stateDBPath)
require.NoError(err)
defer testutil.CleanupPath(testStateDBPath)

cfg := DefaultConfig
cfg.Chain.TrieDBPath = testStateDBPath
cfg.Genesis.InitBalanceMap[identityset.Address(28).String()] = "100"
cfg.Genesis.InitBalanceMap[identityset.Address(29).String()] = "50"
cfg.Genesis.InitBalanceMap[identityset.Address(30).String()] = "0"

registry := protocol.NewRegistry()
acc := account.NewProtocol(rewarding.DepositGas)
require.NoError(acc.Register(registry))

db2, err := db.CreateKVStoreWithCache(db.DefaultConfig, cfg.Chain.TrieDBPath, cfg.Chain.StateDBCacheSize)
require.NoError(err)
sdb, err := NewStateDB(cfg, db2, SkipBlockValidationStateDBOption(), RegistryStateDBOption(registry))
require.NoError(err)

ctx := protocol.WithBlockCtx(
genesis.WithGenesisContext(context.Background(), cfg.Genesis),
protocol.BlockCtx{},
)
require.NoError(sdb.Start(ctx))
defer func() {
require.NoError(sdb.Stop(ctx))
}()

// Mint the first block with a transfer from A to B
a := identityset.Address(28)
b := identityset.Address(29)
priKeyA := identityset.PrivateKey(28)

tsf1 := action.NewTransfer(big.NewInt(20), b.String(), nil)
elp1 := (&action.EnvelopeBuilder{}).SetNonce(1).SetGasLimit(20000).SetAction(tsf1).Build()
selp1, err := action.Sign(elp1, priKeyA)
require.NoError(err)

ctx = protocol.WithBlockCtx(
ctx,
protocol.BlockCtx{
BlockHeight: 1,
Producer: identityset.Address(27),
GasLimit: testutil.TestGasLimit,
},
)
ctx = protocol.WithFeatureCtx(ctx)
mockActPool := mock_actpool.NewMockActPool(gomock.NewController(t))
mockActPool.EXPECT().PendingActionMap().Return(map[string][]*action.SealedEnvelope{
a.String(): {selp1},
}).Times(1)

blk1, err := sdb.Mint(
protocol.WithBlockchainCtx(
ctx,
protocol.BlockchainCtx{
ChainID: 1,
Tip: protocol.TipInfo{
Height: 0,
Hash: hash.ZeroHash256,
},
},
),
mockActPool,
identityset.PrivateKey(27))
require.NoError(err)
require.NotNil(blk1)

ws1, exist, err := sdb.(*stateDB).getFromWorkingSets(ctx, blk1.HashBlock())
require.NoError(err)
require.True(exist)
require.NotNil(ws1)
// Check balances after the first block
accountA, err := accountutil.AccountState(ctx, ws1, a)
require.NoError(err)
accountB, err := accountutil.AccountState(ctx, ws1, b)
require.NoError(err)
require.Equal(big.NewInt(80), accountA.Balance)
require.Equal(big.NewInt(70), accountB.Balance)

// Mint the second block with a transfer from B to C
c := identityset.Address(30)
priKeyB := identityset.PrivateKey(29)

tsf2 := action.NewTransfer(big.NewInt(30), c.String(), nil)
elp2 := (&action.EnvelopeBuilder{}).SetNonce(1).SetGasLimit(20000).SetAction(tsf2).Build()
selp2, err := action.Sign(elp2, priKeyB)
require.NoError(err)

mockActPool.EXPECT().PendingActionMap().Return(map[string][]*action.SealedEnvelope{
b.String(): {selp2},
}).Times(1)

ctx = protocol.WithBlockCtx(
ctx,
protocol.BlockCtx{
BlockHeight: 2,
Producer: identityset.Address(27),
GasLimit: testutil.TestGasLimit,
},
)
ctx = protocol.WithFeatureCtx(ctx)
blk2, err := sdb.Mint(
protocol.WithBlockchainCtx(
ctx,
protocol.BlockchainCtx{
ChainID: 1,
Tip: protocol.TipInfo{
Height: 1,
Hash: blk1.HashBlock(),
},
},
),
mockActPool,
identityset.PrivateKey(27),
)
require.NoError(err)
require.NotNil(blk2)

ws2, exist, err := sdb.(*stateDB).getFromWorkingSets(ctx, blk2.HashBlock())
require.NoError(err)
require.True(exist)
require.NotNil(ws2)

// Check balances after the second block
accountA, err = accountutil.AccountState(ctx, ws2, a)
require.NoError(err)
accountB, err = accountutil.AccountState(ctx, ws2, b)
require.NoError(err)
accountC, err := accountutil.AccountState(ctx, ws2, c)
require.NoError(err)
require.Equal(big.NewInt(80), accountA.Balance)
require.Equal(big.NewInt(40), accountB.Balance)
require.Equal(big.NewInt(30), accountC.Balance)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

put these into a common func checkBalanaceABC(ws, expectBalance [3]big.Int)? then call it after diff actions

checkBalanaceABC(ws2, [3]big.Int{80, 40, 30})
checkBalanaceABC(ws1, [3]big.Int{80, 70, 0})
sdb.PutBlock(ctx, blk1)
checkBalanaceABC(sdb, [3]big.Int{80, 70, 0})
... and more

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for what?

// Check balances in ws1
accountA, err = accountutil.AccountState(ctx, ws1, a)
require.NoError(err)
accountB, err = accountutil.AccountState(ctx, ws1, b)
require.NoError(err)
require.Equal(big.NewInt(80), accountA.Balance)
require.Equal(big.NewInt(70), accountB.Balance)
// Check balances in sdb
accountA, err = accountutil.AccountState(ctx, sdb, a)
require.NoError(err)
accountB, err = accountutil.AccountState(ctx, sdb, b)
require.NoError(err)
accountC, err = accountutil.AccountState(ctx, sdb, c)
require.NoError(err)
require.Equal(big.NewInt(100), accountA.Balance)
require.Equal(big.NewInt(50), accountB.Balance)
require.Equal(big.NewInt(0), accountC.Balance)
// Put blk1 into sdb
require.NoError(sdb.PutBlock(ctx, blk1))

// Check balances after blk1 is committed
accountA, err = accountutil.AccountState(ctx, sdb, a)
require.NoError(err)
accountB, err = accountutil.AccountState(ctx, sdb, b)
require.NoError(err)
require.Equal(big.NewInt(80), accountA.Balance)
require.Equal(big.NewInt(70), accountB.Balance)
// Check balances in ws2
accountA, err = accountutil.AccountState(ctx, ws2, a)
require.NoError(err)
accountB, err = accountutil.AccountState(ctx, ws2, b)
require.NoError(err)
accountC, err = accountutil.AccountState(ctx, ws2, c)
require.NoError(err)
require.Equal(big.NewInt(80), accountA.Balance)
require.Equal(big.NewInt(40), accountB.Balance)
require.Equal(big.NewInt(30), accountC.Balance)
}

func BenchmarkSDBInMemRunAction(b *testing.B) {
cfg := DefaultConfig
sdb, err := NewStateDB(cfg, db.NewMemKVStore(), SkipBlockValidationStateDBOption())
Expand Down