Skip to content

Commit

Permalink
Merge branch 'master' into system_action_check
Browse files Browse the repository at this point in the history
  • Loading branch information
envestcc committed Apr 12, 2023
2 parents fd6e6bf + 3988055 commit 318bab8
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 25 deletions.
4 changes: 2 additions & 2 deletions action/protocol/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ type (
CorrectGasRefund bool
FixRewardErroCheckPosition bool
EnableWeb3Rewarding bool
EnableNodeInfo bool
SkipSystemActionNonce bool
ValidateSystemAction bool
}

Expand Down Expand Up @@ -248,7 +248,7 @@ func WithFeatureCtx(ctx context.Context) context.Context {
CorrectGasRefund: g.IsOkhotsk(height),
FixRewardErroCheckPosition: g.IsOkhotsk(height),
EnableWeb3Rewarding: g.IsPalau(height),
EnableNodeInfo: g.IsPalau(height),
SkipSystemActionNonce: g.IsPalau(height),
ValidateSystemAction: g.IsToBeEnabled(height),
},
)
Expand Down
1 change: 0 additions & 1 deletion blockchain/integrity/benchmark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,6 @@ func newChainInDB() (blockchain.Blockchain, actpool.ActPool, error) {
var genesisNonce uint64 = 0

// make a transfer from genesisAccount to a and b,because stateTX cannot store data in height 0
genesisNonce++
tsf, err := action.SignedTransfer(userA.String(), genesisPriKey, genesisNonce, big.NewInt(1e17), []byte{}, testutil.TestGasLimit, big.NewInt(testutil.TestGasPriceInt64))
if err != nil {
return nil, nil, err
Expand Down
101 changes: 94 additions & 7 deletions blockchain/integrity/integrity_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1466,9 +1466,6 @@ func TestBlockchain_AccountState(t *testing.T) {
require := require.New(t)

cfg := config.Default
// disable account-based testing
// create chain
cfg.Genesis.InitBalanceMap[identityset.Address(0).String()] = "100"
ctx := genesis.WithGenesisContext(context.Background(), cfg.Genesis)
registry := protocol.NewRegistry()
acc := account.NewProtocol(rewarding.DepositGas)
Expand All @@ -1480,14 +1477,104 @@ func TestBlockchain_AccountState(t *testing.T) {
require.NoError(err)
dao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf})
bc := blockchain.NewBlockchain(cfg.Chain, cfg.Genesis, dao, factory.NewMinter(sf, ap))
require.NoError(bc.Start(context.Background()))
require.NoError(bc.Start(ctx))
require.NotNil(bc)
defer func() {
require.NoError(bc.Stop(ctx))
}()
s, err := accountutil.AccountState(ctx, sf, identityset.Address(0))
require.NoError(err)
require.Equal(uint64(1), s.PendingNonce())
require.Equal(big.NewInt(100), s.Balance)
require.Equal(hash.ZeroHash256, s.Root)
require.Equal([]byte(nil), s.CodeHash)
require.Equal(unit.ConvertIotxToRau(100000000), s.Balance)
require.Zero(s.Root)
require.Nil(s.CodeHash)
}

func TestNewAccountAction(t *testing.T) {
require := require.New(t)

cfg := config.Default
cfg.Genesis.OkhotskBlockHeight = 1
ctx := genesis.WithGenesisContext(context.Background(), cfg.Genesis)
registry := protocol.NewRegistry()
acc := account.NewProtocol(rewarding.DepositGas)
require.NoError(acc.Register(registry))
factoryCfg := factory.GenerateConfig(cfg.Chain, cfg.Genesis)
sf, err := factory.NewFactory(factoryCfg, db.NewMemKVStore(), factory.RegistryOption(registry))
require.NoError(err)
ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool)
require.NoError(err)
dao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf})
bc := blockchain.NewBlockchain(cfg.Chain, cfg.Genesis, dao, factory.NewMinter(sf, ap))
require.NoError(bc.Start(ctx))
require.NotNil(bc)
defer func() {
require.NoError(bc.Stop(ctx))
}()

