Skip to content

Commit 64dd415

Browse files
dustinxieLiuhaai
andauthored
[state] fix test and speedup validation (#3842)
Co-authored-by: Liuhaai <[email protected]>
1 parent 5bbe4fe commit 64dd415

File tree

5 files changed

+128
-18
lines changed

5 files changed

+128
-18
lines changed

action/protocol/context.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ type (
110110
CorrectGasRefund bool
111111
FixRewardErroCheckPosition bool
112112
EnableWeb3Rewarding bool
113-
EnableNodeInfo bool
113+
SkipSystemActionNonce bool
114114
}
115115

116116
// FeatureWithHeightCtx provides feature check functions.
@@ -247,7 +247,7 @@ func WithFeatureCtx(ctx context.Context) context.Context {
247247
CorrectGasRefund: g.IsOkhotsk(height),
248248
FixRewardErroCheckPosition: g.IsOkhotsk(height),
249249
EnableWeb3Rewarding: g.IsPalau(height),
250-
EnableNodeInfo: g.IsPalau(height),
250+
SkipSystemActionNonce: g.IsPalau(height),
251251
},
252252
)
253253
}

blockchain/integrity/benchmark_test.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,6 @@ func newChainInDB() (blockchain.Blockchain, actpool.ActPool, error) {
289289
var genesisNonce uint64 = 0
290290

291291
// make a transfer from genesisAccount to a and b,because stateTX cannot store data in height 0
292-
genesisNonce++
293292
tsf, err := action.SignedTransfer(userA.String(), genesisPriKey, genesisNonce, big.NewInt(1e17), []byte{}, testutil.TestGasLimit, big.NewInt(testutil.TestGasPriceInt64))
294293
if err != nil {
295294
return nil, nil, err

blockchain/integrity/integrity_test.go

Lines changed: 94 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1466,9 +1466,6 @@ func TestBlockchain_AccountState(t *testing.T) {
14661466
require := require.New(t)
14671467

14681468
cfg := config.Default
1469-
// disable account-based testing
1470-
// create chain
1471-
cfg.Genesis.InitBalanceMap[identityset.Address(0).String()] = "100"
14721469
ctx := genesis.WithGenesisContext(context.Background(), cfg.Genesis)
14731470
registry := protocol.NewRegistry()
14741471
acc := account.NewProtocol(rewarding.DepositGas)
@@ -1480,14 +1477,104 @@ func TestBlockchain_AccountState(t *testing.T) {
14801477
require.NoError(err)
14811478
dao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf})
14821479
bc := blockchain.NewBlockchain(cfg.Chain, cfg.Genesis, dao, factory.NewMinter(sf, ap))
1483-
require.NoError(bc.Start(context.Background()))
1480+
require.NoError(bc.Start(ctx))
14841481
require.NotNil(bc)
1482+
defer func() {
1483+
require.NoError(bc.Stop(ctx))
1484+
}()
14851485
s, err := accountutil.AccountState(ctx, sf, identityset.Address(0))
14861486
require.NoError(err)
14871487
require.Equal(uint64(1), s.PendingNonce())
1488-
require.Equal(big.NewInt(100), s.Balance)
1489-
require.Equal(hash.ZeroHash256, s.Root)
1490-
require.Equal([]byte(nil), s.CodeHash)
1488+
require.Equal(unit.ConvertIotxToRau(100000000), s.Balance)
1489+
require.Zero(s.Root)
1490+
require.Nil(s.CodeHash)
1491+
}
1492+
1493+
func TestNewAccountAction(t *testing.T) {
1494+
require := require.New(t)
1495+
1496+
cfg := config.Default
1497+
cfg.Genesis.OkhotskBlockHeight = 1
1498+
ctx := genesis.WithGenesisContext(context.Background(), cfg.Genesis)
1499+
registry := protocol.NewRegistry()
1500+
acc := account.NewProtocol(rewarding.DepositGas)
1501+
require.NoError(acc.Register(registry))
1502+
factoryCfg := factory.GenerateConfig(cfg.Chain, cfg.Genesis)
1503+
sf, err := factory.NewFactory(factoryCfg, db.NewMemKVStore(), factory.RegistryOption(registry))
1504+
require.NoError(err)
1505+
ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool)
1506+
require.NoError(err)
1507+
dao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf})
1508+
bc := blockchain.NewBlockchain(cfg.Chain, cfg.Genesis, dao, factory.NewMinter(sf, ap))
1509+
require.NoError(bc.Start(ctx))
1510+
require.NotNil(bc)
1511+
defer func() {
1512+
require.NoError(bc.Stop(ctx))
1513+
}()
1514+
1515+
// create a new address, transfer 4 IOTX
1516+
newSk, err := iotexcrypto.HexStringToPrivateKey("55499c1b09f687488af9e4ee9e2bd53c7c8c3ddc69d4d9345a04b13030cffabe")
1517+
require.NoError(err)
1518+
newAddr := newSk.PublicKey().Address()
1519+
tx, err := action.SignedTransfer(newAddr.String(), identityset.PrivateKey(0), 1, big.NewInt(4*unit.Iotx), nil, testutil.TestGasLimit, testutil.TestGasPrice)
1520+
require.NoError(err)
1521+
require.NoError(ap.Add(ctx, tx))
1522+
blk, err := bc.MintNewBlock(testutil.TimestampNow())
1523+
require.NoError(err)
1524+
require.NoError(bc.CommitBlock(blk))
1525+
ap.Reset()
1526+
1527+
// initiate transfer from new address
1528+
tx, err = action.SignedTransfer(identityset.Address(0).String(), newSk, 0, big.NewInt(unit.Iotx), nil, testutil.TestGasLimit, testutil.TestGasPrice)
1529+
require.NoError(err)
1530+
require.NoError(ap.Add(ctx, tx))
1531+
tx1, err := action.SignedTransfer(identityset.Address(1).String(), newSk, 1, big.NewInt(unit.Iotx), nil, testutil.TestGasLimit, testutil.TestGasPrice)
1532+
require.NoError(err)
1533+
require.NoError(ap.Add(ctx, tx1))
1534+
blk1, err := bc.MintNewBlock(testutil.TimestampNow())
1535+
require.NoError(err)
1536+
require.NoError(bc.CommitBlock(blk1))
1537+
ap.Reset()
1538+
1539+
// commit 2 blocks into a new chain
1540+
for _, validateNonce := range []bool{false, true} {
1541+
if validateNonce {
1542+
cfg.Genesis.PalauBlockHeight = 2
1543+
} else {
1544+
cfg.Genesis.PalauBlockHeight = 20
1545+
}
1546+
ctx = genesis.WithGenesisContext(context.Background(), cfg.Genesis)
1547+
factoryCfg = factory.GenerateConfig(cfg.Chain, cfg.Genesis)
1548+
sf1, err := factory.NewFactory(factoryCfg, db.NewMemKVStore(), factory.RegistryOption(registry))
1549+
require.NoError(err)
1550+
dao1 := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf1})
1551+
bc1 := blockchain.NewBlockchain(cfg.Chain, cfg.Genesis, dao1, factory.NewMinter(sf1, ap))
1552+
require.NoError(bc1.Start(ctx))
1553+
require.NotNil(bc1)
1554+
defer func() {
1555+
require.NoError(bc1.Stop(ctx))
1556+
}()
1557+
require.NoError(bc1.CommitBlock(blk))
1558+
err = bc1.CommitBlock(blk1)
1559+
if validateNonce {
1560+
require.NoError(err)
1561+
} else {
1562+
require.Equal(action.ErrNonceTooHigh, errors.Cause(err))
1563+
}
1564+
1565+
// verify new addr
1566+
s, err := accountutil.AccountState(ctx, sf1, newAddr)
1567+
require.NoError(err)
1568+
if validateNonce {
1569+
require.EqualValues(2, s.PendingNonce())
1570+
require.Equal(big.NewInt(2*unit.Iotx), s.Balance)
1571+
} else {
1572+
require.Zero(s.PendingNonce())
1573+
require.Equal(big.NewInt(4*unit.Iotx), s.Balance)
1574+
}
1575+
require.Zero(s.Root)
1576+
require.Nil(s.CodeHash)
1577+
}
14911578
}
14921579

