miner.hoon 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. /= dk /apps/dumbnet/lib/types
  2. /= sp /common/stark/prover
  3. /= dumb-transact /common/tx-engine
  4. /= * /common/zoon
  5. ::
  6. :: everything to do with mining and mining state
  7. ::
  8. |_ [m=mining-state:dk =blockchain-constants:dumb-transact]
  9. +* t ~(. dumb-transact blockchain-constants)
  10. +| %admin
  11. :: +set-mining: set .mining
  12. ++ set-mining
  13. |= mine=?
  14. ^- mining-state:dk
  15. m(mining mine)
  16. ::
  17. :: +set-pubkey: set .pubkey
  18. ++ set-pubkeys
  19. |= pks=(list lock:t)
  20. ^- mining-state:dk
  21. =. pubkeys.m
  22. (~(gas z-in *(z-set lock:t)) pks)
  23. m
  24. ::
  25. :: +set-shares set .shares
  26. ++ set-shares
  27. |= shr=(list [lock:t @])
  28. =. shares.m
  29. (~(gas z-by *(z-map lock:t @)) shr)
  30. m
  31. ::
  32. +| %candidate-block
  33. ++ set-pow
  34. |= prf=proof:sp
  35. ^- mining-state:dk
  36. m(pow.candidate-block (some prf))
  37. ::
  38. ++ set-digest
  39. ^- mining-state:dk
  40. m(digest.candidate-block (compute-digest:page:t candidate-block.m))
  41. ::
  42. :: +update-timestamp: updates timestamp on candidate block if needed
  43. ::
  44. :: this should be run every time we get a poke.
  45. ++ update-timestamp
  46. |= now=@da
  47. ^- mining-state:dk
  48. ?: |(=(*page:t candidate-block.m) !mining.m)
  49. :: not mining or no candidate block is set so no need to update timestamp
  50. m
  51. ?: %+ gte timestamp.candidate-block.m
  52. (time-in-secs:page:t (sub now update-candidate-timestamp-interval:t))
  53. :: has not been ~m2, so leave timestamp alone
  54. m
  55. =. timestamp.candidate-block.m (time-in-secs:page:t now)
  56. ::~& >
  57. :: "candidate block timestamp updated: {(scow %$ timestamp.candidate-block.m)}"
  58. m
  59. ::
  60. :: +heard-new-tx: potentially changes candidate block in reaction to a raw-tx
  61. ++ heard-new-tx
  62. |= raw=raw-tx:t
  63. ^- mining-state:dk
  64. ?. mining.m m :: if we're not mining, do nothing
  65. ::
  66. :: if the mining pubkey is not set, do nothing
  67. ?: =(*(z-set lock:t) pubkeys.m) m
  68. :: check to see if block is valid with tx - this checks whether the inputs
  69. :: exist, whether the new size will exceed block size, and whether timelocks
  70. :: are valid
  71. =/ tx=(unit tx:t) (mole |.((new:tx:t raw height.candidate-block.m)))
  72. ?~ tx
  73. :: invalid tx. we don't emit a %liar effect from this because it might
  74. :: just not be valid for this particular block
  75. m
  76. =/ new-acc=(unit tx-acc:t)
  77. (process:tx-acc:t candidate-acc.m u.tx height.candidate-block.m)
  78. ?~ new-acc
  79. ::~& >>> """
  80. :: tx {(trip (to-b58:hash:t id.raw))} cannot be added to candidate
  81. :: block.
  82. :: """
  83. m
  84. :: we can add tx to candidate-block
  85. =. tx-ids.candidate-block.m
  86. (~(put z-in tx-ids.candidate-block.m) id.raw)
  87. =/ old-fees=coins:t fees.candidate-acc.m
  88. =. candidate-acc.m u.new-acc
  89. =/ new-fees=coins:t fees.candidate-acc.m
  90. :: check if new-fees != old-fees to determine if split should be recalculated.
  91. :: since we don't have replace-by-fee
  92. ?: =(new-fees old-fees)
  93. :: fees are equal so no need to recalculate split
  94. m
  95. :: fees are unequal. for this miner, fees are only ever monotonically
  96. :: incremented and so this assertion should never fail.
  97. ?> (gth new-fees old-fees)
  98. =/ fee-diff=coins:t (sub new-fees old-fees)
  99. :: compute old emission+fees
  100. =/ old-assets=coins:t
  101. %+ roll ~(val z-by coinbase.candidate-block.m)
  102. |= [c=coins:t sum=coins:t]
  103. (add c sum)
  104. =/ new-assets=coins:t (add old-assets fee-diff)
  105. =. coinbase.candidate-block.m
  106. (new:coinbase-split:t new-assets shares.m)
  107. m
  108. ::
  109. :: +heard-new-block: refreshes the candidate block to be mined in reaction to a new block
  110. ::
  111. :: when we hear a new heaviest block, we need to update the candidate we're attempting
  112. :: to mine. that means we should update the parent and page number of the block, and carry
  113. :: over any transactions we had previously been attempting to include that werent
  114. :: included in the most recent block.
  115. ++ heard-new-block
  116. |= [c=consensus-state:dk p=pending-state:dk now=@da]
  117. ^- mining-state:dk
  118. ?. mining.m m :: if we're not mining, do nothing
  119. ::
  120. :: do a sanity check that we have a heaviest block, and that the heaviest block
  121. :: is not the parent of our current candidate block
  122. ?~ heaviest-block.c
  123. :: genesis block has its own codepath, which is why this conditional does not attempt
  124. :: to generate the genesis block
  125. ::~& >>>
  126. :: "attempted to generate new candidate block when we have no genesis block"
  127. m
  128. ?: =(u.heaviest-block.c parent.candidate-block.m)
  129. ::~& >
  130. :: "heaviest block unchanged, do not generate new candidate block"
  131. m
  132. ?: =(*(z-set lock:t) pubkeys.m)
  133. :: ~& > "no pubkey(s) set so no new candidate block will be generated"
  134. m
  135. ::~& >
  136. :: """
  137. :: generating new candidate block with parent
  138. :: {(trip (to-b58:hash:t u.heaviest-block.c))}
  139. :: """
  140. =. candidate-block.m
  141. %- new:page:t
  142. :* (to-page:local-page:t (~(got z-by blocks.c) u.heaviest-block.c))
  143. now
  144. (~(got z-by targets.c) u.heaviest-block.c)
  145. shares.m
  146. ==
  147. =. candidate-acc.m
  148. (new:tx-acc:t (~(get z-by balance.c) u.heaviest-block.c))
  149. ::
  150. :: roll over the pending txs and try to include them in the new candidate block
  151. %+ roll ~(val z-by raw-txs.p)
  152. |= [raw=raw-tx:t min=_m]
  153. (heard-new-tx raw)
  154. --