Skip to content

Commit

Permalink
add hard fork flag
Browse files Browse the repository at this point in the history
  • Loading branch information
Liuhaai committed Mar 5, 2024
1 parent ea65774 commit 9ff16d7
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 39 deletions.
2 changes: 2 additions & 0 deletions action/protocol/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ type (
ExecutionSizeLimit32KB bool
UseZeroNonceForFreshAccount bool
SharedGasWithDapp bool
RefactorFreshAccountConversion bool
}

// FeatureWithHeightCtx provides feature check functions.
Expand Down Expand Up @@ -257,6 +258,7 @@ func WithFeatureCtx(ctx context.Context) context.Context {
ExecutionSizeLimit32KB: !g.IsSumatra(height),
UseZeroNonceForFreshAccount: g.IsSumatra(height),
SharedGasWithDapp: g.IsToBeEnabled(height),
RefactorFreshAccountConversion: g.IsToBeEnabled(height),
},
)
}
Expand Down
6 changes: 4 additions & 2 deletions action/protocol/execution/evm/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -387,8 +387,10 @@ func prepareStateDB(ctx context.Context, sm protocol.StateManager) (*StateDBAdap
if !featureCtx.FixSortCacheContractsAndUsePendingNonce {
opts = append(opts, DisableSortCachedContractsOption(), UseConfirmedNonceOption())
}
if featureCtx.UseZeroNonceForFreshAccount {
opts = append(opts, UseZeroNonceForFreshAccountOption())
// Before featureCtx.RefactorFreshAccountConversion is activated,
// the type of a legacy fresh account is always 1
if featureCtx.RefactorFreshAccountConversion {
opts = append(opts, ZeroNonceForFreshAccountOption())
}
if featureCtx.NotFixTopicCopyBug {
opts = append(opts, NotFixTopicCopyBugOption())
Expand Down
64 changes: 32 additions & 32 deletions action/protocol/execution/evm/evmstatedbadapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,33 +42,33 @@ type (

// StateDBAdapter represents the state db adapter for evm to access iotx blockchain
StateDBAdapter struct {
sm protocol.StateManager
logs []*action.Log
transactionLogs []*action.TransactionLog
err error
blockHeight uint64
executionHash hash.Hash256
refund uint64
refundSnapshot map[int]uint64
cachedContract contractMap
contractSnapshot map[int]contractMap // snapshots of contracts
suicided deleteAccount // account/contract calling Suicide
suicideSnapshot map[int]deleteAccount // snapshots of suicide accounts
preimages preimageMap
preimageSnapshot map[int]preimageMap
accessList *accessList // per-transaction access list
accessListSnapshot map[int]*accessList
logsSnapshot map[int]int // logs is an array, save len(logs) at time of snapshot suffices
txLogsSnapshot map[int]int
notFixTopicCopyBug bool
asyncContractTrie bool
disableSortCachedContracts bool
useConfirmedNonce bool
legacyNonceAccount bool
fixSnapshotOrder bool
revertLog bool
manualCorrectGasRefund bool
useZeroNonceForFreshAccount bool
sm protocol.StateManager
logs []*action.Log
transactionLogs []*action.TransactionLog
err error
blockHeight uint64
executionHash hash.Hash256
refund uint64
refundSnapshot map[int]uint64
cachedContract contractMap
contractSnapshot map[int]contractMap // snapshots of contracts
suicided deleteAccount // account/contract calling Suicide
suicideSnapshot map[int]deleteAccount // snapshots of suicide accounts
preimages preimageMap
preimageSnapshot map[int]preimageMap
accessList *accessList // per-transaction access list
accessListSnapshot map[int]*accessList
logsSnapshot map[int]int // logs is an array, save len(logs) at time of snapshot suffices
txLogsSnapshot map[int]int
notFixTopicCopyBug bool
asyncContractTrie bool
disableSortCachedContracts bool
useConfirmedNonce bool
legacyNonceAccount bool
fixSnapshotOrder bool
revertLog bool
manualCorrectGasRefund bool
zeroNonceForFreshAccount bool
}
)

Expand Down Expand Up @@ -142,10 +142,10 @@ func ManualCorrectGasRefundOption() StateDBAdapterOption {
}
}

// UseZeroNonceForFreshAccountOption set useZeroNonceForFreshAccount as true
func UseZeroNonceForFreshAccountOption() StateDBAdapterOption {
// ZeroNonceForFreshAccountOption set zeroNonceForFreshAccount as true
func ZeroNonceForFreshAccountOption() StateDBAdapterOption {
return func(adapter *StateDBAdapter) error {
adapter.useZeroNonceForFreshAccount = true
adapter.zeroNonceForFreshAccount = true
return nil
}
}
Expand Down Expand Up @@ -322,7 +322,7 @@ func (stateDB *StateDBAdapter) GetNonce(evmAddr common.Address) uint64 {
log.L().Error("Failed to get nonce.", zap.Error(err))
// stateDB.logError(err)
} else {
if stateDB.useZeroNonceForFreshAccount {
if stateDB.zeroNonceForFreshAccount {
pendingNonce = state.PendingNonceConsideringFreshAccount()
} else {
pendingNonce = state.PendingNonce()
Expand Down Expand Up @@ -363,7 +363,7 @@ func (stateDB *StateDBAdapter) SetNonce(evmAddr common.Address, nonce uint64) {
log.L().Debug("Called SetNonce.",
zap.String("address", addr.String()),
zap.Uint64("nonce", nonce))
if !s.IsNewbieAccount() || s.AccountType() != 0 || nonce != 0 || stateDB.useZeroNonceForFreshAccount {
if !s.IsNewbieAccount() || s.AccountType() != 0 || nonce != 0 || stateDB.zeroNonceForFreshAccount {
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
2 changes: 1 addition & 1 deletion action/protocol/execution/evm/evmstatedbadapter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ func TestNonce(t *testing.T) {
opt := []StateDBAdapterOption{
NotFixTopicCopyBugOption(),
FixSnapshotOrderOption(),
UseZeroNonceForFreshAccountOption(),
ZeroNonceForFreshAccountOption(),
}
stateDB, err := NewStateDBAdapter(sm, 1, hash.ZeroHash256, opt...)
require.NoError(err)
Expand Down
8 changes: 4 additions & 4 deletions api/coreservice.go
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,7 @@ func (core *coreService) ReadContract(ctx context.Context, callerAddr address.Ad
BlockHeight: core.bc.TipHeight(),
}))
var pendingNonce uint64
if protocol.MustGetFeatureCtx(ctx).UseZeroNonceForFreshAccount {
if protocol.MustGetFeatureCtx(ctx).RefactorFreshAccountConversion {
pendingNonce = state.PendingNonceConsideringFreshAccount()
} else {
pendingNonce = state.PendingNonce()
Expand Down Expand Up @@ -1484,7 +1484,7 @@ func (core *coreService) EstimateExecutionGasConsumption(ctx context.Context, sc
BlockHeight: core.bc.TipHeight(),
}))
var pendingNonce uint64
if protocol.MustGetFeatureCtx(ctx).UseZeroNonceForFreshAccount {
if protocol.MustGetFeatureCtx(ctx).RefactorFreshAccountConversion {
pendingNonce = state.PendingNonceConsideringFreshAccount()
} else {
pendingNonce = state.PendingNonce()
Expand Down Expand Up @@ -1697,7 +1697,7 @@ func (core *coreService) SimulateExecution(ctx context.Context, addr address.Add
BlockHeight: core.bc.TipHeight(),
}))
var pendingNonce uint64
if protocol.MustGetFeatureCtx(ctx).UseZeroNonceForFreshAccount {
if protocol.MustGetFeatureCtx(ctx).RefactorFreshAccountConversion {
pendingNonce = state.PendingNonceConsideringFreshAccount()
} else {
pendingNonce = state.PendingNonce()
Expand Down Expand Up @@ -1761,7 +1761,7 @@ func (core *coreService) TraceCall(ctx context.Context,
BlockHeight: core.bc.TipHeight(),
}))
var pendingNonce uint64
if protocol.MustGetFeatureCtx(ctx).UseZeroNonceForFreshAccount {
if protocol.MustGetFeatureCtx(ctx).RefactorFreshAccountConversion {
pendingNonce = state.PendingNonceConsideringFreshAccount()
} else {
pendingNonce = state.PendingNonce()
Expand Down
11 changes: 11 additions & 0 deletions state/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,17 @@ func (st *Account) SetPendingNonce(nonce uint64) error {
return nil
}

// ConvertFreshAccountToZeroNonceType converts a fresh legacy account to zero-nonce account
func (st *Account) ConvertFreshAccountToZeroNonceType(nonce uint64) bool {
if st.accountType == 0 && st.nonce == 0 && nonce == 0 {
// this is a legacy account that had never initiated an outgoing transaction
// so we can convert it to zero-nonce account
st.accountType = 1
return true
}
return false
}

// PendingNonce returns the pending nonce of the account
func (st *Account) PendingNonce() uint64 {
switch st.accountType {
Expand Down
22 changes: 22 additions & 0 deletions state/factory/workingset.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,9 @@ func (ws *workingSet) runAction(
return nil, errors.Wrapf(err, "Failed to get hash")
}
defer ws.ResetSnapshots()
if err := ws.freshAccountConversion(ctx, &actCtx); err != nil {
return nil, err
}
for _, actionHandler := range reg.All() {
receipt, err := actionHandler.Handle(ctx, selp.Action(), ws)
if err != nil {
Expand Down Expand Up @@ -223,6 +226,25 @@ func (ws *workingSet) ResetSnapshots() {
ws.store.ResetSnapshots()
}

// freshAccountConversion happens between UseZeroNonceForFreshAccount height
// and RefactorFreshAccountConversion height
func (ws *workingSet) freshAccountConversion(ctx context.Context, actCtx *protocol.ActionCtx) error {
// check legacy fresh account conversion
if protocol.MustGetFeatureCtx(ctx).UseZeroNonceForFreshAccount &&
!protocol.MustGetFeatureCtx(ctx).RefactorFreshAccountConversion {
sender, err := accountutil.AccountState(ctx, ws, actCtx.Caller)
if err != nil {
return errors.Wrapf(err, "failed to get the confirmed nonce of sender %s", actCtx.Caller.String())
}
if sender.ConvertFreshAccountToZeroNonceType(actCtx.Nonce) {
if err = accountutil.StoreAccount(ws, actCtx.Caller, sender); err != nil {
return errors.Wrapf(err, "failed to store converted sender %s", actCtx.Caller.String())
}
}
}
return nil
}

// Commit persists all changes in RunActions() into the DB
func (ws *workingSet) Commit(ctx context.Context) error {
if err := protocolPreCommit(ctx, ws); err != nil {
Expand Down

0 comments on commit 9ff16d7

Please sign in to comment.