pending.hoon 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /= dcon /apps/dumbnet/lib/consensus
  2. /= dk /apps/dumbnet/lib/types
  3. /= dumb-transact /common/tx-engine
  4. /= * /common/zoon
  5. ::
  6. |_ [p=pending-state:dk bc=blockchain-constants:dumb-transact]
  7. +* t ~(. dumb-transact bc)
  8. +| %logic
  9. :: +find-ready-blocks: blocks for which .id was the last missing tx
  10. ++ find-ready-blocks
  11. ^- (z-set block-id:t)
  12. :: set of all pending blocks
  13. =/ p-bids=(z-set block-id:t) ~(key z-by pending-blocks.p)
  14. :: set of pending blocks still waiting on txs
  15. =/ w-bids=(z-set block-id:t) ~(key z-by block-tx.p)
  16. (~(dif z-in p-bids) w-bids)
  17. ::
  18. ++ inputs-in-spent-by
  19. |= raw=raw-tx:t
  20. ^- ?
  21. =/ inputs-names=(z-set nname:t) (inputs-names:raw-tx:t raw)
  22. =/ spent-by-names=(z-set nname:t) ~(key z-by spent-by.p)
  23. =/ common-names=(z-set nname:t) (~(int z-in spent-by-names) inputs-names)
  24. :: %.y: inputs are present in spent-by
  25. :: %.n: inputs are not present in spent-by
  26. !=(*(z-set nname:t) common-names)
  27. ::
  28. ++ refresh-after-new-block
  29. |= [c=consensus-state:dk retain=(unit @)]
  30. ^- pending-state:dk
  31. ?~ retain
  32. :: never drop transactions
  33. p
  34. ?: =(0 u.retain)
  35. :: never retain anything
  36. %_ p
  37. spent-by *(z-map nname:t tx-id:t)
  38. heard-at *(z-map tx-id:t page-number:t)
  39. raw-txs *(z-map tx-id:t raw-tx:t)
  40. ==
  41. ::
  42. :: enumerate last N block heights inclusive of current block height
  43. =/ cur-height=page-number:t
  44. ~(get-cur-height dcon c bc)
  45. =/ min-height=page-number:t
  46. ?: (lth cur-height u.retain) 0
  47. :: add 1 b/c range is inclusive of cur-height
  48. :: so retain=1 means min-height=cur-height
  49. +((sub cur-height u.retain))
  50. =/ heard-kvs=(list [tx-id:t page-number:t])
  51. ~(tap z-by heard-at.p)
  52. ::
  53. =/ keep-drop=[k=(list [tx-id:t page-number:t]) d=(list raw-tx:t)]
  54. %+ roll heard-kvs
  55. |= $: [tid=tx-id:t num=page-number:t]
  56. [keep=(list [tx-id:t page-number:t]) drop=(list raw-tx:t)]
  57. ==
  58. =/ raw=raw-tx:t (~(got z-by raw-txs.p) tid)
  59. ?: (lth num min-height)
  60. :: tx is old, drop it
  61. [keep [raw drop]]
  62. ?. (~(inputs-in-heaviest-balance dcon c bc) raw)
  63. :: input(s) in tx not in balance, discard
  64. [keep [raw drop]]
  65. :: tx should stay in heard-at
  66. [[[tid num] keep] drop]
  67. ::
  68. :: new heard-at map from k.keep-drop
  69. =. heard-at.p
  70. (~(gas z-by *(z-map tx-id:t page-number:t)) k.keep-drop)
  71. ::
  72. :: remove d.keep-drop from spent-by map
  73. =. p
  74. %+ roll d.keep-drop
  75. |= [raw=raw-tx:t pen=_p]
  76. (remove-inputs-from-spent-by raw)
  77. ::
  78. :: remove d.keep-drop from raw-txs map. we cannot just
  79. :: make a new map with k.keep-drop since raw-txs also includes
  80. :: txs for pending blocks
  81. =. p
  82. %+ roll d.keep-drop
  83. |= [raw=raw-tx:t pen=_p]
  84. (remove-raw-tx id.raw)
  85. ::
  86. p
  87. +| %getters-and-setters
  88. ::
  89. :: +add-tx-not-in-pending-block:
  90. ::
  91. :: these transactions are treated differently from transactions
  92. :: that are in a pending block. we track their inputs and when
  93. :: we heard them. if we hear another transaction using some
  94. :: of the same inputs, we discard it. if we heard the transaction
  95. :: sufficiently long ago, we drop it from pending state.
  96. ++ add-tx-not-in-pending-block
  97. |= [raw=raw-tx:t cur-height=page-number:t]
  98. ^- pending-state:dk
  99. =. p (add-raw-tx raw)
  100. =. p (add-inputs-to-spent-by raw)
  101. =. p (tx-heard-at id.raw cur-height)
  102. p
  103. ::
  104. :: +add-tx-in-pending-block:
  105. ::
  106. :: when a tx is in a pending block, we ignore whether it uses
  107. :: inputs that have been spent in the heaviest balance, or
  108. :: when we heard it.
  109. ++ add-tx-in-pending-block
  110. |= raw=raw-tx:t
  111. ^- pending-state:dk
  112. =. p (add-raw-tx raw)
  113. :: this one needs to go before remove-tx-from-tx-block because
  114. :: the keys it needs to inspect are gotten from .tx-block.
  115. =. p (remove-tx-from-block-tx id.raw)
  116. =. p (remove-tx-from-tx-block id.raw)
  117. p
  118. ::
  119. ++ tx-heard-at
  120. |= [id=tx-id:t height=page-number:t]
  121. ^- pending-state:dk
  122. p(heard-at (~(put z-by heard-at.p) id height))
  123. ::
  124. ++ add-inputs-to-spent-by
  125. |= raw=raw-tx:t
  126. ^- pending-state:dk
  127. =/ inputs-names=(list nname:t)
  128. ~(tap z-in (inputs-names:raw-tx:t raw))
  129. =/ new-entries=(list [nname:t tx-id:t])
  130. (turn inputs-names |=(n=nname:t n^id.raw))
  131. p(spent-by (~(gas z-by spent-by.p) new-entries))
  132. ::
  133. ++ remove-inputs-from-spent-by
  134. |= raw=raw-tx:t
  135. ^- pending-state:dk
  136. =/ inputs-names=(list nname:t)
  137. ~(tap z-in (inputs-names:raw-tx:t raw))
  138. =. spent-by.p
  139. %+ roll inputs-names
  140. |= [nom=nname:t spb=_spent-by.p]
  141. (~(del z-by spb) nom)
  142. p
  143. ::
  144. :: +find-pending-tx-ids: pending tx-ids for pending blocks
  145. ++ find-pending-tx-ids
  146. ^- (z-set tx-id:t)
  147. %+ roll ~(val z-by block-tx.p)
  148. |= [tx-ids=(z-set tx-id:t) all-tx-ids=(z-set tx-id:t)]
  149. (~(uni z-in all-tx-ids) tx-ids)
  150. ::
  151. ++ remove-tx-from-tx-block
  152. |= id=tx-id:t
  153. ^- pending-state:dk
  154. p(tx-block (~(del z-by tx-block.p) id))
  155. ::
  156. ++ remove-tx-from-block-tx
  157. |= tid=tx-id:t
  158. ^- pending-state:dk
  159. =/ block-vals=(unit (z-set block-id:t))
  160. (~(get z-by tx-block.p) tid)
  161. ?~ block-vals
  162. :: no blocks waiting on this tx, so do nothing
  163. p
  164. =/ block-list=(list block-id:t)
  165. ~(tap z-in u.block-vals)
  166. =. block-tx.p
  167. %+ roll block-list
  168. |= [bid=block-id:t blt=_block-tx.p]
  169. (~(del z-ju blt) bid tid)
  170. p
  171. ::
  172. ++ add-pending-block
  173. |= pag=page:t
  174. ^- [(list tx-id:t) pending-state:dk]
  175. :: find missing txs
  176. =/ missing-txs=(list tx-id:t)
  177. ~(tap z-in (~(dif z-in tx-ids.pag) ~(key z-by raw-txs.p)))
  178. :: return missing txs and new pending state
  179. :- missing-txs
  180. =; pen=pending-state:dk
  181. :: add to list of pending blocks if there are missing txs
  182. =? pending-blocks.pen
  183. !=(~ missing-txs)
  184. (~(put z-by pending-blocks.pen) digest.pag (to-local-page:page:t pag))
  185. pen
  186. %+ roll missing-txs
  187. |= [tid=tx-id:t pen=_p]
  188. :: block requires these txs to be complete
  189. =. block-tx.pen
  190. (~(put z-ju block-tx.pen) digest.pag tid)
  191. :: add block to set of blocks that require this tx
  192. =. tx-block.pen
  193. (~(put z-ju tx-block.pen) tid digest.pag)
  194. pen
  195. ::
  196. ++ remove-pending-block
  197. |= bid=block-id:t
  198. ^- pending-state:dk
  199. =. pending-blocks.p (~(del z-by pending-blocks.p) bid)
  200. :: get the txs that were needed for this block. if it was a valid
  201. :: block, this will be empty already, but if it was invalid we
  202. :: want to clean up the state.
  203. =/ tx-vals=(unit (z-set tx-id:t))
  204. (~(get z-by block-tx.p) bid)
  205. ?~ tx-vals
  206. :: no txs needed by block so just delete from block-tx
  207. =. block-tx.p (~(del z-by block-tx.p) bid)
  208. p
  209. =/ tx-list=(list tx-id:t)
  210. ~(tap z-in u.tx-vals)
  211. =. block-tx.p (~(del z-by block-tx.p) bid)
  212. :: remove the block-id from this map.
  213. =. tx-block.p
  214. %+ roll tx-list
  215. |= [tid=tx-id:t txb=_tx-block.p]
  216. (~(del z-ju txb) tid bid)
  217. p
  218. ::
  219. ++ add-raw-tx
  220. |= raw=raw-tx:t
  221. ^- pending-state:dk
  222. p(raw-txs (~(put z-by raw-txs.p) id.raw raw))
  223. ::
  224. ++ remove-raw-tx
  225. |= tid=tx-id:t
  226. ^- pending-state:dk
  227. p(raw-txs (~(del z-by raw-txs.p) tid))
  228. --