github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/eth/tracers/tracers_test.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 //版权所有2017 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 tracers 26 27 import ( 28 "encoding/json" 29 "io/ioutil" 30 "math/big" 31 "path/filepath" 32 "reflect" 33 "strings" 34 "testing" 35 36 "github.com/ethereum/go-ethereum/common" 37 "github.com/ethereum/go-ethereum/common/hexutil" 38 "github.com/ethereum/go-ethereum/common/math" 39 "github.com/ethereum/go-ethereum/core" 40 "github.com/ethereum/go-ethereum/core/types" 41 "github.com/ethereum/go-ethereum/core/vm" 42 "github.com/ethereum/go-ethereum/ethdb" 43 "github.com/ethereum/go-ethereum/rlp" 44 "github.com/ethereum/go-ethereum/tests" 45 ) 46 47 //要生成新的calltracer测试,请将下面的maketest方法复制粘贴到 48 //一个geth控制台,用要导出的事务散列调用它。 49 50 /* 51 //maketest通过运行预状态重新组装和 52 //调用trace run,将收集到的所有信息组装到一个测试用例中。 53 var maketest=功能(tx,倒带) 54 //从块、事务和预存数据生成Genesis块 55 var block=eth.getblock(eth.getTransaction(tx).blockHash); 56 var genesis=eth.getblock(block.parenthash); 57 58 删除genesis.gasused; 59 删除genesis.logsbloom; 60 删除genesis.parenthash; 61 删除genesis.receiptsroot; 62 删除Genesis.sha3uncles; 63 删除genesis.size; 64 删除genesis.transactions; 65 删除genesis.transactionsroot; 66 删除genesis.uncles; 67 68 genesis.gaslimit=genesis.gaslimit.toString(); 69 genesis.number=genesis.number.toString(); 70 genesis.timestamp=genesis.timestamp.toString(); 71 72 genesis.alloc=debug.traceTransaction(tx,tracer:“prestatedtracer”,rewind:rewind); 73 for(genesis.alloc中的var键) 74 genesis.alloc[key].nonce=genesis.alloc[key].nonce.toString(); 75 } 76 genesis.config=admin.nodeinfo.protocols.eth.config; 77 78 //生成调用跟踪并生成测试输入 79 var result=debug.traceTransaction(tx,tracer:“calltracer”,rewind:rewind); 80 删除result.time; 81 82 console.log(json.stringify( 83 创世纪:创世纪, 84 语境:{ 85 编号:block.number.toString(), 86 困难:障碍。困难, 87 timestamp:block.timestamp.toString(), 88 gaslimit:block.gaslimit.toString(), 89 矿工:block.miner, 90 } 91 输入:eth.getrawtransaction(tx) 92 结果: 93 },NULL,2); 94 } 95 **/ 96 97 98 //CallTrace是CallTracer运行的结果。 99 type callTrace struct { 100 Type string `json:"type"` 101 From common.Address `json:"from"` 102 To common.Address `json:"to"` 103 Input hexutil.Bytes `json:"input"` 104 Output hexutil.Bytes `json:"output"` 105 Gas *hexutil.Uint64 `json:"gas,omitempty"` 106 GasUsed *hexutil.Uint64 `json:"gasUsed,omitempty"` 107 Value *hexutil.Big `json:"value,omitempty"` 108 Error string `json:"error,omitempty"` 109 Calls []callTrace `json:"calls,omitempty"` 110 } 111 112 type callContext struct { 113 Number math.HexOrDecimal64 `json:"number"` 114 Difficulty *math.HexOrDecimal256 `json:"difficulty"` 115 Time math.HexOrDecimal64 `json:"timestamp"` 116 GasLimit math.HexOrDecimal64 `json:"gasLimit"` 117 Miner common.Address `json:"miner"` 118 } 119 120 //CallTracerTest定义一个测试来检查调用跟踪程序。 121 type callTracerTest struct { 122 Genesis *core.Genesis `json:"genesis"` 123 Context *callContext `json:"context"` 124 Input string `json:"input"` 125 Result *callTrace `json:"result"` 126 } 127 128 //迭代跟踪测试工具中的所有输入输出数据集,并 129 //对它们运行javascript跟踪程序。 130 func TestCallTracer(t *testing.T) { 131 files, err := ioutil.ReadDir("testdata") 132 if err != nil { 133 t.Fatalf("failed to retrieve tracer test suite: %v", err) 134 } 135 for _, file := range files { 136 if !strings.HasPrefix(file.Name(), "call_tracer_") { 137 continue 138 } 139 file := file //捕获范围变量 140 t.Run(camel(strings.TrimSuffix(strings.TrimPrefix(file.Name(), "call_tracer_"), ".json")), func(t *testing.T) { 141 t.Parallel() 142 143 //找到呼叫追踪测试,从磁盘读取 144 blob, err := ioutil.ReadFile(filepath.Join("testdata", file.Name())) 145 if err != nil { 146 t.Fatalf("failed to read testcase: %v", err) 147 } 148 test := new(callTracerTest) 149 if err := json.Unmarshal(blob, test); err != nil { 150 t.Fatalf("failed to parse testcase: %v", err) 151 } 152 //使用给定的预状态配置区块链 153 tx := new(types.Transaction) 154 if err := rlp.DecodeBytes(common.FromHex(test.Input), tx); err != nil { 155 t.Fatalf("failed to parse testcase input: %v", err) 156 } 157 signer := types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number))) 158 origin, _ := signer.Sender(tx) 159 160 context := vm.Context{ 161 CanTransfer: core.CanTransfer, 162 Transfer: core.Transfer, 163 Origin: origin, 164 Coinbase: test.Context.Miner, 165 BlockNumber: new(big.Int).SetUint64(uint64(test.Context.Number)), 166 Time: new(big.Int).SetUint64(uint64(test.Context.Time)), 167 Difficulty: (*big.Int)(test.Context.Difficulty), 168 GasLimit: uint64(test.Context.GasLimit), 169 GasPrice: tx.GasPrice(), 170 } 171 statedb := tests.MakePreState(ethdb.NewMemDatabase(), test.Genesis.Alloc) 172 173 //创建跟踪程序、EVM环境并运行它 174 tracer, err := New("callTracer") 175 if err != nil { 176 t.Fatalf("failed to create call tracer: %v", err) 177 } 178 evm := vm.NewEVM(context, statedb, test.Genesis.Config, vm.Config{Debug: true, Tracer: tracer}) 179 180 msg, err := tx.AsMessage(signer) 181 if err != nil { 182 t.Fatalf("failed to prepare transaction for tracing: %v", err) 183 } 184 st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas())) 185 if _, _, _, err = st.TransitionDb(); err != nil { 186 t.Fatalf("failed to execute transaction: %v", err) 187 } 188 //检索跟踪结果并与标准具进行比较 189 res, err := tracer.GetResult() 190 if err != nil { 191 t.Fatalf("failed to retrieve trace result: %v", err) 192 } 193 ret := new(callTrace) 194 if err := json.Unmarshal(res, ret); err != nil { 195 t.Fatalf("failed to unmarshal trace result: %v", err) 196 } 197 if !reflect.DeepEqual(ret, test.Result) { 198 t.Fatalf("trace mismatch: have %+v, want %+v", ret, test.Result) 199 } 200 }) 201 } 202 }