github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/core/vm/logger.go (about) 1 2 //此源码被清华学神尹成大魔王专业翻译分析并修改 3 //尹成QQ77025077 4 //尹成微信18510341407 5 //尹成所在QQ群721929980 6 //尹成邮箱 yinc13@mails.tsinghua.edu.cn 7 //尹成毕业于清华大学,微软区块链领域全球最有价值专家 8 //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620 9 //版权所有2015 Go Ethereum作者 10 //此文件是Go以太坊库的一部分。 11 // 12 //Go-Ethereum库是免费软件:您可以重新分发它和/或修改 13 //根据GNU发布的较低通用公共许可证的条款 14 //自由软件基金会,或者许可证的第3版,或者 15 //(由您选择)任何更高版本。 16 // 17 //Go以太坊图书馆的发行目的是希望它会有用, 18 //但没有任何保证;甚至没有 19 //适销性或特定用途的适用性。见 20 //GNU较低的通用公共许可证,了解更多详细信息。 21 // 22 //你应该收到一份GNU较低级别的公共许可证副本 23 //以及Go以太坊图书馆。如果没有,请参见<http://www.gnu.org/licenses/>。 24 25 package vm 26 27 import ( 28 "encoding/hex" 29 "fmt" 30 "io" 31 "math/big" 32 "time" 33 34 "github.com/ethereum/go-ethereum/common" 35 "github.com/ethereum/go-ethereum/common/hexutil" 36 "github.com/ethereum/go-ethereum/common/math" 37 "github.com/ethereum/go-ethereum/core/types" 38 ) 39 40 //存储表示合同的存储。 41 type Storage map[common.Hash]common.Hash 42 43 //复制复制复制当前存储。 44 func (s Storage) Copy() Storage { 45 cpy := make(Storage) 46 for key, value := range s { 47 cpy[key] = value 48 } 49 50 return cpy 51 } 52 53 //logconfig是结构化记录器evm的配置选项 54 type LogConfig struct { 55 DisableMemory bool //禁用内存捕获 56 DisableStack bool //禁用堆栈捕获 57 DisableStorage bool //禁用存储捕获 58 Debug bool //捕获结束时打印输出 59 Limit int //最大输出长度,但零表示无限制 60 } 61 62 //go:生成gencodec-type structlog-field override structlogmarshaling-out gen structlog.go 63 64 //structlog在每个周期发送给evm,并列出有关当前内部状态的信息 65 //在语句执行之前。 66 type StructLog struct { 67 Pc uint64 `json:"pc"` 68 Op OpCode `json:"op"` 69 Gas uint64 `json:"gas"` 70 GasCost uint64 `json:"gasCost"` 71 Memory []byte `json:"memory"` 72 MemorySize int `json:"memSize"` 73 Stack []*big.Int `json:"stack"` 74 Storage map[common.Hash]common.Hash `json:"-"` 75 Depth int `json:"depth"` 76 Err error `json:"-"` 77 } 78 79 //gencodec的覆盖 80 type structLogMarshaling struct { 81 Stack []*math.HexOrDecimal256 82 Gas math.HexOrDecimal64 83 GasCost math.HexOrDecimal64 84 Memory hexutil.Bytes 85 OpName string `json:"opName"` //在marshaljson中添加对opname()的调用 86 ErrorString string `json:"error"` //在marshaljson中添加对ErrorString()的调用 87 } 88 89 //opname将操作数名称格式化为可读格式。 90 func (s *StructLog) OpName() string { 91 return s.Op.String() 92 } 93 94 //ErrorString将日志的错误格式化为字符串。 95 func (s *StructLog) ErrorString() string { 96 if s.Err != nil { 97 return s.Err.Error() 98 } 99 return "" 100 } 101 102 //跟踪程序用于从EVM事务收集执行跟踪 103 //执行。对带有 104 //当前VM状态。 105 //请注意,引用类型是实际的VM数据结构;复制 106 //如果您需要在当前呼叫之外保留它们。 107 type Tracer interface { 108 CaptureStart(from common.Address, to common.Address, call bool, input []byte, gas uint64, value *big.Int) error 109 CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, contract *Contract, depth int, err error) error 110 CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, contract *Contract, depth int, err error) error 111 CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) error 112 } 113 114 //structlogger是一个EVM状态记录器并实现跟踪程序。 115 // 116 //结构记录器可以根据给定的日志配置捕获状态,并且还可以保留 117 //修改后的存储的跟踪记录,用于报告 118 //把他们的仓库收起来。 119 type StructLogger struct { 120 cfg LogConfig 121 122 logs []StructLog 123 changedValues map[common.Address]Storage 124 output []byte 125 err error 126 } 127 128 //newstructlogger返回新的记录器 129 func NewStructLogger(cfg *LogConfig) *StructLogger { 130 logger := &StructLogger{ 131 changedValues: make(map[common.Address]Storage), 132 } 133 if cfg != nil { 134 logger.cfg = *cfg 135 } 136 return logger 137 } 138 139 //CaptureStart实现跟踪程序接口以初始化跟踪操作。 140 func (l *StructLogger) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) error { 141 return nil 142 } 143 144 //CaptureState记录新的结构化日志消息并将其推送到环境中 145 // 146 //CaptureState还跟踪sstore操作以跟踪脏值。 147 func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, contract *Contract, depth int, err error) error { 148 //检查是否已累计指定数量的日志 149 if l.cfg.Limit != 0 && l.cfg.Limit <= len(l.logs) { 150 return ErrTraceLimitReached 151 } 152 153 //为此合同初始化新的更改值存储容器 154 //如果不存在。 155 if l.changedValues[contract.Address()] == nil { 156 l.changedValues[contract.Address()] = make(Storage) 157 } 158 159 //捕获sstore操作码并确定更改的值并存储 160 //它在本地存储容器中。 161 if op == SSTORE && stack.len() >= 2 { 162 var ( 163 value = common.BigToHash(stack.data[stack.len()-2]) 164 address = common.BigToHash(stack.data[stack.len()-1]) 165 ) 166 l.changedValues[contract.Address()][address] = value 167 } 168 //将当前内存状态的快照复制到新缓冲区 169 var mem []byte 170 if !l.cfg.DisableMemory { 171 mem = make([]byte, len(memory.Data())) 172 copy(mem, memory.Data()) 173 } 174 //将当前堆栈状态的快照复制到新缓冲区 175 var stck []*big.Int 176 if !l.cfg.DisableStack { 177 stck = make([]*big.Int, len(stack.Data())) 178 for i, item := range stack.Data() { 179 stck[i] = new(big.Int).Set(item) 180 } 181 } 182 //将当前存储的快照复制到新容器 183 var storage Storage 184 if !l.cfg.DisableStorage { 185 storage = l.changedValues[contract.Address()].Copy() 186 } 187 //创建EVM的新快照。 188 log := StructLog{pc, op, gas, cost, mem, memory.Len(), stck, storage, depth, err} 189 190 l.logs = append(l.logs, log) 191 return nil 192 } 193 194 //CaptureFault实现跟踪程序接口来跟踪执行错误 195 //运行操作码时。 196 func (l *StructLogger) CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, contract *Contract, depth int, err error) error { 197 return nil 198 } 199 200 //在调用完成后调用CaptureEnd以完成跟踪。 201 func (l *StructLogger) CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) error { 202 l.output = output 203 l.err = err 204 if l.cfg.Debug { 205 fmt.Printf("0x%x\n", output) 206 if err != nil { 207 fmt.Printf(" error: %v\n", err) 208 } 209 } 210 return nil 211 } 212 213 //structlogs返回捕获的日志条目。 214 func (l *StructLogger) StructLogs() []StructLog { return l.logs } 215 216 //错误返回跟踪捕获的VM错误。 217 func (l *StructLogger) Error() error { return l.err } 218 219 //输出返回跟踪捕获的VM返回值。 220 func (l *StructLogger) Output() []byte { return l.output } 221 222 //WriteTrace将格式化的跟踪写入给定的写入程序 223 func WriteTrace(writer io.Writer, logs []StructLog) { 224 for _, log := range logs { 225 fmt.Fprintf(writer, "%-16spc=%08d gas=%v cost=%v", log.Op, log.Pc, log.Gas, log.GasCost) 226 if log.Err != nil { 227 fmt.Fprintf(writer, " ERROR: %v", log.Err) 228 } 229 fmt.Fprintln(writer) 230 231 if len(log.Stack) > 0 { 232 fmt.Fprintln(writer, "Stack:") 233 for i := len(log.Stack) - 1; i >= 0; i-- { 234 fmt.Fprintf(writer, "%08d %x\n", len(log.Stack)-i-1, math.PaddedBigBytes(log.Stack[i], 32)) 235 } 236 } 237 if len(log.Memory) > 0 { 238 fmt.Fprintln(writer, "Memory:") 239 fmt.Fprint(writer, hex.Dump(log.Memory)) 240 } 241 if len(log.Storage) > 0 { 242 fmt.Fprintln(writer, "Storage:") 243 for h, item := range log.Storage { 244 fmt.Fprintf(writer, "%x: %x\n", h, item) 245 } 246 } 247 fmt.Fprintln(writer) 248 } 249 } 250 251 //WriteLogs以可读的格式将VM日志写入给定的写入程序 252 func WriteLogs(writer io.Writer, logs []*types.Log) { 253 for _, log := range logs { 254 fmt.Fprintf(writer, "LOG%d: %x bn=%d txi=%x\n", len(log.Topics), log.Address, log.BlockNumber, log.TxIndex) 255 256 for i, topic := range log.Topics { 257 fmt.Fprintf(writer, "%08d %x\n", i, topic) 258 } 259 260 fmt.Fprint(writer, hex.Dump(log.Data)) 261 fmt.Fprintln(writer) 262 } 263 }