vm: add IterBack to the Stack to iterate bottom-to-top

And use it to build user-facing stack representation because that's the order
that C# VM uses.
This commit is contained in:
Roman Khimov 2019-11-26 19:53:30 +03:00
parent f3ed91a1f7
commit 05f3329ec0
3 changed files with 43 additions and 5 deletions

View file

@ -35,7 +35,7 @@ func appendToItems(items *[]stackItem, val StackItem, seen map[StackItem]bool) {
func stackToArray(s *Stack) []stackItem {
items := make([]stackItem, 0, s.Len())
seen := make(map[StackItem]bool)
s.Iter(func(e *Element) {
s.IterBack(func(e *Element) {
appendToItems(&items, e.value, seen)
})
return items

View file

@ -360,6 +360,17 @@ func (s *Stack) Iter(f func(*Element)) {
}
}
// IterBack iterates over all the elements of the stack, starting from the bottom
// of the stack.
// s.IterBack(func(elem *Element) {
// // do something with the element.
// })
func (s *Stack) IterBack(f func(*Element)) {
for e := s.Back(); e != nil; e = e.Prev() {
f(e)
}
}
// popSigElements pops keys or signatures from the stack as needed for
// CHECKMULTISIG.
func (s *Stack) popSigElements() ([][]byte, error) {

View file

@ -154,19 +154,46 @@ func TestIterAfterRemove(t *testing.T) {
func TestIteration(t *testing.T) {
var (
n = 10
s = NewStack("test")
elems = makeElements(10)
elems = makeElements(n)
)
for _, elem := range elems {
s.Push(elem)
}
assert.Equal(t, len(elems), s.Len())
i := 0
iteratedElems := make([]*Element, 0)
s.Iter(func(elem *Element) {
i++
iteratedElems = append(iteratedElems, elem)
})
assert.Equal(t, len(elems), i)
// Top to bottom order of iteration.
poppedElems := make([]*Element, 0)
for elem := s.Pop(); elem != nil; elem = s.Pop() {
poppedElems = append(poppedElems, elem)
}
assert.Equal(t, poppedElems, iteratedElems)
}
func TestBackIteration(t *testing.T) {
var (
n = 10
s = NewStack("test")
elems = makeElements(n)
)
for _, elem := range elems {
s.Push(elem)
}
assert.Equal(t, len(elems), s.Len())
iteratedElems := make([]*Element, 0)
s.IterBack(func(elem *Element) {
iteratedElems = append(iteratedElems, elem)
})
// Bottom to the top order of iteration.
assert.Equal(t, elems, iteratedElems)
}
func TestPushVal(t *testing.T) {