diff --git a/action/protocol/context.go b/action/protocol/context.go index b92503cc90..6b8d3cd350 100644 --- a/action/protocol/context.go +++ b/action/protocol/context.go @@ -152,6 +152,7 @@ type ( VerifyNotContainerBeforeRun bool ValidateActionWithState bool CheckStakingDurationUpperLimit bool + FixRevertSnapshot bool } // FeatureWithHeightCtx provides feature check functions. @@ -315,6 +316,7 @@ func WithFeatureCtx(ctx context.Context) context.Context { VerifyNotContainerBeforeRun: g.IsVanuatu(height), ValidateActionWithState: g.IsVanuatu(height), CheckStakingDurationUpperLimit: g.IsVanuatu(height), + FixRevertSnapshot: g.IsVanuatu(height), }, ) } diff --git a/action/protocol/execution/evm/evm.go b/action/protocol/execution/evm/evm.go index 62adce3e5c..116e856a96 100644 --- a/action/protocol/execution/evm/evm.go +++ b/action/protocol/execution/evm/evm.go @@ -337,10 +337,12 @@ func ReadContractStorage( } func prepareStateDB(ctx context.Context, sm protocol.StateManager) (*StateDBAdapter, error) { - actionCtx := protocol.MustGetActionCtx(ctx) - blkCtx := protocol.MustGetBlockCtx(ctx) - featureCtx := protocol.MustGetFeatureCtx(ctx) - opts := []StateDBAdapterOption{} + var ( + actionCtx = protocol.MustGetActionCtx(ctx) + blkCtx = protocol.MustGetBlockCtx(ctx) + featureCtx = protocol.MustGetFeatureCtx(ctx) + opts = []StateDBAdapterOption{} + ) if featureCtx.CreateLegacyNonceAccount { opts = append(opts, LegacyNonceAccountOption()) } @@ -376,7 +378,9 @@ func prepareStateDB(ctx context.Context, sm protocol.StateManager) (*StateDBAdap if featureCtx.EnableCancunEVM { opts = append(opts, EnableCancunEVMOption()) } - + if featureCtx.FixRevertSnapshot || actionCtx.ReadOnly { + opts = append(opts, FixRevertSnapshotOption()) + } return NewStateDBAdapter( sm, blkCtx.BlockHeight, diff --git a/action/protocol/execution/evm/evmstatedbadapter.go b/action/protocol/execution/evm/evmstatedbadapter.go index a8c62fb953..851f2407d9 100644 --- a/action/protocol/execution/evm/evmstatedbadapter.go +++ b/action/protocol/execution/evm/evmstatedbadapter.go @@ -82,6 +82,7 @@ type ( zeroNonceForFreshAccount bool panicUnrecoverableError bool enableCancun bool + fixRevertSnapshot bool } ) @@ -187,6 +188,14 @@ func EnableCancunEVMOption() StateDBAdapterOption { } } +// FixRevertSnapshotOption set fixRevertSnapshot as true +func FixRevertSnapshotOption() StateDBAdapterOption { + return func(adapter *StateDBAdapter) error { + adapter.fixRevertSnapshot = true + return nil + } +} + // NewStateDBAdapter creates a new state db with iotex blockchain func NewStateDBAdapter( sm protocol.StateManager, @@ -626,10 +635,14 @@ func (stateDB *StateDBAdapter) RevertToSnapshot(snapshot int) { log.L().Error("Failed to revert to snapshot.", zap.Int("snapshot", snapshot)) return } + deleteSnapshot := snapshot + if stateDB.fixRevertSnapshot { + deleteSnapshot++ + } // restore gas refund if !stateDB.manualCorrectGasRefund { stateDB.refund = stateDB.refundSnapshot[snapshot] - for i := snapshot; ; i++ { + for i := deleteSnapshot; ; i++ { if _, ok := stateDB.refundSnapshot[i]; ok { delete(stateDB.refundSnapshot, i) } else { @@ -640,7 +653,7 @@ func (stateDB *StateDBAdapter) RevertToSnapshot(snapshot int) { // restore access list stateDB.accessList = stateDB.accessListSnapshot[snapshot] { - for i := snapshot; ; i++ { + for i := deleteSnapshot; ; i++ { if _, ok := stateDB.accessListSnapshot[i]; ok { delete(stateDB.accessListSnapshot, i) } else { @@ -652,7 +665,7 @@ func (stateDB *StateDBAdapter) RevertToSnapshot(snapshot int) { //restore transientStorage stateDB.transientStorage = stateDB.transientStorageSnapshot[snapshot] { - for i := snapshot; ; i++ { + for i := deleteSnapshot; ; i++ { if _, ok := stateDB.transientStorageSnapshot[i]; ok { delete(stateDB.transientStorageSnapshot, i) } else { @@ -663,7 +676,7 @@ func (stateDB *StateDBAdapter) RevertToSnapshot(snapshot int) { // restore created accounts stateDB.createdAccount = stateDB.createdAccountSnapshot[snapshot] { - for i := snapshot; ; i++ { + for i := deleteSnapshot; ; i++ { if _, ok := stateDB.createdAccountSnapshot[i]; ok { delete(stateDB.createdAccountSnapshot, i) } else { @@ -675,7 +688,7 @@ func (stateDB *StateDBAdapter) RevertToSnapshot(snapshot int) { // restore logs and txLogs if stateDB.revertLog { stateDB.logs = stateDB.logs[:stateDB.logsSnapshot[snapshot]] - for i := snapshot; ; i++ { + for i := deleteSnapshot; ; i++ { if _, ok := stateDB.logsSnapshot[i]; ok { delete(stateDB.logsSnapshot, i) } else { @@ -683,7 +696,7 @@ func (stateDB *StateDBAdapter) RevertToSnapshot(snapshot int) { } } stateDB.transactionLogs = stateDB.transactionLogs[:stateDB.txLogsSnapshot[snapshot]] - for i := snapshot; ; i++ { + for i := deleteSnapshot; ; i++ { if _, ok := stateDB.txLogsSnapshot[i]; ok { delete(stateDB.txLogsSnapshot, i) } else { @@ -694,7 +707,7 @@ func (stateDB *StateDBAdapter) RevertToSnapshot(snapshot int) { // restore the SelfDestruct accounts stateDB.selfDestructed = ds if stateDB.fixSnapshotOrder { - for i := snapshot; ; i++ { + for i := deleteSnapshot; ; i++ { if _, ok := stateDB.selfDestructedSnapshot[i]; ok { delete(stateDB.selfDestructedSnapshot, i) } else { @@ -712,7 +725,7 @@ func (stateDB *StateDBAdapter) RevertToSnapshot(snapshot int) { } } if stateDB.fixSnapshotOrder { - for i := snapshot; ; i++ { + for i := deleteSnapshot; ; i++ { if _, ok := stateDB.contractSnapshot[i]; ok { delete(stateDB.contractSnapshot, i) } else { @@ -723,7 +736,7 @@ func (stateDB *StateDBAdapter) RevertToSnapshot(snapshot int) { // restore preimages stateDB.preimages = stateDB.preimageSnapshot[snapshot] if stateDB.fixSnapshotOrder { - for i := snapshot; ; i++ { + for i := deleteSnapshot; ; i++ { if _, ok := stateDB.preimageSnapshot[i]; ok { delete(stateDB.preimageSnapshot, i) } else {