// create a new address, transfer 4 IOTX
newSk, err := iotexcrypto.HexStringToPrivateKey("55499c1b09f687488af9e4ee9e2bd53c7c8c3ddc69d4d9345a04b13030cffabe")
require.NoError(err)
newAddr := newSk.PublicKey().Address()
tx, err := action.SignedTransfer(newAddr.String(), identityset.PrivateKey(0), 1, big.NewInt(4*unit.Iotx), nil, testutil.TestGasLimit, testutil.TestGasPrice)
require.NoError(err)
require.NoError(ap.Add(ctx, tx))
blk, err := bc.MintNewBlock(testutil.TimestampNow())
require.NoError(err)
require.NoError(bc.CommitBlock(blk))
ap.Reset()

// initiate transfer from new address
tx, err = action.SignedTransfer(identityset.Address(0).String(), newSk, 0, big.NewInt(unit.Iotx), nil, testutil.TestGasLimit, testutil.TestGasPrice)
require.NoError(err)
require.NoError(ap.Add(ctx, tx))
tx1, err := action.SignedTransfer(identityset.Address(1).String(), newSk, 1, big.NewInt(unit.Iotx), nil, testutil.TestGasLimit, testutil.TestGasPrice)
require.NoError(err)
require.NoError(ap.Add(ctx, tx1))
blk1, err := bc.MintNewBlock(testutil.TimestampNow())
require.NoError(err)
require.NoError(bc.CommitBlock(blk1))
ap.Reset()

// commit 2 blocks into a new chain
for _, validateNonce := range []bool{false, true} {
if validateNonce {
cfg.Genesis.PalauBlockHeight = 2
} else {
cfg.Genesis.PalauBlockHeight = 20
}
ctx = genesis.WithGenesisContext(context.Background(), cfg.Genesis)
factoryCfg = factory.GenerateConfig(cfg.Chain, cfg.Genesis)
sf1, err := factory.NewFactory(factoryCfg, db.NewMemKVStore(), factory.RegistryOption(registry))
require.NoError(err)
dao1 := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf1})
bc1 := blockchain.NewBlockchain(cfg.Chain, cfg.Genesis, dao1, factory.NewMinter(sf1, ap))
require.NoError(bc1.Start(ctx))
require.NotNil(bc1)
defer func() {
require.NoError(bc1.Stop(ctx))
}()
require.NoError(bc1.CommitBlock(blk))
err = bc1.CommitBlock(blk1)
if validateNonce {
require.NoError(err)
} else {
require.Equal(action.ErrNonceTooHigh, errors.Cause(err))
}

// verify new addr
s, err := accountutil.AccountState(ctx, sf1, newAddr)
require.NoError(err)
if validateNonce {
require.EqualValues(2, s.PendingNonce())
require.Equal(big.NewInt(2*unit.Iotx), s.Balance)
} else {
require.Zero(s.PendingNonce())
require.Equal(big.NewInt(4*unit.Iotx), s.Balance)
}
require.Zero(s.Root)
require.Nil(s.CodeHash)
}
}

