| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- /= dk /apps/dumbnet/lib/types
- /= sp /common/stark/prover
- /= dumb-transact /common/tx-engine
- /= * /common/zoon
- ::
- :: everything to do with mining and mining state
- ::
- |_ [m=mining-state:dk =blockchain-constants:dumb-transact]
- +* t ~(. dumb-transact blockchain-constants)
- +| %admin
- :: +set-mining: set .mining
- ++ set-mining
- |= mine=?
- ^- mining-state:dk
- m(mining mine)
- ::
- :: +set-pubkey: set .pubkey
- ++ set-pubkeys
- |= pks=(list lock:t)
- ^- mining-state:dk
- =. pubkeys.m
- (~(gas z-in *(z-set lock:t)) pks)
- m
- ::
- :: +set-shares set .shares
- ++ set-shares
- |= shr=(list [lock:t @])
- =. shares.m
- (~(gas z-by *(z-map lock:t @)) shr)
- m
- ::
- +| %candidate-block
- ++ set-pow
- |= prf=proof:sp
- ^- mining-state:dk
- m(pow.candidate-block (some prf))
- ::
- ++ set-digest
- ^- mining-state:dk
- m(digest.candidate-block (compute-digest:page:t candidate-block.m))
- ::
- :: +update-timestamp: updates timestamp on candidate block if needed
- ::
- :: this should be run every time we get a poke.
- ++ update-timestamp
- |= now=@da
- ^- mining-state:dk
- ?: |(=(*page:t candidate-block.m) !mining.m)
- :: not mining or no candidate block is set so no need to update timestamp
- m
- ?: %+ gte timestamp.candidate-block.m
- (time-in-secs:page:t (sub now update-candidate-timestamp-interval:t))
- :: has not been ~m2, so leave timestamp alone
- m
- =. timestamp.candidate-block.m (time-in-secs:page:t now)
- ::~& >
- :: "candidate block timestamp updated: {(scow %$ timestamp.candidate-block.m)}"
- m
- ::
- :: +heard-new-tx: potentially changes candidate block in reaction to a raw-tx
- ++ heard-new-tx
- |= raw=raw-tx:t
- ^- mining-state:dk
- ?. mining.m m :: if we're not mining, do nothing
- ::
- :: if the mining pubkey is not set, do nothing
- ?: =(*(z-set lock:t) pubkeys.m) m
- :: check to see if block is valid with tx - this checks whether the inputs
- :: exist, whether the new size will exceed block size, and whether timelocks
- :: are valid
- =/ tx=(unit tx:t) (mole |.((new:tx:t raw height.candidate-block.m)))
- ?~ tx
- :: invalid tx. we don't emit a %liar effect from this because it might
- :: just not be valid for this particular block
- m
- =/ new-acc=(unit tx-acc:t)
- (process:tx-acc:t candidate-acc.m u.tx height.candidate-block.m)
- ?~ new-acc
- ::~& >>> """
- :: tx {(trip (to-b58:hash:t id.raw))} cannot be added to candidate
- :: block.
- :: """
- m
- :: we can add tx to candidate-block
- =. tx-ids.candidate-block.m
- (~(put z-in tx-ids.candidate-block.m) id.raw)
- =/ old-fees=coins:t fees.candidate-acc.m
- =. candidate-acc.m u.new-acc
- =/ new-fees=coins:t fees.candidate-acc.m
- :: check if new-fees != old-fees to determine if split should be recalculated.
- :: since we don't have replace-by-fee
- ?: =(new-fees old-fees)
- :: fees are equal so no need to recalculate split
- m
- :: fees are unequal. for this miner, fees are only ever monotonically
- :: incremented and so this assertion should never fail.
- ?> (gth new-fees old-fees)
- =/ fee-diff=coins:t (sub new-fees old-fees)
- :: compute old emission+fees
- =/ old-assets=coins:t
- %+ roll ~(val z-by coinbase.candidate-block.m)
- |= [c=coins:t sum=coins:t]
- (add c sum)
- =/ new-assets=coins:t (add old-assets fee-diff)
- =. coinbase.candidate-block.m
- (new:coinbase-split:t new-assets shares.m)
- m
- ::
- :: +heard-new-block: refreshes the candidate block to be mined in reaction to a new block
- ::
- :: when we hear a new heaviest block, we need to update the candidate we're attempting
- :: to mine. that means we should update the parent and page number of the block, and carry
- :: over any transactions we had previously been attempting to include that werent
- :: included in the most recent block.
- ++ heard-new-block
- |= [c=consensus-state:dk p=pending-state:dk now=@da]
- ^- mining-state:dk
- ?. mining.m m :: if we're not mining, do nothing
- ::
- :: do a sanity check that we have a heaviest block, and that the heaviest block
- :: is not the parent of our current candidate block
- ?~ heaviest-block.c
- :: genesis block has its own codepath, which is why this conditional does not attempt
- :: to generate the genesis block
- ::~& >>>
- :: "attempted to generate new candidate block when we have no genesis block"
- m
- ?: =(u.heaviest-block.c parent.candidate-block.m)
- ::~& >
- :: "heaviest block unchanged, do not generate new candidate block"
- m
- ?: =(*(z-set lock:t) pubkeys.m)
- :: ~& > "no pubkey(s) set so no new candidate block will be generated"
- m
- ::~& >
- :: """
- :: generating new candidate block with parent
- :: {(trip (to-b58:hash:t u.heaviest-block.c))}
- :: """
- =. candidate-block.m
- %- new:page:t
- :* (to-page:local-page:t (~(got z-by blocks.c) u.heaviest-block.c))
- now
- (~(got z-by targets.c) u.heaviest-block.c)
- shares.m
- ==
- =. candidate-acc.m
- (new:tx-acc:t (~(get z-by balance.c) u.heaviest-block.c))
- ::
- :: roll over the pending txs and try to include them in the new candidate block
- %+ roll ~(val z-by raw-txs.p)
- |= [raw=raw-tx:t min=_m]
- (heard-new-tx raw)
- --
|