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.

126 lines
2.1 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
  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 *int64
  11. err *error
  12. }
  13. func NewStack(capacity int, gas *int64, 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 int64) {
  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. // currently only called after Sha3
  43. func (st *Stack) PushBytes(bz []byte) {
  44. if len(bz) != 32 {
  45. PanicSanity("Invalid bytes size: expected 32")
  46. }
  47. st.Push(LeftPadWord256(bz))
  48. }
  49. func (st *Stack) Push64(i int64) {
  50. st.Push(Int64ToWord256(i))
  51. }
  52. func (st *Stack) Pop() Word256 {
  53. st.useGas(GasStackOp)
  54. if st.ptr == 0 {
  55. st.setErr(ErrDataStackUnderflow)
  56. return Zero256
  57. }
  58. st.ptr--
  59. return st.data[st.ptr]
  60. }
  61. func (st *Stack) PopBytes() []byte {
  62. return st.Pop().Bytes()
  63. }
  64. func (st *Stack) Pop64() int64 {
  65. d := st.Pop()
  66. return Int64FromWord256(d)
  67. }
  68. func (st *Stack) Len() int {
  69. return st.ptr
  70. }
  71. func (st *Stack) Swap(n int) {
  72. st.useGas(GasStackOp)
  73. if st.ptr < n {
  74. st.setErr(ErrDataStackUnderflow)
  75. return
  76. }
  77. st.data[st.ptr-n], st.data[st.ptr-1] = st.data[st.ptr-1], st.data[st.ptr-n]
  78. return
  79. }
  80. func (st *Stack) Dup(n int) {
  81. st.useGas(GasStackOp)
  82. if st.ptr < n {
  83. st.setErr(ErrDataStackUnderflow)
  84. return
  85. }
  86. st.Push(st.data[st.ptr-n])
  87. return
  88. }
  89. // Not an opcode, costs no gas.
  90. func (st *Stack) Peek() Word256 {
  91. if st.ptr == 0 {
  92. st.setErr(ErrDataStackUnderflow)
  93. return Zero256
  94. }
  95. return st.data[st.ptr-1]
  96. }
  97. func (st *Stack) Print(n int) {
  98. fmt.Println("### stack ###")
  99. if st.ptr > 0 {
  100. nn := MinInt(n, st.ptr)
  101. for j, i := 0, st.ptr-1; i > st.ptr-1-nn; i-- {
  102. fmt.Printf("%-3d %X\n", j, st.data[i])
  103. j += 1
  104. }
  105. } else {
  106. fmt.Println("-- empty --")
  107. }
  108. fmt.Println("#############")
  109. }