txscript: Unexport Stack type.

This commit unexports the Stack type since it is only intended to be
used internally during script execution.  Further, the engine exposes
the {G,S}etStack and {G,S}etAltStack functions which return the items as
a slice of byte slices ([][]byte) for caller access while stepping.
This commit is contained in:
Dave Collins 2015-04-25 16:19:43 -05:00
parent ab2ed710cb
commit 7411e65b1e
3 changed files with 222 additions and 223 deletions

View file

@ -84,8 +84,8 @@ type Engine struct {
scriptIdx int scriptIdx int
scriptOff int scriptOff int
lastcodesep int lastcodesep int
dstack Stack // data stack dstack stack // data stack
astack Stack // alt stack astack stack // alt stack
tx wire.MsgTx tx wire.MsgTx
txIdx int txIdx int
condStack []int condStack []int
@ -444,7 +444,7 @@ func (vm *Engine) checkSignatureEncoding(sig []byte) error {
} }
// getStack returns the contents of stack as a byte array bottom up // getStack returns the contents of stack as a byte array bottom up
func getStack(stack *Stack) [][]byte { func getStack(stack *stack) [][]byte {
array := make([][]byte, stack.Depth()) array := make([][]byte, stack.Depth())
for i := range array { for i := range array {
// PeekByteArry can't fail due to overflow, already checked // PeekByteArry can't fail due to overflow, already checked
@ -455,7 +455,7 @@ func getStack(stack *Stack) [][]byte {
// setStack sets the stack to the contents of the array where the last item in // setStack sets the stack to the contents of the array where the last item in
// the array is the top item in the stack. // the array is the top item in the stack.
func setStack(stack *Stack, data [][]byte) { func setStack(stack *stack, data [][]byte) {
// This can not error. Only errors are for invalid arguments. // This can not error. Only errors are for invalid arguments.
_ = stack.DropN(stack.Depth()) _ = stack.DropN(stack.Depth())

View file

@ -96,17 +96,18 @@ func fromBool(v bool) []byte {
return []byte{0} return []byte{0}
} }
// Stack represents a stack of immutable objects to be used with bitcoin scripts // stack represents a stack of immutable objects to be used with bitcoin
// Objects may be shared, therefore in usage if a value is to be changed it // scripts. Objects may be shared, therefore in usage if a value is to be
// *must* be deep-copied first to avoid changing other values on the stack. // changed it *must* be deep-copied first to avoid changing other values on the
type Stack struct { // stack.
type stack struct {
stk [][]byte stk [][]byte
verifyMinimalData bool verifyMinimalData bool
} }
// checkMinimalData returns whether or not the passed byte array adheres to // checkMinimalData returns whether or not the passed byte array adheres to
// the minimal encoding requirements, if enabled. // the minimal encoding requirements, if enabled.
func (s *Stack) checkMinimalData(so []byte) error { func (s *stack) checkMinimalData(so []byte) error {
if !s.verifyMinimalData || len(so) == 0 { if !s.verifyMinimalData || len(so) == 0 {
return nil return nil
} }
@ -131,30 +132,30 @@ func (s *Stack) checkMinimalData(so []byte) error {
} }
// PushByteArray adds the given back array to the top of the stack. // PushByteArray adds the given back array to the top of the stack.
func (s *Stack) PushByteArray(so []byte) { func (s *stack) PushByteArray(so []byte) {
s.stk = append(s.stk, so) s.stk = append(s.stk, so)
} }
// PushInt converts the provided bignum to a suitable byte array then pushes // PushInt converts the provided bignum to a suitable byte array then pushes
// it onto the top of the stack. // it onto the top of the stack.
func (s *Stack) PushInt(val *big.Int) { func (s *stack) PushInt(val *big.Int) {
s.PushByteArray(fromInt(val)) s.PushByteArray(fromInt(val))
} }
// PushBool converts the provided boolean to a suitable byte array then pushes // PushBool converts the provided boolean to a suitable byte array then pushes
// it onto the top of the stack. // it onto the top of the stack.
func (s *Stack) PushBool(val bool) { func (s *stack) PushBool(val bool) {
s.PushByteArray(fromBool(val)) s.PushByteArray(fromBool(val))
} }
// PopByteArray pops the value off the top of the stack and returns it. // PopByteArray pops the value off the top of the stack and returns it.
func (s *Stack) PopByteArray() ([]byte, error) { func (s *stack) PopByteArray() ([]byte, error) {
return s.nipN(0) return s.nipN(0)
} }
// PopInt pops the value off the top of the stack, converts it into a bignum and // PopInt pops the value off the top of the stack, converts it into a bignum and
// returns it. // returns it.
func (s *Stack) PopInt() (*big.Int, error) { func (s *stack) PopInt() (*big.Int, error) {
so, err := s.PopByteArray() so, err := s.PopByteArray()
if err != nil { if err != nil {
return nil, err return nil, err
@ -169,7 +170,7 @@ func (s *Stack) PopInt() (*big.Int, error) {
// PopBool pops the value off the top of the stack, converts it into a bool and // PopBool pops the value off the top of the stack, converts it into a bool and
// returns it. // returns it.
func (s *Stack) PopBool() (bool, error) { func (s *stack) PopBool() (bool, error) {
so, err := s.PopByteArray() so, err := s.PopByteArray()
if err != nil { if err != nil {
return false, err return false, err
@ -178,7 +179,7 @@ func (s *Stack) PopBool() (bool, error) {
} }
// PeekByteArray returns the nth item on the stack without removing it. // PeekByteArray returns the nth item on the stack without removing it.
func (s *Stack) PeekByteArray(idx int) (so []byte, err error) { func (s *stack) PeekByteArray(idx int) (so []byte, err error) {
sz := len(s.stk) sz := len(s.stk)
if idx < 0 || idx >= sz { if idx < 0 || idx >= sz {
return nil, ErrStackUnderflow return nil, ErrStackUnderflow
@ -187,7 +188,7 @@ func (s *Stack) PeekByteArray(idx int) (so []byte, err error) {
} }
// PeekInt returns the nth item on the stack as a bignum without removing it. // PeekInt returns the nth item on the stack as a bignum without removing it.
func (s *Stack) PeekInt(idx int) (i *big.Int, err error) { func (s *stack) PeekInt(idx int) (i *big.Int, err error) {
so, err := s.PeekByteArray(idx) so, err := s.PeekByteArray(idx)
if err != nil { if err != nil {
return nil, err return nil, err
@ -201,7 +202,7 @@ func (s *Stack) PeekInt(idx int) (i *big.Int, err error) {
} }
// PeekBool returns the nth item on the stack as a bool without removing it. // PeekBool returns the nth item on the stack as a bool without removing it.
func (s *Stack) PeekBool(idx int) (i bool, err error) { func (s *stack) PeekBool(idx int) (i bool, err error) {
so, err := s.PeekByteArray(idx) so, err := s.PeekByteArray(idx)
if err != nil { if err != nil {
return false, err return false, err
@ -211,7 +212,7 @@ func (s *Stack) PeekBool(idx int) (i bool, err error) {
// nipN is an internal function that removes the nth item on the stack and // nipN is an internal function that removes the nth item on the stack and
// returns it. // returns it.
func (s *Stack) nipN(idx int) (so []byte, err error) { func (s *stack) nipN(idx int) (so []byte, err error) {
sz := len(s.stk) sz := len(s.stk)
if idx < 0 || idx > sz-1 { if idx < 0 || idx > sz-1 {
err = ErrStackUnderflow err = ErrStackUnderflow
@ -233,14 +234,14 @@ func (s *Stack) nipN(idx int) (so []byte, err error) {
} }
// NipN removes the Nth object on the stack // NipN removes the Nth object on the stack
func (s *Stack) NipN(idx int) error { func (s *stack) NipN(idx int) error {
_, err := s.nipN(idx) _, err := s.nipN(idx)
return err return err
} }
// Tuck copies the item at the top of the stack and inserts it before the 2nd // Tuck copies the item at the top of the stack and inserts it before the 2nd
// to top item. e.g.: 2,1 -> 2,1,2 // to top item. e.g.: 2,1 -> 2,1,2
func (s *Stack) Tuck() error { func (s *stack) Tuck() error {
so2, err := s.PopByteArray() so2, err := s.PopByteArray()
if err != nil { if err != nil {
return err return err
@ -257,7 +258,7 @@ func (s *Stack) Tuck() error {
} }
// Depth returns the number of items on the stack. // Depth returns the number of items on the stack.
func (s *Stack) Depth() (sz int) { func (s *stack) Depth() (sz int) {
sz = len(s.stk) sz = len(s.stk)
return return
} }
@ -266,7 +267,7 @@ func (s *Stack) Depth() (sz int) {
// e.g. // e.g.
// DropN(1): 1,2,3 -> 1,2 // DropN(1): 1,2,3 -> 1,2
// DropN(2): 1,2,3 -> 1 // DropN(2): 1,2,3 -> 1
func (s *Stack) DropN(n int) error { func (s *stack) DropN(n int) error {
if n < 1 { if n < 1 {
return ErrStackInvalidArgs return ErrStackInvalidArgs
} }
@ -283,7 +284,7 @@ func (s *Stack) DropN(n int) error {
// e.g. // e.g.
// DupN(1): 1,2,3 -> 1,2,3,3 // DupN(1): 1,2,3 -> 1,2,3,3
// DupN(2): 1,2,3 -> 1,2,3,2,3 // DupN(2): 1,2,3 -> 1,2,3,2,3
func (s *Stack) DupN(n int) error { func (s *stack) DupN(n int) error {
if n < 1 { if n < 1 {
return ErrStackInvalidArgs return ErrStackInvalidArgs
} }
@ -303,7 +304,7 @@ func (s *Stack) DupN(n int) error {
// RotN rotates the top 3N items on the stack to the left // RotN rotates the top 3N items on the stack to the left
// e.g. // e.g.
// RotN(1): 1,2,3 -> 2,3,1 // RotN(1): 1,2,3 -> 2,3,1
func (s *Stack) RotN(n int) error { func (s *stack) RotN(n int) error {
if n < 1 { if n < 1 {
return ErrStackInvalidArgs return ErrStackInvalidArgs
} }
@ -325,7 +326,7 @@ func (s *Stack) RotN(n int) error {
// E.g.: // E.g.:
// SwapN(1): 1,2 -> 2,1 // SwapN(1): 1,2 -> 2,1
// SwapN(2): 1,2,3,4 -> 3,4,1,2 // SwapN(2): 1,2,3,4 -> 3,4,1,2
func (s *Stack) SwapN(n int) error { func (s *stack) SwapN(n int) error {
if n < 1 { if n < 1 {
return ErrStackInvalidArgs return ErrStackInvalidArgs
} }
@ -346,7 +347,7 @@ func (s *Stack) SwapN(n int) error {
// e.g.: // e.g.:
// OverN(1): 1,2 -> 1,2,1 // OverN(1): 1,2 -> 1,2,1
// OverN(2): 1,2,3,4 -> 1,2,3,4,1,2 // OverN(2): 1,2,3,4 -> 1,2,3,4,1,2
func (s *Stack) OverN(n int) error { func (s *stack) OverN(n int) error {
if n < 1 { if n < 1 {
return ErrStackInvalidArgs return ErrStackInvalidArgs
} }
@ -368,7 +369,7 @@ func (s *Stack) OverN(n int) error {
// e.g.: // e.g.:
// PickN(1): 1,2,3 -> 1,2,3,2 // PickN(1): 1,2,3 -> 1,2,3,2
// PickN(2): 1,2,3 -> 1,2,3,1 // PickN(2): 1,2,3 -> 1,2,3,1
func (s *Stack) PickN(n int) error { func (s *stack) PickN(n int) error {
so, err := s.PeekByteArray(n) so, err := s.PeekByteArray(n)
if err != nil { if err != nil {
return err return err
@ -383,7 +384,7 @@ func (s *Stack) PickN(n int) error {
// e.g.: // e.g.:
// RollN(1): 1,2,3 -> 1,3,2 // RollN(1): 1,2,3 -> 1,3,2
// RollN(2): 1,2,3 -> 2,3,1 // RollN(2): 1,2,3 -> 2,3,1
func (s *Stack) RollN(n int) error { func (s *stack) RollN(n int) error {
so, err := s.nipN(n) so, err := s.nipN(n)
if err != nil { if err != nil {
return err return err
@ -395,7 +396,7 @@ func (s *Stack) RollN(n int) error {
} }
// String returns the stack in a readable format. // String returns the stack in a readable format.
func (s *Stack) String() string { func (s *stack) String() string {
var result string var result string
for _, stack := range s.stk { for _, stack := range s.stk {

View file

@ -2,7 +2,7 @@
// Use of this source code is governed by an ISC // Use of this source code is governed by an ISC
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package txscript_test package txscript
import ( import (
"bytes" "bytes"
@ -10,8 +10,6 @@ import (
"fmt" "fmt"
"math/big" "math/big"
"testing" "testing"
"github.com/btcsuite/btcd/txscript"
) )
// TestStack tests that all of the stack operations work as expected. // TestStack tests that all of the stack operations work as expected.
@ -21,14 +19,14 @@ func TestStack(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
before [][]byte before [][]byte
operation func(*txscript.Stack) error operation func(*stack) error
expectedReturn error expectedReturn error
after [][]byte after [][]byte
}{ }{
{ {
"noop", "noop",
[][]byte{{1}, {2}, {3}, {4}, {5}}, [][]byte{{1}, {2}, {3}, {4}, {5}},
func(stack *txscript.Stack) error { func(s *stack) error {
return nil return nil
}, },
nil, nil,
@ -37,43 +35,43 @@ func TestStack(t *testing.T) {
{ {
"peek underflow (byte)", "peek underflow (byte)",
[][]byte{{1}, {2}, {3}, {4}, {5}}, [][]byte{{1}, {2}, {3}, {4}, {5}},
func(stack *txscript.Stack) error { func(s *stack) error {
_, err := stack.PeekByteArray(5) _, err := s.PeekByteArray(5)
return err return err
}, },
txscript.ErrStackUnderflow, ErrStackUnderflow,
[][]byte{}, [][]byte{},
}, },
{ {
"peek underflow (int)", "peek underflow (int)",
[][]byte{{1}, {2}, {3}, {4}, {5}}, [][]byte{{1}, {2}, {3}, {4}, {5}},
func(stack *txscript.Stack) error { func(s *stack) error {
_, err := stack.PeekInt(5) _, err := s.PeekInt(5)
return err return err
}, },
txscript.ErrStackUnderflow, ErrStackUnderflow,
[][]byte{}, [][]byte{},
}, },
{ {
"peek underflow (bool)", "peek underflow (bool)",
[][]byte{{1}, {2}, {3}, {4}, {5}}, [][]byte{{1}, {2}, {3}, {4}, {5}},
func(stack *txscript.Stack) error { func(s *stack) error {
_, err := stack.PeekBool(5) _, err := s.PeekBool(5)
return err return err
}, },
txscript.ErrStackUnderflow, ErrStackUnderflow,
[][]byte{}, [][]byte{},
}, },
{ {
"pop", "pop",
[][]byte{{1}, {2}, {3}, {4}, {5}}, [][]byte{{1}, {2}, {3}, {4}, {5}},
func(stack *txscript.Stack) error { func(s *stack) error {
val, err := stack.PopByteArray() val, err := s.PopByteArray()
if err != nil { if err != nil {
return err return err
} }
if !bytes.Equal(val, []byte{5}) { if !bytes.Equal(val, []byte{5}) {
return errors.New("not equal!") return errors.New("not equal")
} }
return err return err
}, },
@ -83,13 +81,13 @@ func TestStack(t *testing.T) {
{ {
"pop", "pop",
[][]byte{{1}, {2}, {3}, {4}, {5}}, [][]byte{{1}, {2}, {3}, {4}, {5}},
func(stack *txscript.Stack) error { func(s *stack) error {
val, err := stack.PopByteArray() val, err := s.PopByteArray()
if err != nil { if err != nil {
return err return err
} }
if !bytes.Equal(val, []byte{5}) { if !bytes.Equal(val, []byte{5}) {
return errors.New("not equal!") return errors.New("not equal")
} }
return err return err
}, },
@ -99,9 +97,9 @@ func TestStack(t *testing.T) {
{ {
"pop everything", "pop everything",
[][]byte{{1}, {2}, {3}, {4}, {5}}, [][]byte{{1}, {2}, {3}, {4}, {5}},
func(stack *txscript.Stack) error { func(s *stack) error {
for i := 0; i < 5; i++ { for i := 0; i < 5; i++ {
_, err := stack.PopByteArray() _, err := s.PopByteArray()
if err != nil { if err != nil {
return err return err
} }
@ -114,23 +112,23 @@ func TestStack(t *testing.T) {
{ {
"pop underflow", "pop underflow",
[][]byte{{1}, {2}, {3}, {4}, {5}}, [][]byte{{1}, {2}, {3}, {4}, {5}},
func(stack *txscript.Stack) error { func(s *stack) error {
for i := 0; i < 6; i++ { for i := 0; i < 6; i++ {
_, err := stack.PopByteArray() _, err := s.PopByteArray()
if err != nil { if err != nil {
return err return err
} }
} }
return nil return nil
}, },
txscript.ErrStackUnderflow, ErrStackUnderflow,
[][]byte{}, [][]byte{},
}, },
{ {
"pop bool", "pop bool",
[][]byte{{0}}, [][]byte{{0}},
func(stack *txscript.Stack) error { func(s *stack) error {
val, err := stack.PopBool() val, err := s.PopBool()
if err != nil { if err != nil {
return err return err
} }
@ -146,8 +144,8 @@ func TestStack(t *testing.T) {
{ {
"pop bool", "pop bool",
[][]byte{{1}}, [][]byte{{1}},
func(stack *txscript.Stack) error { func(s *stack) error {
val, err := stack.PopBool() val, err := s.PopBool()
if err != nil { if err != nil {
return err return err
} }
@ -163,22 +161,22 @@ func TestStack(t *testing.T) {
{ {
"pop bool", "pop bool",
[][]byte{}, [][]byte{},
func(stack *txscript.Stack) error { func(s *stack) error {
_, err := stack.PopBool() _, err := s.PopBool()
if err != nil { if err != nil {
return err return err
} }
return nil return nil
}, },
txscript.ErrStackUnderflow, ErrStackUnderflow,
[][]byte{}, [][]byte{},
}, },
{ {
"popInt 0", "popInt 0",
[][]byte{{0x0}}, [][]byte{{0x0}},
func(stack *txscript.Stack) error { func(s *stack) error {
v, err := stack.PopInt() v, err := s.PopInt()
if err != nil { if err != nil {
return err return err
} }
@ -193,8 +191,8 @@ func TestStack(t *testing.T) {
{ {
"popInt -0", "popInt -0",
[][]byte{{0x80}}, [][]byte{{0x80}},
func(stack *txscript.Stack) error { func(s *stack) error {
v, err := stack.PopInt() v, err := s.PopInt()
if err != nil { if err != nil {
return err return err
} }
@ -209,8 +207,8 @@ func TestStack(t *testing.T) {
{ {
"popInt 1", "popInt 1",
[][]byte{{0x01}}, [][]byte{{0x01}},
func(stack *txscript.Stack) error { func(s *stack) error {
v, err := stack.PopInt() v, err := s.PopInt()
if err != nil { if err != nil {
return err return err
} }
@ -225,8 +223,8 @@ func TestStack(t *testing.T) {
{ {
"popInt 1 leading 0", "popInt 1 leading 0",
[][]byte{{0x01, 0x00, 0x00, 0x00}}, [][]byte{{0x01, 0x00, 0x00, 0x00}},
func(stack *txscript.Stack) error { func(s *stack) error {
v, err := stack.PopInt() v, err := s.PopInt()
if err != nil { if err != nil {
return err return err
} }
@ -242,8 +240,8 @@ func TestStack(t *testing.T) {
{ {
"popInt -1", "popInt -1",
[][]byte{{0x81}}, [][]byte{{0x81}},
func(stack *txscript.Stack) error { func(s *stack) error {
v, err := stack.PopInt() v, err := s.PopInt()
if err != nil { if err != nil {
return err return err
} }
@ -258,8 +256,8 @@ func TestStack(t *testing.T) {
{ {
"popInt -1 leading 0", "popInt -1 leading 0",
[][]byte{{0x01, 0x00, 0x00, 0x80}}, [][]byte{{0x01, 0x00, 0x00, 0x80}},
func(stack *txscript.Stack) error { func(s *stack) error {
v, err := stack.PopInt() v, err := s.PopInt()
if err != nil { if err != nil {
return err return err
} }
@ -276,8 +274,8 @@ func TestStack(t *testing.T) {
{ {
"popInt -513", "popInt -513",
[][]byte{{0x1, 0x82}}, [][]byte{{0x1, 0x82}},
func(stack *txscript.Stack) error { func(s *stack) error {
v, err := stack.PopInt() v, err := s.PopInt()
if err != nil { if err != nil {
return err return err
} }
@ -294,8 +292,8 @@ func TestStack(t *testing.T) {
{ {
"peekint nomodify -1", "peekint nomodify -1",
[][]byte{{0x01, 0x00, 0x00, 0x80}}, [][]byte{{0x01, 0x00, 0x00, 0x80}},
func(stack *txscript.Stack) error { func(s *stack) error {
v, err := stack.PeekInt(0) v, err := s.PeekInt(0)
if err != nil { if err != nil {
return err return err
} }
@ -311,8 +309,8 @@ func TestStack(t *testing.T) {
{ {
"PushInt 0", "PushInt 0",
[][]byte{}, [][]byte{},
func(stack *txscript.Stack) error { func(s *stack) error {
stack.PushInt(big.NewInt(0)) s.PushInt(big.NewInt(0))
return nil return nil
}, },
nil, nil,
@ -321,8 +319,8 @@ func TestStack(t *testing.T) {
{ {
"PushInt 1", "PushInt 1",
[][]byte{}, [][]byte{},
func(stack *txscript.Stack) error { func(s *stack) error {
stack.PushInt(big.NewInt(1)) s.PushInt(big.NewInt(1))
return nil return nil
}, },
nil, nil,
@ -331,8 +329,8 @@ func TestStack(t *testing.T) {
{ {
"PushInt -1", "PushInt -1",
[][]byte{}, [][]byte{},
func(stack *txscript.Stack) error { func(s *stack) error {
stack.PushInt(big.NewInt(-1)) s.PushInt(big.NewInt(-1))
return nil return nil
}, },
nil, nil,
@ -341,8 +339,8 @@ func TestStack(t *testing.T) {
{ {
"PushInt two bytes", "PushInt two bytes",
[][]byte{}, [][]byte{},
func(stack *txscript.Stack) error { func(s *stack) error {
stack.PushInt(big.NewInt(256)) s.PushInt(big.NewInt(256))
return nil return nil
}, },
nil, nil,
@ -352,9 +350,9 @@ func TestStack(t *testing.T) {
{ {
"PushInt leading zeros", "PushInt leading zeros",
[][]byte{}, [][]byte{},
func(stack *txscript.Stack) error { func(s *stack) error {
// this will have the highbit set // this will have the highbit set
stack.PushInt(big.NewInt(128)) s.PushInt(big.NewInt(128))
return nil return nil
}, },
nil, nil,
@ -363,8 +361,8 @@ func TestStack(t *testing.T) {
{ {
"dup", "dup",
[][]byte{{1}}, [][]byte{{1}},
func(stack *txscript.Stack) error { func(s *stack) error {
err := stack.DupN(1) err := s.DupN(1)
if err != nil { if err != nil {
return err return err
} }
@ -377,8 +375,8 @@ func TestStack(t *testing.T) {
{ {
"dup2", "dup2",
[][]byte{{1}, {2}}, [][]byte{{1}, {2}},
func(stack *txscript.Stack) error { func(s *stack) error {
err := stack.DupN(2) err := s.DupN(2)
if err != nil { if err != nil {
return err return err
} }
@ -391,8 +389,8 @@ func TestStack(t *testing.T) {
{ {
"dup3", "dup3",
[][]byte{{1}, {2}, {3}}, [][]byte{{1}, {2}, {3}},
func(stack *txscript.Stack) error { func(s *stack) error {
err := stack.DupN(3) err := s.DupN(3)
if err != nil { if err != nil {
return err return err
} }
@ -405,64 +403,64 @@ func TestStack(t *testing.T) {
{ {
"dup0", "dup0",
[][]byte{{1}}, [][]byte{{1}},
func(stack *txscript.Stack) error { func(s *stack) error {
err := stack.DupN(0) err := s.DupN(0)
if err != nil { if err != nil {
return err return err
} }
return nil return nil
}, },
txscript.ErrStackInvalidArgs, ErrStackInvalidArgs,
[][]byte{}, [][]byte{},
}, },
{ {
"dup-1", "dup-1",
[][]byte{{1}}, [][]byte{{1}},
func(stack *txscript.Stack) error { func(s *stack) error {
err := stack.DupN(-1) err := s.DupN(-1)
if err != nil { if err != nil {
return err return err
} }
return nil return nil
}, },
txscript.ErrStackInvalidArgs, ErrStackInvalidArgs,
[][]byte{}, [][]byte{},
}, },
{ {
"dup too much", "dup too much",
[][]byte{{1}}, [][]byte{{1}},
func(stack *txscript.Stack) error { func(s *stack) error {
err := stack.DupN(2) err := s.DupN(2)
if err != nil { if err != nil {
return err return err
} }
return nil return nil
}, },
txscript.ErrStackUnderflow, ErrStackUnderflow,
[][]byte{}, [][]byte{},
}, },
{ {
"dup-1", "dup-1",
[][]byte{{1}}, [][]byte{{1}},
func(stack *txscript.Stack) error { func(s *stack) error {
err := stack.DupN(-1) err := s.DupN(-1)
if err != nil { if err != nil {
return err return err
} }
return nil return nil
}, },
txscript.ErrStackInvalidArgs, ErrStackInvalidArgs,
[][]byte{}, [][]byte{},
}, },
{ {
"PushBool true", "PushBool true",
[][]byte{}, [][]byte{},
func(stack *txscript.Stack) error { func(s *stack) error {
stack.PushBool(true) s.PushBool(true)
return nil return nil
}, },
@ -472,8 +470,8 @@ func TestStack(t *testing.T) {
{ {
"PushBool false", "PushBool false",
[][]byte{}, [][]byte{},
func(stack *txscript.Stack) error { func(s *stack) error {
stack.PushBool(false) s.PushBool(false)
return nil return nil
}, },
@ -483,9 +481,9 @@ func TestStack(t *testing.T) {
{ {
"PushBool PopBool", "PushBool PopBool",
[][]byte{}, [][]byte{},
func(stack *txscript.Stack) error { func(s *stack) error {
stack.PushBool(true) s.PushBool(true)
val, err := stack.PopBool() val, err := s.PopBool()
if err != nil { if err != nil {
return err return err
} }
@ -501,9 +499,9 @@ func TestStack(t *testing.T) {
{ {
"PushBool PopBool 2", "PushBool PopBool 2",
[][]byte{}, [][]byte{},
func(stack *txscript.Stack) error { func(s *stack) error {
stack.PushBool(false) s.PushBool(false)
val, err := stack.PopBool() val, err := s.PopBool()
if err != nil { if err != nil {
return err return err
} }
@ -519,9 +517,9 @@ func TestStack(t *testing.T) {
{ {
"PushInt PopBool", "PushInt PopBool",
[][]byte{}, [][]byte{},
func(stack *txscript.Stack) error { func(s *stack) error {
stack.PushInt(big.NewInt(1)) s.PushInt(big.NewInt(1))
val, err := stack.PopBool() val, err := s.PopBool()
if err != nil { if err != nil {
return err return err
} }
@ -537,9 +535,9 @@ func TestStack(t *testing.T) {
{ {
"PushInt PopBool 2", "PushInt PopBool 2",
[][]byte{}, [][]byte{},
func(stack *txscript.Stack) error { func(s *stack) error {
stack.PushInt(big.NewInt(0)) s.PushInt(big.NewInt(0))
val, err := stack.PopBool() val, err := s.PopBool()
if err != nil { if err != nil {
return err return err
} }
@ -555,9 +553,9 @@ func TestStack(t *testing.T) {
{ {
"PushInt PopBool 2", "PushInt PopBool 2",
[][]byte{}, [][]byte{},
func(stack *txscript.Stack) error { func(s *stack) error {
stack.PushInt(big.NewInt(0)) s.PushInt(big.NewInt(0))
val, err := stack.PopBool() val, err := s.PopBool()
if err != nil { if err != nil {
return err return err
} }
@ -573,8 +571,8 @@ func TestStack(t *testing.T) {
{ {
"Nip top", "Nip top",
[][]byte{{1}, {2}, {3}}, [][]byte{{1}, {2}, {3}},
func(stack *txscript.Stack) error { func(s *stack) error {
return stack.NipN(0) return s.NipN(0)
}, },
nil, nil,
[][]byte{{1}, {2}}, [][]byte{{1}, {2}},
@ -582,8 +580,8 @@ func TestStack(t *testing.T) {
{ {
"Nip middle", "Nip middle",
[][]byte{{1}, {2}, {3}}, [][]byte{{1}, {2}, {3}},
func(stack *txscript.Stack) error { func(s *stack) error {
return stack.NipN(1) return s.NipN(1)
}, },
nil, nil,
[][]byte{{1}, {3}}, [][]byte{{1}, {3}},
@ -591,8 +589,8 @@ func TestStack(t *testing.T) {
{ {
"Nip low", "Nip low",
[][]byte{{1}, {2}, {3}}, [][]byte{{1}, {2}, {3}},
func(stack *txscript.Stack) error { func(s *stack) error {
return stack.NipN(2) return s.NipN(2)
}, },
nil, nil,
[][]byte{{2}, {3}}, [][]byte{{2}, {3}},
@ -600,28 +598,28 @@ func TestStack(t *testing.T) {
{ {
"Nip too much", "Nip too much",
[][]byte{{1}, {2}, {3}}, [][]byte{{1}, {2}, {3}},
func(stack *txscript.Stack) error { func(s *stack) error {
// bite off more than we can chew // bite off more than we can chew
return stack.NipN(3) return s.NipN(3)
}, },
txscript.ErrStackUnderflow, ErrStackUnderflow,
[][]byte{{2}, {3}}, [][]byte{{2}, {3}},
}, },
{ {
"Nip too much", "Nip too much",
[][]byte{{1}, {2}, {3}}, [][]byte{{1}, {2}, {3}},
func(stack *txscript.Stack) error { func(s *stack) error {
// bite off more than we can chew // bite off more than we can chew
return stack.NipN(3) return s.NipN(3)
}, },
txscript.ErrStackUnderflow, ErrStackUnderflow,
[][]byte{{2}, {3}}, [][]byte{{2}, {3}},
}, },
{ {
"keep on tucking", "keep on tucking",
[][]byte{{1}, {2}, {3}}, [][]byte{{1}, {2}, {3}},
func(stack *txscript.Stack) error { func(s *stack) error {
return stack.Tuck() return s.Tuck()
}, },
nil, nil,
[][]byte{{1}, {3}, {2}, {3}}, [][]byte{{1}, {3}, {2}, {3}},
@ -629,26 +627,26 @@ func TestStack(t *testing.T) {
{ {
"a little tucked up", "a little tucked up",
[][]byte{{1}}, // too few arguments for tuck [][]byte{{1}}, // too few arguments for tuck
func(stack *txscript.Stack) error { func(s *stack) error {
return stack.Tuck() return s.Tuck()
}, },
txscript.ErrStackUnderflow, ErrStackUnderflow,
[][]byte{}, [][]byte{},
}, },
{ {
"all tucked up", "all tucked up",
[][]byte{}, // too few arguments for tuck [][]byte{}, // too few arguments for tuck
func(stack *txscript.Stack) error { func(s *stack) error {
return stack.Tuck() return s.Tuck()
}, },
txscript.ErrStackUnderflow, ErrStackUnderflow,
[][]byte{}, [][]byte{},
}, },
{ {
"drop 1", "drop 1",
[][]byte{{1}, {2}, {3}, {4}}, [][]byte{{1}, {2}, {3}, {4}},
func(stack *txscript.Stack) error { func(s *stack) error {
return stack.DropN(1) return s.DropN(1)
}, },
nil, nil,
[][]byte{{1}, {2}, {3}}, [][]byte{{1}, {2}, {3}},
@ -656,8 +654,8 @@ func TestStack(t *testing.T) {
{ {
"drop 2", "drop 2",
[][]byte{{1}, {2}, {3}, {4}}, [][]byte{{1}, {2}, {3}, {4}},
func(stack *txscript.Stack) error { func(s *stack) error {
return stack.DropN(2) return s.DropN(2)
}, },
nil, nil,
[][]byte{{1}, {2}}, [][]byte{{1}, {2}},
@ -665,8 +663,8 @@ func TestStack(t *testing.T) {
{ {
"drop 3", "drop 3",
[][]byte{{1}, {2}, {3}, {4}}, [][]byte{{1}, {2}, {3}, {4}},
func(stack *txscript.Stack) error { func(s *stack) error {
return stack.DropN(3) return s.DropN(3)
}, },
nil, nil,
[][]byte{{1}}, [][]byte{{1}},
@ -674,8 +672,8 @@ func TestStack(t *testing.T) {
{ {
"drop 4", "drop 4",
[][]byte{{1}, {2}, {3}, {4}}, [][]byte{{1}, {2}, {3}, {4}},
func(stack *txscript.Stack) error { func(s *stack) error {
return stack.DropN(4) return s.DropN(4)
}, },
nil, nil,
[][]byte{}, [][]byte{},
@ -683,26 +681,26 @@ func TestStack(t *testing.T) {
{ {
"drop 4/5", "drop 4/5",
[][]byte{{1}, {2}, {3}, {4}}, [][]byte{{1}, {2}, {3}, {4}},
func(stack *txscript.Stack) error { func(s *stack) error {
return stack.DropN(5) return s.DropN(5)
}, },
txscript.ErrStackUnderflow, ErrStackUnderflow,
[][]byte{}, [][]byte{},
}, },
{ {
"drop invalid", "drop invalid",
[][]byte{{1}, {2}, {3}, {4}}, [][]byte{{1}, {2}, {3}, {4}},
func(stack *txscript.Stack) error { func(s *stack) error {
return stack.DropN(0) return s.DropN(0)
}, },
txscript.ErrStackInvalidArgs, ErrStackInvalidArgs,
[][]byte{}, [][]byte{},
}, },
{ {
"Rot1", "Rot1",
[][]byte{{1}, {2}, {3}, {4}}, [][]byte{{1}, {2}, {3}, {4}},
func(stack *txscript.Stack) error { func(s *stack) error {
return stack.RotN(1) return s.RotN(1)
}, },
nil, nil,
[][]byte{{1}, {3}, {4}, {2}}, [][]byte{{1}, {3}, {4}, {2}},
@ -710,8 +708,8 @@ func TestStack(t *testing.T) {
{ {
"Rot2", "Rot2",
[][]byte{{1}, {2}, {3}, {4}, {5}, {6}}, [][]byte{{1}, {2}, {3}, {4}, {5}, {6}},
func(stack *txscript.Stack) error { func(s *stack) error {
return stack.RotN(2) return s.RotN(2)
}, },
nil, nil,
[][]byte{{3}, {4}, {5}, {6}, {1}, {2}}, [][]byte{{3}, {4}, {5}, {6}, {1}, {2}},
@ -719,26 +717,26 @@ func TestStack(t *testing.T) {
{ {
"Rot too little", "Rot too little",
[][]byte{{1}, {2}}, [][]byte{{1}, {2}},
func(stack *txscript.Stack) error { func(s *stack) error {
return stack.RotN(1) return s.RotN(1)
}, },
txscript.ErrStackUnderflow, ErrStackUnderflow,
[][]byte{}, [][]byte{},
}, },
{ {
"Rot0", "Rot0",
[][]byte{{1}, {2}, {3}}, [][]byte{{1}, {2}, {3}},
func(stack *txscript.Stack) error { func(s *stack) error {
return stack.RotN(0) return s.RotN(0)
}, },
txscript.ErrStackInvalidArgs, ErrStackInvalidArgs,
[][]byte{}, [][]byte{},
}, },
{ {
"Swap1", "Swap1",
[][]byte{{1}, {2}, {3}, {4}}, [][]byte{{1}, {2}, {3}, {4}},
func(stack *txscript.Stack) error { func(s *stack) error {
return stack.SwapN(1) return s.SwapN(1)
}, },
nil, nil,
[][]byte{{1}, {2}, {4}, {3}}, [][]byte{{1}, {2}, {4}, {3}},
@ -746,8 +744,8 @@ func TestStack(t *testing.T) {
{ {
"Swap2", "Swap2",
[][]byte{{1}, {2}, {3}, {4}}, [][]byte{{1}, {2}, {3}, {4}},
func(stack *txscript.Stack) error { func(s *stack) error {
return stack.SwapN(2) return s.SwapN(2)
}, },
nil, nil,
[][]byte{{3}, {4}, {1}, {2}}, [][]byte{{3}, {4}, {1}, {2}},
@ -755,26 +753,26 @@ func TestStack(t *testing.T) {
{ {
"Swap too little", "Swap too little",
[][]byte{{1}}, [][]byte{{1}},
func(stack *txscript.Stack) error { func(s *stack) error {
return stack.SwapN(1) return s.SwapN(1)
}, },
txscript.ErrStackUnderflow, ErrStackUnderflow,
[][]byte{}, [][]byte{},
}, },
{ {
"Swap0", "Swap0",
[][]byte{{1}, {2}, {3}}, [][]byte{{1}, {2}, {3}},
func(stack *txscript.Stack) error { func(s *stack) error {
return stack.SwapN(0) return s.SwapN(0)
}, },
txscript.ErrStackInvalidArgs, ErrStackInvalidArgs,
[][]byte{}, [][]byte{},
}, },
{ {
"Over1", "Over1",
[][]byte{{1}, {2}, {3}, {4}}, [][]byte{{1}, {2}, {3}, {4}},
func(stack *txscript.Stack) error { func(s *stack) error {
return stack.OverN(1) return s.OverN(1)
}, },
nil, nil,
[][]byte{{1}, {2}, {3}, {4}, {3}}, [][]byte{{1}, {2}, {3}, {4}, {3}},
@ -782,8 +780,8 @@ func TestStack(t *testing.T) {
{ {
"Over2", "Over2",
[][]byte{{1}, {2}, {3}, {4}}, [][]byte{{1}, {2}, {3}, {4}},
func(stack *txscript.Stack) error { func(s *stack) error {
return stack.OverN(2) return s.OverN(2)
}, },
nil, nil,
[][]byte{{1}, {2}, {3}, {4}, {1}, {2}}, [][]byte{{1}, {2}, {3}, {4}, {1}, {2}},
@ -791,26 +789,26 @@ func TestStack(t *testing.T) {
{ {
"Over too little", "Over too little",
[][]byte{{1}}, [][]byte{{1}},
func(stack *txscript.Stack) error { func(s *stack) error {
return stack.OverN(1) return s.OverN(1)
}, },
txscript.ErrStackUnderflow, ErrStackUnderflow,
[][]byte{}, [][]byte{},
}, },
{ {
"Over0", "Over0",
[][]byte{{1}, {2}, {3}}, [][]byte{{1}, {2}, {3}},
func(stack *txscript.Stack) error { func(s *stack) error {
return stack.OverN(0) return s.OverN(0)
}, },
txscript.ErrStackInvalidArgs, ErrStackInvalidArgs,
[][]byte{}, [][]byte{},
}, },
{ {
"Pick1", "Pick1",
[][]byte{{1}, {2}, {3}, {4}}, [][]byte{{1}, {2}, {3}, {4}},
func(stack *txscript.Stack) error { func(s *stack) error {
return stack.PickN(1) return s.PickN(1)
}, },
nil, nil,
[][]byte{{1}, {2}, {3}, {4}, {3}}, [][]byte{{1}, {2}, {3}, {4}, {3}},
@ -818,8 +816,8 @@ func TestStack(t *testing.T) {
{ {
"Pick2", "Pick2",
[][]byte{{1}, {2}, {3}, {4}}, [][]byte{{1}, {2}, {3}, {4}},
func(stack *txscript.Stack) error { func(s *stack) error {
return stack.PickN(2) return s.PickN(2)
}, },
nil, nil,
[][]byte{{1}, {2}, {3}, {4}, {2}}, [][]byte{{1}, {2}, {3}, {4}, {2}},
@ -827,17 +825,17 @@ func TestStack(t *testing.T) {
{ {
"Pick too little", "Pick too little",
[][]byte{{1}}, [][]byte{{1}},
func(stack *txscript.Stack) error { func(s *stack) error {
return stack.PickN(1) return s.PickN(1)
}, },
txscript.ErrStackUnderflow, ErrStackUnderflow,
[][]byte{}, [][]byte{},
}, },
{ {
"Roll1", "Roll1",
[][]byte{{1}, {2}, {3}, {4}}, [][]byte{{1}, {2}, {3}, {4}},
func(stack *txscript.Stack) error { func(s *stack) error {
return stack.RollN(1) return s.RollN(1)
}, },
nil, nil,
[][]byte{{1}, {2}, {4}, {3}}, [][]byte{{1}, {2}, {4}, {3}},
@ -845,8 +843,8 @@ func TestStack(t *testing.T) {
{ {
"Roll2", "Roll2",
[][]byte{{1}, {2}, {3}, {4}}, [][]byte{{1}, {2}, {3}, {4}},
func(stack *txscript.Stack) error { func(s *stack) error {
return stack.RollN(2) return s.RollN(2)
}, },
nil, nil,
[][]byte{{1}, {3}, {4}, {2}}, [][]byte{{1}, {3}, {4}, {2}},
@ -854,19 +852,19 @@ func TestStack(t *testing.T) {
{ {
"Roll too little", "Roll too little",
[][]byte{{1}}, [][]byte{{1}},
func(stack *txscript.Stack) error { func(s *stack) error {
return stack.RollN(1) return s.RollN(1)
}, },
txscript.ErrStackUnderflow, ErrStackUnderflow,
[][]byte{}, [][]byte{},
}, },
{ {
"Peek bool", "Peek bool",
[][]byte{{1}}, [][]byte{{1}},
func(stack *txscript.Stack) error { func(s *stack) error {
// Peek bool is otherwise pretty well tested, // Peek bool is otherwise pretty well tested,
// just check it works. // just check it works.
val, err := stack.PeekBool(0) val, err := s.PeekBool(0)
if err != nil { if err != nil {
return err return err
} }
@ -881,10 +879,10 @@ func TestStack(t *testing.T) {
{ {
"Peek bool 2", "Peek bool 2",
[][]byte{{0}}, [][]byte{{0}},
func(stack *txscript.Stack) error { func(s *stack) error {
// Peek bool is otherwise pretty well tested, // Peek bool is otherwise pretty well tested,
// just check it works. // just check it works.
val, err := stack.PeekBool(0) val, err := s.PeekBool(0)
if err != nil { if err != nil {
return err return err
} }
@ -899,10 +897,10 @@ func TestStack(t *testing.T) {
{ {
"Peek int", "Peek int",
[][]byte{{1}}, [][]byte{{1}},
func(stack *txscript.Stack) error { func(s *stack) error {
// Peek int is otherwise pretty well tested, // Peek int is otherwise pretty well tested,
// just check it works. // just check it works.
val, err := stack.PeekInt(0) val, err := s.PeekInt(0)
if err != nil { if err != nil {
return err return err
} }
@ -917,10 +915,10 @@ func TestStack(t *testing.T) {
{ {
"Peek int 2", "Peek int 2",
[][]byte{{0}}, [][]byte{{0}},
func(stack *txscript.Stack) error { func(s *stack) error {
// Peek int is otherwise pretty well tested, // Peek int is otherwise pretty well tested,
// just check it works. // just check it works.
val, err := stack.PeekInt(0) val, err := s.PeekInt(0)
if err != nil { if err != nil {
return err return err
} }
@ -935,11 +933,11 @@ func TestStack(t *testing.T) {
{ {
"pop int", "pop int",
[][]byte{}, [][]byte{},
func(stack *txscript.Stack) error { func(s *stack) error {
stack.PushInt(big.NewInt(1)) s.PushInt(big.NewInt(1))
// Peek int is otherwise pretty well tested, // Peek int is otherwise pretty well tested,
// just check it works. // just check it works.
val, err := stack.PopInt() val, err := s.PopInt()
if err != nil { if err != nil {
return err return err
} }
@ -954,24 +952,24 @@ func TestStack(t *testing.T) {
{ {
"pop empty", "pop empty",
[][]byte{}, [][]byte{},
func(stack *txscript.Stack) error { func(s *stack) error {
// Peek int is otherwise pretty well tested, // Peek int is otherwise pretty well tested,
// just check it works. // just check it works.
_, err := stack.PopInt() _, err := s.PopInt()
return err return err
}, },
txscript.ErrStackUnderflow, ErrStackUnderflow,
[][]byte{}, [][]byte{},
}, },
} }
for _, test := range tests { for _, test := range tests {
stack := txscript.Stack{} s := stack{}
for i := range test.before { for i := range test.before {
stack.PushByteArray(test.before[i]) s.PushByteArray(test.before[i])
} }
err := test.operation(&stack) err := test.operation(&s)
if err != test.expectedReturn { if err != test.expectedReturn {
t.Errorf("%s: operation return not what expected: %v "+ t.Errorf("%s: operation return not what expected: %v "+
"vs %v", test.name, err, test.expectedReturn) "vs %v", test.name, err, test.expectedReturn)
@ -980,14 +978,14 @@ func TestStack(t *testing.T) {
continue continue
} }
if len(test.after) != stack.Depth() { if len(test.after) != s.Depth() {
t.Errorf("%s: stack depth doesn't match expected: %v "+ t.Errorf("%s: stack depth doesn't match expected: %v "+
"vs %v", test.name, len(test.after), "vs %v", test.name, len(test.after),
stack.Depth()) s.Depth())
} }
for i := range test.after { for i := range test.after {
val, err := stack.PeekByteArray(stack.Depth() - i - 1) val, err := s.PeekByteArray(s.Depth() - i - 1)
if err != nil { if err != nil {
t.Errorf("%s: can't peek %dth stack entry: %v", t.Errorf("%s: can't peek %dth stack entry: %v",
test.name, i, err) test.name, i, err)