three.hoon 55 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921
  1. /= ztd-two /common/ztd/two
  2. => ztd-two
  3. ~% %misc-lib ..lift ~
  4. :: misc-lib
  5. |%
  6. :: +flec: reflect a noun, i.e. switch head and tail
  7. ++ flec
  8. |* *
  9. ?@ +< +<
  10. +<+^+<-
  11. ::
  12. ++ lib-u32
  13. ~% %lib-u32 + ~
  14. :: Unsigned 32-bit Arithmetic
  15. |%
  16. +$ u32 @udthirtytwo
  17. ++ bex32 ^~((bex 32)) :: 4.294.967.296
  18. ++ max32 ^~((dec (bex 32))) :: 4.294.967.295
  19. ::
  20. :: +is-u32: is atom a u32?
  21. ++ is-u32
  22. ~/ %is-u32
  23. |= a=@
  24. ^- ?
  25. (lth a bex32)
  26. ::
  27. :: +belt-to-u32: decompose a belt to u32s
  28. ++ belt-to-u32s
  29. ~/ %btu32s
  30. |= sam=belt
  31. ^- [lo=u32 hi=u32]
  32. ?> (lth sam p) ::NOTE: in flib and jutes, this is bex64 instead of goldilocks prime?
  33. :: ?> (lth sam (bex 64))
  34. (flec (dvr sam bex32))
  35. ::
  36. ++ belt-from-u32s
  37. ~/ %bfu32s
  38. |= [lo=u32 hi=u32]
  39. ^- belt
  40. ?> ?&((is-u32 lo) (is-u32 hi))
  41. (add lo (mul bex32 hi))
  42. ::
  43. :: +u32-add: a + b = lo + (2^32)*car
  44. ++ u32-add
  45. |= [a=u32 b=u32]
  46. ^- [lo=u32 car=u32]
  47. ?> ?&((is-u32 a) (is-u32 b))
  48. (flec (dvr (badd a b) (bex 32)))
  49. ::
  50. :: +u32-sub: a - b = -(2^32)*bor + com
  51. ::
  52. :: If a>b, then a-b=c is interpreable as an ordinary u32. But if a<b, you
  53. :: can imagine we "borrow" 2^32 to add to `a` before we subtract so we can
  54. :: represent the difference as an ordinary u32. Equivalently we're just
  55. :: adding 2^32 to any negative answer, i.e. we're doing arithmetic mod 2^32.
  56. ++ u32-sub
  57. |= [a=u32 b=u32]
  58. :: com=complement (i.e. 2's-complement), bor=borrow
  59. ^- [com=u32 bor=u32]
  60. ?> ?&((is-u32 a) (is-u32 b))
  61. [(~(dif fo (bex 32)) a b) ?:((lth a b) 1 0)]
  62. ::
  63. :: +u32-lth: [a b] --> 0/1 according to a < b T/F
  64. ++ u32-lth
  65. ~/ %u32-lth
  66. |= [a=u32 b=u32]
  67. ^- ?
  68. ?> ?&((is-u32 a) (is-u32 b))
  69. (lth a b)
  70. ::
  71. :: +u32-mul: a*b = lo + (2^32)*hi
  72. ++ u32-mul
  73. ~/ %u32-mul
  74. |= [a=u32 b=u32]
  75. ^- [lo=u32 hi=u32]
  76. ?> ?&((is-u32 a) (is-u32 b))
  77. (flec (dvr (bmul a b) bex32))
  78. ::
  79. :: +u32-dvr: a = qot*b + rem, rem < b
  80. ++ u32-dvr
  81. ~/ %u32-dvr
  82. |= [a=u32 b=u32]
  83. ^- [qot=u32 rem=u32]
  84. ?> ?&((is-u32 a) (is-u32 b))
  85. (dvr a b)
  86. ::
  87. :: +u32-div: a / b = c such that a - b*c < b
  88. ++ u32-div
  89. ~/ %u32-div
  90. |= [a=u32 b=u32]
  91. ^- u32
  92. ?> ?&((is-u32 a) (is-u32 b))
  93. qot:(u32-dvr a b)
  94. ::
  95. :: +u32-mod: a - b*(a / b)
  96. ++ u32-mod
  97. ~/ %u32-mod
  98. |= [a=u32 b=u32]
  99. ^- u32
  100. ?> ?&((is-u32 a) (is-u32 b))
  101. rem:(u32-dvr a b)
  102. --
  103. ::
  104. ++ bignum :: /lib/bignum
  105. ~% %bignum + ~
  106. |%
  107. ++ l32 lib-u32
  108. ++ u32 u32:l32
  109. :: mirrors bignum from flib
  110. :: 32 bits = 2^5 bits => bloq size of 5
  111. +$ bignum
  112. :: LSB order (based on result of rip)
  113. :: empty array is 0
  114. [%bn p=(list u32)]
  115. ::
  116. :: +p: Goldilocks prime, written in bignum form
  117. ::
  118. :: least significant bit first, so:
  119. :: p = 2^64-2^32+1 = 2^32(2^32 - 1) + 1
  120. ++ p
  121. ^- bignum
  122. [%bn ~[1 4.294.967.295]]
  123. ::
  124. :: +p2: p^2
  125. ++ p2
  126. ^- bignum
  127. [%bn ~[1 4.294.967.294 2 4.294.967.294]]
  128. ::
  129. :: +p3: p^3
  130. ++ p3
  131. ^- bignum
  132. [%bn ~[1 4.294.967.293 5 4.294.967.289 5 4.294.967.293]]
  133. ::
  134. ++ chunk
  135. ~/ %chunk
  136. |= a=@
  137. ^- bignum
  138. [%bn (rip-correct 5 a)]
  139. ::
  140. ++ merge
  141. ~/ %merge
  142. |= b=bignum
  143. ^- @
  144. :: fock always turns unchunked bignums into chunked case
  145. (rep 5 p.b)
  146. ::
  147. ++ valid
  148. :: are all elements of the list valid big int chunks, i.e., less than u32.max_val
  149. ~/ %valid
  150. |= b=bignum
  151. ^- ?
  152. (levy p.b |=(c=@ (lth c (bex 32))))
  153. -- ::bignum
  154. ::
  155. ++ shape :: /lib/shape
  156. ~% %shape ..shape ~
  157. =, mp-to-mega
  158. |%
  159. :: +dyck: produce the Dyck word describing the shape of a tree
  160. ++ dyck
  161. ~/ %dyck
  162. |= t=*
  163. %- flop
  164. ^- (list @)
  165. =| vec=(list @)
  166. |-
  167. ?@ t vec
  168. $(t +.t, vec [1 $(t -.t, vec [0 vec])])
  169. ::
  170. :: +grow: grow the tree with given shape and leaves
  171. ++ grow
  172. ~/ %grow
  173. |= [shape=(list @) leaves=(list @)]
  174. ^- *
  175. ?> ?&(=((lent shape) (mul 2 (dec (lent leaves)))) (valid-shape shape))
  176. ?~ shape
  177. ?> ?=([@ ~] leaves)
  178. i.leaves
  179. =/ lr-shape (left-right-shape shape)
  180. =/ split-idx (shape-size -:lr-shape)
  181. =/ split-leaves (split split-idx leaves)
  182. :- (grow -:lr-shape -:split-leaves)
  183. (grow +:lr-shape +:split-leaves)
  184. ::
  185. :: +shape-size: size of the tree in #leaves described by a given Dyck word
  186. ++ shape-size
  187. ~/ %shape-size
  188. |= shape=(list @)
  189. ^- @
  190. (add 1 (div (lent shape) 2))
  191. ::
  192. ++ leaf-sequence
  193. ~/ %leaf-sequence
  194. |= t=*
  195. %- flop
  196. ^- (list @)
  197. =| vec=(list @)
  198. |-
  199. ?@ t t^vec
  200. $(t +.t, vec $(t -.t))
  201. ::
  202. ++ num-of-leaves
  203. ~/ %num-of-leaves
  204. |= t=*
  205. ?@ t 1
  206. %+ add
  207. (num-of-leaves -:t)
  208. (num-of-leaves +:t)
  209. ::
  210. :: +left-right-shape: extract left and right tree shapes from given tree shape
  211. ++ left-right-shape
  212. ~/ %left-right-shape
  213. |= shape=(list @)
  214. ^- [(list @) (list @)]
  215. ?> (valid-shape shape)
  216. ?: =((lent shape) 0)
  217. ~| "Empty tree has no left subtree."
  218. !!
  219. =. shape (slag 1 shape)
  220. =/ stack-height 1
  221. =| lefsh=(list @)
  222. |-
  223. ?: =(stack-height 0)
  224. ?< ?=(~ lefsh)
  225. [(flop t.lefsh) shape]
  226. ?< ?=(~ shape)
  227. ?: =(i.shape 0)
  228. $(lefsh [i.shape lefsh], shape t.shape, stack-height +(stack-height))
  229. $(lefsh [i.shape lefsh], shape t.shape, stack-height (dec stack-height))
  230. ::
  231. ++ axis-to-axes
  232. ~/ %axis-to-axes
  233. |= axi=@
  234. ^- (list @)
  235. =| lis=(list @)
  236. |-
  237. ?: =(1 axi) lis
  238. =/ hav (dvr axi 2)
  239. $(axi p.hav, lis [?:(=(q.hav 0) 2 3) lis])
  240. ::
  241. :: +valid-shape: computes whether a given vector is a valid tree shape
  242. ++ valid-shape
  243. ~/ %valid-shape
  244. |= shape=(list @)
  245. ^- ?
  246. =/ stack-height 0
  247. |-
  248. ?: ?=(~ shape)
  249. ?: =(stack-height 0)
  250. %.y
  251. %.n
  252. ?> ?|(=(i.shape 0) =(i.shape 1))
  253. ?: =(i.shape 0)
  254. $(shape t.shape, stack-height +(stack-height))
  255. ?: =(stack-height 0)
  256. %.n
  257. $(shape t.shape, stack-height (dec stack-height))
  258. ::
  259. :: +split: split ~[a_1 ... a_n] into [~[a)1 ... a_{idx -1}] ~[a_{idx} ... a_n]]
  260. ++ split
  261. ~/ %split
  262. |= [idx=@ lis=(list @)]
  263. ^- [(list @) (list @)]
  264. ~| "Index argument must be less than list length."
  265. ?> (lth idx (lent lis))
  266. =| lef=(list @)
  267. =/ i 0
  268. |-
  269. ?: =(i idx)
  270. [(flop lef) lis]
  271. ?< ?=(~ lis)
  272. $(lef [i.lis lef], lis t.lis, i +(i))
  273. ::
  274. ++ shape-axis-to-index
  275. ~/ %shape-axis-to-index
  276. |= [tre=* axis=@]
  277. ^- [dyck-index=@ leaf-index=@]
  278. =/ axes (axis-to-axes axis)
  279. =/ shape (dyck tre)
  280. =/ dyck-index 0
  281. =/ leaf-index 0
  282. |-
  283. ?~ axes
  284. [dyck-index leaf-index]
  285. =/ lr-shape (left-right-shape shape)
  286. ?: =(i.axes 2)
  287. $(axes t.axes, shape -.lr-shape)
  288. ?> =(i.axes 3)
  289. %_ $
  290. axes t.axes
  291. shape +.lr-shape
  292. dyck-index (add dyck-index (lent -.lr-shape))
  293. leaf-index (add leaf-index (shape-size -.lr-shape))
  294. ==
  295. ::
  296. :: +path-to-axis: binary directions to input axis
  297. ++ path-to-axis
  298. |= axis=belt
  299. ^- (list belt)
  300. (slag 1 (flop (rip 0 axis)))
  301. ::
  302. :: +ion-eval: eval first arg as poly at alpha
  303. ::
  304. :: First arg is a polynomial, read high powers to low from L to R.
  305. :: In practice this poly is a dyck word or leaf vector.
  306. ++ ion-eval
  307. |= [word-vec=(list belt) alpha=belt]
  308. ^- belt
  309. %+ roll word-vec
  310. |= [coeff=_f0 acc=_f0]
  311. ^- belt
  312. (badd (bmul alpha acc) coeff)
  313. ::
  314. ++ ion-eval-symbolic
  315. |= [word-vec=(list mp-mega) alpha=mp-mega]
  316. ^- mp-mega
  317. %+ roll word-vec
  318. |= [coeff=mp-mega acc=mp-mega]
  319. ^- mp-mega
  320. (mpadd (mpmul alpha acc) coeff)
  321. -- ::shape
  322. ::
  323. ++ tip5 :: lib/tip5
  324. ~% %tip5-lib ..tip5 ~
  325. |%
  326. +| %user-types
  327. +$ noun-digest [belt belt belt belt belt]
  328. +$ ten-cell [noun-digest noun-digest]
  329. ::
  330. ++ digest-dyck-word
  331. ^- (list @)
  332. ~[0 1 0 1 0 1 0 1]
  333. ++ ten-cell-dyck-word
  334. ^~ ^- (list @)
  335. (weld [0 digest-dyck-word] [1 digest-dyck-word])
  336. ::
  337. :: a sponge-tuple is a 16-tuple of belts; relevant for hash5.hoon
  338. ++ sponge-tuple-dyck-word
  339. ^~ ^- (list @)
  340. (zing (reap (dec state-size) ~[0 1]))
  341. ::
  342. +| %user-funcs
  343. ::
  344. :: +hash-ten-cell
  345. ++ hash-ten-cell
  346. ~/ %hash-ten-cell
  347. |= =ten-cell
  348. ^- noun-digest
  349. =- ?> ?=(noun-digest -) -
  350. %- list-to-tuple
  351. %- hash-10
  352. %- leaf-sequence:shape
  353. ten-cell
  354. ::
  355. :: +hash-leaf
  356. ++ hash-leaf
  357. |= leaf=belt
  358. ^- noun-digest
  359. :: ?> (based leaf) commented out because its performed in +hash-varlen
  360. (hash-belts-list ~[leaf])
  361. ::
  362. :: $hashable: a DSL for hashing anything
  363. +$ hashable
  364. $~ [%leaf p=*]
  365. $^ [p=hashable q=hashable]
  366. $% [%leaf p=*]
  367. [%hash p=noun-digest]
  368. [%list p=(list hashable)]
  369. [%mary p=mary]
  370. ==
  371. ::
  372. :: +hash-hashable
  373. ++ hash-hashable
  374. ~/ %hash-hashable
  375. |= h=hashable
  376. ^- noun-digest
  377. ?: ?=(%hash -.h)
  378. p.h
  379. ?: ?=(%leaf -.h)
  380. (hash-noun-varlen p.h)
  381. ?: ?=(%list -.h)
  382. (hash-noun-varlen (turn p.h hash-hashable))
  383. ?: ?=(%mary -.h)
  384. %- hash-hashable
  385. :- leaf+step.p.h
  386. :- leaf+len.array.p.h
  387. hash+(hash-belts-list (bpoly-to-list array:(~(change-step ave p.h) 1)))
  388. %- hash-ten-cell
  389. [$(h p.h) $(h q.h)]
  390. ::
  391. ++ hashable-noun-digests
  392. |= lis=(list noun-digest)
  393. ^- hashable
  394. list+(turn lis |=(nd=noun-digest hash+nd))
  395. ::
  396. ++ hashable-bpoly
  397. |= bp=bpoly
  398. ^- hashable
  399. mary+`mary`[%1 bp]
  400. ::
  401. ++ hashable-fpoly
  402. |= fp=fpoly
  403. ^- hashable
  404. mary+`mary`[%3 fp]
  405. ::
  406. ++ hashable-mary
  407. |= =mary
  408. ^- hashable
  409. mary+mary
  410. ::
  411. :: +hash-noun-varlen
  412. ++ hash-noun-varlen
  413. ~/ %hash-noun-varlen
  414. |= n=*
  415. ^- noun-digest
  416. =/ leaf=(list @) (leaf-sequence:shape n)
  417. =/ dyck=(list @) (dyck:shape n)
  418. =/ size (lent leaf)
  419. (hash-belts-list [size (weld leaf dyck)])
  420. ::
  421. :: +hash-felt
  422. ++ hash-felt
  423. ~/ %hash-felt
  424. |= =felt
  425. ^- noun-digest:tip5
  426. =/ felt-tuple=[@ @ @ @ @]
  427. ;; [@ @ @ @ @]
  428. %- list-to-tuple
  429. (weld (felt-to-list felt) ~[0 0])
  430. (hash-ten-cell felt-tuple [0 0 0 0 0])
  431. ::
  432. ::
  433. ++ hash-belts-list
  434. ~/ %hash-belts-list
  435. |= belts=(list belt)
  436. ^- noun-digest:tip5
  437. =- ?> ?=(noun-digest -) -
  438. %- list-to-tuple
  439. (hash-varlen belts)
  440. ::
  441. :: +hash-pairs
  442. ++ hash-pairs
  443. ~/ %hash-pairs
  444. |= lis=(list (list @))
  445. ^- (list (list @))
  446. |^
  447. %+ turn
  448. (indices (lent lis))
  449. |= b=@
  450. ?: =(+(b) (lent lis))
  451. (snag b lis)
  452. (hash-10:tip5 (weld (snag b lis) (snag +(b) lis)))
  453. ::
  454. :: TODO: there is probably a more clean way to generate indices.
  455. ++ indices
  456. |= n=@
  457. ^- (list @)
  458. ?< =(n 0)
  459. =/ i 0
  460. |-
  461. ?: (gte i n)
  462. ~
  463. [i $(i (add 2 i))]
  464. --
  465. ::
  466. :: +snag-as-digest
  467. ::
  468. :: Retrieve the i-th entry of the mary return it as a tip5 hash digest.
  469. :: Assumes that each entry of the mary is a single hash encoded in base 64.
  470. ::
  471. ++ snag-as-digest
  472. ~/ %snag-as-digest
  473. |= [m=mary i=@]
  474. ^- noun-digest:tip5
  475. ?> =(5 step.m)
  476. =/ buf (~(snag ave m) i)
  477. :* (cut 6 [0 1] buf)
  478. (cut 6 [1 1] buf)
  479. (cut 6 [2 1] buf)
  480. (cut 6 [3 1] buf)
  481. (cut 6 [4 1] buf)
  482. ==
  483. ::
  484. :: +list-to-digest
  485. ++ list-to-digest
  486. ~/ %list-to-digest
  487. |= lis=(list @)
  488. ^- noun-digest:tip5
  489. ?> =(5 (lent lis))
  490. :* (snag 0 lis)
  491. (snag 1 lis)
  492. (snag 2 lis)
  493. (snag 3 lis)
  494. (snag 4 lis)
  495. ==
  496. ::
  497. :: +atom-to-digest
  498. ::
  499. :: Converts hex buffer into base-p representation
  500. ++ atom-to-digest
  501. ~/ %atom-to-digest
  502. |= buffer=@ux
  503. ^- noun-digest:tip5
  504. =/ [q=@ a=@] (dvr buffer p)
  505. =/ [q=@ b=@] (dvr q p)
  506. =/ [q=@ c=@] (dvr q p)
  507. =/ [e=@ d=@] (dvr q p)
  508. [a b c d e]
  509. ::
  510. :: +digest-to-atom
  511. ::
  512. :: Returns a hexadecimal representation of the hash.
  513. :: We treat the tip-5 hash as a base-p number.
  514. ++ digest-to-atom
  515. ~/ %digest-to-atom
  516. |= [a=belt b=belt c=belt d=belt e=belt]
  517. ^- @ux
  518. =/ p2 (mul p p)
  519. =/ p3 (mul p2 p)
  520. =/ p4 (mul p3 p)
  521. ;: add
  522. a
  523. (mul p b)
  524. (mul p2 c)
  525. (mul p3 d)
  526. (mul p4 e)
  527. ==
  528. ::
  529. +| %dev-types
  530. +$ digest (list melt) :: length = digest-length
  531. +$ state (list melt) :: length = state-size
  532. +$ domain ?(%variable %fixed)
  533. +$ tip5-state (list melt)
  534. ::
  535. +| %dev-constants
  536. ++ digest-length 5
  537. ++ state-size 16
  538. ++ num-split-and-lookup 4
  539. ++ capacity 6
  540. ++ rate 10
  541. ++ num-rounds 5
  542. ++ max-tip5-atom (digest-to-atom [(dec p) (dec p) (dec p) (dec p) (dec p)])
  543. ::
  544. ++ state-dyck-word
  545. ^~ ^- (list @)
  546. (zing (reap state-size ~[0 1]))
  547. ::
  548. :: +lookup-table: represents the map x -> (x+1)^3 - 1 (mod 257) on {0, ..., 255}
  549. ::
  550. :: Used on the first 4 state elements in the S-box layer of each round of Tip5
  551. ++ lookup-table
  552. ^- (list @)
  553. :~ 0 7 26 63 124 215 85 254 214 228 45 185 140 173 33 240
  554. 29 177 176 32 8 110 87 202 204 99 150 106 230 14 235 128
  555. 213 239 212 138 23 130 208 6 44 71 93 116 146 189 251 81
  556. 199 97 38 28 73 179 95 84 152 48 35 119 49 88 242 3
  557. 148 169 72 120 62 161 166 83 175 191 137 19 100 129 112 55
  558. 221 102 218 61 151 237 68 164 17 147 46 234 203 216 22 141
  559. 65 57 123 12 244 54 219 231 96 77 180 154 5 253 133 165
  560. 98 195 205 134 245 30 9 188 59 142 186 197 181 144 92 31
  561. 224 163 111 74 58 69 113 196 67 246 225 10 121 50 60 157
  562. 90 122 2 250 101 75 178 159 24 36 201 11 243 132 198 190
  563. 114 233 39 52 21 209 108 238 91 187 18 104 194 37 153 34
  564. 200 143 126 155 236 118 64 80 172 89 94 193 135 183 86 107
  565. 252 13 167 206 136 220 207 103 171 160 76 182 227 217 158 56
  566. 174 4 66 109 139 162 184 211 249 47 125 232 117 43 16 42
  567. 127 20 241 25 149 105 156 51 53 168 145 247 223 79 78 226
  568. 15 222 82 115 70 210 27 41 1 170 40 131 192 229 248 255
  569. ==
  570. ::
  571. :: +round-constants: 5 length=16 vectors added to the state in the final layer each round
  572. ++ round-constants
  573. :: notice melt and montify: these are in Montgomery representation
  574. ^~ ^- (list melt)
  575. %- turn :_ montify
  576. :: length = num-rounds * state-size = 80
  577. :~
  578. :: 1st round constants
  579. 13.630.775.303.355.457.758 16.896.927.574.093.233.874
  580. 10.379.449.653.650.130.495 1.965.408.364.413.093.495
  581. 15.232.538.947.090.185.111 15.892.634.398.091.747.074
  582. 3.989.134.140.024.871.768 2.851.411.912.127.730.865
  583. 8.709.136.439.293.758.776 3.694.858.669.662.939.734
  584. 12.692.440.244.315.327.141 10.722.316.166.358.076.749
  585. 12.745.429.320.441.639.448 17.932.424.223.723.990.421
  586. 7.558.102.534.867.937.463 15.551.047.435.855.531.404
  587. :: 2nd round constants
  588. 17.532.528.648.579.384.106 5.216.785.850.422.679.555
  589. 15.418.071.332.095.031.847 11.921.929.762.955.146.258
  590. 9.738.718.993.677.019.874 3.464.580.399.432.997.147
  591. 13.408.434.769.117.164.050 264.428.218.649.616.431
  592. 4.436.247.869.008.081.381 4.063.129.435.850.804.221
  593. 2.865.073.155.741.120.117 5.749.834.437.609.765.994
  594. 6.804.196.764.189.408.435 17.060.469.201.292.988.508
  595. 9.475.383.556.737.206.708 12.876.344.085.611.465.020
  596. :: 3rd round constants
  597. 13.835.756.199.368.269.249 1.648.753.455.944.344.172
  598. 9.836.124.473.569.258.483 12.867.641.597.107.932.229
  599. 11.254.152.636.692.960.595 16.550.832.737.139.861.108
  600. 11.861.573.970.480.733.262 1.256.660.473.588.673.495
  601. 13.879.506.000.676.455.136 10.564.103.842.682.358.721
  602. 16.142.842.524.796.397.521 3.287.098.591.948.630.584
  603. 685.911.471.061.284.805 5.285.298.776.918.878.023
  604. 18.310.953.571.768.047.354 3.142.266.350.630.002.035
  605. :: 4th round constants
  606. 549.990.724.933.663.297 4.901.984.846.118.077.401
  607. 11.458.643.033.696.775.769 8.706.785.264.119.212.710
  608. 12.521.758.138.015.724.072 11.877.914.062.416.978.196
  609. 11.333.318.251.134.523.752 3.933.899.631.278.608.623
  610. 16.635.128.972.021.157.924 10.291.337.173.108.950.450
  611. 4.142.107.155.024.199.350 16.973.934.533.787.743.537
  612. 11.068.111.539.125.175.221 17.546.769.694.830.203.606
  613. 5.315.217.744.825.068.993 4.609.594.252.909.613.081
  614. :: 5th round constants
  615. 3.350.107.164.315.270.407 17.715.942.834.299.349.177
  616. 9.600.609.149.219.873.996 12.894.357.635.820.003.949
  617. 4.597.649.658.040.514.631 7.735.563.950.920.491.847
  618. 1.663.379.455.870.887.181 13.889.298.103.638.829.706
  619. 7.375.530.351.220.884.434 3.502.022.433.285.269.151
  620. 9.231.805.330.431.056.952 9.252.272.755.288.523.725
  621. 10.014.268.662.326.746.219 15.565.031.632.950.843.234
  622. 1.209.725.273.521.819.323 6.024.642.864.597.845.108
  623. ==
  624. ::
  625. :: +mds-matrix-first-column: the mds matrix is determined by any column
  626. ++ mds-matrix-first-column
  627. :: length = state-size = 16
  628. ^- (list belt)
  629. :~ 61.402 1.108 28.750 33.823 7.454 43.244 53.865 12.034
  630. 56.951 27.521 41.351 40.901 12.021 59.689 26.798 17.845
  631. ==
  632. ::
  633. ++ mds-first-column-fft
  634. ^- (list belt)
  635. :~ 524.757 12.925.608.463.476.951.657
  636. 15.523.111.717.718.611.263 16.532.524.212.944.612.299
  637. 7.588.283.897.142.562.168 15.572.835.691.259.601.621
  638. 2.891.241.344.421.052.990 4.554.321.248.572.910.116
  639. 52.427 3.009.663.708.287.279.710
  640. 15.424.499.013.074.857.791 4.457.503.309.926.164.732
  641. 10.858.460.172.271.996.281 243.395.401.255.089.650
  642. 3.054.636.063.615.042.110 16.491.124.241.935.763.107
  643. ==
  644. ::
  645. :: list of rows
  646. ++ mds-matrix
  647. ^~
  648. ^- (list (list belt))
  649. |^
  650. ^~((gen-circulant-matrix mds-matrix-first-column))
  651. ::
  652. :: +gen-circulant-matrix: use first column to produce mds-matrix
  653. ::
  654. :: The first row of mds is a cyclic rotation of the flop of the
  655. :: first column, and successive rows are obtained by more cyclic
  656. :: rotations.
  657. ++ gen-circulant-matrix
  658. |= first-column=(list @)
  659. ^- (list (list @))
  660. %+ spun (range (lent first-column))
  661. |= [i=@ acc=_(flop first-column)]
  662. [(rotate acc) (rotate acc)]
  663. ::
  664. :: +rotate: cyclic vector rotation
  665. ++ rotate
  666. |= lst=(list @)
  667. ^- (list @)
  668. [(rear lst) (snip lst)]
  669. --
  670. ::
  671. ++ primitive-16-roots
  672. ^- (list belt)
  673. :~ 4.096 :: o (o=2^12; 2 is a primitive 192nd rou, & 192=12*16)
  674. 68.719.476.736 :: o^3
  675. 1.152.921.504.606.846.976 :: o^5
  676. 4.503.599.626.321.920 :: o^7
  677. 18.446.744.069.414.580.225 :: o^9
  678. 18.446.744.000.695.107.585 :: o^11
  679. 17.293.822.564.807.737.345 :: o^13
  680. 18.442.240.469.788.262.401 :: o^15
  681. ==
  682. ::
  683. ++ layer-two-twiddles
  684. ^~ ^- (map belt (list belt))
  685. %- ~(gas by *(map belt (list belt)))
  686. %+ turn primitive-16-roots
  687. |= r=belt
  688. =/ fourth-rou (bpow r (div 16 4))
  689. :- r (turn (range 2) |=(i=@ (bpow fourth-rou i)))
  690. ::
  691. ++ layer-three-twiddles
  692. ^~ ^- (map belt (list belt))
  693. %- ~(gas by *(map belt (list belt)))
  694. %+ turn primitive-16-roots
  695. |= r=belt
  696. =/ eighth-rou (bpow r (div 16 8))
  697. :- r (turn (range 4) |=(i=@ (bpow eighth-rou i)))
  698. ::
  699. ++ layer-four-twiddles
  700. ^~ ^- (map belt (list belt))
  701. %- ~(gas by *(map belt (list belt)))
  702. %+ turn primitive-16-roots
  703. |= r=belt
  704. :- r (turn (range 8) |=(i=@ (bpow r i)))
  705. ::
  706. ::
  707. :: For the cognoscenti:
  708. ::
  709. :: The formal mathematical specification of Tip5 involves conversion to
  710. :: and from Montgomery representation in the S-box layer of each round.
  711. :: In practice it is inefficient to do this, so the MDS and round constants
  712. :: layers are done in Montgomery representation. This demands that the
  713. :: round constants be given in Montgomery representation, but, confusingly
  714. :: enough, does not demand the same of the MDS matrix constants, for the
  715. :: simple reason that ordinary multiplication of melt a' (whose underlying
  716. :: belt is a) and belt b yields (ab)'; this owes to the fact that
  717. :: "Montification" is multiplication by 2^64 mod p = 2^32 - 1. Basically,
  718. :: we "stay in Montgomery space" if we multiply a melt and a belt.
  719. ::
  720. :: This manifests clearly in +hash-10, where the input is montified and
  721. :: the output is demontified before being returned.
  722. +| %dev-funcs
  723. ++ init-tip5-state
  724. |= =domain
  725. ^- tip5-state
  726. ?- domain
  727. %variable
  728. ^~((reap state-size 0))
  729. ::
  730. %fixed
  731. ^~((weld (reap rate 0) (reap capacity (montify 1))))
  732. ==
  733. ::
  734. :: +offset-fermat-cube-map: generates and can be used to test lookup-table
  735. ++ offset-fermat-cube-map
  736. |= x=@
  737. ^- @
  738. ?> (lth x 256)
  739. =/ xx +(x)
  740. %- mod :_ 257
  741. (add :(mul xx xx xx) 256)
  742. ::
  743. :: +split-and-lookup: splits b into bytes, applies offset-fermat-cube-map to each, & recombines bytes
  744. ++ split-and-lookup
  745. |= m=melt
  746. ^- melt
  747. :: split
  748. =/ bytes=(list @) (weld (rip 3 m) (reap (sub 8 (lent (rip 3 m))) 0))
  749. :: lookup=offset-fermat-cube
  750. =. bytes (turn bytes |=(byte=@ (snag byte lookup-table)))
  751. :: recombine
  752. (can 3 (zip-up (reap 8 1) bytes))
  753. ::
  754. :: +cyclomul16-fft: fft of f and g, hadamard multiply result, then ifft.
  755. ::
  756. :: This is different than polynomial multiplication of f and g bc output length equals input lengths.
  757. :: In fact, it is polynomial multiplication modulo the cyclotomic polynomial X^16 - 1. (Not obvious.)
  758. ++ cyclomul16-fft
  759. |= [f=(list belt) g=(list belt)]
  760. ^- (list belt)
  761. ?> ?&(=((lent f) state-size) =((lent g) state-size))
  762. =/ [fx=fpoly gx=fpoly] [(lift-to-fpoly f) (lift-to-fpoly g)]
  763. %- turn :_ drop
  764. %- fpoly-to-list
  765. (fp-ifft (~(zip fop (fp-fft fx)) (fp-fft gx) fmul))
  766. ::
  767. :: +fft-16-w-root:
  768. ++ fft-16-w-root
  769. ~/ %fft-16-w-root
  770. |= [bp=(list belt) r=belt]
  771. ^- (list belt)
  772. |^
  773. =/ current-layer=(list (list belt))
  774. %- turn :_ interpolate-linear
  775. (zip-up (scag 8 bp) (slag 8 bp))
  776. =. current-layer
  777. %+ turn (zip-up (scag 4 current-layer) (slag 4 current-layer))
  778. (cury interpolate-next (~(got by layer-two-twiddles) r))
  779. =/ current-layer
  780. %+ turn (zip-up (scag 2 current-layer) (slag 2 current-layer))
  781. (cury interpolate-next (~(got by layer-three-twiddles) r))
  782. %- interpolate-next
  783. :+ (~(got by layer-four-twiddles) r)
  784. (snag 0 current-layer) (snag 1 current-layer)
  785. ::
  786. ++ interpolate-linear
  787. |= [b=belt c=belt]
  788. ~[(badd b c) (bsub b c)]
  789. ::
  790. ++ interpolate-next
  791. |= [twids=(list belt) dft1=(list belt) dft2=(list belt)]
  792. ^- (list belt)
  793. =/ right (zip dft2 twids bmul)
  794. %+ weld
  795. (zip dft1 right badd)
  796. (zip dft1 right bsub)
  797. --
  798. ::
  799. ++ fft-16
  800. ~/ %fft-16
  801. |= bp=(list belt)
  802. (fft-16-w-root bp 4.096)
  803. ::
  804. ++ ifft-16
  805. ~/ %ifft-16
  806. |= evals=(list belt)
  807. ^- (list belt)
  808. %- turn :_ |=(=belt (bmul belt 17.293.822.565.076.172.801))
  809. (fft-16-w-root evals 18.442.240.469.788.262.401)
  810. ::
  811. :: +mds-cyclomul: applies the mds matrix as a linear transformation to state
  812. :: w/o doing matrix multiplication
  813. ++ mds-cyclomul
  814. ~/ %mds-cyclomul
  815. |= =state
  816. ^- ^state
  817. %- ifft-16
  818. (zip mds-first-column-fft (fft-16 state) bmul)
  819. ::
  820. :: +mds-cyclomul-m: applies the mds matrix as a linear transformation to state
  821. :: doing matrix multiplication.
  822. ++ mds-cyclomul-m
  823. ~/ %mds-cyclomul-m
  824. |= v=(list @)
  825. ^- (list @)
  826. %+ turn
  827. mds-matrix
  828. |= row=(list @)
  829. (mod (inner-product row v) p)
  830. ::
  831. ++ inner-product
  832. ~/ %inner-product
  833. |= [l=(list @) t=(list @)]
  834. ^- belt
  835. %^ zip-roll l t
  836. |= [[a=@ b=@] res=@]
  837. (add res (mul a b))
  838. ::
  839. :: +sbox-layer: applies fermat map to first 4 elements and 7th-power map to remainder
  840. ++ sbox-layer
  841. ~/ %sbox-layer
  842. |= =state
  843. ^- (list melt)
  844. ?> =((lent state) state-size)
  845. %+ weld
  846. (turn (scag num-split-and-lookup state) split-and-lookup)
  847. %+ turn (slag num-split-and-lookup state)
  848. :: computes b^7 in 4 base field multiplications
  849. ::
  850. :: Note that we are able to replace montiplys with
  851. :: bmuls due to the fact that R^3 = 1 mod p. Thus:
  852. :: m^7 = R^7*b^7
  853. :: = (R^3)^2*R*b^7
  854. :: = R*b^7 mod p
  855. |= m=melt
  856. ^- melt
  857. =/ sq (bmul m m)
  858. =/ qu (bmul sq sq)
  859. :(bmul m sq qu)
  860. ::
  861. :: +round: one round has three components; sbox, linear (mds), add round constants
  862. ++ round
  863. ~/ %round
  864. |= [sponge=tip5-state round-index=@]
  865. ^- tip5-state
  866. =. sponge (mds-cyclomul-m (sbox-layer sponge))
  867. %^ zip sponge (range state-size)
  868. |= [b=belt i=@]
  869. (badd b (snag (add (mul round-index state-size) i) round-constants))
  870. ::
  871. :: +permutation: applies rounds iteratively, num-rounds times
  872. ++ permutation
  873. ~/ %permutation
  874. |= sponge=tip5-state
  875. ^- tip5-state
  876. %+ roll (range num-rounds)
  877. |= [round-index=@ acc=_sponge]
  878. (round acc round-index)
  879. ::
  880. :: +trace: a record of the tip5-state's evolution during permutation
  881. ++ trace
  882. ~/ %trace
  883. |= sponge=tip5-state
  884. ^- (list tip5-state)
  885. :- sponge
  886. %+ spun (range num-rounds)
  887. |= [i=@ sp=_sponge]
  888. [(round sp i) (round sp i)]
  889. ::
  890. :: +hash-10: hash list of 10 belts into a list of 5 belts
  891. ++ hash-10
  892. ~/ %hash-10
  893. |= input=(list belt)
  894. :: output length is 5
  895. ^- (list belt)
  896. ?> =((lent input) rate)
  897. ?> (levy input based)
  898. =. input (turn input montify)
  899. =/ sponge (init-tip5-state %fixed)
  900. =. sponge (permutation (weld input (slag rate sponge)))
  901. (turn (scag digest-length sponge) mont-reduction)
  902. ::
  903. :: +hash-varlen: hash a list of belts, but in practice only a single belt
  904. ::
  905. :: you might think this is the function for hashing lists of belts,
  906. :: but you'd be wrong. +hash-varlen is part of the tip5 spec, so
  907. :: we need to have it. but because hoon is structurally typed, the
  908. :: type system cannot distinguish between a list ~[1 2 3] and a tuple
  909. :: [1 2 3 0]. unfortunately, +hash-noun of [1 2 3 0] is different from
  910. :: +hash-varlen of ~[1 2 3]. having identical nouns of belts with different
  911. :: hashes would be catastrophic.
  912. ::
  913. :: the two tip5 primitives are +hash-varlen and +hash-ten-cell.
  914. :: +hash-ten-cell can't be used on a single atom, so we must use
  915. :: +hash-varlen on it. +hash-ten-cell is only to be used to combine two
  916. :: hashes. so +hash-noun works out to be: +hash-varlen on every belt
  917. :: atom, and +hash-ten-cell on every cell.
  918. ::
  919. :: we also make use of +hash-varlen for hashing marys. see +hash-mary
  920. :: for more information
  921. ++ hash-varlen
  922. ~/ %hash-varlen
  923. |= input=(list belt)
  924. ^- (list belt)
  925. =/ spo (new:sponge)
  926. =. spo (absorb:spo input)
  927. =^ output spo
  928. (squeeze:spo)
  929. (scag digest-length output)
  930. ::
  931. ++ sponge
  932. ~% %sponge +> ~
  933. |_ sponge=tip5-state
  934. ++ new
  935. |. ^+ +.$
  936. =. sponge (init-tip5-state %variable)
  937. +.$
  938. ::
  939. ++ absorb
  940. ~/ %absorb
  941. |= input=(list belt)
  942. ^+ +>.$
  943. =* rng +>.$
  944. |^
  945. :: assert that input is made of base field elements
  946. ?> (levy input based)
  947. =/ [q=@ r=@] (dvr (lent input) rate)
  948. :: pad input with ~[1 0 ... 0] to be a multiple of rate
  949. =. input (weld input [1 (reap (dec (sub rate r)) 0)])
  950. :: bring input into montgomery space
  951. =. input (turn input montify)
  952. |-
  953. =. sponge (absorb-rate (scag rate input))
  954. ?: =(q 0)
  955. rng
  956. $(q (dec q), input (slag rate input))
  957. ::
  958. ++ absorb-rate
  959. |= input=(list belt)
  960. ^+ sponge
  961. ?> =((lent input) rate)
  962. =. sponge (weld input (slag rate sponge))
  963. $:permute
  964. --
  965. ::
  966. ++ permute
  967. ~% %permute + ~
  968. |. ^+ sponge
  969. (permutation sponge)
  970. ::
  971. ++ squeeze
  972. ~% %squeeze + ~
  973. |. ^+ [*(list belt) +.$]
  974. =* rng +.$
  975. :: squeeze out the full rate and bring out of montgomery space
  976. =/ output (turn (scag rate sponge) mont-reduction)
  977. =. sponge $:permute
  978. [output rng]
  979. --
  980. ::
  981. :: +list-to-tuple: strips ~ from a list and yields a tuple
  982. ::
  983. :: hash-10 returns a length=5 list and this function is useful
  984. :: for converting it to a tuple
  985. ++ list-to-tuple
  986. ~/ %list-to-tuple
  987. |= lis=(list @)
  988. :: address of [a_{k-1} ~] (final nontrivial tail of list)
  989. =+ (dec (bex (lent lis)))
  990. .* lis
  991. [10 [- [0 (mul 2 -)]] [0 1]]
  992. ::
  993. :: +tog: Tip5 Sponge PRNG
  994. ::
  995. ++ tog
  996. ~% %tog +> ~
  997. |_ spo=tip5-state
  998. ::
  999. ++ new
  1000. |= sponge-state=tip5-state
  1001. ~(. tog sponge-state)
  1002. ::
  1003. ++ belts
  1004. ~/ %belts
  1005. |= n=@
  1006. ^+ [*(list belt) +>.$]
  1007. =* rng +>.$
  1008. =/ sponge ~(. sponge spo)
  1009. =/ [q=@ r=@] (dvr n rate)
  1010. =| output=(list belt)
  1011. |-
  1012. =^ out sponge
  1013. (squeeze:sponge)
  1014. =. spo sponge:sponge
  1015. ?: =(q 0)
  1016. [(weld output (scag r out)) rng]
  1017. $(q (dec q), output (weld output out))
  1018. ::
  1019. ++ felt
  1020. ~% %felt + ~
  1021. |. ^+ [*^felt +.$]
  1022. =^ felt-list +.$ (felts 1)
  1023. [(head felt-list) +.$]
  1024. ::
  1025. ++ felts
  1026. ~/ %felts
  1027. |= n=@
  1028. ^+ [*(list ^felt) +>.$]
  1029. =* outer +>.$
  1030. =^ lis-belts +>.$ (belts (mul n 3))
  1031. =| ret=(list ^felt)
  1032. =/ i 0
  1033. |-
  1034. ?: =(i n)
  1035. [(flop ret) outer]
  1036. =/ f=^felt (frep (scag 3 lis-belts))
  1037. $(ret [f ret], lis-belts (slag 3 lis-belts), i +(i))
  1038. ::
  1039. ++ index
  1040. ~/ %index
  1041. |= size=@
  1042. ^+ [*@ +>.$]
  1043. =^ belt-list +>.$ (belts 1)
  1044. [(mod (head belt-list) size) +>.$]
  1045. ::
  1046. ++ indices
  1047. ~/ %indices
  1048. |= [n=@ size=@ reduced-size=@]
  1049. ^+ [*(list @) +>.$]
  1050. =* rng +>.$
  1051. ~| "cannot sample more indices than available in last codeword"
  1052. ?> (lte n reduced-size)
  1053. =| indices=(list @)
  1054. =| reduced-indices=(list @)
  1055. |-
  1056. ?: (gte (lent indices) n)
  1057. [(flop indices) rng]
  1058. =^ index rng (index size)
  1059. =/ reduced-index (mod index reduced-size)
  1060. ?^ (find reduced-index^~ reduced-indices)
  1061. $
  1062. ?^ (find index^~ indices) $
  1063. %_ $
  1064. indices [index indices]
  1065. reduced-indices [reduced-index reduced-indices]
  1066. ==
  1067. --
  1068. ::
  1069. ++ test-tip5
  1070. |%
  1071. ::
  1072. ++ lookup-table-test
  1073. ^- ?
  1074. ?> =((lent lookup-table) 256)
  1075. %+ levy (range 256)
  1076. |= i=@
  1077. =((snag i lookup-table) (offset-fermat-cube-map i))
  1078. ::
  1079. ++ fermat-cube-map-is-permutation
  1080. ^- ?
  1081. =((range 256) (sort lookup-table lth))
  1082. ::
  1083. :: needs Blake3 hash function; I've painstakingly checked our list against the one in Neptune's code
  1084. ++ round-constants-test
  1085. ^- ?
  1086. !!
  1087. ::
  1088. :: +reduce-mod-cyclotomic: reduce f mod X^n-1
  1089. ++ reduce-mod-cyclotomic
  1090. |= [f=(list belt) n=@]
  1091. ^- (list belt)
  1092. =. f (weld f (reap (sub n (mod (lent f) n)) 0))
  1093. =/ result (reap n 0)
  1094. |-
  1095. ?~ f
  1096. result
  1097. =/ f-lst `(list belt)`f
  1098. %_ $
  1099. f (slag n f-lst)
  1100. result (zip (scag n f-lst) result badd)
  1101. ==
  1102. ::
  1103. ++ cyclomul-is-bpmul-mod-cyclotomic-test
  1104. |= [f=(list belt) g=(list belt)]
  1105. ^- ?
  1106. ?> ?&((lte (lent f) 16) (lte (lent g) 16))
  1107. =. f (weld f (reap (sub 16 (lent f)) 0))
  1108. =. g (weld g (reap (sub 16 (lent g)) 0))
  1109. =/ prod=(list belt) (bpoly-to-list (bpmul (init-bpoly f) (init-bpoly g)))
  1110. =. prod (weld prod (reap (sub 32 (lent prod)) 0))
  1111. .= (cyclomul16-fft f g)
  1112. (zip (scag 16 prod) (slag 16 prod) badd)
  1113. ::
  1114. ++ matrix-vector-product
  1115. |= [matrix=(list (list belt)) vector=(list belt)]
  1116. ^- (list belt)
  1117. %+ turn matrix
  1118. :: dot product
  1119. |= row=(list belt)
  1120. ^- belt
  1121. %+ roll (zip-up row vector)
  1122. |= [[entry=belt component=belt] acc=belt]
  1123. ^- belt
  1124. (badd acc (bmul entry component))
  1125. ::
  1126. ++ mds-cyclomul-test
  1127. |= input=(list belt)
  1128. ^- ?
  1129. ?> =((lent input) 16)
  1130. =((mds-cyclomul input) (matrix-vector-product mds-matrix input))
  1131. ::
  1132. ++ test-hash10-0
  1133. =/ expected=(list belt)
  1134. :~ 941.080.798.860.502.477
  1135. 5.295.886.365.985.465.639
  1136. 14.728.839.126.885.177.993
  1137. 10.358.449.902.914.633.406
  1138. 14.220.746.792.122.877.272
  1139. ==
  1140. =/ got (hash-10 (reap 10 0))
  1141. (zip-up expected got)
  1142. ::
  1143. ++ hash10-test-vectors
  1144. ^- ?
  1145. =/ input=(list belt) (reap rate 0)
  1146. =+ %+ roll (range 6)
  1147. |= [i=@ in=_input]
  1148. =/ out (hash-10 in)
  1149. :(weld (scag i in) out (reap (sub 5 i) 0))
  1150. =/ digest (hash-10 -)
  1151. =/ final=(list belt)
  1152. :~ 10.869.784.347.448.351.760
  1153. 1.853.783.032.222.938.415
  1154. 6.856.460.589.287.344.822
  1155. 17.178.399.545.409.290.325
  1156. 7.650.660.984.651.717.733
  1157. ==
  1158. =/ expected-got=(list [belt belt]) (zip-up final digest)
  1159. ~& expected-got
  1160. (levy expected-got |=([a=belt b=belt] =(a b)))
  1161. ::
  1162. :: comment out the jet hint on hash-varlen before running this test
  1163. ++ test-hash-varlen
  1164. |= [num=@ seed=@]
  1165. ^- ?
  1166. |^
  1167. =| counter=@
  1168. |-
  1169. ?: =(counter num) %.y
  1170. =/ [tv=(list belt) new-seed=@]
  1171. %^ spin (range counter) seed
  1172. |= [i=@ sd=belt]
  1173. =- -^-
  1174. (badd (bmul sd sd) 1)
  1175. ?. =((hash-varlen tv) (old-hash-varlen tv))
  1176. ~& fail-on+tv %.n
  1177. $(counter +(counter), seed new-seed)
  1178. ::
  1179. ++ old-hash-varlen
  1180. |= input=(list belt)
  1181. =/ [q=@ r=@] (dvr (lent input) rate)
  1182. :: append ~[1 0 ... 0] to input
  1183. =. input (turn (weld input [1 (reap (dec (sub rate r)) 0)]) montify)
  1184. =/ sponge (init-tip5-state %variable)
  1185. =- (turn (scag digest-length sp) mont-reduction)
  1186. %+ roll (gulf 0 q)
  1187. |= [i=@ [sp=_sponge in=_input]]
  1188. :_ (slag rate in)
  1189. (permutation (weld (scag rate in) (slag rate sp)))
  1190. --
  1191. --
  1192. --
  1193. ::
  1194. :: TODO: needs to be audited and thoroughly tested
  1195. ++ cheetah
  1196. ~% %cheetah ..cheetah ~
  1197. :: degree-six extension of F_p is cheetah curve's base field
  1198. |%
  1199. :: f6lt: element of F_p[x]/(x^6 - 7)
  1200. +$ f6lt [a0=belt a1=belt a2=belt a3=belt a4=belt a5=belt]
  1201. ++ f6lt-dyck-word
  1202. ^- (list @)
  1203. ~[0 1 0 1 0 1 0 1 0 1]
  1204. ++ f6lt-cell-dyck-word
  1205. ^~ ^- (list @)
  1206. (weld [0 f6lt-dyck-word] [1 f6lt-dyck-word])
  1207. ++ f6lt-triple-dyck-word
  1208. ^~ ^- (list @)
  1209. :(weld [0 f6lt-dyck-word] [1 [0 f6lt-dyck-word]] [1 f6lt-dyck-word])
  1210. ++ f6lt-triple-cell-dyck-word
  1211. ^~ ^- (list @)
  1212. (weld [0 f6lt-triple-dyck-word] [1 f6lt-triple-dyck-word])
  1213. ++ f6-zero `f6lt`[0 0 0 0 0 0]
  1214. ++ f6-one `f6lt`[1 0 0 0 0 0]
  1215. ::
  1216. ++ f6lt-to-list
  1217. |= f=f6lt
  1218. ^- (list belt)
  1219. ~[a0.f a1.f a2.f a3.f a4.f a5.f]
  1220. ::
  1221. ++ list-to-f6lt
  1222. |= lis=(list belt)
  1223. ^- f6lt
  1224. ?> =((lent lis) 6)
  1225. :: 63 = axis of [a_5 ~] in ~[a0 ... a_5]
  1226. :: 126 = axis of a_5 in ~[a0 ... a_5]
  1227. :: replace axis 63 (=[a_5 ~]) of *[lis [0 1]]=lis with *[lis [0 126]]=a_5
  1228. =/ n
  1229. .* lis
  1230. [10 [63 [0 126]] [0 1]]
  1231. ?> ?=(f6lt n) n
  1232. ::
  1233. ++ f6-add
  1234. |= [f1=f6lt f2=f6lt]
  1235. ^- f6lt
  1236. :* (badd a0.f1 a0.f2)
  1237. (badd a1.f1 a1.f2)
  1238. (badd a2.f1 a2.f2)
  1239. (badd a3.f1 a3.f2)
  1240. (badd a4.f1 a4.f2)
  1241. (badd a5.f1 a5.f2)
  1242. ==
  1243. ::
  1244. ++ f6-neg
  1245. |= f=f6lt
  1246. ^- f6lt
  1247. :* (bneg a0.f)
  1248. (bneg a1.f)
  1249. (bneg a2.f)
  1250. (bneg a3.f)
  1251. (bneg a4.f)
  1252. (bneg a5.f)
  1253. ==
  1254. ::
  1255. ++ f6-sub
  1256. |= [f1=f6lt f2=f6lt]
  1257. ^- f6lt
  1258. (f6-add f1 (f6-neg f2))
  1259. ::
  1260. ++ f6-scal
  1261. |= [c=belt f=f6lt]
  1262. ^- f6lt
  1263. :* (bmul c a0.f)
  1264. (bmul c a1.f)
  1265. (bmul c a2.f)
  1266. (bmul c a3.f)
  1267. (bmul c a4.f)
  1268. (bmul c a5.f)
  1269. ==
  1270. ::
  1271. :: +karat3: mults 2 quadratic polys w only 6 bmuls (vs naive 9)
  1272. ++ karat3
  1273. |= [[a0=belt a1=belt a2=belt] [b0=belt b1=belt b2=belt]]
  1274. ^- [c0=belt c1=belt c2=belt c3=belt c4=belt]
  1275. =/ [m0=belt m1=belt m2=belt]
  1276. [(bmul a0 b0) (bmul a1 b1) (bmul a2 b2)]
  1277. :* m0
  1278. (bsub (bmul (badd a0 a1) (badd b0 b1)) (badd m0 m1))
  1279. (badd (bsub (bmul (badd a0 a2) (badd b0 b2)) (badd m0 m2)) m1)
  1280. (bsub (bmul (badd a1 a2) (badd b1 b2)) (badd m1 m2))
  1281. m2
  1282. ==
  1283. ::
  1284. :: +karat3-square: squares quadratic poly w only 5 bmuls
  1285. ++ karat3-square
  1286. |= [a0=belt a1=belt a2=belt]
  1287. ^- [c0=belt c1=belt c2=belt c3=belt c4=belt]
  1288. =/ [m0=belt m2=belt] [(bmul a0 a0) (bmul a2 a2)]
  1289. =/ [n01=belt n12=belt] [(bmul a0 a1) (bmul a1 a2)]
  1290. =: n01 (badd n01 n01)
  1291. n12 (badd n12 n12)
  1292. ==
  1293. =/ tri2=belt
  1294. =/ tri :(badd a0 a1 a2)
  1295. (bmul tri tri)
  1296. =/ coeff2 (bsub tri2 :(badd m0 m2 n01 n12))
  1297. [m0 n01 coeff2 n12 m2]
  1298. ::
  1299. ++ f6-mul
  1300. |= [f=f6lt g=f6lt]
  1301. ^- f6lt
  1302. =/ f0g0 (karat3 [a0.f a1.f a2.f] [a0.g a1.g a2.g])
  1303. =/ f1g1 (karat3 [a3.f a4.f a5.f] [a3.g a4.g a5.g])
  1304. =/ foil
  1305. %- karat3
  1306. :- [(badd a0.f a3.f) (badd a1.f a4.f) (badd a2.f a5.f)]
  1307. [(badd a0.g a3.g) (badd a1.g a4.g) (badd a2.g a5.g)]
  1308. =/ cross=[c0=belt c1=belt c2=belt c3=belt c4=belt]
  1309. :* (bsub c0.foil (badd c0.f0g0 c0.f1g1))
  1310. (bsub c1.foil (badd c1.f0g0 c1.f1g1))
  1311. (bsub c2.foil (badd c2.f0g0 c2.f1g1))
  1312. (bsub c3.foil (badd c3.f0g0 c3.f1g1))
  1313. (bsub c4.foil (badd c4.f0g0 c4.f1g1))
  1314. ==
  1315. :* (badd c0.f0g0 (bmul 7 (badd c3.cross c0.f1g1)))
  1316. (badd c1.f0g0 (bmul 7 (badd c4.cross c1.f1g1)))
  1317. (badd c2.f0g0 (bmul 7 c2.f1g1))
  1318. :(badd c3.f0g0 c0.cross (bmul 7 c3.f1g1))
  1319. :(badd c4.f0g0 c1.cross (bmul 7 c4.f1g1))
  1320. c2.cross
  1321. ==
  1322. ::
  1323. :: +f6-square: uses karat3-square for more efficiency than (f6-mul f f)
  1324. ++ f6-square
  1325. |= f=f6lt
  1326. ^- f6lt
  1327. =/ lo [a0.f a1.f a2.f]
  1328. =/ hi [a3.f a4.f a5.f]
  1329. =/ lo2 (karat3-square lo)
  1330. =/ hi2 (karat3-square hi)
  1331. =/ folded2 :: (lo + hi)^2
  1332. (karat3-square [(badd a0.f a3.f) (badd a1.f a4.f) (badd a2.f a5.f)])
  1333. =/ cross=[c0=belt c1=belt c2=belt c3=belt c4=belt]
  1334. :* (bsub c0.folded2 (badd c0.lo2 c0.hi2))
  1335. (bsub c1.folded2 (badd c1.lo2 c1.hi2))
  1336. (bsub c2.folded2 (badd c2.lo2 c2.hi2))
  1337. (bsub c3.folded2 (badd c3.lo2 c3.hi2))
  1338. (bsub c4.folded2 (badd c4.lo2 c4.hi2))
  1339. ==
  1340. :* :(badd c0.lo2 (bmul 7 c3.cross) (bmul 7 c0.hi2))
  1341. :(badd c1.lo2 (bmul 7 c4.cross) (bmul 7 c1.hi2))
  1342. (badd c2.lo2 (bmul 7 c2.hi2))
  1343. :(badd c3.lo2 c0.cross (bmul 7 c3.hi2))
  1344. :(badd c4.lo2 c1.cross (bmul 7 c4.hi2))
  1345. c2.cross
  1346. ==
  1347. ::
  1348. ++ f6-pow
  1349. |= [f=f6lt n=@]
  1350. ^- f6lt
  1351. =/ acc=f6lt f6-one
  1352. |-
  1353. ?: =(n 0) acc
  1354. %_ $
  1355. acc ?:(=((end 0 n) 0) acc (f6-mul acc f))
  1356. f (f6-square f)
  1357. n (rsh 0 n)
  1358. ==
  1359. ::
  1360. ++ f6-inv
  1361. |= f=f6lt
  1362. ^- f6lt
  1363. =/ eucl
  1364. %+ bpegcd
  1365. (init-bpoly (f6lt-to-list f))
  1366. (init-bpoly ~[(bneg 7) 0 0 0 0 0 1])
  1367. %- list-to-f6lt
  1368. =+ %- bpoly-to-list
  1369. (bpscal (binv (snag 0 (bpoly-to-list d.eucl))) u.eucl)
  1370. (weld - (reap (sub 6 (lent -)) 0))
  1371. ::
  1372. ++ f6-div
  1373. |= [f1=f6lt f2=f6lt]
  1374. ^- f6lt
  1375. (f6-mul f1 (f6-inv f2))
  1376. ::
  1377. :: elliptic cheetah curve operations
  1378. ++ curve
  1379. ~% %curve ..curve ~
  1380. |%
  1381. ++ b `f6lt`[395 1 0 0 0 0]
  1382. ::
  1383. :: +gx: x-coordinate of g in affine coordinates
  1384. ++ gx
  1385. ^- f6lt
  1386. :* 2.754.611.494.552.410.273
  1387. 8.599.518.745.794.843.693
  1388. 10.526.511.002.404.673.680
  1389. 4.830.863.958.577.994.148
  1390. 375.185.138.577.093.320
  1391. 12.938.930.721.685.970.739
  1392. ==
  1393. :: +gy: y-coordinate of g in affine coordinates
  1394. ++ gy
  1395. ^- f6lt
  1396. :* 15.384.029.202.802.550.068
  1397. 2.774.812.795.997.841.935
  1398. 14.375.303.400.746.062.753
  1399. 10.708.493.419.890.101.954
  1400. 13.187.678.623.570.541.764
  1401. 9.990.732.138.772.505.951
  1402. ==
  1403. ::
  1404. :: +g-order: order of g; 255 bits
  1405. ++ g-order
  1406. 0x7af2.599b.3b3f.22d0.563f.bf0f.990a.37b5.327a.a723.3015.7722.d443.623e.aed4.accf
  1407. :: +a-pt: affine coordinates
  1408. ::
  1409. :: If the infinity flag inf if %.n, this is an (x, y) point in the
  1410. :: affine plane, which we identify with the z=1 plane in projective
  1411. :: space. If %.y, this is a point on the projective line
  1412. :: "at infinity," i.e. (x, y) is identified with [x, y, 0] in
  1413. :: projective space. By the projective equivalence relation, this
  1414. :: representation is not unique.
  1415. +$ a-pt [x=f6lt y=f6lt inf=?]
  1416. ++ a-pt-dyck-word
  1417. ^~ ^- (list @)
  1418. (snoc (weld [0 f6lt-dyck-word] [1 0 f6lt-dyck-word]) 1)
  1419. ++ a-pt-cell-dyck-word
  1420. ^~ ^- (list @)
  1421. (weld [0 a-pt-dyck-word] [1 a-pt-dyck-word])
  1422. ::
  1423. :: +a-id
  1424. ::
  1425. :: The curve is defined by y^2 = x^3 + x + b over F^6.
  1426. :: To add the point at infinity we interpret these (x, y)
  1427. :: points as [x, y, 1] in P^2 over F^6. In projective [x, y, z]
  1428. :: coordinates the equation is y^2z = x^3 + xz^2 + bz^3. A
  1429. :: point at infinity (z=0), must satisfy x^3=0 so [0, y, 0] (y≠0)
  1430. :: is the only point at infinity on the curve (this is the same
  1431. :: pt for any y by the projective equivalence relation). Thus we
  1432. :: can take [0 1 %.y] as the identity point.
  1433. ::
  1434. :: Note that [0 -1 %.y] also represents the identity point.
  1435. ++ a-id `a-pt`[f6-zero f6-one %.y]
  1436. ++ a-gen
  1437. ^- a-pt
  1438. [gx gy %.n]
  1439. ::
  1440. :: +affine: curve operations in affine coordinates
  1441. ++ affine
  1442. ~% %affine ..affine ~
  1443. |%
  1444. ++ in-g
  1445. |= p=a-pt
  1446. =(a-id (ch-scal g-order p))
  1447. ::
  1448. :: +ch-neg: negate a cheetah point
  1449. ::
  1450. :: In Weierstrass form an elliptic curve has f([x y z]) = [x -y z] symmetry.
  1451. :: The line in the z=constant plane thru p and f(p) is vertical so passes
  1452. :: through O, the point at infinity; thus by the straight line relation for
  1453. :: elliptic curve addition, p + f(p) + O = O i.e. f(p) = -p.
  1454. ++ ch-neg
  1455. |= p=a-pt
  1456. ^- a-pt
  1457. [x.p (f6-neg y.p) inf.p]
  1458. ::
  1459. :: +ch-add: add two cheetah points
  1460. ++ ch-add-unsafe
  1461. |= [p=a-pt q=a-pt]
  1462. ^- a-pt
  1463. =/ slope (f6-div (f6-sub y.p y.q) (f6-sub x.p x.q))
  1464. =/ x-out (f6-sub (f6-square slope) (f6-add x.p x.q))
  1465. :+ x-out
  1466. (f6-sub (f6-mul slope (f6-sub x.p x-out)) y.p)
  1467. %.n
  1468. ::
  1469. ++ ch-add
  1470. |= [p=a-pt q=a-pt]
  1471. ^- a-pt
  1472. ?: inf.p q
  1473. ?: inf.q p
  1474. ?: =(p (ch-neg q)) a-id
  1475. ?: =(p q) (ch-double p)
  1476. (ch-add-unsafe p q)
  1477. ::
  1478. :: +ch-double-unsafe: generic add w/o special case checks
  1479. ++ ch-double-unsafe
  1480. |= p=a-pt
  1481. ^- a-pt
  1482. =/ slope
  1483. %+ f6-div
  1484. (f6-add (f6-scal 3 (f6-square x.p)) f6-one)
  1485. (f6-scal 2 y.p)
  1486. =/ x-out (f6-sub (f6-square slope) (f6-scal 2 x.p))
  1487. :+ x-out
  1488. (f6-sub (f6-mul slope (f6-sub x.p x-out)) y.p)
  1489. %.n
  1490. ::
  1491. :: +ch-double: [2]p, p a cheetah point
  1492. ::
  1493. :: Analog of squaring; fundamental for computing [n]p quickly.
  1494. :: Two special cases: the double of the point at infinity is itself;
  1495. :: and the double of any point with infinite slope is infinite. A
  1496. :: point with infinite slope is any point with y=0 by the equation
  1497. :: dy/dx = (3x^2 + 1)/2y.
  1498. ++ ch-double
  1499. |= p=a-pt
  1500. ^- a-pt
  1501. ?: inf.p a-id
  1502. ?: =(y.p f6-zero) a-id
  1503. (ch-double-unsafe p)
  1504. ::
  1505. :: +ch-scal: compute [n]p, p a cheetah point
  1506. ::
  1507. :: This is the action of Z on cheetah as an abelian group.
  1508. ++ ch-scal
  1509. |= [n=@ p=a-pt]
  1510. ^- a-pt
  1511. =/ acc a-id
  1512. |-
  1513. ?: =(n 0) acc
  1514. %_ $
  1515. acc ?:(=((end 0 n) 0) acc (ch-add acc p))
  1516. n (rsh 0 n)
  1517. p (ch-double p)
  1518. ==
  1519. --
  1520. --
  1521. ::
  1522. ++ schnorr
  1523. ~% %schnorr ..schnorr ~
  1524. |%
  1525. ++ affine
  1526. ~% %affine ..affine ~
  1527. |%
  1528. ++ sign
  1529. ~/ %sign
  1530. |= [sk-as-32-bit-belts=(list belt) m=(list belt)]
  1531. ^- [c=@ux s=@ux]
  1532. ?> =((lent m) 5)
  1533. =/ b-32 (bex 32)
  1534. ?> (levy sk-as-32-bit-belts |=(n=@ (lth n b-32)))
  1535. =/ sk (rep 5 sk-as-32-bit-belts)
  1536. ?< =(sk 0)
  1537. ?> (lth sk g-order:curve)
  1538. =/ pubkey (ch-scal:affine:curve sk a-gen:curve)
  1539. =/ transcript=(list (list belt))
  1540. [(f6lt-to-list x.pubkey) (f6lt-to-list y.pubkey) m ~]
  1541. =/ nonce
  1542. (trunc-g-order (hash-varlen:tip5 (zing transcript)))
  1543. ?< =(nonce 0)
  1544. =/ scalar (ch-scal:affine:curve nonce a-gen:curve)
  1545. =. transcript [(f6lt-to-list x.scalar) (f6lt-to-list y.scalar) transcript]
  1546. =/ chal
  1547. (trunc-g-order (hash-varlen:tip5 (zing transcript)))
  1548. ?< =(chal 0)
  1549. =/ sig
  1550. %+ mod
  1551. (add nonce (mul chal sk))
  1552. g-order:curve
  1553. ?< =(sig 0)
  1554. [chal sig]
  1555. ::
  1556. ++ verify
  1557. ~/ %verify
  1558. |= [pubkey=a-pt:curve m=(list belt) chal=@ux sig=@ux]
  1559. ^- ?
  1560. ?&
  1561. =((lent m) 5) :: m must be a tip5 hash
  1562. (gth chal 0) (lth chal g-order:curve)
  1563. ::
  1564. (gth sig 0) (lth sig g-order:curve)
  1565. ::
  1566. =/ scalar
  1567. %+ ch-add:affine:curve
  1568. (ch-scal:affine:curve sig a-gen:curve)
  1569. (ch-neg:affine:curve (ch-scal:affine:curve chal pubkey))
  1570. ?< =(scalar f6-zero)
  1571. .= chal
  1572. %- trunc-g-order
  1573. %- hash-varlen:tip5
  1574. %- zing
  1575. :~ (f6lt-to-list x.scalar) (f6lt-to-list y.scalar)
  1576. (f6lt-to-list x.pubkey) (f6lt-to-list y.pubkey)
  1577. m
  1578. ==
  1579. ==
  1580. --
  1581. --
  1582. ::
  1583. :: +trunc-g-order: truncates a list of ≥4 belts to a 255-bit number
  1584. ++ trunc-g-order
  1585. |= a=(list belt)
  1586. ^- @
  1587. %+ mod
  1588. ;: add
  1589. (snag 0 a)
  1590. (mul p (snag 1 a))
  1591. :(mul p p (snag 2 a))
  1592. :(mul p p p (snag 3 a))
  1593. ==
  1594. g-order:curve
  1595. ::
  1596. :: +a-pt-to-base58: concatenate a-pt coords
  1597. ::
  1598. :: we treat an a-pt as 12 64-bit atoms (6 for x, 6 for y). we concatenate them as
  1599. :: fixed-width atoms, put a leading 1 in front of it, and then
  1600. :: convert to a base58 cord.
  1601. ::
  1602. :: we crash when inf=%.y since that is for projective coordinates, which does not
  1603. :: have a unique representation and so must be treated differently.
  1604. ++ a-pt-to-base58
  1605. ~/ %a-pt-to-base58
  1606. |= a=a-pt:curve
  1607. ^- cord
  1608. ?: inf.a !!
  1609. (crip (en-base58 (ser-a-pt a)))
  1610. ::
  1611. ++ ser-a-pt
  1612. ~/ %ser-a-pt
  1613. |= a=a-pt:curve
  1614. ^- @ux
  1615. ?> &((in-g:affine:curve a) !=(a-id:curve p))
  1616. ?: inf.a !!
  1617. %+ rep 6 :: 64 bit atoms
  1618. :~ a0.x.a a1.x.a a2.x.a a3.x.a a4.x.a a5.x.a
  1619. a0.y.a a1.y.a a2.y.a a3.y.a a4.y.a a5.y.a
  1620. 1 :: the leading 1
  1621. ==
  1622. ::
  1623. ++ de-a-pt
  1624. ~/ %de-a-pt
  1625. |= a=@ux
  1626. ^- a-pt:curve
  1627. |^
  1628. =/ pt-list=(list @) (rip-correct 6 a)
  1629. =/ x=f6lt (conv (scag 6 pt-list))
  1630. =/ y=f6lt (conv (scag 6 (oust [0 6] pt-list)))
  1631. ::
  1632. :: We assume the point we are provided is not projective
  1633. :: and set inf to %.n. This will be true so long
  1634. :: as `a` was encoded using ser-a-pt. This also means that a-pt
  1635. :: will never be the identity point, so we skip the check.
  1636. =/ =a-pt:curve [x y %.n]
  1637. ?> (in-g:affine:curve a-pt)
  1638. a-pt
  1639. ++ conv
  1640. |= n=(list @)
  1641. ^- f6lt
  1642. :* (snag 0 n) (snag 1 n) (snag 2 n)
  1643. (snag 3 n) (snag 4 n) (snag 5 n)
  1644. ==
  1645. --
  1646. ++ base58-to-a-pt
  1647. ~/ %base58-to-a-pt
  1648. |= a=cord
  1649. ^- a-pt:curve
  1650. (de-a-pt (de-base58 (trip a)))
  1651. ::
  1652. ::
  1653. ::
  1654. :: +belt-schnorr: a wrapper for Schnorr signatures that works only with belts
  1655. :: TODO: audit this around how rip and rep are used
  1656. ++ belt-schnorr
  1657. |%
  1658. +$ t8 [@ux @ux @ux @ux @ux @ux @ux @ux] :: 8-tuple of belts
  1659. +$ sk t8
  1660. +$ sig t8
  1661. +$ chal t8
  1662. ::
  1663. ++ atom-to-t8
  1664. |= a=@ux
  1665. ^- t8
  1666. =/ ripped=(list @) (rip-correct 5 a)
  1667. :: most of the time, .rippped will be 8 @, but if it has enough leading
  1668. :: zeroes then it won't. +rip reverses the endianness, so we put the
  1669. :: leading zeroes at the end.
  1670. =/ length-dif=@ (sub 8 (lent ripped))
  1671. =. ripped (weld ripped (reap length-dif 0))
  1672. ;;(t8 (list-to-tuple:tip5 (rip-correct 5 a)))
  1673. ::
  1674. ++ t8-to-atom
  1675. |= t=t8
  1676. ^- @ux
  1677. (rap 5 (leaf-sequence:shape t))
  1678. ::
  1679. ++ t8-to-list
  1680. |= t=t8
  1681. ^- (list belt)
  1682. (leaf-sequence:shape t)
  1683. ::
  1684. ++ affine
  1685. |%
  1686. ++ sign
  1687. |= [=sk m=(list belt)]
  1688. ^- [c=chal s=sig]
  1689. =/ [c=@ux s=@ux]
  1690. (sign:affine:schnorr (t8-to-list sk) m)
  1691. [(atom-to-t8 c) (atom-to-t8 s)]
  1692. ::
  1693. ++ verify
  1694. |= [pk=a-pt:curve m=(list belt) =chal =sig]
  1695. ^- ?
  1696. %- verify:affine:schnorr
  1697. :* pk m
  1698. (t8-to-atom chal)
  1699. (t8-to-atom sig)
  1700. ==
  1701. -- ::+affine
  1702. -- ::+belt-schnorr
  1703. -- ::+cheetah
  1704. ::
  1705. ++ merkle :: /lib/merkle
  1706. ~% %merkle ..merkle ~
  1707. |%
  1708. +| %types
  1709. :: TODO: switch merk over to this type once tip5 changes are finalized
  1710. ++ other-merk
  1711. |$ node
  1712. $: h=noun-digest:tip5
  1713. $@ ~
  1714. (pair (merk node) (merk node))
  1715. ==
  1716. ++ merk
  1717. |$ [node]
  1718. $~ [%leaf *noun-digest:tip5 ~]
  1719. $% [%leaf h=noun-digest:tip5 ~]
  1720. [%tree h=noun-digest:tip5 t=(pair (merk node) (merk node))]
  1721. ==
  1722. +$ vector (list @) :: replace with bitvector
  1723. +$ merk-proof [root=noun-digest:tip5 path=(list noun-digest:tip5)]
  1724. +$ merk-heap [h=noun-digest:tip5 m=mary]
  1725. ++ mee
  1726. |$ [node]
  1727. $~ [%leaf *node]
  1728. $% [%leaf n=node]
  1729. [%tree l=(mee node) r=(mee node)]
  1730. ==
  1731. ::
  1732. +| %work
  1733. ++ build-merk
  1734. ~/ %build-merk
  1735. |= m=mary
  1736. ^- (pair @ (merk mary))
  1737. =/ [h=@ n=(mee mary)] (list-to-balanced-tree m)
  1738. :- h
  1739. |-
  1740. ?: ?=([%leaf *] n)
  1741. [%leaf (hash-hashable:tip5 (hashable-mary:tip5 n.n)) ~]
  1742. =/ l=(merk mary) $(n l.n)
  1743. =/ r=(merk mary) $(n r.n)
  1744. [%tree (hash-ten-cell:tip5 h.l h.r) l r]
  1745. ::
  1746. ++ build-merk-heap
  1747. ~/ %build-merk-heap
  1748. |= m=mary
  1749. ^- [depth=@ heap=merk-heap]
  1750. |^
  1751. =/ heap-mary (heapify-mary m)
  1752. :- (xeb len.array.m)
  1753. [(snag-as-digest:tip5 heap-mary 0) heap-mary]
  1754. ::
  1755. :: +heapify-mary
  1756. :: Take a mary of felts, merklize it, and return it as a heap
  1757. ++ heapify-mary
  1758. |= m=mary
  1759. ^- mary
  1760. =/ size (dec (bex (xeb len.array.m)))
  1761. =/ high-bit (lsh [6 (mul size 5)] 1)
  1762. :: make leaves
  1763. =/ res=(list (list @))
  1764. %+ turn
  1765. (range len.array.m)
  1766. |= i=@
  1767. =/ t (~(snag-as-fpoly ave m) i)
  1768. (leaf-sequence:shape (hash-hashable:tip5 (hashable-fpoly:tip5 t)))
  1769. :+ 5
  1770. size
  1771. %+ add
  1772. high-bit
  1773. %+ rep 6
  1774. %- zing
  1775. ^- (list (list @))
  1776. =/ curr res
  1777. |-
  1778. ?: =((lent curr) 1)
  1779. res
  1780. =/ pairs (hash-pairs:tip5 curr)
  1781. %= $
  1782. res (weld pairs res)
  1783. curr pairs
  1784. ==
  1785. --
  1786. ::
  1787. ++ bp-build-merk-heap
  1788. ~/ %bp-build-merk-heap
  1789. |= m=mary
  1790. ^- (pair @ merk-heap)
  1791. |^
  1792. =/ heap-mary (heapify-mary m)
  1793. :- (xeb len.array.m)
  1794. [(snag-as-digest:tip5 heap-mary 0) heap-mary]
  1795. ::
  1796. :: +heapify-mary
  1797. :: Take a mary of belts, merklize it, and return it as a heap
  1798. ++ heapify-mary
  1799. |= m=mary
  1800. ^- mary
  1801. =/ size (dec (bex (xeb len.array.m)))
  1802. =/ high-bit (lsh [6 (mul size 5)] 1)
  1803. :: make leaves
  1804. =/ res=(list (list @))
  1805. %+ turn
  1806. (range len.array.m)
  1807. |= i=@
  1808. =/ t (~(snag-as-bpoly ave m) i)
  1809. (leaf-sequence:shape (hash-hashable:tip5 (hashable-bpoly:tip5 t)))
  1810. :+ 5
  1811. size
  1812. %+ add
  1813. high-bit
  1814. %+ rep 6
  1815. %- zing
  1816. ^- (list (list @))
  1817. =/ curr res
  1818. |-
  1819. ?: =((lent curr) 1)
  1820. res
  1821. =/ pairs (hash-pairs:tip5 curr)
  1822. %= $
  1823. res (weld pairs res)
  1824. curr pairs
  1825. ==
  1826. --
  1827. ::
  1828. ++ index-to-axis
  1829. ~/ %index-to-axis
  1830. |= [h=@ i=@]
  1831. ^- axis
  1832. =/ min (bex (dec h))
  1833. (add min i)
  1834. ::
  1835. ++ list-to-balanced-merk
  1836. ~/ %list-to-balanced-merk
  1837. |= lis=mary
  1838. ^- (pair @ (merk mary))
  1839. (build-merk lis)
  1840. ::
  1841. ++ list-to-balanced-tree
  1842. ~/ %list-to-balanced-tree
  1843. |= lis=mary
  1844. ^- [h=@ t=(mee mary)]
  1845. :- (xeb len.array.lis)
  1846. |-
  1847. ?> !=(0 len.array.lis)
  1848. =/ len len.array.lis
  1849. ?: =(1 len)
  1850. [%leaf (~(change-step ave [step.lis 1 (~(snag ave lis) 0)]) 3)]
  1851. ?: =(2 len)
  1852. :+ %tree
  1853. [%leaf (~(change-step ave [step.lis 1 (~(snag ave lis) 0)]) 3)]
  1854. [%leaf (~(change-step ave [step.lis 1 (~(snag ave lis) 1)]) 3)]
  1855. =/ l=(mee mary)
  1856. ?: =((mod len 2) 0)
  1857. $(lis (~(scag ave lis) (div len 2)))
  1858. $(lis (~(scag ave lis) +((div len 2))))
  1859. =/ r=(mee mary)
  1860. ?: =((mod len 2) 0)
  1861. $(lis (~(slag ave lis) (div len 2)))
  1862. $(lis (~(slag ave lis) +((div len 2))))
  1863. [%tree l r]
  1864. ::
  1865. ++ build-merk-proof
  1866. ~/ %build-merk-proof
  1867. |= [merk=merk-heap axis=@]
  1868. ^- merk-proof
  1869. ?: =(0 axis) !!
  1870. :- h.merk
  1871. ?: =(1 axis) ~
  1872. ::
  1873. :: Convert axis to heap index by decrementing
  1874. =. axis (dec axis)
  1875. ^- (list noun-digest:tip5)
  1876. |-
  1877. ?: =(0 axis)
  1878. ~
  1879. =/ parent (div (dec axis) 2)
  1880. =/ sibling
  1881. ?: =(1 (mod axis 2))
  1882. (add axis 1)
  1883. (sub axis 1)
  1884. [(snag-as-digest:tip5 m.merk sibling) $(axis parent)]
  1885. ::
  1886. ++ snag-as-merk-proof
  1887. |= [i=@ root=noun-digest:tip5 merk=mary]
  1888. ^- merk-proof
  1889. =/ mary-pat=mary (~(snag-as-mary ave merk) i)
  1890. =/ pat (~(change-step ave mary-pat) 5)
  1891. =/ merk-path=(list noun-digest:tip5)
  1892. %+ turn (range len.array.pat)
  1893. |= i=@
  1894. (snag-as-digest:tip5 pat i)
  1895. [root merk-path]
  1896. ::
  1897. +$ merk-data [leaf=noun-digest:tip5 axis=@ p=merk-proof]
  1898. ++ verify-merk-proof
  1899. ~/ %verify-merk-proof
  1900. |= [leaf=noun-digest:tip5 axis=@ merk-proof]
  1901. ^- ?
  1902. ?: =(0 axis) %.n
  1903. |-
  1904. ?: =(1 axis)
  1905. &(=(root leaf) ?=(~ path))
  1906. ?~ path %.n
  1907. =* sib i.path
  1908. ::
  1909. :: axis=2 when your parent is the root and you are the left child
  1910. ?: =(2 axis)
  1911. &(=(root (hash-ten-cell:tip5 leaf sib)) ?=(~ t.path))
  1912. ::
  1913. :: axis=3 when your parent is the root and you are the right child
  1914. ?: =(3 axis)
  1915. &(=(root (hash-ten-cell:tip5 sib leaf)) ?=(~ t.path))
  1916. ?: =((mod axis 2) 0)
  1917. $(axis (div axis 2), leaf (hash-ten-cell:tip5 leaf sib), path t.path)
  1918. $(axis (div (dec axis) 2), leaf (hash-ten-cell:tip5 sib leaf), path t.path)
  1919. ::
  1920. --
  1921. --