17
17
package core
18
18
19
19
import (
20
+ "fmt"
21
+
22
+ "github.com/ava-labs/libevm/core/vm"
20
23
"github.com/ava-labs/libevm/log"
21
24
"github.com/ava-labs/libevm/params"
22
25
)
@@ -27,6 +30,50 @@ func (st *StateTransition) rulesHooks() params.RulesHooks {
27
30
return rules .Hooks ()
28
31
}
29
32
33
+ // NOTE: other than the final paragraph, the comment on
34
+ // [StateTransition.TransitionDb] is copied, verbatim, from the upstream
35
+ // version, which has been changed to [StateTransition.transitionDb] to allow
36
+ // its behaviour to be augmented.
37
+
38
+ // Keeps the vm package imported by this specific file so VS Code can support
39
+ // comments like [vm.EVM].
40
+ var _ = (* vm .EVM )(nil )
41
+
42
+ // TransitionDb will transition the state by applying the current message and
43
+ // returning the evm execution result with following fields.
44
+ //
45
+ // - used gas: total gas used (including gas being refunded)
46
+ // - returndata: the returned data from evm
47
+ // - concrete execution error: various EVM errors which abort the execution, e.g.
48
+ // ErrOutOfGas, ErrExecutionReverted
49
+ //
50
+ // However if any consensus issue encountered, return the error directly with
51
+ // nil evm execution result.
52
+ //
53
+ // libevm-specific behaviour: if, during execution, [vm.EVM.InvalidateExecution]
54
+ // is called with a non-nil error then said error will be returned, wrapped. All
55
+ // state transitions (e.g. nonce incrementing) will be reverted to a snapshot
56
+ // taken before execution.
57
+ func (st * StateTransition ) TransitionDb () (* ExecutionResult , error ) {
58
+ if err := st .canExecuteTransaction (); err != nil {
59
+ return nil , err
60
+ }
61
+
62
+ snap := st .state .Snapshot () // computationally cheap operation
63
+ res , err := st .transitionDb () // original geth implementation
64
+
65
+ // [NOTE]: At the time of implementation of this libevm override, non-nil
66
+ // values of `err` and `invalid` (below) are mutually exclusive. However, as
67
+ // a defensive measure, we don't return early on non-nil `err` in case an
68
+ // upstream update breaks this invariant.
69
+
70
+ if invalid := st .evm .ExecutionInvalidated (); invalid != nil {
71
+ st .state .RevertToSnapshot (snap )
72
+ err = fmt .Errorf ("execution invalidated: %w" , invalid )
73
+ }
74
+ return res , err
75
+ }
76
+
30
77
// canExecuteTransaction is a convenience wrapper for calling the
31
78
// [params.RulesHooks.CanExecuteTransaction] hook.
32
79
func (st * StateTransition ) canExecuteTransaction () error {
0 commit comments