Illustration of "Stack" elements not accurate
bitrocks opened this issue · 6 comments
I read your work, it's really great illustration of the EVM.
However, it's the call depth limited to 1024 other than the stack size. https://github.com/ethereum/wiki/wiki/Design-Rationale#virtual-machine.
So slide 49,50 are not accurate.
Thank you, I was confused about that too.
However, with yellow paper's specification and geth's implementation, the size of the data stack is also limited to 1024.
Perhaps the description of Design-Rationale#virtual-machine ('Not having a stack size limit') seems to be not accurate.
The yellowpaper and geth code are as follows:
yellowpaper : https://ethereum.github.io/yellowpaper/paper.pdf
9.1 Basic
The stack has a maximum size of 1024.
9.4.2. Exceptional Halting.
(136)
‖μs‖ - δw + αw > 1024
Geth implementation:
https://github.com/ethereum/go-ethereum/blob/master/core/vm/stack.go#L32
func newstack() *Stack {
return &Stack{data: make([]*big.Int, 0, 1024)}
}
https://github.com/ethereum/go-ethereum/blob/master/core/vm/stack.go#L40
func (st *Stack) push(d *big.Int) {
// NOTE push limit (1024) is checked in baseCheck
//stackItem := new(big.Int).Set(d)
//st.data = append(st.data, stackItem)
st.data = append(st.data, d)
}
Cheers
Inspired by you, I checked the git history of the file
https://github.com/ethereum/go-ethereum/blob/master/core/vm/stack.go
it surprises me that the 1024 limit is recently updated:
Besides, the append function can auto extend if the capacity is insufficient:
// The append built-in function appends elements to the end of a slice. If
// it has sufficient capacity, the destination is resliced to accommodate the
// new elements. If it does not, a new underlying array will be allocated.
// Append returns the updated slice. It is therefore necessary to store the
// result of append, often in the variable holding the slice itself:
// slice = append(slice, elem1, elem2)
// slice = append(slice, anotherSlice...)
// As a special case, it is legal to append a string to a byte slice, like this:
// slice = append([]byte("hello "), "world"...)
func append(slice []Type, elems ...Type) []Type
It seems still unsettled.
It is interesting. I also explored a little.
GO lang's append
is extended automatically, but EVM of Geth checks the stack size as follows:
https://github.com/ethereum/go-ethereum/blob/master/params/protocol_params.go#L56
StackLimit uint64 = 1024 // Maximum size of VM stack allowed.
https://github.com/ethereum/go-ethereum/blob/master/core/vm/stack_table.go#L31
func makeStackFunc(pop, push int) stackValidationFunc {
return func(stack *Stack) error {
if err := stack.require(pop); err != nil {
return err
}
if stack.len()+push-pop > int(params.StackLimit) {
return fmt.Errorf("stack limit reached %d (%d)", stack.len(), params.StackLimit)
}
return nil
}
}
I tried to find the so-called "baseCheck" part but failed. The evidence convinces me now. It's the design rationale outdated. The git history of the stack_table.go still shows the dev-team didn't add the limitation until 2017-1-5. But that's another story.
Thanks a lot :-)
hupengbuaa, thanks. I submitted issue to ethereum/wiki.
Closed this.