github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/execution/evm/stack.go (about)

     1  // Copyright Monax Industries Limited
     2  // SPDX-License-Identifier: Apache-2.0
     3  
     4  package evm
     5  
     6  import (
     7  	"fmt"
     8  	"math"
     9  	"math/big"
    10  
    11  	"github.com/hyperledger/burrow/execution/engine"
    12  
    13  	. "github.com/hyperledger/burrow/binary"
    14  	"github.com/hyperledger/burrow/crypto"
    15  	"github.com/hyperledger/burrow/execution/errors"
    16  )
    17  
    18  // Not goroutine safe
    19  type Stack struct {
    20  	slice       []Word256
    21  	maxCapacity uint64
    22  	ptr         int
    23  
    24  	gas     *big.Int
    25  	errSink errors.Sink
    26  }
    27  
    28  func NewStack(errSink errors.Sink, initialCapacity uint64, maxCapacity uint64, gas *big.Int) *Stack {
    29  	return &Stack{
    30  		slice:       make([]Word256, initialCapacity),
    31  		ptr:         0,
    32  		maxCapacity: maxCapacity,
    33  		gas:         gas,
    34  		errSink:     errSink,
    35  	}
    36  }
    37  
    38  func (st *Stack) Push(d Word256) {
    39  	st.useGas(engine.GasStackOp)
    40  	err := st.ensureCapacity(uint64(st.ptr) + 1)
    41  	if err != nil {
    42  		st.pushErr(errors.Codes.DataStackOverflow)
    43  		return
    44  	}
    45  	st.slice[st.ptr] = d
    46  	st.ptr++
    47  }
    48  
    49  func (st *Stack) Pop() Word256 {
    50  	st.useGas(engine.GasStackOp)
    51  	if st.ptr == 0 {
    52  		st.pushErr(errors.Codes.DataStackUnderflow)
    53  		return Zero256
    54  	}
    55  	st.ptr--
    56  	return st.slice[st.ptr]
    57  }
    58  
    59  // currently only called after sha3.Sha3
    60  func (st *Stack) PushBytes(bz []byte) {
    61  	if len(bz) != 32 {
    62  		panic("Invalid bytes size: expected 32")
    63  	}
    64  	st.Push(LeftPadWord256(bz))
    65  }
    66  
    67  func (st *Stack) PushAddress(address crypto.Address) {
    68  	st.Push(address.Word256())
    69  }
    70  
    71  func (st *Stack) Push64(i uint64) {
    72  	st.Push(Uint64ToWord256(i))
    73  }
    74  
    75  func (st *Stack) Pop64() uint64 {
    76  	d := st.Pop()
    77  	if Is64BitOverflow(d) {
    78  		st.pushErr(errors.Errorf(errors.Codes.IntegerOverflow, "uint64 overflow from word: %v", d))
    79  		return 0
    80  	}
    81  	return Uint64FromWord256(d)
    82  }
    83  
    84  // Pushes the bigInt as a Word256 encoding negative values in 32-byte twos complement and returns the encoded result
    85  func (st *Stack) PushBigInt(bigInt *big.Int) Word256 {
    86  	word := LeftPadWord256(U256(bigInt).Bytes())
    87  	st.Push(word)
    88  	return word
    89  }
    90  
    91  func (st *Stack) PopBigIntSigned() *big.Int {
    92  	return S256(st.PopBigInt())
    93  }
    94  
    95  func (st *Stack) PopBigInt() *big.Int {
    96  	d := st.Pop()
    97  	return new(big.Int).SetBytes(d[:])
    98  }
    99  
   100  func (st *Stack) PopBytes() []byte {
   101  	return st.Pop().Bytes()
   102  }
   103  
   104  func (st *Stack) PopAddress() crypto.Address {
   105  	return crypto.AddressFromWord256(st.Pop())
   106  }
   107  
   108  func (st *Stack) Len() int {
   109  	return st.ptr
   110  }
   111  
   112  func (st *Stack) Swap(n int) {
   113  	st.useGas(engine.GasStackOp)
   114  	if st.ptr < n {
   115  		st.pushErr(errors.Codes.DataStackUnderflow)
   116  		return
   117  	}
   118  	st.slice[st.ptr-n], st.slice[st.ptr-1] = st.slice[st.ptr-1], st.slice[st.ptr-n]
   119  }
   120  
   121  func (st *Stack) Dup(n int) {
   122  	st.useGas(engine.GasStackOp)
   123  	if st.ptr < n {
   124  		st.pushErr(errors.Codes.DataStackUnderflow)
   125  		return
   126  	}
   127  	st.Push(st.slice[st.ptr-n])
   128  }
   129  
   130  // Not an opcode, costs no gas.
   131  func (st *Stack) Peek() Word256 {
   132  	if st.ptr == 0 {
   133  		st.pushErr(errors.Codes.DataStackUnderflow)
   134  		return Zero256
   135  	}
   136  	return st.slice[st.ptr-1]
   137  }
   138  
   139  func (st *Stack) Print(n int) {
   140  	fmt.Println("### stack ###")
   141  	if st.ptr > 0 {
   142  		nn := n
   143  		if st.ptr < n {
   144  			nn = st.ptr
   145  		}
   146  		for j, i := 0, st.ptr-1; i > st.ptr-1-nn; i-- {
   147  			fmt.Printf("%-3d  %X\n", j, st.slice[i])
   148  			j += 1
   149  		}
   150  	} else {
   151  		fmt.Println("-- empty --")
   152  	}
   153  	fmt.Println("#############")
   154  }
   155  
   156  func Is64BitOverflow(word Word256) bool {
   157  	for i := 0; i < len(word)-8; i++ {
   158  		if word[i] != 0 {
   159  			return true
   160  		}
   161  	}
   162  	return false
   163  }
   164  
   165  // Ensures the current stack can hold a new element. Will only grow the
   166  // backing array (will not shrink).
   167  func (st *Stack) ensureCapacity(newCapacity uint64) error {
   168  	// Maximum length of a slice that allocates memory is the same as the native int max size
   169  	// We could rethink this limit, but we don't want different validators to disagree on
   170  	// transaction validity so we pick the lowest common denominator
   171  	if newCapacity > math.MaxInt32 {
   172  		// If we ever did want more than an int32 of space then we would need to
   173  		// maintain multiple pages of memory
   174  		return fmt.Errorf("cannot address memory beyond a maximum index "+
   175  			"with int32 width (%v bytes)", math.MaxInt32)
   176  	}
   177  	newCapacityInt := int(newCapacity)
   178  	// We're already big enough so return
   179  	if newCapacityInt <= len(st.slice) {
   180  		return nil
   181  	}
   182  	if st.maxCapacity > 0 && newCapacity > st.maxCapacity {
   183  		return fmt.Errorf("cannot grow memory because it would exceed the "+
   184  			"current maximum limit of %v bytes", st.maxCapacity)
   185  	}
   186  	// Ensure the backing array of slice is big enough
   187  	// Grow the memory one word at time using the pre-allocated zeroWords to avoid
   188  	// unnecessary allocations. Use append to make use of any spare capacity in
   189  	// the slice's backing array.
   190  	for newCapacityInt > cap(st.slice) {
   191  		// We'll trust Go exponentially grow our arrays (at first).
   192  		st.slice = append(st.slice, Zero256)
   193  	}
   194  	// Now we've ensured the backing array of the slice is big enough we can
   195  	// just re-slice (even if len(mem.slice) < newCapacity)
   196  	st.slice = st.slice[:newCapacity]
   197  	return nil
   198  }
   199  
   200  func (st *Stack) useGas(gasToUse uint64) {
   201  	st.pushErr(engine.UseGasNegative(st.gas, gasToUse))
   202  }
   203  
   204  func (st *Stack) pushErr(err errors.CodedError) {
   205  	st.errSink.PushError(err)
   206  }