stack.go 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. // Copyright (c) 2013-2017 The btcsuite developers
  2. // Use of this source code is governed by an ISC
  3. // license that can be found in the LICENSE file.
  4. package txscript
  5. import (
  6. "encoding/hex"
  7. "fmt"
  8. "github.com/pkt-cash/pktd/btcutil/er"
  9. "github.com/pkt-cash/pktd/txscript/scriptnum"
  10. "github.com/pkt-cash/pktd/txscript/txscripterr"
  11. )
  12. // asBool gets the boolean value of the byte array.
  13. func asBool(t []byte) bool {
  14. for i := range t {
  15. if t[i] != 0 {
  16. // Negative 0 is also considered false.
  17. if i == len(t)-1 && t[i] == 0x80 {
  18. return false
  19. }
  20. return true
  21. }
  22. }
  23. return false
  24. }
  25. // fromBool converts a boolean into the appropriate byte array.
  26. func fromBool(v bool) []byte {
  27. if v {
  28. return []byte{1}
  29. }
  30. return nil
  31. }
  32. // stack represents a stack of immutable objects to be used with bitcoin
  33. // scripts. Objects may be shared, therefore in usage if a value is to be
  34. // changed it *must* be deep-copied first to avoid changing other values on the
  35. // stack.
  36. type stack struct {
  37. stk [][]byte
  38. verifyMinimalData bool
  39. }
  40. // Depth returns the number of items on the stack.
  41. func (s *stack) Depth() int32 {
  42. return int32(len(s.stk))
  43. }
  44. // PushByteArray adds the given back array to the top of the stack.
  45. //
  46. // Stack transformation: [... x1 x2] -> [... x1 x2 data]
  47. func (s *stack) PushByteArray(so []byte) {
  48. s.stk = append(s.stk, so)
  49. }
  50. // PushInt converts the provided scriptNum to a suitable byte array then pushes
  51. // it onto the top of the stack.
  52. //
  53. // Stack transformation: [... x1 x2] -> [... x1 x2 int]
  54. func (s *stack) PushInt(val scriptnum.ScriptNum) {
  55. s.PushByteArray(val.Bytes())
  56. }
  57. // PushBool converts the provided boolean to a suitable byte array then pushes
  58. // it onto the top of the stack.
  59. //
  60. // Stack transformation: [... x1 x2] -> [... x1 x2 bool]
  61. func (s *stack) PushBool(val bool) {
  62. s.PushByteArray(fromBool(val))
  63. }
  64. // PopByteArray pops the value off the top of the stack and returns it.
  65. //
  66. // Stack transformation: [... x1 x2 x3] -> [... x1 x2]
  67. func (s *stack) PopByteArray() ([]byte, er.R) {
  68. return s.nipN(0)
  69. }
  70. // PopInt pops the value off the top of the stack, converts it into a script
  71. // num, and returns it. The act of converting to a script num enforces the
  72. // consensus rules imposed on data interpreted as numbers.
  73. //
  74. // Stack transformation: [... x1 x2 x3] -> [... x1 x2]
  75. func (s *stack) PopInt() (scriptnum.ScriptNum, er.R) {
  76. so, err := s.PopByteArray()
  77. if err != nil {
  78. return 0, err
  79. }
  80. return scriptnum.MakeScriptNum(so, s.verifyMinimalData, scriptnum.DefaultScriptNumLen)
  81. }
  82. // PopBool pops the value off the top of the stack, converts it into a bool, and
  83. // returns it.
  84. //
  85. // Stack transformation: [... x1 x2 x3] -> [... x1 x2]
  86. func (s *stack) PopBool() (bool, er.R) {
  87. so, err := s.PopByteArray()
  88. if err != nil {
  89. return false, err
  90. }
  91. return asBool(so), nil
  92. }
  93. // PeekByteArray returns the Nth item on the stack without removing it.
  94. func (s *stack) PeekByteArray(idx int32) ([]byte, er.R) {
  95. sz := int32(len(s.stk))
  96. if idx < 0 || idx >= sz {
  97. str := fmt.Sprintf("index %d is invalid for stack size %d", idx,
  98. sz)
  99. return nil, txscripterr.ScriptError(txscripterr.ErrInvalidStackOperation, str)
  100. }
  101. return s.stk[sz-idx-1], nil
  102. }
  103. // PeekInt returns the Nth item on the stack as a script num without removing
  104. // it. The act of converting to a script num enforces the consensus rules
  105. // imposed on data interpreted as numbers.
  106. func (s *stack) PeekInt(idx int32) (scriptnum.ScriptNum, er.R) {
  107. so, err := s.PeekByteArray(idx)
  108. if err != nil {
  109. return 0, err
  110. }
  111. return scriptnum.MakeScriptNum(so, s.verifyMinimalData, scriptnum.DefaultScriptNumLen)
  112. }
  113. // PeekBool returns the Nth item on the stack as a bool without removing it.
  114. func (s *stack) PeekBool(idx int32) (bool, er.R) {
  115. so, err := s.PeekByteArray(idx)
  116. if err != nil {
  117. return false, err
  118. }
  119. return asBool(so), nil
  120. }
  121. // nipN is an internal function that removes the nth item on the stack and
  122. // returns it.
  123. //
  124. // Stack transformation:
  125. // nipN(0): [... x1 x2 x3] -> [... x1 x2]
  126. // nipN(1): [... x1 x2 x3] -> [... x1 x3]
  127. // nipN(2): [... x1 x2 x3] -> [... x2 x3]
  128. func (s *stack) nipN(idx int32) ([]byte, er.R) {
  129. sz := int32(len(s.stk))
  130. if idx < 0 || idx > sz-1 {
  131. str := fmt.Sprintf("index %d is invalid for stack size %d", idx,
  132. sz)
  133. return nil, txscripterr.ScriptError(txscripterr.ErrInvalidStackOperation, str)
  134. }
  135. so := s.stk[sz-idx-1]
  136. if idx == 0 {
  137. s.stk = s.stk[:sz-1]
  138. } else if idx == sz-1 {
  139. s1 := make([][]byte, sz-1)
  140. copy(s1, s.stk[1:])
  141. s.stk = s1
  142. } else {
  143. s1 := s.stk[sz-idx : sz]
  144. s.stk = s.stk[:sz-idx-1]
  145. s.stk = append(s.stk, s1...)
  146. }
  147. return so, nil
  148. }
  149. // NipN removes the Nth object on the stack
  150. //
  151. // Stack transformation:
  152. // NipN(0): [... x1 x2 x3] -> [... x1 x2]
  153. // NipN(1): [... x1 x2 x3] -> [... x1 x3]
  154. // NipN(2): [... x1 x2 x3] -> [... x2 x3]
  155. func (s *stack) NipN(idx int32) er.R {
  156. _, err := s.nipN(idx)
  157. return err
  158. }
  159. // Tuck copies the item at the top of the stack and inserts it before the 2nd
  160. // to top item.
  161. //
  162. // Stack transformation: [... x1 x2] -> [... x2 x1 x2]
  163. func (s *stack) Tuck() er.R {
  164. so2, err := s.PopByteArray()
  165. if err != nil {
  166. return err
  167. }
  168. so1, err := s.PopByteArray()
  169. if err != nil {
  170. return err
  171. }
  172. s.PushByteArray(so2) // stack [... x2]
  173. s.PushByteArray(so1) // stack [... x2 x1]
  174. s.PushByteArray(so2) // stack [... x2 x1 x2]
  175. return nil
  176. }
  177. // DropN removes the top N items from the stack.
  178. //
  179. // Stack transformation:
  180. // DropN(1): [... x1 x2] -> [... x1]
  181. // DropN(2): [... x1 x2] -> [...]
  182. func (s *stack) DropN(n int32) er.R {
  183. if n < 1 {
  184. str := fmt.Sprintf("attempt to drop %d items from stack", n)
  185. return txscripterr.ScriptError(txscripterr.ErrInvalidStackOperation, str)
  186. }
  187. for ; n > 0; n-- {
  188. _, err := s.PopByteArray()
  189. if err != nil {
  190. return err
  191. }
  192. }
  193. return nil
  194. }
  195. // DupN duplicates the top N items on the stack.
  196. //
  197. // Stack transformation:
  198. // DupN(1): [... x1 x2] -> [... x1 x2 x2]
  199. // DupN(2): [... x1 x2] -> [... x1 x2 x1 x2]
  200. func (s *stack) DupN(n int32) er.R {
  201. if n < 1 {
  202. str := fmt.Sprintf("attempt to dup %d stack items", n)
  203. return txscripterr.ScriptError(txscripterr.ErrInvalidStackOperation, str)
  204. }
  205. // Iteratively duplicate the value n-1 down the stack n times.
  206. // This leaves an in-order duplicate of the top n items on the stack.
  207. for i := n; i > 0; i-- {
  208. so, err := s.PeekByteArray(n - 1)
  209. if err != nil {
  210. return err
  211. }
  212. s.PushByteArray(so)
  213. }
  214. return nil
  215. }
  216. // RotN rotates the top 3N items on the stack to the left N times.
  217. //
  218. // Stack transformation:
  219. // RotN(1): [... x1 x2 x3] -> [... x2 x3 x1]
  220. // RotN(2): [... x1 x2 x3 x4 x5 x6] -> [... x3 x4 x5 x6 x1 x2]
  221. func (s *stack) RotN(n int32) er.R {
  222. if n < 1 {
  223. str := fmt.Sprintf("attempt to rotate %d stack items", n)
  224. return txscripterr.ScriptError(txscripterr.ErrInvalidStackOperation, str)
  225. }
  226. // Nip the 3n-1th item from the stack to the top n times to rotate
  227. // them up to the head of the stack.
  228. entry := 3*n - 1
  229. for i := n; i > 0; i-- {
  230. so, err := s.nipN(entry)
  231. if err != nil {
  232. return err
  233. }
  234. s.PushByteArray(so)
  235. }
  236. return nil
  237. }
  238. // SwapN swaps the top N items on the stack with those below them.
  239. //
  240. // Stack transformation:
  241. // SwapN(1): [... x1 x2] -> [... x2 x1]
  242. // SwapN(2): [... x1 x2 x3 x4] -> [... x3 x4 x1 x2]
  243. func (s *stack) SwapN(n int32) er.R {
  244. if n < 1 {
  245. str := fmt.Sprintf("attempt to swap %d stack items", n)
  246. return txscripterr.ScriptError(txscripterr.ErrInvalidStackOperation, str)
  247. }
  248. entry := 2*n - 1
  249. for i := n; i > 0; i-- {
  250. // Swap 2n-1th entry to top.
  251. so, err := s.nipN(entry)
  252. if err != nil {
  253. return err
  254. }
  255. s.PushByteArray(so)
  256. }
  257. return nil
  258. }
  259. // OverN copies N items N items back to the top of the stack.
  260. //
  261. // Stack transformation:
  262. // OverN(1): [... x1 x2 x3] -> [... x1 x2 x3 x2]
  263. // OverN(2): [... x1 x2 x3 x4] -> [... x1 x2 x3 x4 x1 x2]
  264. func (s *stack) OverN(n int32) er.R {
  265. if n < 1 {
  266. str := fmt.Sprintf("attempt to perform over on %d stack items",
  267. n)
  268. return txscripterr.ScriptError(txscripterr.ErrInvalidStackOperation, str)
  269. }
  270. // Copy 2n-1th entry to top of the stack.
  271. entry := 2*n - 1
  272. for ; n > 0; n-- {
  273. so, err := s.PeekByteArray(entry)
  274. if err != nil {
  275. return err
  276. }
  277. s.PushByteArray(so)
  278. }
  279. return nil
  280. }
  281. // PickN copies the item N items back in the stack to the top.
  282. //
  283. // Stack transformation:
  284. // PickN(0): [x1 x2 x3] -> [x1 x2 x3 x3]
  285. // PickN(1): [x1 x2 x3] -> [x1 x2 x3 x2]
  286. // PickN(2): [x1 x2 x3] -> [x1 x2 x3 x1]
  287. func (s *stack) PickN(n int32) er.R {
  288. so, err := s.PeekByteArray(n)
  289. if err != nil {
  290. return err
  291. }
  292. s.PushByteArray(so)
  293. return nil
  294. }
  295. // RollN moves the item N items back in the stack to the top.
  296. //
  297. // Stack transformation:
  298. // RollN(0): [x1 x2 x3] -> [x1 x2 x3]
  299. // RollN(1): [x1 x2 x3] -> [x1 x3 x2]
  300. // RollN(2): [x1 x2 x3] -> [x2 x3 x1]
  301. func (s *stack) RollN(n int32) er.R {
  302. so, err := s.nipN(n)
  303. if err != nil {
  304. return err
  305. }
  306. s.PushByteArray(so)
  307. return nil
  308. }
  309. // String returns the stack in a readable format.
  310. func (s *stack) String() string {
  311. var result string
  312. for _, stack := range s.stk {
  313. if len(stack) == 0 {
  314. result += "00000000 <empty>\n"
  315. }
  316. result += hex.Dump(stack)
  317. }
  318. return result
  319. }