Trace can be passed as an option to Validate. It causes a textual execution trace to be written to the given io.Writer.
(w io.Writer)
| 108 | // Trace can be passed as an option to Validate. It causes a textual |
| 109 | // execution trace to be written to the given io.Writer. |
| 110 | func Trace(w io.Writer) Option { |
| 111 | return Option{ |
| 112 | apply: func(vm *VM) { |
| 113 | var loglen int |
| 114 | lastRunstack := len(vm.runstack) |
| 115 | vm.beforeStep = append(vm.beforeStep, func(vm *VM) { |
| 116 | if len(vm.runstack) > lastRunstack { |
| 117 | fmt.Fprintf(w, "=> vm %d\n", len(vm.runstack)) |
| 118 | lastRunstack = len(vm.runstack) |
| 119 | } |
| 120 | var name string |
| 121 | switch { |
| 122 | case op.IsSmallIntOp(vm.opcode): |
| 123 | name = fmt.Sprintf("%d", vm.opcode-op.MinSmallInt) |
| 124 | case op.IsPushdataOp(vm.opcode): |
| 125 | name = fmt.Sprintf("pushdata%d", len(vm.data)) |
| 126 | default: |
| 127 | name = op.Name(vm.opcode) |
| 128 | } |
| 129 | fmt.Fprintf(w, "vm %d pc %d limit %d ", len(vm.runstack), vm.run.pc, vm.runlimit) |
| 130 | if vm.contract != nil { |
| 131 | fmt.Fprintf(w, "contract %x ", vm.contract.seed) |
| 132 | } |
| 133 | fmt.Fprintf(w, "%s (%02x)", name, vm.opcode) |
| 134 | if op.IsPushdataOp(vm.opcode) { |
| 135 | fmt.Fprintf(w, " %s", Bytes(vm.data)) |
| 136 | } |
| 137 | fmt.Fprint(w, "\n") |
| 138 | loglen = len(vm.Log) |
| 139 | }) |
| 140 | vm.afterStep = append(vm.afterStep, func(vm *VM) { |
| 141 | if vm.contract.stack.Len() > 0 { |
| 142 | fmt.Fprint(w, " con stack:\n") |
| 143 | for i := 0; i < len(vm.contract.stack); i++ { |
| 144 | fmt.Fprintf(w, " %d: %s\n", i, vm.contract.stack[len(vm.contract.stack)-1-i]) |
| 145 | } |
| 146 | } |
| 147 | if len(vm.argstack) > 0 { |
| 148 | fmt.Fprint(w, " arg stack:\n") |
| 149 | for i := 0; i < len(vm.argstack); i++ { |
| 150 | fmt.Fprintf(w, " %d: %s\n", i, vm.argstack[len(vm.argstack)-1-i]) |
| 151 | } |
| 152 | } |
| 153 | if len(vm.Log) > loglen { |
| 154 | fmt.Fprintf(w, " log:\n") |
| 155 | for i := 0; i < len(vm.Log); i++ { |
| 156 | fmt.Fprintf(w, " %d: %s\n", i, vm.Log[i]) |
| 157 | } |
| 158 | } |
| 159 | if len(vm.runstack) < lastRunstack { |
| 160 | fmt.Fprintf(w, "<= vm %d\n", lastRunstack) |
| 161 | lastRunstack = len(vm.runstack) |
| 162 | } |
| 163 | }) |
| 164 | }, |
| 165 | } |
| 166 | } |