Skip to content

Commit 1bca2f6

Browse files
committed
Merge pull request #1256 from obscuren/fix-printable-chars
core/vm: fixed strange output for trace logging & error reporting
2 parents aaac1f0 + 287f990 commit 1bca2f6

File tree

5 files changed

+47
-52
lines changed

5 files changed

+47
-52
lines changed

core/block_processor.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,10 @@ func (sm *BlockProcessor) TransitionState(statedb *state.StateDB, parent, block
7171

7272
func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, statedb *state.StateDB, block *types.Block, tx *types.Transaction, usedGas *big.Int, transientProcess bool) (*types.Receipt, *big.Int, error) {
7373
// If we are mining this block and validating we want to set the logs back to 0
74-
//statedb.EmptyLogs()
7574

7675
cb := statedb.GetStateObject(coinbase.Address())
7776
_, gas, err := ApplyMessage(NewEnv(statedb, self.bc, tx, block), tx, cb)
7877
if err != nil && (IsNonceErr(err) || state.IsGasLimitErr(err) || IsInvalidTxErr(err)) {
79-
// If the account is managed, remove the invalid nonce.
80-
//from, _ := tx.From()
81-
//self.bc.TxState().RemoveNonce(from, tx.Nonce())
8278
return nil, nil, err
8379
}
8480

core/vm/environment.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ type StructLog struct {
4545
Memory []byte
4646
Stack []*big.Int
4747
Storage map[common.Hash][]byte
48+
Err error
4849
}
4950

5051
type Account interface {

core/vm/errors.go

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,14 @@ package vm
22

33
import (
44
"fmt"
5+
56
"github.com/ethereum/go-ethereum/params"
6-
"math/big"
77
)
88

9-
type OutOfGasError struct {
10-
req, has *big.Int
11-
}
12-
13-
func OOG(req, has *big.Int) OutOfGasError {
14-
return OutOfGasError{req, has}
15-
}
9+
type OutOfGasError struct{}
1610

1711
func (self OutOfGasError) Error() string {
18-
return fmt.Sprintf("out of gas! require %v, have %v", self.req, self.has)
12+
return "Out Of Gas"
1913
}
2014

2115
func IsOOGErr(err error) bool {

core/vm/logger.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,20 @@ package vm
33
import (
44
"fmt"
55
"os"
6-
"unicode/utf8"
6+
"unicode"
77

88
"github.com/ethereum/go-ethereum/common"
99
)
1010

1111
func StdErrFormat(logs []StructLog) {
12-
fmt.Fprintf(os.Stderr, "VM Stats %d ops\n", len(logs))
12+
fmt.Fprintf(os.Stderr, "VM STAT %d OPs\n", len(logs))
1313
for _, log := range logs {
14-
fmt.Fprintf(os.Stderr, "PC %08d: %s GAS: %v COST: %v\n", log.Pc, log.Op, log.Gas, log.GasCost)
14+
fmt.Fprintf(os.Stderr, "PC %08d: %s GAS: %v COST: %v", log.Pc, log.Op, log.Gas, log.GasCost)
15+
if log.Err != nil {
16+
fmt.Fprintf(os.Stderr, " ERROR: %v", log.Err)
17+
}
18+
fmt.Fprintf(os.Stderr, "\n")
19+
1520
fmt.Fprintln(os.Stderr, "STACK =", len(log.Stack))
1621

1722
for i := len(log.Stack) - 1; i >= 0; i-- {
@@ -27,7 +32,7 @@ func StdErrFormat(logs []StructLog) {
2732
for _, r := range data {
2833
if r == 0 {
2934
str += "."
30-
} else if utf8.ValidRune(rune(r)) {
35+
} else if unicode.IsPrint(rune(r)) {
3136
str += fmt.Sprintf("%s", string(r))
3237
} else {
3338
str += "?"

core/vm/vm.go

Lines changed: 34 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,31 @@ func (self *Vm) Run(context *Context, input []byte) (ret []byte, err error) {
4343
code = context.Code
4444
value = context.value
4545
price = context.Price
46+
47+
op OpCode // current opcode
48+
codehash = crypto.Sha3Hash(code) // codehash is used when doing jump dest caching
49+
mem = NewMemory() // bound memory
50+
stack = newstack() // local stack
51+
statedb = self.env.State() // current state
52+
// For optimisation reason we're using uint64 as the program counter.
53+
// It's theoretically possible to go above 2^64. The YP defines the PC to be uint256. Pratically much less so feasible.
54+
pc = uint64(0) // program counter
55+
56+
// jump evaluates and checks whether the given jump destination is a valid one
57+
// if valid move the `pc` otherwise return an error.
58+
jump = func(from uint64, to *big.Int) error {
59+
if !context.jumpdests.has(codehash, code, to) {
60+
nop := context.GetOp(to.Uint64())
61+
return fmt.Errorf("invalid jump destination (%v) %v", nop, to)
62+
}
63+
64+
pc = to.Uint64()
65+
66+
return nil
67+
}
68+
69+
newMemSize *big.Int
70+
cost *big.Int
4671
)
4772

4873
// User defer pattern to check for an error and, based on the error being nil or not, use all gas and return.
@@ -52,6 +77,7 @@ func (self *Vm) Run(context *Context, input []byte) (ret []byte, err error) {
5277
}
5378

5479
if err != nil {
80+
self.log(pc, op, context.Gas, cost, mem, stack, context, err)
5581

5682
// In case of a VM exception (known exceptions) all gas consumed (panics NOT included).
5783
context.UseGas(context.Gas)
@@ -71,30 +97,6 @@ func (self *Vm) Run(context *Context, input []byte) (ret []byte, err error) {
7197
return context.Return(nil), nil
7298
}
7399

74-
var (
75-
op OpCode // current opcode
76-
codehash = crypto.Sha3Hash(code) // codehash is used when doing jump dest caching
77-
mem = NewMemory() // bound memory
78-
stack = newstack() // local stack
79-
statedb = self.env.State() // current state
80-
// For optimisation reason we're using uint64 as the program counter.
81-
// It's theoretically possible to go above 2^64. The YP defines the PC to be uint256. Pratically much less so feasible.
82-
pc = uint64(0) // program counter
83-
84-
// jump evaluates and checks whether the given jump destination is a valid one
85-
// if valid move the `pc` otherwise return an error.
86-
jump = func(from uint64, to *big.Int) error {
87-
if !context.jumpdests.has(codehash, code, to) {
88-
nop := context.GetOp(to.Uint64())
89-
return fmt.Errorf("invalid jump destination (%v) %v", nop, to)
90-
}
91-
92-
pc = to.Uint64()
93-
94-
return nil
95-
}
96-
)
97-
98100
for {
99101
// The base for all big integer arithmetic
100102
base := new(big.Int)
@@ -103,24 +105,23 @@ func (self *Vm) Run(context *Context, input []byte) (ret []byte, err error) {
103105
op = context.GetOp(pc)
104106

105107
// calculate the new memory size and gas price for the current executing opcode
106-
newMemSize, gas, err := self.calculateGasAndSize(context, caller, op, statedb, mem, stack)
108+
newMemSize, cost, err = self.calculateGasAndSize(context, caller, op, statedb, mem, stack)
107109
if err != nil {
108110
return nil, err
109111
}
110112

111-
self.log(pc, op, context.Gas, gas, mem, stack, context)
112-
113113
// Use the calculated gas. When insufficient gas is present, use all gas and return an
114114
// Out Of Gas error
115-
if !context.UseGas(gas) {
116-
tmp := new(big.Int).Set(context.Gas)
115+
if !context.UseGas(cost) {
117116

118117
context.UseGas(context.Gas)
119118

120-
return context.Return(nil), OOG(gas, tmp)
119+
return context.Return(nil), OutOfGasError{}
121120
}
122121
// Resize the memory calculated previously
123122
mem.Resize(newMemSize.Uint64())
123+
// Add a log message
124+
self.log(pc, op, context.Gas, cost, mem, stack, context, nil)
124125

125126
switch op {
126127
case ADD:
@@ -783,15 +784,13 @@ func (self *Vm) RunPrecompiled(p *PrecompiledAccount, input []byte, context *Con
783784

784785
return context.Return(ret), nil
785786
} else {
786-
tmp := new(big.Int).Set(context.Gas)
787-
788-
return nil, OOG(gas, tmp)
787+
return nil, OutOfGasError{}
789788
}
790789
}
791790

792791
// log emits a log event to the environment for each opcode encountered. This is not to be confused with the
793792
// LOG* opcode.
794-
func (self *Vm) log(pc uint64, op OpCode, gas, cost *big.Int, memory *Memory, stack *stack, context *Context) {
793+
func (self *Vm) log(pc uint64, op OpCode, gas, cost *big.Int, memory *Memory, stack *stack, context *Context, err error) {
795794
if Debug {
796795
mem := make([]byte, len(memory.Data()))
797796
copy(mem, memory.Data())
@@ -804,7 +803,7 @@ func (self *Vm) log(pc uint64, op OpCode, gas, cost *big.Int, memory *Memory, st
804803
storage[common.BytesToHash(k)] = v
805804
})
806805

807-
self.env.AddStructLog(StructLog{pc, op, new(big.Int).Set(gas), cost, mem, stck, storage})
806+
self.env.AddStructLog(StructLog{pc, op, new(big.Int).Set(gas), cost, mem, stck, storage, err})
808807
}
809808
}
810809

0 commit comments

Comments
 (0)