github.com/karalabe/go-ethereum@v0.8.5/vm/stack.go (about)

     1  package vm
     2  
     3  import (
     4  	"fmt"
     5  	"math/big"
     6  )
     7  
     8  type OpType int
     9  
    10  const (
    11  	tNorm = iota
    12  	tData
    13  	tExtro
    14  	tCrypto
    15  )
    16  
    17  type TxCallback func(opType OpType) bool
    18  
    19  // Simple push/pop stack mechanism
    20  type Stack struct {
    21  	data []*big.Int
    22  }
    23  
    24  func NewStack() *Stack {
    25  	return &Stack{}
    26  }
    27  
    28  func (st *Stack) Data() []*big.Int {
    29  	return st.data
    30  }
    31  
    32  func (st *Stack) Len() int {
    33  	return len(st.data)
    34  }
    35  
    36  func (st *Stack) Pop() *big.Int {
    37  	str := st.data[len(st.data)-1]
    38  
    39  	copy(st.data[:len(st.data)-1], st.data[:len(st.data)-1])
    40  	st.data = st.data[:len(st.data)-1]
    41  
    42  	return str
    43  }
    44  
    45  func (st *Stack) Popn() (*big.Int, *big.Int) {
    46  	ints := st.data[len(st.data)-2:]
    47  
    48  	copy(st.data[:len(st.data)-2], st.data[:len(st.data)-2])
    49  	st.data = st.data[:len(st.data)-2]
    50  
    51  	return ints[0], ints[1]
    52  }
    53  
    54  func (st *Stack) Peek() *big.Int {
    55  	str := st.data[len(st.data)-1]
    56  
    57  	return str
    58  }
    59  
    60  func (st *Stack) Peekn() (*big.Int, *big.Int) {
    61  	ints := st.data[len(st.data)-2:]
    62  
    63  	return ints[0], ints[1]
    64  }
    65  
    66  func (st *Stack) Swapn(n int) (*big.Int, *big.Int) {
    67  	st.data[len(st.data)-n], st.data[len(st.data)-1] = st.data[len(st.data)-1], st.data[len(st.data)-n]
    68  
    69  	return st.data[len(st.data)-n], st.data[len(st.data)-1]
    70  }
    71  
    72  func (st *Stack) Dupn(n int) *big.Int {
    73  	st.Push(st.data[len(st.data)-n])
    74  
    75  	return st.Peek()
    76  }
    77  
    78  func (st *Stack) Push(d *big.Int) {
    79  	st.data = append(st.data, new(big.Int).Set(d))
    80  }
    81  
    82  func (st *Stack) Get(amount *big.Int) []*big.Int {
    83  	// offset + size <= len(data)
    84  	length := big.NewInt(int64(len(st.data)))
    85  	if amount.Cmp(length) <= 0 {
    86  		start := new(big.Int).Sub(length, amount)
    87  		return st.data[start.Int64():length.Int64()]
    88  	}
    89  
    90  	return nil
    91  }
    92  
    93  func (st *Stack) require(n int) {
    94  	if st.Len() < n {
    95  		panic(fmt.Sprintf("stack underflow (%d <=> %d)", st.Len(), n))
    96  	}
    97  }
    98  
    99  func (st *Stack) Print() {
   100  	fmt.Println("### stack ###")
   101  	if len(st.data) > 0 {
   102  		for i, val := range st.data {
   103  			fmt.Printf("%-3d  %v\n", i, val)
   104  		}
   105  	} else {
   106  		fmt.Println("-- empty --")
   107  	}
   108  	fmt.Println("#############")
   109  }
   110  
   111  type Memory struct {
   112  	store []byte
   113  }
   114  
   115  func NewMemory() *Memory {
   116  	return &Memory{nil}
   117  }
   118  
   119  func (m *Memory) Set(offset, size uint64, value []byte) {
   120  	if len(value) > 0 {
   121  		totSize := offset + size
   122  		lenSize := uint64(len(m.store) - 1)
   123  		if totSize > lenSize {
   124  			// Calculate the diff between the sizes
   125  			diff := totSize - lenSize
   126  			if diff > 0 {
   127  				// Create a new empty slice and append it
   128  				newSlice := make([]byte, diff-1)
   129  				// Resize slice
   130  				m.store = append(m.store, newSlice...)
   131  			}
   132  		}
   133  		copy(m.store[offset:offset+size], value)
   134  	}
   135  }
   136  
   137  func (m *Memory) Resize(size uint64) {
   138  	if uint64(m.Len()) < size {
   139  		m.store = append(m.store, make([]byte, size-uint64(m.Len()))...)
   140  	}
   141  }
   142  
   143  func (self *Memory) Get(offset, size int64) (cpy []byte) {
   144  	if size == 0 {
   145  		return nil
   146  	}
   147  
   148  	if len(self.store) > int(offset) {
   149  		cpy = make([]byte, size)
   150  		copy(cpy, self.store[offset:offset+size])
   151  
   152  		return
   153  	}
   154  
   155  	return
   156  }
   157  
   158  func (m *Memory) Len() int {
   159  	return len(m.store)
   160  }
   161  
   162  func (m *Memory) Data() []byte {
   163  	return m.store
   164  }
   165  
   166  func (m *Memory) Print() {
   167  	fmt.Printf("### mem %d bytes ###\n", len(m.store))
   168  	if len(m.store) > 0 {
   169  		addr := 0
   170  		for i := 0; i+32 <= len(m.store); i += 32 {
   171  			fmt.Printf("%03d: % x\n", addr, m.store[i:i+32])
   172  			addr++
   173  		}
   174  	} else {
   175  		fmt.Println("-- empty --")
   176  	}
   177  	fmt.Println("####################")
   178  }