From f954e6f2ca536751f60ee6820c329d9f7be5eccb Mon Sep 17 00:00:00 2001 From: BlockChainDev Date: Fri, 15 Mar 2019 22:33:32 +0000 Subject: [PATCH] Add Invocation stack - convenience RAS --- pkg/vm/stack/Int.go | 2 -- pkg/vm/stack/invocation.go | 53 ++++++++++++++++++++++++++++++++++++++ pkg/vm/stack/stack.go | 12 +++++++++ 3 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 pkg/vm/stack/invocation.go diff --git a/pkg/vm/stack/Int.go b/pkg/vm/stack/Int.go index 08ee41629..2483a78ea 100644 --- a/pkg/vm/stack/Int.go +++ b/pkg/vm/stack/Int.go @@ -11,8 +11,6 @@ type Int struct { // NewInt will convert a big integer into // a StackInteger func NewInt(val *big.Int) (*Int, error) { - // TOODO: check it is 32 bytes - return &Int{ abstractItem: &abstractItem{}, val: val, diff --git a/pkg/vm/stack/invocation.go b/pkg/vm/stack/invocation.go new file mode 100644 index 000000000..991e28231 --- /dev/null +++ b/pkg/vm/stack/invocation.go @@ -0,0 +1,53 @@ +package stack + +import "errors" + +// Invocation embeds a Random Access stack +// Providing helper methods for the context object +type Invocation struct{ RandomAccess } + +//NewInvocation will return a new +// Invocation stack +func NewInvocation() *Invocation { + return &Invocation{ + RandomAccess{ + vals: make([]Item, 0, StackAverageSize), + }, + } +} + +func (i *Invocation) peekContext(n uint16) (*Context, error) { + item, err := i.Peek(n) + if err != nil { + return nil, err + } + ctx, err := item.Context() + if err != nil { + return nil, err + } + return ctx, nil +} + +// CurrentContext returns the current context on the invocation stack +func (i *Invocation) CurrentContext() (*Context, error) { + return i.peekContext(0) +} + +// CallingContext will return the cntext item +// that will be called next. +func (i *Invocation) CallingContext() (*Context, error) { + if i.Len() < 1 { + return nil, errors.New("Length of invocation stack is < 1, no calling context") + } + return i.peekContext(1) +} + +// EntryContext will return the context item that +// started the program +func (i *Invocation) EntryContext() (*Context, error) { + + // firstItemIndex refers to the first item + // that was popped on the stack + firstItemIndex := uint16(i.Len() - 1) // N.B. if this overflows because len is zero, then an error will be returned + return i.peekContext(firstItemIndex) +} diff --git a/pkg/vm/stack/stack.go b/pkg/vm/stack/stack.go index 3c01ad4e7..a298897e4 100644 --- a/pkg/vm/stack/stack.go +++ b/pkg/vm/stack/stack.go @@ -119,3 +119,15 @@ func (ras *RandomAccess) Peek(n uint16) (Item, error) { return ras.vals[index], nil } + +// Convenience Functions + +// PopInt will remove the last stack item that was added +// And cast it to an integer +func (ras *RandomAccess) PopInt() (*Int, error) { + item, err := ras.Pop() + if err != nil { + return nil, err + } + return item.Integer() +}