Skip to content

Commit 08cdbb9

Browse files
authored
Merge pull request #459 from OffchainLabs/gas-dimension-tracing
feat: Add Gas dimension tracers
2 parents a565b8c + 347a2b2 commit 08cdbb9

14 files changed

+3401
-1
lines changed

core/blockchain.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2125,7 +2125,11 @@ func (bc *BlockChain) processBlock(block *types.Block, statedb *state.StateDB, s
21252125
triedbCommitTimer.Update(statedb.TrieDBCommits) // Trie database commits are complete, we can mark them
21262126

21272127
blockWriteTimer.Update(time.Since(wstart) - max(statedb.AccountCommits, statedb.StorageCommits) /* concurrent */ - statedb.SnapshotCommits - statedb.TrieDBCommits)
2128-
blockInsertTimer.UpdateSince(start)
2128+
insertDuration := time.Since(start)
2129+
blockInsertTimer.Update(insertDuration)
2130+
if bc.logger != nil && bc.logger.OnBlockEndMetrics != nil {
2131+
bc.logger.OnBlockEndMetrics(block.NumberU64(), insertDuration)
2132+
}
21292133

21302134
return &blockProcessingResult{usedGas: res.GasUsed, procTime: proctime, status: status}, nil
21312135
}

core/state/statedb.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1555,6 +1555,15 @@ func (s *StateDB) SlotInAccessList(addr common.Address, slot common.Hash) (addre
15551555
return s.accessList.Contains(addr, slot)
15561556
}
15571557

1558+
// GetAccessList returns the data of the access list directly for tracers to consume
1559+
// this is necessary because the accessList is not exported from the state package
1560+
func (s *StateDB) GetAccessList() (addresses map[common.Address]int, slots []map[common.Hash]struct{}) {
1561+
accessListCopy := s.accessList.Copy()
1562+
addresses = accessListCopy.addresses
1563+
slots = accessListCopy.slots
1564+
return
1565+
}
1566+
15581567
// markDelete is invoked when an account is deleted but the deletion is
15591568
// not yet committed. The pending mutation is cached and will be applied
15601569
// all together

core/state/statedb_hooked.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,3 +373,7 @@ func (s *hookedStateDB) GetSelfDestructs() []common.Address {
373373
func (s *hookedStateDB) GetCurrentTxLogs() []*types.Log {
374374
return s.inner.GetCurrentTxLogs()
375375
}
376+
377+
func (s *hookedStateDB) GetAccessList() (addresses map[common.Address]int, slots []map[common.Hash]struct{}) {
378+
return s.inner.GetAccessList()
379+
}

core/tracing/hooks.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ package tracing
2626

2727
import (
2828
"math/big"
29+
"time"
2930

3031
"github.com/ethereum/go-ethereum/common"
3132
"github.com/ethereum/go-ethereum/core/types"
@@ -55,6 +56,7 @@ type StateDB interface {
5556
GetTransientState(common.Address, common.Hash) common.Hash
5657
Exist(common.Address) bool
5758
GetRefund() uint64
59+
GetAccessList() (addresses map[common.Address]int, slots []map[common.Hash]struct{})
5860
}
5961

6062
// VMContext provides the context for the EVM execution.
@@ -136,6 +138,9 @@ type (
136138
// BlockEndHook is called after executing a block.
137139
BlockEndHook = func(err error)
138140

141+
// BlockEndMetricsHook is called after executing a block and calculating the metrics timers
142+
BlockEndMetricsHook = func(blockNumber uint64, blockInsertDuration time.Duration)
143+
139144
// SkippedBlockHook indicates a block was skipped during processing
140145
// due to it being known previously. This can happen e.g. when recovering
141146
// from a crash.
@@ -210,6 +215,7 @@ type Hooks struct {
210215
OnClose CloseHook
211216
OnBlockStart BlockStartHook
212217
OnBlockEnd BlockEndHook
218+
OnBlockEndMetrics BlockEndMetricsHook
213219
OnSkippedBlock SkippedBlockHook
214220
OnGenesisBlock GenesisBlockHook
215221
OnSystemCallStart OnSystemCallStartHook

core/vm/interface.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ type StateDB interface {
116116
// AddSlotToAccessList adds the given (address,slot) to the access list. This operation is safe to perform
117117
// even if the feature/fork is not active yet
118118
AddSlotToAccessList(addr common.Address, slot common.Hash)
119+
// GetAccessList returns the access list
120+
GetAccessList() (addresses map[common.Address]int, slots []map[common.Hash]struct{})
119121

120122
// PointCache returns the point cache used in computations
121123
PointCache() *utils.PointCache
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package live
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"os"
7+
"path/filepath"
8+
"time"
9+
10+
"github.com/ethereum/go-ethereum/core/tracing"
11+
"github.com/ethereum/go-ethereum/eth/tracers"
12+
)
13+
14+
type blockInsertTimes struct {
15+
Path string `json:"path"`
16+
}
17+
18+
func init() {
19+
tracers.LiveDirectory.Register("blockInsertTimes", newBlockInsertTimes)
20+
}
21+
22+
type blockInsertTimesConfig struct {
23+
Path string `json:"path"` // Path to directory for output
24+
}
25+
26+
func newBlockInsertTimes(cfg json.RawMessage) (*tracing.Hooks, error) {
27+
var config blockInsertTimesConfig
28+
if err := json.Unmarshal(cfg, &config); err != nil {
29+
return nil, err
30+
}
31+
32+
if config.Path == "" {
33+
return nil, fmt.Errorf("gas dimension live tracer path for output is required: %v", config)
34+
}
35+
36+
t := &blockInsertTimes{
37+
Path: config.Path,
38+
}
39+
40+
return &tracing.Hooks{
41+
OnBlockEndMetrics: t.OnBlockEndMetrics,
42+
}, nil
43+
}
44+
45+
func (t *blockInsertTimes) OnBlockEndMetrics(blockNumber uint64, blockInsertDuration time.Duration) {
46+
filename := fmt.Sprintf("%d.json", blockNumber)
47+
filepath := filepath.Join(t.Path, filename)
48+
49+
// Ensure the directory exists
50+
if err := os.MkdirAll(t.Path, 0755); err != nil {
51+
fmt.Printf("Failed to create directory %s: %v\n", t.Path, err)
52+
return
53+
}
54+
55+
// the output is the duration in nanoseconds
56+
var outData int64 = blockInsertDuration.Nanoseconds()
57+
58+
// Write the file
59+
if err := os.WriteFile(filepath, []byte(fmt.Sprintf("%d", outData)), 0644); err != nil {
60+
fmt.Printf("Failed to write file %s: %v\n", filepath, err)
61+
return
62+
}
63+
}

0 commit comments

Comments
 (0)