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

9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 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. }