14931580
func TestBlocks(t *testing.T) {

state/factory/workingset.go

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -333,26 +333,44 @@ func (ws *workingSet) validateNonce(ctx context.Context, blk *block.Block) error
333333
}
334334
appendActionIndex(accountNonceMap, caller.String(), selp.Nonce())
335335
}
336+
return ws.checkNonceContinuity(ctx, accountNonceMap)
337+
}
336338

337-
// Special handling for genesis block
338-
if blk.Height() == 0 {
339-
return nil
339+
func (ws *workingSet) validateNonceSkipSystemAction(ctx context.Context, blk *block.Block) error {
340+
accountNonceMap := make(map[string][]uint64)
341+
for _, selp := range blk.Actions {
342+
if action.IsSystemAction(selp) {
343+
continue
344+
}
345+
346+
caller := selp.SenderAddress()
347+
if caller == nil {
348+
return errors.New("failed to get address")
349+
}
350+
srcAddr := caller.String()
351+
if _, ok := accountNonceMap[srcAddr]; !ok {
352+
accountNonceMap[srcAddr] = make([]uint64, 0)
353+
}
354+
accountNonceMap[srcAddr] = append(accountNonceMap[srcAddr], selp.Nonce())
340355
}
356+
return ws.checkNonceContinuity(ctx, accountNonceMap)
357+
}
358+
359+
func (ws *workingSet) checkNonceContinuity(ctx context.Context, accountNonceMap map[string][]uint64) error {
341360
// Verify each account's Nonce
342361
for srcAddr, receivedNonces := range accountNonceMap {
343362
addr, _ := address.FromString(srcAddr)
344363
confirmedState, err := accountutil.AccountState(ctx, ws, addr)
345364
if err != nil {
346365
return errors.Wrapf(err, "failed to get the confirmed nonce of address %s", srcAddr)
347366
}
348-
receivedNonces := receivedNonces
349367
sort.Slice(receivedNonces, func(i, j int) bool { return receivedNonces[i] < receivedNonces[j] })
350368
pendingNonce := confirmedState.PendingNonce()
351369
for i, nonce := range receivedNonces {
352370
if nonce != pendingNonce+uint64(i) {
353371
return errors.Wrapf(
354372
action.ErrNonceTooHigh,
355-
"the %d nonce %d of address %s (init pending nonce %d) is not continuously increasing",
373+
"the %d-th nonce %d of address %s (init pending nonce %d) is not continuously increasing",
356374
i,
357375
nonce,
358376
srcAddr,
@@ -517,8 +535,14 @@ func updateReceiptIndex(receipts []*action.Receipt) {
517535
}
518536

519537
func (ws *workingSet) ValidateBlock(ctx context.Context, blk *block.Block) error {
520-
if err := ws.validateNonce(ctx, blk); err != nil {
521-
return errors.Wrap(err, "failed to validate nonce")
538+
if protocol.MustGetFeatureCtx(ctx).SkipSystemActionNonce {
539+
if err := ws.validateNonceSkipSystemAction(ctx, blk); err != nil {
540+
return errors.Wrap(err, "failed to validate nonce")
541+
}
542+
} else {
543+
if err := ws.validateNonce(ctx, blk); err != nil {
544+
return errors.Wrap(err, "failed to validate nonce")
545+
}
522546
}
523547
if err := ws.process(ctx, blk.RunnableActions().Actions()); err != nil {
524548
log.L().Error("Failed to update state.", zap.Uint64("height", ws.height), zap.Error(err))

testutil/timestamp_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,5 @@ import (
1515
func TestTimestamp(t *testing.T) {
1616
assert := assert.New(t)
1717
time1 := TimestampNow()
18-
assert.True(time.Now().After(time1))
18+
assert.False(time.Now().Before(time1))
1919
}

0 commit comments

Comments
 (0)