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.

118 lines
1.9 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(RightPadWord256(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. return GetUint64(st.Pop().Bytes())
  65. }
  66. func (st *Stack) Len() int {
  67. return st.ptr
  68. }
  69. func (st *Stack) Swap(n int) {
  70. st.useGas(GasStackOp)
  71. if st.ptr < n {
  72. st.setErr(ErrDataStackUnderflow)
  73. return
  74. }
  75. st.data[st.ptr-n], st.data[st.ptr-1] = st.data[st.ptr-1], st.data[st.ptr-n]
  76. return
  77. }
  78. func (st *Stack) Dup(n int) {
  79. st.useGas(GasStackOp)
  80. if st.ptr < n {
  81. st.setErr(ErrDataStackUnderflow)
  82. return
  83. }
  84. st.Push(st.data[st.ptr-n])
  85. return
  86. }
  87. // Not an opcode, costs no gas.
  88. func (st *Stack) Peek() Word256 {
  89. return st.data[st.ptr-1]
  90. }
  91. func (st *Stack) Print() {
  92. fmt.Println("### stack ###")
  93. if st.ptr > 0 {
  94. for i, val := range st.data {
  95. fmt.Printf("%-3d %v\n", i, val)
  96. }
  97. } else {
  98. fmt.Println("-- empty --")
  99. }
  100. fmt.Println("#############")
  101. }