Skip to content

Commit

Permalink
address comment
Browse files Browse the repository at this point in the history
  • Loading branch information
dustinxie committed Dec 4, 2023
1 parent 57e4552 commit 4d9fb01
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 27 deletions.
4 changes: 3 additions & 1 deletion action/protocol/account/transfer.go
Expand Up @@ -66,7 +66,9 @@ func (p *Protocol) handleTransfer(ctx context.Context, tsf *action.Transfer, sm

if fCtx.FixGasAndNonceUpdate || tsf.Nonce() != 0 {
// update sender Nonce
sender.ConvertFreshAccountToZeroNonceType(tsf.Nonce())
if fCtx.UseZeroNonceForFreshAccount {
sender.ConvertFreshAccountToZeroNonceType(tsf.Nonce())
}
if err := sender.SetPendingNonce(tsf.Nonce() + 1); err != nil {
return nil, errors.Wrapf(err, "failed to update pending nonce of sender %s", actionCtx.Caller.String())
}
Expand Down
8 changes: 5 additions & 3 deletions action/protocol/execution/evm/evmstatedbadapter.go
Expand Up @@ -341,8 +341,8 @@ func (stateDB *StateDBAdapter) GetNonce(evmAddr common.Address) uint64 {
}
pendingNonce--
}
if pendingNonce == 1 && stateDB.convertFreshAddress {
pendingNonce = state.AdjustNonceForFreshAccount(pendingNonce)
if stateDB.convertFreshAddress {
pendingNonce = state.PendingNonceConsideringFreshAccount()
}
log.L().Debug("Called GetNonce.",
zap.String("address", evmAddr.Hex()),
Expand Down Expand Up @@ -374,7 +374,9 @@ func (stateDB *StateDBAdapter) SetNonce(evmAddr common.Address, nonce uint64) {
zap.String("address", addr.String()),
zap.Uint64("nonce", nonce))
if !s.IsNewbieAccount() || s.AccountType() != 0 || nonce != 0 {
s.ConvertFreshAccountToZeroNonceType(nonce)
if stateDB.convertFreshAddress {
s.ConvertFreshAccountToZeroNonceType(nonce)
}
if err := s.SetPendingNonce(nonce + 1); err != nil {
log.L().Panic("Failed to set nonce.", zap.Error(err), zap.String("addr", addr.Hex()), zap.Uint64("pendingNonce", s.PendingNonce()), zap.Uint64("nonce", nonce), zap.String("execution", hex.EncodeToString(stateDB.executionHash[:])))
stateDB.logError(err)
Expand Down
12 changes: 8 additions & 4 deletions action/protocol/generic_validator.go
Expand Up @@ -58,15 +58,19 @@ func (v *GenericValidator) Validate(ctx context.Context, selp action.SealedEnvel
return action.ErrSystemActionNonce
}
} else {
featureCtx, ok := GetFeatureCtx(ctx)
var (
nonce uint64
featureCtx, ok = GetFeatureCtx(ctx)
)
if ok && featureCtx.FixGasAndNonceUpdate || selp.Nonce() != 0 {
confirmedState, err := v.accountState(ctx, v.sr, caller)
if err != nil {
return errors.Wrapf(err, "invalid state of account %s", caller.String())
}
nonce := confirmedState.PendingNonce()
if nonce == 1 && featureCtx.UseZeroNonceForFreshAccount {
nonce = confirmedState.AdjustNonceForFreshAccount(nonce)
if featureCtx.UseZeroNonceForFreshAccount {
nonce = confirmedState.PendingNonceConsideringFreshAccount()
} else {
nonce = confirmedState.PendingNonce()
}
if nonce > selp.Nonce() {
return action.ErrNonceTooLow
Expand Down
11 changes: 8 additions & 3 deletions action/protocol/rewarding/protocol.go
Expand Up @@ -440,16 +440,21 @@ func (p *Protocol) settleAction(
}

func (p *Protocol) increaseNonce(ctx context.Context, sm protocol.StateManager, addr address.Address, nonce uint64, skipSetNonce bool) error {
accountCreationOpts := []state.AccountCreationOption{}
if protocol.MustGetFeatureCtx(ctx).CreateLegacyNonceAccount {
var (
fCtx = protocol.MustGetFeatureCtx(ctx)
accountCreationOpts = []state.AccountCreationOption{}
)
if fCtx.CreateLegacyNonceAccount {
accountCreationOpts = append(accountCreationOpts, state.LegacyNonceAccountTypeOption())
}
acc, err := accountutil.LoadOrCreateAccount(sm, addr, accountCreationOpts...)
if err != nil {
return err
}
if !skipSetNonce {
acc.ConvertFreshAccountToZeroNonceType(nonce)
if fCtx.UseZeroNonceForFreshAccount {
acc.ConvertFreshAccountToZeroNonceType(nonce)
}
if err := acc.SetPendingNonce(nonce + 1); err != nil {
return errors.Wrapf(err, "invalid nonce %d", nonce)
}
Expand Down
17 changes: 11 additions & 6 deletions action/protocol/staking/protocol.go
Expand Up @@ -609,22 +609,27 @@ func (p *Protocol) settleAction(
logs []*action.Log,
tLogs []*action.TransactionLog,
) (*action.Receipt, error) {
actionCtx := protocol.MustGetActionCtx(ctx)
blkCtx := protocol.MustGetBlockCtx(ctx)
gasFee := big.NewInt(0).Mul(actionCtx.GasPrice, big.NewInt(0).SetUint64(actionCtx.IntrinsicGas))
var (
actionCtx = protocol.MustGetActionCtx(ctx)
blkCtx = protocol.MustGetBlockCtx(ctx)
fCtx = protocol.MustGetFeatureCtx(ctx)
gasFee = big.NewInt(0).Mul(actionCtx.GasPrice, big.NewInt(0).SetUint64(actionCtx.IntrinsicGas))
accountCreationOpts = []state.AccountCreationOption{}
)
depositLog, err := p.depositGas(ctx, sm, gasFee)
if err != nil {
return nil, errors.Wrap(err, "failed to deposit gas")
}
accountCreationOpts := []state.AccountCreationOption{}
if protocol.MustGetFeatureCtx(ctx).CreateLegacyNonceAccount {
if fCtx.CreateLegacyNonceAccount {
accountCreationOpts = append(accountCreationOpts, state.LegacyNonceAccountTypeOption())
}
acc, err := accountutil.LoadAccount(sm, actionCtx.Caller, accountCreationOpts...)
if err != nil {
return nil, err
}
acc.ConvertFreshAccountToZeroNonceType(actionCtx.Nonce)
if fCtx.UseZeroNonceForFreshAccount {
acc.ConvertFreshAccountToZeroNonceType(actionCtx.Nonce)
}
if err := acc.SetPendingNonce(actionCtx.Nonce + 1); err != nil {
return nil, errors.Wrap(err, "failed to set nonce")
}
Expand Down
4 changes: 2 additions & 2 deletions api/coreservice.go
Expand Up @@ -499,13 +499,13 @@ func (core *coreService) PendingNonce(addr address.Address) (uint64, error) {
if nonce > 1 || !g.IsSumatra(core.TipHeight()) {
return nonce, nil
}
// check possible convert clean address to zero-type
// check possible convert fresh address to zero-type
ctx := genesis.WithGenesisContext(context.Background(), g)
state, err := accountutil.AccountState(ctx, core.sf, addr)
if err != nil {
return 0, err
}
return state.AdjustNonceForFreshAccount(state.PendingNonce()), nil
return state.PendingNonceConsideringFreshAccount(), nil
}

func (core *coreService) validateChainID(chainID uint32) error {
Expand Down
8 changes: 4 additions & 4 deletions state/account.go
Expand Up @@ -187,14 +187,14 @@ func (st *Account) PendingNonce() uint64 {
}
}

// AdjustNonceForFreshAccount adjust the nonce for a fresh legacy account
func (st *Account) AdjustNonceForFreshAccount(nonce uint64) uint64 {
if st.accountType == 0 && st.nonce == 0 && nonce == 1 {
// PendingNonceConsideringFreshAccount return the pending nonce considering fresh legacy account
func (st *Account) PendingNonceConsideringFreshAccount() uint64 {
if st.accountType == 0 && st.nonce == 0 {
// this is a legacy account that had never initiated an outgoing transaction
// so we can use 0 as the nonce for its very first transaction
return 0
}
return nonce
return st.PendingNonce()
}

// MarkAsCandidate marks the account as a candidate
Expand Down
42 changes: 42 additions & 0 deletions state/account_test.go
Expand Up @@ -175,3 +175,45 @@ func TestClone(t *testing.T) {
require.Equal(big.NewInt(200), ss.Balance)
require.Equal(big.NewInt(200+100), account.Balance)
}

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

var (
s1, _ = NewAccount(LegacyNonceAccountTypeOption())
s2, _ = NewAccount(LegacyNonceAccountTypeOption())
s3, _ = NewAccount()
s4, _ = NewAccount()
)
s2.nonce, s4.nonce = 1, 1

for i, v := range []struct {
s *Account
accType, cvtType int32
first, second, third uint64
}{
{s1, 0, 1, 1, 0, 1},
{s2, 0, 0, 2, 2, 3},
{s3, 1, 1, 0, 0, 1},
{s4, 1, 1, 1, 1, 2},
} {
require.Equal(v.accType, v.s.accountType)
require.Equal(v.first, v.s.PendingNonce())
require.Equal(v.second, v.s.PendingNonceConsideringFreshAccount())
// trying convert using pending noce does not take effect
v.s.ConvertFreshAccountToZeroNonceType(v.first)
require.Equal(v.accType, v.s.accountType)
// only adjusted nonce can convert legacy fresh address to zero-nonce type
v.s.ConvertFreshAccountToZeroNonceType(v.second)
require.Equal(v.cvtType, v.s.accountType)
// after conversion, fresh address is still fresh
require.Equal(i == 0 || i == 2, v.s.IsNewbieAccount())
// after conversion, 2 pending nonces become the same
require.Equal(v.second, v.s.PendingNonce())
require.Equal(v.second, v.s.PendingNonceConsideringFreshAccount())
require.NoError(v.s.SetPendingNonce(v.second + 1))
// for dirty address, 2 pending nonces are the same
require.Equal(v.third, v.s.PendingNonce())
require.Equal(v.third, v.s.PendingNonceConsideringFreshAccount())
}
}
12 changes: 8 additions & 4 deletions state/factory/workingset.go
Expand Up @@ -358,18 +358,22 @@ func (ws *workingSet) validateNonceSkipSystemAction(ctx context.Context, blk *bl
}

func (ws *workingSet) checkNonceContinuity(ctx context.Context, accountNonceMap map[string][]uint64) error {
var (
pendingNonce uint64
useZeroNonce = protocol.MustGetFeatureCtx(ctx).UseZeroNonceForFreshAccount
)
// Verify each account's Nonce
useZeroNonce := protocol.MustGetFeatureCtx(ctx).UseZeroNonceForFreshAccount
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)
}
sort.Slice(receivedNonces, func(i, j int) bool { return receivedNonces[i] < receivedNonces[j] })
pendingNonce := confirmedState.PendingNonce()
if pendingNonce == 1 && useZeroNonce {
pendingNonce = confirmedState.AdjustNonceForFreshAccount(pendingNonce)
if useZeroNonce {
pendingNonce = confirmedState.PendingNonceConsideringFreshAccount()
} else {
pendingNonce = confirmedState.PendingNonce()
}
for i, nonce := range receivedNonces {
if nonce != pendingNonce+uint64(i) {
Expand Down

0 comments on commit 4d9fb01

Please sign in to comment.