Skip to content

Commit c984d90

Browse files
draganms1na
andauthored
eth/tracers/native: add keccak256preimage tracer (#32569)
Introduces a new tracer which returns the preimages of evm KECCAK256 hashes. See #32570. --------- Co-authored-by: Sina M <[email protected]> Co-authored-by: Sina Mahmoodi <[email protected]>
1 parent 8e87b75 commit c984d90

File tree

2 files changed

+528
-0
lines changed

2 files changed

+528
-0
lines changed
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package native
2+
3+
// Copyright 2021 The go-ethereum Authors
4+
// This file is part of the go-ethereum library.
5+
//
6+
// The go-ethereum library is free software: you can redistribute it and/or modify
7+
// it under the terms of the GNU Lesser General Public License as published by
8+
// the Free Software Foundation, either version 3 of the License, or
9+
// (at your option) any later version.
10+
//
11+
// The go-ethereum library is distributed in the hope that it will be useful,
12+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
// GNU Lesser General Public License for more details.
15+
//
16+
// You should have received a copy of the GNU Lesser General Public License
17+
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
18+
19+
import (
20+
"encoding/json"
21+
22+
"github.com/ethereum/go-ethereum/common"
23+
"github.com/ethereum/go-ethereum/common/hexutil"
24+
"github.com/ethereum/go-ethereum/core/tracing"
25+
"github.com/ethereum/go-ethereum/core/vm"
26+
"github.com/ethereum/go-ethereum/crypto"
27+
"github.com/ethereum/go-ethereum/eth/tracers"
28+
"github.com/ethereum/go-ethereum/eth/tracers/internal"
29+
"github.com/ethereum/go-ethereum/log"
30+
"github.com/ethereum/go-ethereum/params"
31+
)
32+
33+
func init() {
34+
tracers.DefaultDirectory.Register("keccak256PreimageTracer", newKeccak256PreimageTracer, false)
35+
}
36+
37+
// keccak256PreimageTracer is a native tracer that collects preimages of all KECCAK256 operations.
38+
// This tracer is particularly useful for analyzing smart contract execution patterns,
39+
// especially when debugging storage access in Solidity mappings and dynamic arrays.
40+
type keccak256PreimageTracer struct {
41+
computedHashes map[common.Hash]hexutil.Bytes
42+
}
43+
44+
// newKeccak256PreimageTracer returns a new keccak256PreimageTracer instance.
45+
func newKeccak256PreimageTracer(ctx *tracers.Context, cfg json.RawMessage, chainConfig *params.ChainConfig) (*tracers.Tracer, error) {
46+
t := &keccak256PreimageTracer{
47+
computedHashes: make(map[common.Hash]hexutil.Bytes),
48+
}
49+
return &tracers.Tracer{
50+
Hooks: &tracing.Hooks{
51+
OnOpcode: t.OnOpcode,
52+
},
53+
GetResult: t.GetResult,
54+
}, nil
55+
}
56+
57+
func (t *keccak256PreimageTracer) OnOpcode(pc uint64, op byte, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
58+
if op == byte(vm.KECCAK256) {
59+
sd := scope.StackData()
60+
// it turns out that sometimes the stack is empty, evm will fail in this case, but we should not panic here
61+
if len(sd) < 2 {
62+
return
63+
}
64+
65+
dataOffset := internal.StackBack(sd, 0).Uint64()
66+
dataLength := internal.StackBack(sd, 1).Uint64()
67+
preimage, err := internal.GetMemoryCopyPadded(scope.MemoryData(), int64(dataOffset), int64(dataLength))
68+
if err != nil {
69+
log.Warn("keccak256PreimageTracer: failed to copy keccak preimage from memory", "err", err)
70+
return
71+
}
72+
73+
hash := crypto.Keccak256(preimage)
74+
75+
t.computedHashes[common.Hash(hash)] = hexutil.Bytes(preimage)
76+
}
77+
}
78+
79+
// GetResult returns the collected keccak256 preimages as a JSON object mapping hashes to preimages.
80+
func (t *keccak256PreimageTracer) GetResult() (json.RawMessage, error) {
81+
msg, err := json.Marshal(t.computedHashes)
82+
if err != nil {
83+
return nil, err
84+
}
85+
return msg, nil
86+
}

0 commit comments

Comments
 (0)