You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

121 lines
2.0 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. package vm
  2. import (
  3. "fmt"
  4. . "github.com/tendermint/tendermint/common"
  5. )
  6. // Not goroutine safe
  7. type Stack struct {
  8. data []Word256
  9. ptr int
  10. gas *uint64
  11. err *error
  12. }
  13. func NewStack(capacity int, gas *uint64, err *error) *Stack {
  14. return &Stack{
  15. data: make([]Word256, capacity),
  16. ptr: 0,
  17. gas: gas,
  18. err: err,
  19. }
  20. }
  21. func (st *Stack) useGas(gasToUse uint64) {
  22. if *st.gas > gasToUse {
  23. *st.gas -= gasToUse
  24. } else {
  25. st.setErr(ErrInsufficientGas)
  26. }
  27. }
  28. func (st *Stack) setErr(err error) {
  29. if *st.err == nil {
  30. *st.err = err
  31. }
  32. }
  33. func (st *Stack) Push(d Word256) {
  34. st.useGas(GasStackOp)
  35. if st.ptr == cap(st.data) {
  36. st.setErr(ErrDataStackOverflow)
  37. return
  38. }
  39. st.data[st.ptr] = d
  40. st.ptr++
  41. }
  42. func (st *Stack) PushBytes(bz []byte) {
  43. if len(bz) != 32 {
  44. panic("Invalid bytes size: expected 32")
  45. }
  46. st.Push(LeftPadWord256(bz))
  47. }
  48. func (st *Stack) Push64(i uint64) {
  49. st.Push(Uint64ToWord256(i))
  50. }
  51. func (st *Stack) Pop() Word256 {
  52. st.useGas(GasStackOp)
  53. if st.ptr == 0 {
  54. st.setErr(ErrDataStackUnderflow)
  55. return Zero256
  56. }
  57. st.ptr--
  58. return st.data[st.ptr]
  59. }
  60. func (st *Stack) PopBytes() []byte {
  61. return st.Pop().Bytes()
  62. }
  63. func (st *Stack) Pop64() uint64 {
  64. d := st.Pop()
  65. return Uint64FromWord256(d)
  66. }
  67. func (st *Stack) Len() int {
  68. return st.ptr
  69. }
  70. func (st *Stack) Swap(n int) {
  71. st.useGas(GasStackOp)
  72. if st.ptr < n {
  73. st.setErr(ErrDataStackUnderflow)
  74. return
  75. }
  76. st.data[st.ptr-n], st.data[st.ptr-1] = st.data[st.ptr-1], st.data[st.ptr-n]
  77. return
  78. }
  79. func (st *Stack) Dup(n int) {
  80. st.useGas(GasStackOp)
  81. if st.ptr < n {
  82. st.setErr(ErrDataStackUnderflow)
  83. return
  84. }
  85. st.Push(st.data[st.ptr-n])
  86. return
  87. }
  88. // Not an opcode, costs no gas.
  89. func (st *Stack) Peek() Word256 {
  90. return st.data[st.ptr-1]
  91. }
  92. func (st *Stack) Print(n int) {
  93. fmt.Println("### stack ###")
  94. if st.ptr > 0 {
  95. nn := MinInt(n, st.ptr)
  96. for j, i := 0, st.ptr-1; i > st.ptr-1-nn; i-- {
  97. fmt.Printf("%-3d %X\n", j, st.data[i])
  98. j += 1
  99. }
  100. } else {
  101. fmt.Println("-- empty --")
  102. }
  103. fmt.Println("#############")
  104. }