func TestBlocks(t *testing.T) {
Expand Down
23 changes: 16 additions & 7 deletions ioctl/newcmd/action/xrc20transferfrom_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,15 @@ func TestNewXrc20TransferFromCmd(t *testing.T) {
Return(&iotexapi.ReadContractResponse{Data: contractData}, nil).AnyTimes()
api.EXPECT().GetAccount(gomock.Any(), gomock.Any(), gomock.Any()).
Return(&iotexapi.GetAccountResponse{
AccountMeta: &iotextypes.AccountMeta{PendingNonce: 100},
AccountMeta: &iotextypes.AccountMeta{
PendingNonce: 100,
Balance: balance,
},
}, nil).AnyTimes()
api.EXPECT().GetChainMeta(gomock.Any(), gomock.Any()).
Return(&iotexapi.GetChainMetaResponse{}, nil).AnyTimes()

api.EXPECT().GetAccount(gomock.Any(), gomock.Any()).
Return(&iotexapi.GetAccountResponse{
AccountMeta: &iotextypes.AccountMeta{Balance: balance},
}, nil).AnyTimes()
api.EXPECT().SendAction(gomock.Any(), gomock.Any()).Return(&iotexapi.SendActionResponse{}, nil).AnyTimes()
api.EXPECT().SendAction(gomock.Any(), gomock.Any()).
Return(&iotexapi.SendActionResponse{}, nil).AnyTimes()

cli.EXPECT().Config().Return(config.Config{
Explorer: "iotexscan",
Expand Down Expand Up @@ -133,6 +132,16 @@ func TestNewXrc20TransferFromCmd(t *testing.T) {
[]string{dftOwner, dftRecipient, dftAmount},
newcmd(dftContract, wrongContractData, dftOwner, dftBalance),
fmt.Sprintf("failed to parse amount: failed to convert string into int64: strconv.ParseInt: parsing \"%s\": invalid syntax", wrongContractData),
}, {
"BalanceNotEnough",
[]string{dftOwner, dftRecipient, dftAmount},
newcmd(dftContract, dftContractData, accountAddr.String(), "0"),
"failed to pass balance check: balance is not enough",
}, {
"ShouldPass",
[]string{dftOwner, dftRecipient, dftAmount},
newcmd(dftContract, dftContractData, accountAddr.String(), dftBalance),
"",
}}

for _, test := range tests {
Expand Down
38 changes: 31 additions & 7 deletions state/factory/workingset.go
Original file line number Diff line number Diff line change
Expand Up @@ -334,26 +334,44 @@ func (ws *workingSet) validateNonce(ctx context.Context, blk *block.Block) error
}
appendActionIndex(accountNonceMap, caller.String(), selp.Nonce())
}
return ws.checkNonceContinuity(ctx, accountNonceMap)
}

// Special handling for genesis block
if blk.Height() == 0 {
return nil
func (ws *workingSet) validateNonceSkipSystemAction(ctx context.Context, blk *block.Block) error {
accountNonceMap := make(map[string][]uint64)
for _, selp := range blk.Actions {
if action.IsSystemAction(selp) {
continue
}

caller := selp.SenderAddress()
if caller == nil {
return errors.New("failed to get address")
}
srcAddr := caller.String()
if _, ok := accountNonceMap[srcAddr]; !ok {
accountNonceMap[srcAddr] = make([]uint64, 0)
}
accountNonceMap[srcAddr] = append(accountNonceMap[srcAddr], selp.Nonce())
}
return ws.checkNonceContinuity(ctx, accountNonceMap)
}

func (ws *workingSet) checkNonceContinuity(ctx context.Context, accountNonceMap map[string][]uint64) error {
// Verify each account's Nonce
for srcAddr, receivedNonces := range accountNonceMap {
addr, _ := address.FromString(srcAddr)
confirmedState, err := accountutil.AccountState(ctx, ws, addr)
if err != nil {
return errors.Wrapf(err, "failed to get the confirmed nonce of address %s", srcAddr)
}
receivedNonces := receivedNonces
sort.Slice(receivedNonces, func(i, j int) bool { return receivedNonces[i] < receivedNonces[j] })
pendingNonce := confirmedState.PendingNonce()
for i, nonce := range receivedNonces {
if nonce != pendingNonce+uint64(i) {
return errors.Wrapf(
action.ErrNonceTooHigh,
"the %d nonce %d of address %s (init pending nonce %d) is not continuously increasing",
"the %d-th nonce %d of address %s (init pending nonce %d) is not continuously increasing",
i,
nonce,
srcAddr,
Expand Down Expand Up @@ -558,8 +576,14 @@ func updateReceiptIndex(receipts []*action.Receipt) {
}

func (ws *workingSet) ValidateBlock(ctx context.Context, blk *block.Block) error {
if err := ws.validateNonce(ctx, blk); err != nil {
return errors.Wrap(err, "failed to validate nonce")
if protocol.MustGetFeatureCtx(ctx).SkipSystemActionNonce {
if err := ws.validateNonceSkipSystemAction(ctx, blk); err != nil {
return errors.Wrap(err, "failed to validate nonce")
}
} else {
if err := ws.validateNonce(ctx, blk); err != nil {
return errors.Wrap(err, "failed to validate nonce")
}
}
if protocol.MustGetFeatureCtx(ctx).ValidateSystemAction {
if err := ws.validateSystemActionLayout(ctx, blk.RunnableActions().Actions()); err != nil {
Expand Down
2 changes: 1 addition & 1 deletion testutil/timestamp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ import (
func TestTimestamp(t *testing.T) {
assert := assert.New(t)
time1 := TimestampNow()
assert.True(time.Now().After(time1))
assert.False(time.Now().Before(time1))
}

0 comments on commit 318bab8

Please sign in to comment.