Skip to content

[WIP] cmd/evm: prestate config and json trace fixes#14900

Closed
cdetrio wants to merge 2 commits into
ethereum:masterfrom
cdetrio:evm-receiver-prestate
Closed

[WIP] cmd/evm: prestate config and json trace fixes#14900
cdetrio wants to merge 2 commits into
ethereum:masterfrom
cdetrio:evm-receiver-prestate

Conversation

@cdetrio
Copy link
Copy Markdown
Member

@cdetrio cdetrio commented Aug 4, 2017

This is only half-done [WIP do not merge]. The evm command is probably broken if certain arguments aren't passed in (no default fallbacks yet).

This PR includes #14873.

Some of these changes add more support for configs given in a prestate (#14476). Others, like charging for intrinsic gas, are to reproduce the results of state tests. Those changes are mostly copy/pasted from state_test_util.go and state_transition.go.

Additionally there are changes to the json tracing. These are done to converge with the EVM traces that pyethereum produces, where it makes sense. For instance, a stackCopy variable was added to fix cases where the trace would print a mutated stack (the stack after the operation was applied), rather than printing the stack before the operation was applied.

Comment thread core/vm/interpreter.go
gasCopy = uint64(contract.Gas)
stackCopy = newstack()
for _, val := range stack.data {
stackCopy.push(val)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the intent here? The stackCopy will contain the same bigint objects as the original stack, so if any of those are modified (e.g. by being popped, added to intpool, and then reused), they will change also in the stackCopy.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know how the memory management works, but I tested it again to check. Changing it to:

if in.cfg.Debug {
  pcCopy = uint64(pc)
  gasCopy = uint64(contract.Gas)
  stackCopy = stack
}

reproduces the bug where the mutated stack is logged (from stBoundsTest/CALL_BoundsOOG.json):

{"pc":0,"op":96,"gas":"0x1f7e8","gasCost":"0x3","memory":"0x","memSize":0,"stack":[],"depth":1,"error":null,"opName":"PUSH1"}
{"pc":2,"op":96,"gas":"0x1f7e5","gasCost":"0x3","memory":"0x","memSize":0,"stack":["0x0"],"depth":1,"error":null,"opName":"PUSH1"}
{"pc":4,"op":96,"gas":"0x1f7e2","gasCost":"0x3","memory":"0x","memSize":0,"stack":["0x0","0x0"],"depth":1,"error":null,"opName":"PUSH1"}
{"pc":6,"op":96,"gas":"0x1f7df","gasCost":"0x3","memory":"0x","memSize":0,"stack":["0x0","0x0","0x0"],"depth":1,"error":null,"opName":"PUSH1"}
{"pc":8,"op":96,"gas":"0x1f7dc","gasCost":"0x3","memory":"0x","memSize":0,"stack":["0x0","0x0","0x0","0x0"],"depth":1,"error":null,"opName":"PUSH1"}
{"pc":10,"op":115,"gas":"0x1f7d9","gasCost":"0x3","memory":"0x","memSize":0,"stack":["0x0","0x0","0x0","0x0","0x0"],"depth":1,"error":null,"opName":"PUSH20"}
{"pc":31,"op":103,"gas":"0x1f7d6","gasCost":"0x3","memory":"0x","memSize":0,"stack":["0x0","0x0","0x0","0x0","0x0","0x1000000000000000000000000000000000000001"],"depth":1,"error":null,"opName":"PUSH8"}
{"pc":40,"op":241,"gas":"0x1f7d3","gasCost":"0x1efff","memory":"0x","memSize":0,"stack":["0x0","0x0","0x0","0x0","0x0","0x1000000000000000000000000000000000000001","0x1ed43"],"depth":1,"error":null,"opName":"CALL"}
{"pc":0,"op":96,"gas":"0x1ed43","gasCost":"0x3","memory":"0x","memSize":0,"stack":[],"depth":2,"error":null,"opName":"PUSH1"}

The 0x1ed43 gas argument to CALL is a mutated value (from the 63/64 rule).

Using stackCopy = newstack() and the for loop gives the correct (unmutated) value 0x7ffffffffffffff:

{"pc":31,"op":103,"gas":"0x1f7d6","gasCost":"0x3","memory":"0x","memSize":0,"stack":["0x0","0x0","0x0","0x0","0x0","0x1000000000000000000000000000000000000001"],"depth":1,"error":null,"opName":"PUSH8"}
{"pc":40,"op":241,"gas":"0x1f7d3","gasCost":"0x1efff","memory":"0x","memSize":0,"stack":["0x0","0x0","0x0","0x0","0x0","0x1000000000000000000000000000000000000001","0x7ffffffffffffff"],"depth":1,"error":null,"opName":"CALL"}
{"pc":0,"op":96,"gas":"0x1ed43","gasCost":"0x3","memory":"0x","memSize":0,"stack":[],"depth":2,"error":null,"opName":"PUSH1"}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, so apparently the 63/64-th handling does not operate on the actual bigint already on the stack, but places a new one there, so your fix works (even though it's a bit brittle).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Happens here:

stack.data[stack.len()-1] = new(big.Int).SetUint64(cg)

Comment thread core/vm/interpreter.go
op OpCode // current opcode
mem = NewMemory() // bound memory
stack = newstack() // local stack
stackCopy = newstack()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does stackCopy really need to exist in this scope? Can't it just be created on the fly when needed?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried removing this line and changing L151 to stackCopy := newstack(), but I get:

core/vm/interpreter.go:129: undefined: stackCopy
core/vm/interpreter.go:197: undefined: stackCopy

@cdetrio
Copy link
Copy Markdown
Member Author

cdetrio commented Aug 24, 2017

Replaced by #15035 and #15034

@cdetrio cdetrio closed this Aug 24, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants