77
88 "github.com/ava-labs/avalanchego/vms/components/gas"
99 "github.com/ava-labs/libevm/common"
10+ "github.com/ava-labs/libevm/core/rawdb"
1011 "github.com/ava-labs/libevm/core/types"
12+ "github.com/ava-labs/libevm/ethdb"
1113 "github.com/ava-labs/libevm/trie"
1214 "github.com/ava-labs/strevm/gastime"
1315)
@@ -48,10 +50,10 @@ func (e *executionResults) Equal(f *executionResults) bool {
4850// time(s) and with the specified results. This function MUST NOT be called more
4951// than once. The wall-clock [time.Time] is for metrics only.
5052//
51- // Note: only in-memory state is updated. Receipts SHOULD be stored
52- // independently of a call to MarkExecuted, along with a call to
53- // [Block.WritePostExecutionState] .
54- func (b * Block ) MarkExecuted (byGas * gastime.Time , byWall time.Time , receipts types.Receipts , stateRootPost common.Hash ) error {
53+ // MarkExecuted guarantees that state is persisted to the database before
54+ // in-memory indicators of execution are updated. [Block.Executed] returning
55+ // true is therefore indicative of a successful database write by MarkExecuted .
56+ func (b * Block ) MarkExecuted (db ethdb. Database , isLastSyncBlock bool , byGas * gastime.Time , byWall time.Time , receipts types.Receipts , stateRootPost common.Hash ) error {
5557 var used gas.Gas
5658 for _ , r := range receipts {
5759 used += gas .Gas (r .GasUsed )
@@ -65,22 +67,45 @@ func (b *Block) MarkExecuted(byGas *gastime.Time, byWall time.Time, receipts typ
6567 receiptRoot : types .DeriveSha (receipts , trie .NewStackTrie (nil )),
6668 stateRootPost : stateRootPost ,
6769 }
70+
71+ batch := db .NewBatch ()
72+ if ! isLastSyncBlock {
73+ // Although the last synchronous block is required to be the head block
74+ // at the time of upgrade, not setting the head here allows this method
75+ // to be called idempotently for that block. This is useful when
76+ // converting it to an SAE block.
77+ rawdb .WriteHeadBlockHash (batch , b .Hash ())
78+ rawdb .WriteHeadHeaderHash (batch , b .Hash ())
79+ }
80+ rawdb .WriteReceipts (batch , b .Hash (), b .NumberU64 (), receipts )
81+ if err := b .writePostExecutionState (batch , e ); err != nil {
82+ return err
83+ }
84+ if err := batch .Write (); err != nil {
85+ return err
86+ }
87+
88+ return b .markExecuted (e )
89+ }
90+
91+ func (b * Block ) markExecuted (e * executionResults ) error {
6892 if ! b .execution .CompareAndSwap (nil , e ) {
6993 b .log .Error ("Block re-marked as executed" )
7094 return fmt .Errorf ("block %d re-marked as executed" , b .Height ())
7195 }
7296 return nil
7397}
7498
75- // Executed reports whether [Block.MarkExecuted] has been called.
99+ // Executed reports whether [Block.MarkExecuted] has been called and returned
100+ // without error.
76101func (b * Block ) Executed () bool {
77102 return b .execution .Load () != nil
78103}
79104
80105func zero [T any ]() (z T ) { return }
81106
82107// ExecutedByGasTime returns a clone of the gas time passed to
83- // [Block.MarkExecuted] or nil if no such call has been made.
108+ // [Block.MarkExecuted] or nil if no such successful call has been made.
84109func (b * Block ) ExecutedByGasTime () * gastime.Time {
85110 if e := b .execution .Load (); e != nil {
86111 return e .byGas .Clone ()
@@ -90,7 +115,7 @@ func (b *Block) ExecutedByGasTime() *gastime.Time {
90115}
91116
92117// ExecutedByWallTime returns the wall time passed to [Block.MarkExecuted] or
93- // the zero time if no such call has been made.
118+ // the zero time if no such successful call has been made.
94119func (b * Block ) ExecutedByWallTime () time.Time {
95120 if e := b .execution .Load (); e != nil {
96121 return e .byWall
@@ -100,7 +125,7 @@ func (b *Block) ExecutedByWallTime() time.Time {
100125}
101126
102127// Receipts returns the receipts passed to [Block.MarkExecuted] or nil if no
103- // such call has been made.
128+ // such successful call has been made.
104129func (b * Block ) Receipts () types.Receipts {
105130 if e := b .execution .Load (); e != nil {
106131 return slices .Clone (e .receipts )
@@ -110,7 +135,7 @@ func (b *Block) Receipts() types.Receipts {
110135}
111136
112137// PostExecutionStateRoot returns the state root passed to [Block.MarkExecuted]
113- // or the zero hash if no such call has been made.
138+ // or the zero hash if no such successful call has been made.
114139func (b * Block ) PostExecutionStateRoot () common.Hash {
115140 if e := b .execution .Load (); e != nil {
116141 return e .stateRootPost
0 commit comments