17
17
package logger
18
18
19
19
import (
20
+ "bytes"
20
21
"encoding/hex"
21
22
"encoding/json"
22
23
"fmt"
@@ -48,12 +49,13 @@ func (s Storage) Copy() Storage {
48
49
49
50
// Config are the configuration options for structured logger the EVM
50
51
type Config struct {
51
- EnableMemory bool // enable memory capture
52
- DisableStack bool // disable stack capture
53
- DisableStorage bool // disable storage capture
54
- EnableReturnData bool // enable return data capture
55
- Debug bool // print output during capture end
56
- Limit int // maximum length of output, but zero means unlimited
52
+ EnableMemory bool // enable memory capture
53
+ DisableStack bool // disable stack capture
54
+ DisableStorage bool // disable storage capture
55
+ EnableReturnData bool // enable return data capture
56
+ Debug bool // print output during capture end
57
+ Limit int // maximum length of output, but zero means unlimited
58
+ MemoryCompressionWindow int
57
59
// Chain overrides, can be used to execute a trace using future fork rules
58
60
Overrides * params.ChainConfig `json:"overrides,omitempty"`
59
61
}
@@ -68,6 +70,7 @@ type StructLog struct {
68
70
Gas uint64 `json:"gas"`
69
71
GasCost uint64 `json:"gasCost"`
70
72
Memory []byte `json:"memory,omitempty"`
73
+ Meq * int `json:"meq,omitempty"`
71
74
MemorySize int `json:"memSize"`
72
75
Stack []uint256.Int `json:"stack"`
73
76
ReturnData []byte `json:"returnData,omitempty"`
@@ -116,6 +119,10 @@ type StructLogger struct {
116
119
gasLimit uint64
117
120
usedGas uint64
118
121
122
+ prevMem [][]byte
123
+ prevMemWindow int
124
+ prevMemIdx int
125
+
119
126
interrupt atomic.Bool // Atomic flag to signal execution interruption
120
127
reason error // Textual reason for the interruption
121
128
}
@@ -127,6 +134,9 @@ func NewStructLogger(cfg *Config) *StructLogger {
127
134
}
128
135
if cfg != nil {
129
136
logger .cfg = * cfg
137
+ logger .prevMemWindow = cfg .MemoryCompressionWindow
138
+ logger .prevMemIdx = 0
139
+ logger .prevMem = make ([][]byte , cfg .MemoryCompressionWindow )
130
140
}
131
141
return logger
132
142
}
@@ -162,9 +172,36 @@ func (l *StructLogger) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, s
162
172
contract := scope .Contract
163
173
// Copy a snapshot of the current memory state to a new buffer
164
174
var mem []byte
175
+ var meq * int
165
176
if l .cfg .EnableMemory {
166
177
mem = make ([]byte , len (memory .Data ()))
167
178
copy (mem , memory .Data ())
179
+
180
+ foundEq := false
181
+ if l .prevMemWindow > 0 {
182
+ i := l .prevMemIdx
183
+ for dist := 1 ; dist <= l .prevMemWindow ; dist ++ {
184
+ if i -- ; i < 0 {
185
+ i = l .prevMemWindow - 1
186
+ }
187
+ if len (l .prevMem [i ]) == len (mem ) && bytes .Equal (l .prevMem [i ], mem ) {
188
+ foundEq = true
189
+ meq = new (int )
190
+ * meq = dist
191
+ mem = nil
192
+ break
193
+ }
194
+ }
195
+ if l .prevMemIdx ++ ; l .prevMemIdx == l .prevMemWindow {
196
+ l .prevMemIdx = 0
197
+ }
198
+ if foundEq {
199
+ l .prevMem [l .prevMemIdx ] = l .prevMem [i ]
200
+ } else {
201
+ l .prevMem [l .prevMemIdx ] = make ([]byte , len (mem ))
202
+ copy (l .prevMem [l .prevMemIdx ], mem )
203
+ }
204
+ }
168
205
}
169
206
// Copy a snapshot of the current stack state to a new buffer
170
207
var stck []uint256.Int
@@ -208,7 +245,7 @@ func (l *StructLogger) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, s
208
245
copy (rdata , rData )
209
246
}
210
247
// create a new snapshot of the EVM.
211
- log := StructLog {pc , op , gas , cost , mem , memory .Len (), stck , rdata , storage , depth , l .env .StateDB .GetRefund (), err }
248
+ log := StructLog {pc , op , gas , cost , mem , meq , memory .Len (), stck , rdata , storage , depth , l .env .StateDB .GetRefund (), err }
212
249
l .logs = append (l .logs , log )
213
250
}
214
251
0 commit comments