inner.hoon 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855
  1. /= dk /apps/dumbnet/lib/types
  2. /= sp /common/stark/prover
  3. /= c-transact /common/tx-engine
  4. /= dumb-miner /apps/dumbnet/lib/miner
  5. /= dumb-pending /apps/dumbnet/lib/pending
  6. /= dumb-derived /apps/dumbnet/lib/derived
  7. /= dumb-consensus /apps/dumbnet/lib/consensus
  8. /= mine /common/pow
  9. /= nv /common/nock-verifier
  10. /= zeke /common/zeke
  11. /= * /common/zoon
  12. /= * /common/wrapper
  13. ::
  14. :: Never use c-transact face, always use the lustar `t`
  15. :: alias, otherwise the blockchain constants set in the kernel
  16. :: will not be active.
  17. ::
  18. |%
  19. ++ moat (keep kernel-state:dk)
  20. ++ inner
  21. |_ k=kernel-state:dk
  22. +* min ~(. dumb-miner m.k constants.k)
  23. pen ~(. dumb-pending p.k constants.k)
  24. der ~(. dumb-derived d.k constants.k)
  25. con ~(. dumb-consensus c.k constants.k)
  26. t ~(. c-transact constants.k)
  27. ::
  28. :: We should be calling the inner kernel load in case of update
  29. ++ load
  30. |= arg=kernel-state:dk
  31. arg
  32. ::
  33. ::TODO make referentially transparent by requiring event number in the scry path
  34. ++ peek
  35. |= arg=path
  36. ^- (unit (unit *))
  37. =/ =(pole) arg
  38. ?+ pole ~
  39. ::
  40. [%blocks ~]
  41. ^- (unit (unit (z-map block-id:t page:t)))
  42. ``(~(run by blocks.c.k) to-page:local-page:t)
  43. ::
  44. [%transactions ~]
  45. ^- (unit (unit (z-mip block-id:t tx-id:t tx:t)))
  46. ``txs.c.k
  47. ::
  48. [%raw-transactions ~]
  49. ^- (unit (unit (z-map tx-id:t raw-tx:t)))
  50. ``raw-txs.p.k
  51. ::
  52. :: For %block, %transaction, %raw-transaction, and %balance scries, the ID is
  53. :: passed as a base58 encoded string in the scry path.
  54. [%block bid=@ ~]
  55. ^- (unit (unit page:t))
  56. :: scry for a validated block (this does not look at pending state)
  57. =/ block-id (from-b58:hash:t bid.pole)
  58. `(bind (~(get z-by blocks.c.k) block-id) to-page:local-page:t)
  59. ::
  60. [%elders bid=@ peer-id=@ ~]
  61. :: get ancestor block IDs up to 24 deep for a given block
  62. ^- (unit (unit [page-number:t (list block-id:t)]))
  63. =/ block-id (from-b58:hash:t bid.pole)
  64. =/ elders (get-elders:con d.k block-id)
  65. ?~ elders
  66. [~ ~]
  67. ``u.elders
  68. ::
  69. [%transaction tid=@ ~]
  70. :: scry for a tx that has been included in a validated block
  71. ^- (unit (unit (z-map tx-id:t tx:t)))
  72. :- ~
  73. %- ~(get z-by txs.c.k)
  74. (from-b58:hash:t tid.pole)
  75. ::
  76. [%raw-transaction tid=@ ~]
  77. :: scry for a raw-tx
  78. ^- (unit (unit raw-tx:t))
  79. :- ~
  80. %- ~(get z-by raw-txs.p.k)
  81. (from-b58:hash:t tid.pole)
  82. ::
  83. [%heavy ~]
  84. ^- (unit (unit (unit block-id:t)))
  85. ``heaviest-block.c.k
  86. ::
  87. [%heavy-n pag=@ ~]
  88. ^- (unit (unit page:t))
  89. =/ num=(unit page-number:t)
  90. ((soft page-number:t) pag.pole)
  91. ?~ num
  92. ~
  93. =/ id=(unit block-id:t)
  94. (~(get z-by heaviest-chain.d.k) u.num)
  95. ?~ id
  96. [~ ~]
  97. `(bind (~(get z-by blocks.c.k) u.id) to-page:local-page:t)
  98. ::
  99. [%desk-hash ~]
  100. ^- (unit (unit (unit @uvI)))
  101. ``desk-hash.a.k
  102. ::
  103. [%mining-pubkeys ~]
  104. ^- (unit (unit (list [m=@ pks=(list @t)])))
  105. =/ locks=(list [m=@ pks=(list @t)])
  106. %+ turn ~(tap z-in pubkeys.m.k)
  107. |=(=lock:t (to-b58:lock:t lock))
  108. ``locks
  109. ::
  110. [%balance bid=@ ~]
  111. ^- (unit (unit (z-map nname:t nnote:t)))
  112. :- ~
  113. %- ~(get z-by balance.c.k)
  114. (from-b58:hash:t bid.pole)
  115. ::
  116. [%heaviest-block ~]
  117. ^- (unit (unit page:t))
  118. ?~ heaviest-block.c.k
  119. [~ ~]
  120. =/ heaviest-block (~(get z-by blocks.c.k) u.heaviest-block.c.k)
  121. ?~ heaviest-block ~
  122. ``(to-page:local-page:t u.heaviest-block)
  123. ::
  124. [%heavy-summary ~]
  125. ^- (unit (unit [(z-set lock:t) (unit page-summary:t)]))
  126. ?~ heaviest-block.c.k
  127. ``[pubkeys.m.k ~]
  128. =/ heaviest-block (~(get z-by blocks.c.k) u.heaviest-block.c.k)
  129. :+ ~ ~
  130. :- pubkeys.m.k
  131. ?~ heaviest-block
  132. ~
  133. `(to-page-summary:page:t (to-page:local-page:t u.heaviest-block))
  134. ==
  135. ::
  136. ++ poke
  137. |= [wir=wire eny=@ our=@ux now=@da dat=*]
  138. ^- [(list effect:dk) kernel-state:dk]
  139. |^
  140. =/ cause ((soft cause:dk) dat)
  141. ?~ cause
  142. ~> %slog.[0 [%leaf "error: badly formatted cause, should never occur"]]
  143. ~& ;;([thing=@t ver=@ type=@t] [-.dat +<.dat +>-.dat])
  144. `k
  145. =/ cause u.cause
  146. ::~& "inner dumbnet cause: {<[-.cause -.+.cause]>}"
  147. =^ effs k
  148. ?+ wir ~|("unsupported wire: {<wir>}" !!)
  149. [%poke src=?(%nc %timer %sys %miner %npc) ver=@ *]
  150. ?- -.cause
  151. %command (handle-command now p.cause)
  152. %fact (handle-fact wir eny our now p.cause)
  153. ==
  154. ::
  155. [%poke %libp2p ver=@ typ=?(%gossip %response) %peer-id =peer-id:dk *]
  156. ?> ?=(%fact -.cause)
  157. (handle-fact wir eny our now p.cause)
  158. ==
  159. :: possibly update timestamp on candidate block for mining
  160. =. m.k (update-timestamp:min now)
  161. effs^k
  162. ::
  163. :: +heard-genesis-block: check if block is a genesis block and decide whether to keep it
  164. ++ heard-genesis-block
  165. |= [wir=wire now=@da pag=page:t]
  166. ^- [(list effect:dk) kernel-state:dk]
  167. ?: (check-duplicate-block digest.pag)
  168. :: do nothing (idempotency), we already have block
  169. `k
  170. ::
  171. ?~ btc-data.c.k
  172. ~> %slog.[0 leaf+"btc-data not set, crashing"]
  173. !!
  174. ?. (check-genesis pag u.btc-data.c.k genesis-seal.c.k)
  175. :: is not a genesis block, throw it out and inform the king. note this
  176. :: must be a %liar effect since genesis blocks have no powork and are
  177. :: thus cheap to make, so we cannot trust their block-id.
  178. [[(liar-effect wir %not-a-genesis-block)]~ k]
  179. :: heard valid genesis block
  180. ~> %slog.[0 leaf+"validated genesis block!"]
  181. (new-block now pag *tx-acc:t)
  182. ::
  183. ++ heard-block
  184. |= [wir=wire now=@da pag=page:t eny=@]
  185. ^- [(list effect:dk) kernel-state:dk]
  186. ?: =(*page-number:t height.pag)
  187. :: heard genesis block
  188. ~> %slog.[0 leaf+"heard genesis block"]
  189. (heard-genesis-block wir now pag)
  190. ?~ heaviest-block.c.k
  191. =/ peer-id=(unit @) (get-peer-id wir)
  192. ?~ peer-id
  193. :: received block before genesis from source other than libp2p
  194. `k
  195. ~> %slog.[0 [%leaf "no genesis block yet, requesting elders"]]
  196. :_ k
  197. [%request %block %elders digest.pag u.peer-id]~
  198. :: if we don't have parent and block claims to be heaviest
  199. :: request ancestors to catch up or handle reorg
  200. ?. (~(has z-by blocks.c.k) parent.pag)
  201. ?: %+ compare-heaviness:page:t pag
  202. (~(got z-by blocks.c.k) u.heaviest-block.c.k)
  203. =/ peer-id=(unit @) (get-peer-id wir)
  204. ?~ peer-id
  205. ~|("unsupported wire: {<wir>}" !!)
  206. =/ print-var
  207. %- trip
  208. ^- @t
  209. %^ cat 3
  210. 'potential reorg: requesting elders for heavier block: '
  211. (to-b58:hash:t digest.pag)
  212. ~> %slog.[0 [%leaf print-var]]
  213. :_ k
  214. [%request %block %elders digest.pag u.peer-id]~
  215. :: received block, don't have parent, isn't heaviest, ignore.
  216. `k
  217. :: yes, we have its parent
  218. ::
  219. :: do we already have this block?
  220. ?: (check-duplicate-block digest.pag)
  221. :: do nothing (idempotency), we already have block
  222. `k
  223. ::
  224. :: check to see if the .digest is valid. if it is not, we
  225. :: emit a %liar-peer. if it is, then any further %liar effects
  226. :: should be %liar-block-id. this tells the runtime that
  227. :: anybody who sends us this block id is a liar
  228. ?. (check-digest:page:t pag)
  229. ~> %slog.[0 leaf+"digest is not valid"]
  230. :_ k
  231. [(liar-effect wir %page-digest-invalid)]~
  232. ::
  233. :: since we know the digest is valid, we want to tell the runtime
  234. :: to start tracking that block-id.
  235. =/ block-effs=(list effect:dk)
  236. =/ =(pole) wir
  237. ?. ?=([%poke %libp2p ver=@ typ=?(%gossip %response) %peer-id =peer-id:dk *] pole)
  238. ~
  239. [%track %add digest.pag peer-id.pole]~
  240. ::
  241. :: %liar-block-id only says that anybody who sends us this
  242. :: block-id is a liar, but it doesn't (and can't) include the
  243. :: peer id. so it gets cross-referenced with the blocks being
  244. :: tracked to know who to ban.
  245. ::
  246. :: the crash case is when we get a bad block from the npc driver or
  247. :: from the kernel itself.
  248. =/ check-page-without-txs=(reason:dk ~)
  249. (validate-page-without-txs-da:con pag now)
  250. ?: ?=(%.n -.check-page-without-txs)
  251. :: block has bad data
  252. :_ k
  253. :: the order here matters since we want to add the block to tracking
  254. :: and then ban the peer who sent it. we do this instead of %liar-peer
  255. :: since its possible for another poke to be processed after %track %add
  256. :: but before %liar-block-id, so more peers may be added to tracking
  257. :: before %liar-block-id is processed.
  258. %+ snoc block-effs
  259. [%liar-block-id digest.pag +.check-page-without-txs]
  260. ::
  261. ?. (check-pow pag)
  262. :_ k
  263. %+ snoc block-effs
  264. [%liar-block-id digest.pag %failed-pow-check]
  265. ::
  266. :: tell driver we have seen this block so don't send it back to the kernel again
  267. =. block-effs
  268. [[%seen %block digest.pag] block-effs]
  269. :: stop tracking block id as soon as we verify pow
  270. =. block-effs
  271. %+ snoc block-effs
  272. ^- effect:dk
  273. [%track %remove digest.pag]
  274. =^ missing-txs=(list tx-id:t) p.k
  275. (add-pending-block:pen pag)
  276. ?: !=(missing-txs *(list tx-id:t))
  277. ~> %slog.[0 leaf+"missing txs"]
  278. :: block has missing txs
  279. =. block-effs
  280. %+ weld block-effs
  281. %+ turn missing-txs
  282. |= =tx-id:t
  283. ^- effect:dk
  284. [%request %raw-tx %by-id tx-id]
  285. :_ k
  286. ?: %+ compare-heaviness:page:t pag
  287. (~(got z-by blocks.c.k) (need heaviest-block.c.k))
  288. ~> %slog.[0 %leaf^"gossip new heaviest block, have not validated txs yet"]
  289. :- [%gossip %0 %heard-block pag]
  290. block-effs
  291. block-effs
  292. ::
  293. :: block has no missing transactions, so we check that its transactions
  294. :: are valid
  295. (process-block-with-txs now pag block-effs)
  296. ::
  297. :: +heard-elders: handle response to parent hashes request
  298. ++ heard-elders
  299. |= [wir=wire now=@da oldest=page-number:t ids=(list block-id:t)]
  300. ^- [(list effect:dk) kernel-state:dk]
  301. :: extract peer ID from wire
  302. =/ peer-id=(unit @) (get-peer-id wir)
  303. ?~ peer-id
  304. ~|("unsupported wire: {<wir>}" !!)
  305. =/ ids-lent (lent ids)
  306. ?: (gth ids-lent 24)
  307. :_ k
  308. [[%liar-peer u.peer-id %more-than-24-parent-hashes]~]
  309. ?. ?| =(oldest *page-number:t)
  310. =(ids-lent 24)
  311. ==
  312. ~> %slog.[0 %leaf^"bad elders: either oldest should be genesis or need 24 elders"]
  313. :: either oldest is genesis OR we must have received exactly 24 ids
  314. :_ k
  315. [[%liar-peer u.peer-id %less-than-24-parent-hashes]~]
  316. :: find highest block we have in the ancestor list
  317. =/ latest-known=(unit [=block-id:t =page-number:t])
  318. =/ height (dec (add oldest ids-lent))
  319. |-
  320. ?~ ids ~
  321. ?: =(height 0) ~
  322. ?: (~(has z-by blocks.c.k) i.ids)
  323. `[i.ids height]
  324. $(ids t.ids, height (dec height))
  325. ?~ latest-known
  326. ?: =(oldest *page-number:t)
  327. ?: =(~ heaviest-block.c.k)
  328. :: request genesis block because we don't have it yet
  329. :_ k
  330. [%request %block %by-height *page-number:t]~
  331. :: if we have differing genesis blocks, liar
  332. ~> %slog.[0 %leaf^"bad elders: differing genesis blocks"]
  333. :_ k
  334. [[%liar-peer u.peer-id %differing-genesis]~]
  335. :: request elders of oldest ancestor to catch up faster
  336. :: hashes are ordered newest>oldest
  337. =/ print-var
  338. "processed elders and asking for oldest: requesting elders"
  339. ~> %slog.[0 %leaf^print-var]
  340. :_ k
  341. [%request %block %elders (rear ids) u.peer-id]~
  342. =/ print-var
  343. %- trip
  344. %^ cat 3
  345. 'processed elders and found intersection: requesting next block '
  346. (scot %ud +(page-number.u.latest-known))
  347. ~> %slog.[0 %leaf^print-var]
  348. :: request next block after our highest known block
  349. :: this will trigger either catchup or reorg from this point
  350. :_ k
  351. [%request %block %by-height +(page-number.u.latest-known)]~
  352. ::
  353. ++ check-duplicate-block
  354. |= digest=block-id:t
  355. ?| (~(has z-by blocks.c.k) digest)
  356. (~(has z-by pending-blocks.p.k) digest)
  357. ==
  358. ::
  359. ++ check-genesis
  360. |= [pag=page:t =btc-hash:t =genesis-seal:t]
  361. ^- ?
  362. =/ check-pow-hash=?
  363. ?. check-pow-flag:t
  364. :: this case only happens during testing
  365. ::~& "skipping pow hash check for {(trip (to-b58:hash:t digest.pag))}"
  366. %.y
  367. %- check-target:mine
  368. :_ target.pag
  369. (digest-to-atom:tip5:zeke (hash-proof:zeke (need pow.pag)))
  370. =/ check-pow-valid=? (check-pow pag)
  371. =/ check-txs=? =(tx-ids.pag *(z-set tx-id:t))
  372. =/ check-epoch=? =(epoch-counter.pag *@)
  373. =/ check-target=? =(target.pag genesis-target:t)
  374. =/ check-work=? =(accumulated-work.pag (compute-work:page:t genesis-target:t))
  375. =/ check-coinbase=? =(coinbase.pag *(z-map lock:t @))
  376. =/ check-height=? =(height.pag *page-number:t)
  377. =/ check-btc-hash=?
  378. =(parent.pag (hash:btc-hash:t btc-hash))
  379. ::
  380. :: check that the message matches what's in the seal
  381. =/ check-msg=?
  382. ?~ genesis-seal %.y
  383. =((hash:page-msg:t msg.pag) msg-hash.u.genesis-seal)
  384. ?& check-pow-hash
  385. check-pow-valid
  386. check-txs
  387. check-epoch
  388. check-target
  389. check-work
  390. check-coinbase
  391. check-height
  392. check-msg
  393. check-btc-hash
  394. ==
  395. ++ check-pow
  396. |= pag=page:t
  397. ^- ?
  398. ?. check-pow-flag:t
  399. ~> %slog.[0 leaf+"WARNING: check-pow-flag is off, skipping pow check"]
  400. :: this case only happens during testing
  401. %.y
  402. ?~ pow.pag
  403. %.n
  404. ::
  405. :: validate that powork puzzle in the proof is correct.
  406. ?& (check-pow-puzzle u.pow.pag pag)
  407. ::
  408. :: validate the powork. this is done separately since the
  409. :: other checks are much cheaper.
  410. (verify:nv u.pow.pag ~ eny)
  411. ==
  412. ::
  413. ++ check-pow-puzzle
  414. |= [pow=proof:sp pag=page:t]
  415. ^- ?
  416. ?: =((lent objects.pow) 0)
  417. %.n
  418. =/ puzzle (snag 0 objects.pow)
  419. ?. ?=(%puzzle -.puzzle)
  420. %.n
  421. ?& =((block-commitment:page:t pag) commitment.puzzle)
  422. =(pow-len.zeke len.puzzle)
  423. ==
  424. ::
  425. ++ heard-tx
  426. |= [wir=wire now=@da raw=raw-tx:t]
  427. ^- [(list effect:dk) kernel-state:dk]
  428. =/ id-b58 (to-b58:hash:t id.raw)
  429. ::
  430. :: check tx-id. this is the fastest check to do, so we try it first before
  431. :: calling validate:raw-tx (which also checks the id)
  432. ?. =((compute-id:raw-tx:t raw) id.raw)
  433. :_ k
  434. [(liar-effect wir %tx-id-invalid)]~
  435. ::
  436. :: do we already have raw-tx?
  437. ?: (~(has z-by raw-txs.p.k) id.raw)
  438. :: do nothing (idempotency), we already have it
  439. `k
  440. ::
  441. :: check if raw-tx is part of a pending block
  442. ::
  443. =/ tx-pending-blocks=(list block-id:t)
  444. ~(tap z-in (~(get z-ju tx-block.p.k) id.raw))
  445. ?: !=(*(list block-id:t) tx-pending-blocks)
  446. :: pending blocks are waiting on tx
  447. ?. (validate:raw-tx:t raw)
  448. :: raw-tx doesn't validate.
  449. :: remove blocks containing bad tx from pending state. note that since
  450. :: we already checked that the id of the transaction was valid, we
  451. :: won't accidentally throw out a block that contained a valid tx-id
  452. :: just because we received a tx that claimed the same id as the valid
  453. :: one.
  454. =. p.k
  455. %+ roll tx-pending-blocks
  456. |= [id=block-id:t pend=_p.k]
  457. (remove-pending-block:pen id)
  458. ::
  459. :_ k
  460. [(liar-effect wir %page-pending-raw-tx-invalid) ~]
  461. :: add to raw-txs map, remove from tx-block jug, remove from
  462. :: block-tx jug
  463. =. p.k (add-tx-in-pending-block:pen raw)
  464. (process-ready-blocks now raw)
  465. :: no pending blocks waiting on tx
  466. ::
  467. :: check if any inputs are absent in heaviest balance
  468. ?. (inputs-in-heaviest-balance:con raw)
  469. :: input(s) in tx not in balance, discard tx
  470. `k
  471. :: all inputs in balance
  472. ::
  473. :: check if any inputs are in spent-by
  474. ?: (inputs-in-spent-by:pen raw)
  475. :: inputs present in spent-by, discard tx
  476. `k
  477. :: inputs not present in spent-by
  478. ?. (validate:raw-tx:t raw)
  479. :: raw-tx doesn't validate.
  480. :_ k
  481. [(liar-effect wir %tx-inputs-not-in-spent-by-and-invalid)]~
  482. ::
  483. =. p.k
  484. (add-tx-not-in-pending-block:pen raw get-cur-height:con)
  485. ::
  486. :: next we would process blocks made ready by tx but we already
  487. :: determined that no pending blocks were waiting on this this,
  488. :: so we just tell the miner.
  489. =. m.k (heard-new-tx:min raw)
  490. :- ~[[%seen %tx id.raw]]
  491. k
  492. ::
  493. :: +process-ready-blocks: process blocks no longer waitings on txs
  494. ++ process-ready-blocks
  495. |= [now=@da raw=raw-tx:t]
  496. ^- [(list effect:dk) kernel-state:dk]
  497. :: .work contains block-ids for blocks that no longer have any
  498. :: missing transactions
  499. =/ work=(z-set block-id:t) find-ready-blocks:pen
  500. =^ eff k
  501. %+ roll ~(tap z-in work)
  502. |= [bid=block-id:t effs=(list effect:dk) k=_k]
  503. :: process the block, skipping the steps that we know its already
  504. :: done by the fact that it was in pending-blocks.p.k
  505. =^ new-effs k
  506. %^ process-block-with-txs now
  507. (to-page:local-page:t (~(got z-by pending-blocks.p.k) bid))
  508. :: if the block is bad, then tell the driver never to send it
  509. :: to us again
  510. ~[[%seen %block bid]]
  511. :: remove the block from pending blocks. at this point, its either
  512. :: been discarded by the kernel or lives in the consensus state
  513. =. p.k (remove-pending-block:pen bid)
  514. :: add the effects onto the list and return the updated kernel state
  515. [(weld new-effs effs) k]
  516. ::
  517. :: tell the miner about the new transaction. this might look strange
  518. :: informing it here, potentially after new blocks have been made ready
  519. :: by it, but this tx may be part of a reorg, so the processed blocks
  520. :: might not be the heaviest.
  521. =. m.k (heard-new-tx:min raw)
  522. ::
  523. eff^k
  524. ::
  525. ::
  526. ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  527. :: the remaining arms are used by both %heard-tx and %heard-block
  528. ::
  529. :: +process-block-with-txs: process a block that we have all txs for
  530. ::
  531. :: this is called along the codepath for both %heard-block and +heard-tx,
  532. :: since once we hear the last transaction we're waiting for in a given
  533. :: block, we immediately try to validate it. the genesis block does _not_
  534. :: go through here.
  535. ::
  536. :: bad-block-effs are effects which are passed through and emitted
  537. :: only if the block is bad. If the block is good then ++new-block
  538. :: emits effects and bad-block-effs is ignored.
  539. ++ process-block-with-txs
  540. |= [now=@da pag=page:t bad-block-effs=(list effect:dk)]
  541. ^- [(list effect:dk) kernel-state:dk]
  542. =/ digest-b58 (to-b58:hash:t digest.pag)
  543. ::
  544. :: if we do have all raw-txs, check if pag validates
  545. :: (i.e. transactions are valid and size isnt too big)
  546. =/ new-transfers=(reason:dk tx-acc:t)
  547. (validate-page-with-txs:con p.k pag)
  548. ?- -.new-transfers
  549. %.y
  550. (new-block now pag +.new-transfers)
  551. ::
  552. %.n
  553. :: did not validate, so we throw the block out and stop
  554. :: tracking it
  555. [bad-block-effs k]
  556. ==
  557. ::
  558. :: +new-block: update kernel state with new valid block.
  559. ++ new-block
  560. |= [now=@da pag=page:t acc=tx-acc:t]
  561. ^- [(list effect:dk) kernel-state:dk]
  562. ::
  563. :: page is validated, update consensus and derived state
  564. =. c.k (add-page:con pag acc now)
  565. =/ print-var
  566. %- trip
  567. ^- @t
  568. %+ rap 3
  569. :~ 'block ' (to-b58:hash:t digest.pag)
  570. ' added to validated blocks at ' (scot %u height.pag)
  571. ==
  572. ~> %slog.[0 %leaf^print-var]
  573. ::
  574. =/ effs=(list effect:dk)
  575. :: request block N+1 on each peer's heaviest chain
  576. :+ [%request %block %by-height +(height.pag)]
  577. :: tell driver we've seen this block so don't process it again
  578. [%seen %block digest.pag]
  579. ~
  580. ::
  581. =/ old-heavy heaviest-block.c.k
  582. =. c.k (update-heaviest:con pag)
  583. :: if block is the new heaviest block, gossip it to peers
  584. =? effs !=(old-heavy heaviest-block.c.k)
  585. ~> %slog.[0 %leaf^"dumbnet: new heaviest block!"]
  586. =/ span=span-effect:dk
  587. :+ %span %new-heaviest-chain
  588. ~['block_height'^n+height.pag 'heaviest_block_digest'^s+(to-b58:hash:t digest.pag)]
  589. :* [%gossip %0 %heard-block pag]
  590. span
  591. effs
  592. ==
  593. :: refresh pending state
  594. =. p.k (refresh-after-new-block:pen c.k retain.a.k)
  595. ::
  596. :: tell the miner about the new block
  597. =. m.k (heard-new-block:min c.k p.k now)
  598. ::
  599. :: update derived state
  600. =. d.k (update:der c.k pag)
  601. ::
  602. effs^k
  603. ::
  604. :: +liar-effect: produce the appropriate liar effect
  605. ::
  606. :: this only produces the `%liar-peer` effect. the other possibilities
  607. :: are receiving a bad block or tx via the npc driver or from within
  608. :: the miner module or +do-genesis. in this case we just emit a
  609. :: warning and crash, since that means there's a bug.
  610. ++ liar-effect
  611. |= [wir=wire r=term]
  612. ^- effect:dk
  613. ?+ wir ~|("bad wire for liar effect! {<wir>}" !!)
  614. [%poke %libp2p ver=@ typ=?(%gossip %response) %peer-id id=@ *]
  615. [%liar-peer (need (get-peer-id wir)) r]
  616. ::
  617. [%poke %npc ver=@ *]
  618. ~| 'ATTN: received a bad block or tx via npc driver'
  619. !!
  620. ::
  621. [%poke %miner *]
  622. :: this indicates that the mining module built a bad block and then
  623. :: told the kernel about it. alternatively, +do-genesis produced
  624. :: a bad genesis block. this should never happen, it indicates
  625. :: a serious bug otherwise.
  626. ~| 'ATTN: miner or +do-genesis produced a bad block!'
  627. !!
  628. ==
  629. ::
  630. ++ get-peer-id
  631. |= wir=wire
  632. ^- (unit @)
  633. =/ =(pole) wir
  634. ?. ?=([%poke %libp2p ver=@ typ=?(%gossip %response) %peer-id id=@ *] pole)
  635. ~
  636. (some id.pole)
  637. ::
  638. ++ handle-command
  639. |= [now=@da =command:dk]
  640. ^- [(list effect:dk) kernel-state:dk]
  641. :: ~& "handling command: {<-.command>}"
  642. ?: &(?=(init-command:dk -.command) !init.a.k)
  643. :: kernel no longer in init phase, can't do init command
  644. ~> %slog.[0 leaf+"kernel no longer in init phase, can't do init command"]
  645. `k
  646. ?: &(?=(non-init-command:dk -.command) init.a.k)
  647. :: kernel in init phase, can't perform command
  648. ~> %slog.[0 leaf+"kernel is in init phase, can't do non-init command"]
  649. `k
  650. |^
  651. ?- -.command
  652. %born
  653. do-born
  654. ::
  655. %mine
  656. do-mine
  657. ::
  658. %set-mining-key
  659. do-set-mining-key
  660. ::
  661. %set-mining-key-advanced
  662. do-set-mining-key-advanced
  663. ::
  664. %enable-mining
  665. do-enable-mining
  666. ::
  667. %timer
  668. do-timer
  669. ::
  670. %set-genesis-seal
  671. =. c.k (set-genesis-seal:con p.command)
  672. `k
  673. ::
  674. %genesis
  675. do-genesis
  676. ::
  677. %btc-data
  678. do-btc-data
  679. ::
  680. %set-constants
  681. `k(constants p.command)
  682. ==
  683. ::
  684. ++ do-born
  685. ^- [(list effect:dk) kernel-state:dk]
  686. ?> ?=([%born *] command)
  687. :: once born command is registered, the init phase is over
  688. :: note state update won't be registered unless poke is successful.
  689. =. k k(init.a %.n)
  690. :: do we have any blocks?
  691. ?~ heaviest-block.c.k
  692. :: no, request genesis block
  693. ?~ btc-data.c.k
  694. ~> %slog.[0 leaf+"No genesis parent btc block hash set, crashing"]
  695. !!
  696. :: requesting any genesis block, keeping first one we see.
  697. :: we do not request blocks by id so we can only request height 0
  698. :: blocks and throw out ones we aren't expecting
  699. ~> %slog.[0 leaf+"Requesting genesis block"]
  700. :_ k
  701. [%request %block %by-height *page-number:t]~
  702. :: yes, so get height N of heaviest block and request the block
  703. :: of height N+1
  704. =/ height=page-number:t
  705. +(height:(~(got z-by blocks.c.k) u.heaviest-block.c.k))
  706. ~> %slog.[0 leaf+"dumbnet born"]
  707. :_ k
  708. [%request %block %by-height height]~
  709. ::
  710. ++ do-mine
  711. ^- [(list effect:dk) kernel-state:dk]
  712. ?> ?=([%mine *] command)
  713. ?: =(*(z-set lock:t) pubkeys.m.k)
  714. ::~& "cannot mine without first setting pubkey with %set-mining-key"
  715. `k
  716. ?. mining.m.k
  717. `k
  718. =/ commit=block-commitment:t
  719. (block-commitment:page:t candidate-block.m.k)
  720. =/ [prf=proof:sp dig=tip5-hash-atom:zeke]
  721. (prove-block:mine commit p.command)
  722. ?: %+ check-target:mine dig
  723. (~(got z-by targets.c.k) parent.candidate-block.m.k)
  724. =. m.k (set-pow:min prf)
  725. =. m.k set-digest:min
  726. ::
  727. (heard-block /poke/miner now candidate-block.m.k eny)
  728. `k
  729. ::
  730. ++ do-set-mining-key
  731. ^- [(list effect:dk) kernel-state:dk]
  732. ?> ?=([%set-mining-key *] command)
  733. =/ pk=schnorr-pubkey:t (from-b58:schnorr-pubkey:t p.command)
  734. =/ =lock:t (new:lock:t pk)
  735. =. m.k (set-pubkeys:min [lock]~)
  736. =. m.k (set-shares:min [lock 100]~)
  737. :: ~& > "pubkeys.m set to {<pubkeys.m.k>}"
  738. :: ~& > "shares.m set to {<shares.m.k>}"
  739. `k
  740. ::
  741. ++ do-set-mining-key-advanced
  742. ^- [(list effect:dk) kernel-state:dk]
  743. ?> ?=([%set-mining-key-advanced *] command)
  744. ?: (gth (lent p.command) 2)
  745. ~> %slog.[0 [%leaf "coinbase split for more than two locks not yet supported, doing nothing"]]
  746. `k
  747. ?~ p.command
  748. ~> %slog.[0 [%leaf "empty list of locks, doing nothing."]]
  749. `k
  750. ::
  751. =/ keys=(list lock:t)
  752. %+ turn p.command
  753. |= [s=@ m=@ ks=(list @t)]
  754. (from-b58:lock:t m ks)
  755. =/ shares=(list [lock:t @])
  756. %+ turn p.command
  757. |= [s=@ m=@ ks=(list @t)]
  758. [(from-b58:lock:t m ks) s]
  759. =. m.k (set-pubkeys:min keys)
  760. =. m.k (set-shares:min shares)
  761. :: ~& > "pubkeys.m set to {<pubkeys.m.k>}"
  762. :: ~& > "shares.m set to {<shares.m.k>}"
  763. `k
  764. ::
  765. ++ do-enable-mining
  766. ^- [(list effect:dk) kernel-state:dk]
  767. ?> ?=([%enable-mining *] command)
  768. ?. p.command
  769. ::~& > 'generation of candidate blocks disabled'
  770. =. m.k (set-mining:min p.command)
  771. `k
  772. ?: =(*(z-set lock:t) pubkeys.m.k)
  773. :: ~& >
  774. :: """
  775. :: generation of candidate blocks has not been enabled because mining pubkey
  776. :: is empty. set it with %set-mining-key then run %enable-mining again
  777. :: """
  778. `k
  779. ?: =(~ heaviest-block.c.k)
  780. ::~& >
  781. :: """
  782. :: generation of candidate blocks enabled. candidate block will be generated
  783. :: once a genesis block has been received.
  784. :: """
  785. =. m.k (set-mining:min p.command)
  786. `k
  787. ::~& > 'generation of candidate blocks enabled.'
  788. =. m.k (set-mining:min p.command)
  789. =. m.k (heard-new-block:min c.k p.k now)
  790. `k
  791. ::
  792. ++ do-timer
  793. ::TODO post-dumbnet: only rerequest transactions a max of once/twice (maybe an admin param)
  794. ^- [(list effect:dk) kernel-state:dk]
  795. ?> ?=([%timer *] command)
  796. ?: init.a.k
  797. :: kernel in init phase, command ignored
  798. `k
  799. =/ tx-req-effs=(list effect:dk)
  800. %+ turn ~(tap z-by find-pending-tx-ids:pen)
  801. |= =tx-id:t
  802. ^- effect:dk
  803. [%request %raw-tx %by-id tx-id]
  804. ::
  805. :: we always request the next heaviest block with each %timer event
  806. =/ heavy-height=page-number:t
  807. ?~ heaviest-block.c.k
  808. *page-number:t :: rerequest genesis block
  809. +(height:(~(got z-by blocks.c.k) u.heaviest-block.c.k))
  810. =/ effs=(list effect:dk)
  811. :- [%request %block %by-height heavy-height]
  812. tx-req-effs
  813. effs^k
  814. ::
  815. ++ do-genesis
  816. :: generate genesis block and sets it as candidate block
  817. ^- [(list effect:dk) kernel-state:dk]
  818. ?> ?=([%genesis *] command)
  819. :: creating genesis block with template
  820. ~> %slog.[0 leaf+"create genesis block with template"]
  821. =/ =genesis-template:t
  822. (new:genesis-template:t p.command)
  823. =/ genesis-page=page:t
  824. (new-genesis:page:t genesis-template now)
  825. =. candidate-block.m.k genesis-page
  826. =. c.k (add-btc-data:con btc-hash.p.command)
  827. `k
  828. ::
  829. ++ do-btc-data
  830. ^- [(list effect:dk) kernel-state:dk]
  831. ?> ?=([%btc-data *] command)
  832. =. c.k (add-btc-data:con p.command)
  833. ~> %slog.[0 leaf+"received btc block hash, waiting to hear nockchain genesis block!"]
  834. `k
  835. --::+handle-command
  836. ::
  837. ++ handle-fact
  838. |= [wir=wire eny=@ our=@ux now=@da =fact:dk]
  839. ^- [(list effect:dk) kernel-state:dk]
  840. ?: init.a.k
  841. :: kernel in init phase, fact ignored
  842. `k
  843. ?- -.data.fact
  844. %heard-block
  845. (heard-block wir now p.data.fact eny)
  846. ::
  847. %heard-tx
  848. (heard-tx wir now p.data.fact)
  849. ::
  850. %heard-elders
  851. (heard-elders wir now p.data.fact)
  852. ==
  853. --:: +poke
  854. --:: +kernel
  855. --