├── .gitignore ├── desk ├── sys.kelvin ├── desk.ship ├── desk.bill ├── mar │ ├── wallets.hoon │ ├── balances.hoon │ ├── history.hoon │ ├── bloc-update.hoon │ ├── token │ │ ├── block-alert.hoon │ │ └── block.hoon │ ├── transactions.hoon │ ├── atom.hoon │ ├── ship.hoon │ ├── noun.hoon │ ├── docket-0.hoon │ ├── kelvin.hoon │ ├── mime.hoon │ ├── css.hoon │ ├── bill.hoon │ ├── hoon.hoon │ └── txt.hoon ├── sur │ ├── pki-store.hoon │ ├── verb.hoon │ ├── chain.hoon │ ├── ledger.hoon │ ├── settings.hoon │ ├── docket.hoon │ ├── clockwork.hoon │ ├── dice.hoon │ └── token.hoon ├── desk.docket-0 ├── lib │ ├── skeleton.hoon │ ├── mip.hoon │ ├── default-agent.hoon │ ├── signatures.hoon │ ├── clockwork.hoon │ ├── token.hoon │ ├── verb.hoon │ ├── dbug.hoon │ ├── docket.hoon │ ├── style.css │ ├── azimuth.hoon │ ├── tiny.hoon │ └── naive.hoon └── app │ ├── clockstep.hoon │ ├── pki-store.hoon │ ├── ledger.hoon │ ├── token.hoon │ ├── chain.hoon │ ├── chain-ui.hoon │ └── clockwork.hoon ├── doc ├── core-feedback.txt └── WORKLIST.md ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | zod/ 2 | piers/ -------------------------------------------------------------------------------- /desk/sys.kelvin: -------------------------------------------------------------------------------- 1 | [%zuse 411] 2 | -------------------------------------------------------------------------------- /desk/desk.ship: -------------------------------------------------------------------------------- 1 | ~dister-dozzod-dalten -------------------------------------------------------------------------------- /desk/desk.bill: -------------------------------------------------------------------------------- 1 | :~ %clockwork 2 | %clockstep 3 | %pki-store 4 | %chain 5 | %ledger 6 | %chain-ui 7 | == 8 | -------------------------------------------------------------------------------- /desk/mar/wallets.hoon: -------------------------------------------------------------------------------- 1 | |_ wallets=(map cord @ux) 2 | ++ grad %noun 3 | ++ grow 4 | |% 5 | ++ noun wallets 6 | -- 7 | ++ grab 8 | |% 9 | ++ noun (map cord @ux) 10 | -- 11 | -- 12 | -------------------------------------------------------------------------------- /desk/mar/balances.hoon: -------------------------------------------------------------------------------- 1 | /- lg=ledger 2 | |_ =balances:lg 3 | ++ grad %noun 4 | ++ grow 5 | |% 6 | ++ noun balances 7 | -- 8 | ++ grab 9 | |% 10 | ++ noun balances:lg 11 | -- 12 | -- 13 | -------------------------------------------------------------------------------- /desk/mar/history.hoon: -------------------------------------------------------------------------------- 1 | /- cw=clockwork 2 | |_ =history:cw 3 | ++ grad %noun 4 | ++ grow 5 | |% 6 | ++ noun history 7 | -- 8 | ++ grab 9 | |% 10 | ++ noun history:cw 11 | -- 12 | -- 13 | -------------------------------------------------------------------------------- /desk/sur/pki-store.hoon: -------------------------------------------------------------------------------- 1 | /+ *mip 2 | :: A store of historical key data 3 | :: For purposes of being able to verify old keys 4 | |% 5 | +$ pki-store (mip ship life pass) 6 | +$ pki-entry [=ship =life =pass] 7 | -- 8 | -------------------------------------------------------------------------------- /desk/mar/bloc-update.hoon: -------------------------------------------------------------------------------- 1 | /- cw=clockwork 2 | |_ =bloc-update:cw 3 | ++ grad %noun 4 | ++ grow 5 | |% 6 | ++ noun bloc-update 7 | -- 8 | ++ grab 9 | |% 10 | ++ noun bloc-update:cw 11 | -- 12 | -- 13 | -------------------------------------------------------------------------------- /desk/mar/token/block-alert.hoon: -------------------------------------------------------------------------------- 1 | /- token 2 | |_ res=@ud 3 | ++ grab 4 | |% 5 | ++ noun @ud 6 | ++ atom @ud 7 | -- 8 | ++ grow 9 | |% 10 | ++ noun res 11 | ++ atom res 12 | -- 13 | ++ grad %atom 14 | -- -------------------------------------------------------------------------------- /desk/mar/token/block.hoon: -------------------------------------------------------------------------------- 1 | /- token 2 | |_ res=raw-signed-block.token 3 | ++ grab 4 | |% 5 | ++ noun @ 6 | ++ atom @ 7 | -- 8 | ++ grow 9 | |% 10 | ++ noun res 11 | ++ atom res 12 | -- 13 | ++ grad %atom 14 | -- -------------------------------------------------------------------------------- /desk/mar/transactions.hoon: -------------------------------------------------------------------------------- 1 | /- ch=chain 2 | |_ transactions=(list txn-signed:ch) 3 | ++ grad %noun 4 | ++ grow 5 | |% 6 | ++ noun transactions 7 | -- 8 | ++ grab 9 | |% 10 | ++ noun (list txn-signed:ch) 11 | -- 12 | -- 13 | -------------------------------------------------------------------------------- /desk/desk.docket-0: -------------------------------------------------------------------------------- 1 | :~ title+'%chain' 2 | info+'An Urbit-native L1 blockchain that implements a cryptocurrency $TOKEN.' 3 | color+0x44ff 4 | image+'' 5 | version+[0 0 1] 6 | website+'https://urbit.org/' 7 | license+'MIT' 8 | site+/apps/chain 9 | == -------------------------------------------------------------------------------- /desk/sur/verb.hoon: -------------------------------------------------------------------------------- 1 | |% 2 | +$ event 3 | $% [%on-init ~] 4 | [%on-load ~] 5 | [%on-poke =mark] 6 | [%on-watch =path] 7 | [%on-leave =path] 8 | [%on-agent =wire sign=term] 9 | [%on-arvo =wire vane=term sign=term] 10 | [%on-fail =term] 11 | == 12 | -- -------------------------------------------------------------------------------- /desk/mar/atom.hoon: -------------------------------------------------------------------------------- 1 | :: 2 | :::: /hoon/atom/mar 3 | :: 4 | /? 310 5 | :: 6 | :::: A minimal atom mark 7 | :: 8 | =, mimes:html 9 | |_ ato=@ 10 | ++ grab |% 11 | ++ noun @ 12 | ++ mime |=([* p=octs] q.p) 13 | -- 14 | ++ grow |% 15 | ++ mime [/application/x-urb-unknown (as-octs ato)] 16 | -- 17 | ++ grad %mime 18 | -- 19 | -------------------------------------------------------------------------------- /doc/core-feedback.txt: -------------------------------------------------------------------------------- 1 | - Jael should keep a key revision history for me so I don't need to build %pki-store 2 | - Jael should sign things for me so I don't have to store private keys in my state 3 | - Crub is basically impossible to use in anger without reading the code, which is opaque 4 | 5 | less relevant: 6 | - Hoon should recognize that I made a recursive type instead of just looping and crashing -------------------------------------------------------------------------------- /desk/mar/ship.hoon: -------------------------------------------------------------------------------- 1 | |_ s=ship 2 | ++ grad %noun 3 | ++ grow 4 | |% 5 | ++ noun s 6 | ++ json s+(scot %p s) 7 | ++ mime 8 | ^- ^mime 9 | [/text/x-ship (as-octt:mimes:html (scow %p s))] 10 | 11 | -- 12 | ++ grab 13 | |% 14 | ++ noun ship 15 | ++ json (su:dejs:format ;~(pfix sig fed:ag)) 16 | ++ mime 17 | |= [=mite len=@ tex=@] 18 | (slav %p (snag 0 (to-wain:format tex))) 19 | -- 20 | -- 21 | -------------------------------------------------------------------------------- /desk/sur/chain.hoon: -------------------------------------------------------------------------------- 1 | /+ *mip 2 | |% 3 | ++ addr @ux 4 | ++ sent-txns (mip addr @ud txn-signed) 5 | ++ txn-signed 6 | $: signature=@ux 7 | txn-unsigned 8 | == 9 | ++ txn-unsigned 10 | $: who=addr 11 | nonce=@ud 12 | txn-stub 13 | == 14 | ++ txn-stub 15 | $: app=@tas 16 | :: fees are ignored for now 17 | fee=@ud 18 | cmd=* 19 | == 20 | ++ wallet 21 | $: pub=@ux 22 | sec=@ux 23 | == 24 | ++ wallets (map cord wallet) 25 | -- 26 | -------------------------------------------------------------------------------- /desk/mar/noun.hoon: -------------------------------------------------------------------------------- 1 | :: 2 | :::: /hoon/noun/mar 3 | :: 4 | /? 310 5 | !: 6 | :::: A minimal noun mark 7 | |_ non=* 8 | ++ grab |% 9 | ++ noun * 10 | -- 11 | ++ grow |% 12 | ++ mime [/application/x-urb-jam (as-octs:mimes:html (jam non))] 13 | -- 14 | ++ grad 15 | |% 16 | ++ form %noun 17 | ++ diff |=(* +<) 18 | ++ pact |=(* +<) 19 | ++ join |=([* *] *(unit *)) 20 | ++ mash |=([[ship desk *] [ship desk *]] `*`~|(%noun-mash !!)) 21 | -- 22 | -- 23 | -------------------------------------------------------------------------------- /desk/mar/docket-0.hoon: -------------------------------------------------------------------------------- 1 | /+ dock=docket 2 | |_ =docket:dock 3 | ++ grow 4 | |% 5 | ++ mime 6 | ^- ^mime 7 | [/text/x-docket (as-octt:mimes:html (spit-docket:mime:dock docket))] 8 | ++ noun docket 9 | ++ json (docket:enjs:dock docket) 10 | -- 11 | ++ grab 12 | |% 13 | :: 14 | ++ mime 15 | |= [=mite len=@ud tex=@] 16 | ^- docket:dock 17 | %- need 18 | %- from-clauses:mime:dock 19 | !<((list clause:dock) (slap !>(~) (ream tex))) 20 | 21 | :: 22 | ++ noun docket:dock 23 | -- 24 | ++ grad %noun 25 | -- 26 | -------------------------------------------------------------------------------- /desk/sur/ledger.hoon: -------------------------------------------------------------------------------- 1 | /- ch=chain 2 | |% 3 | ++ txn-ledger 4 | $: signature=@ 5 | txn-unsigned-ledger 6 | == 7 | ++ txn-unsigned-ledger 8 | $: who=addr:ch 9 | nonce=@ud 10 | txn-stub-ledger 11 | == 12 | ++ txn-stub-ledger 13 | $: app=%ledger 14 | :: fees are ignored for now 15 | fee=@ud 16 | cmd=ledger-cmd 17 | == 18 | ++ internal-balance 19 | $: balance=@ud 20 | nonce=@ud 21 | faucet=? 22 | == 23 | ++ internal-balances (map addr:ch internal-balance) 24 | ++ balances (map addr:ch @ud) 25 | ++ ledger-cmd 26 | $% [%send target=addr:ch amount=@ud] 27 | == 28 | -- 29 | -------------------------------------------------------------------------------- /desk/mar/kelvin.hoon: -------------------------------------------------------------------------------- 1 | |_ kal=waft:clay 2 | ++ grow 3 | |% 4 | ++ mime `^mime`[/text/x-kelvin (as-octs:mimes:html hoon)] 5 | ++ noun kal 6 | ++ hoon 7 | %+ rap 3 8 | %+ turn 9 | %+ sort 10 | ~(tap in (waft-to-wefts:clay kal)) 11 | |= [a=weft b=weft] 12 | ?: =(lal.a lal.b) 13 | (gte num.a num.b) 14 | (gte lal.a lal.b) 15 | |= =weft 16 | (rap 3 '[%' (scot %tas lal.weft) ' ' (scot %ud num.weft) ']\0a' ~) 17 | :: 18 | ++ txt (to-wain:format hoon) 19 | -- 20 | ++ grab 21 | |% 22 | ++ noun waft:clay 23 | ++ mime 24 | |= [=mite len=@ud tex=@] 25 | (cord-to-waft:clay tex) 26 | -- 27 | ++ grad %noun 28 | -- 29 | -------------------------------------------------------------------------------- /desk/mar/mime.hoon: -------------------------------------------------------------------------------- 1 | :: 2 | :::: /hoon/mime/mar 3 | :: 4 | /? 310 5 | :: 6 | |_ own=mime 7 | ++ grow 8 | ^? 9 | |% 10 | ++ jam `@`q.q.own 11 | -- 12 | :: 13 | ++ grab :: convert from 14 | ^? 15 | |% 16 | ++ noun mime :: clam from %noun 17 | ++ tape 18 | |=(a=_"" [/application/x-urb-unknown (as-octt:mimes:html a)]) 19 | -- 20 | ++ grad 21 | ^? 22 | |% 23 | ++ form %mime 24 | ++ diff |=(mime +<) 25 | ++ pact |=(mime +<) 26 | ++ join |=([mime mime] `(unit mime)`~) 27 | ++ mash 28 | |= [[ship desk mime] [ship desk mime]] 29 | ^- mime 30 | ~|(%mime-mash !!) 31 | -- 32 | -- 33 | -------------------------------------------------------------------------------- /desk/mar/css.hoon: -------------------------------------------------------------------------------- 1 | :: 2 | :::: /hoon/css/mar 3 | :: 4 | /? 310 5 | =, eyre 6 | =, mimes:html 7 | |_ mud=@t 8 | ++ grow :: convert to 9 | |% 10 | ++ mime [/text/css (as-octs mud)] :: convert to %mime 11 | ++ hymn :: convert to %hymn 12 | |^ html 13 | ++ style ;style 14 | ;- (trip mud) 15 | == 16 | ++ html ;html:(head:"{style}" body) 17 | -- 18 | -- 19 | ++ grab 20 | |% :: convert from 21 | ++ mime |=([p=mite q=octs] (@t q.q)) 22 | ++ noun @t :: clam from %noun 23 | -- 24 | ++ grad %mime 25 | -- 26 | -------------------------------------------------------------------------------- /desk/mar/bill.hoon: -------------------------------------------------------------------------------- 1 | |_ bil=(list dude:gall) 2 | ++ grow 3 | |% 4 | ++ mime `^mime`[/text/x-bill (as-octs:mimes:html hoon)] 5 | ++ noun bil 6 | ++ hoon 7 | ^- @t 8 | |^ (crip (of-wall:format (wrap-lines (spit-duz bil)))) 9 | :: 10 | ++ wrap-lines 11 | |= taz=wall 12 | ^- wall 13 | ?~ taz ["~"]~ 14 | :- (weld ":~ " i.taz) 15 | %- snoc :_ "==" 16 | (turn t.taz |=(t=tape (weld " " t))) 17 | :: 18 | ++ spit-duz 19 | |= duz=(list dude:gall) 20 | ^- wall 21 | (turn duz |=(=dude:gall ['%' (trip dude)])) 22 | -- 23 | ++ txt (to-wain:format hoon) 24 | -- 25 | ++ grab 26 | |% 27 | ++ noun (list dude:gall) 28 | ++ mime 29 | |= [=mite len=@ud tex=@] 30 | ~_ tex 31 | !<((list dude:gall) (slap !>(~) (ream tex))) 32 | -- 33 | ++ grad %noun 34 | -- 35 | -------------------------------------------------------------------------------- /desk/sur/settings.hoon: -------------------------------------------------------------------------------- 1 | /+ *mip 2 | |% 3 | :: 4 | ++ settings-0 5 | =< settings 6 | |% 7 | +$ settings (map key bucket) 8 | +$ bucket (map key val) 9 | +$ val 10 | $% [%s p=@t] 11 | [%b p=?] 12 | [%n p=@] 13 | == 14 | -- 15 | :: 16 | ++ settings-1 17 | =< settings 18 | |% 19 | +$ settings (map key bucket) 20 | -- 21 | +$ bucket (map key val) 22 | +$ key term 23 | +$ val 24 | $~ [%n 0] 25 | $% [%s p=@t] 26 | [%b p=?] 27 | [%n p=@] 28 | [%a p=(list val)] 29 | == 30 | :: 31 | +$ settings (mip desk key bucket) 32 | +$ event 33 | $% [%put-bucket =desk =key =bucket] 34 | [%del-bucket =desk =key] 35 | [%put-entry =desk buc=key =key =val] 36 | [%del-entry =desk buc=key =key] 37 | == 38 | +$ data 39 | $% [%all =settings] 40 | [%bucket =bucket] 41 | [%desk desk=(map key bucket)] 42 | [%entry =val] 43 | == 44 | -- 45 | -------------------------------------------------------------------------------- /desk/lib/skeleton.hoon: -------------------------------------------------------------------------------- 1 | :: Similar to default-agent except crashes everywhere 2 | ^- agent:gall 3 | |_ bowl:gall 4 | ++ on-init 5 | ^- (quip card:agent:gall agent:gall) 6 | !! 7 | :: 8 | ++ on-save 9 | ^- vase 10 | !! 11 | :: 12 | ++ on-load 13 | |~ old-state=vase 14 | ^- (quip card:agent:gall agent:gall) 15 | !! 16 | :: 17 | ++ on-poke 18 | |~ in-poke-data=cage 19 | ^- (quip card:agent:gall agent:gall) 20 | !! 21 | :: 22 | ++ on-watch 23 | |~ path 24 | ^- (quip card:agent:gall agent:gall) 25 | !! 26 | :: 27 | ++ on-leave 28 | |~ path 29 | ^- (quip card:agent:gall agent:gall) 30 | !! 31 | :: 32 | ++ on-peek 33 | |~ path 34 | ^- (unit (unit cage)) 35 | !! 36 | :: 37 | ++ on-agent 38 | |~ [wire sign:agent:gall] 39 | ^- (quip card:agent:gall agent:gall) 40 | !! 41 | :: 42 | ++ on-arvo 43 | |~ [wire =sign-arvo] 44 | ^- (quip card:agent:gall agent:gall) 45 | !! 46 | :: 47 | ++ on-fail 48 | |~ [term tang] 49 | ^- (quip card:agent:gall agent:gall) 50 | !! 51 | -- 52 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 tiller-tolbus 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /doc/WORKLIST.md: -------------------------------------------------------------------------------- 1 | # `%token` 2 | 3 | %pki-store 4 | - %token subscribes to %pki-store 5 | - roundtrip block/txn signatures 6 | 7 | - TX structure 8 | - TX collector 9 | - TX validator 10 | - etc. 11 | 12 | 13 | - [ ] pending TXN tracking 14 | - [ ] kelvin-versioning types on Urbit? 15 | - gates for signing txns, signing/hashing blocks 16 | 17 | questions: 18 | - assert on path resolution? 19 | - case? 20 | 21 | caveats: 22 | - performance 23 | - block length likely quite long at first 24 | 25 | 26 | scry maximalist route: 27 | - consensus on urbit but you may not have direct route to node 28 | - relay signature? current ames/remote scry cannot do, but NDN can 29 | - proof-of-authority, slow blockchain as a result 30 | - scry the path to validate the TXN 31 | - (thus the kernel has already validated the TXN when you scry successfully) 32 | - question: what happens to bound scry values after breach? 33 | - do we need to gossip/mirror these? 34 | 35 | ```hoon 36 | :token &token-axn [%sire germ=[src=~zod met=[%put des=~tiller-tolbus amt=100 bid=1]]] 37 | .^((list path) %gt /=token=//token/txn) 38 | 39 | ``` 40 | 41 | New: 42 | * Create %clockstep 43 | * Rip out arms into lib 44 | * Write tests -------------------------------------------------------------------------------- /desk/lib/mip.hoon: -------------------------------------------------------------------------------- 1 | |% 2 | ++ mip :: map of maps 3 | |$ [kex key value] 4 | (map kex (map key value)) 5 | :: 6 | ++ bi :: mip engine 7 | =| a=(map * (map)) 8 | |@ 9 | ++ del 10 | |* [b=* c=*] 11 | =+ d=(~(gut by a) b ~) 12 | =+ e=(~(del by d) c) 13 | ?~ e 14 | (~(del by a) b) 15 | (~(put by a) b e) 16 | :: 17 | ++ get 18 | |* [b=* c=*] 19 | => .(b `_?>(?=(^ a) p.n.a)`b, c `_?>(?=(^ a) ?>(?=(^ q.n.a) p.n.q.n.a))`c) 20 | ^- (unit _?>(?=(^ a) ?>(?=(^ q.n.a) q.n.q.n.a))) 21 | (~(get by (~(gut by a) b ~)) c) 22 | :: 23 | ++ got 24 | |* [b=* c=*] 25 | (need (get b c)) 26 | :: 27 | ++ gut 28 | |* [b=* c=* d=*] 29 | (~(gut by (~(gut by a) b ~)) c d) 30 | :: 31 | ++ has 32 | |* [b=* c=*] 33 | !=(~ (get b c)) 34 | :: 35 | ++ key 36 | |* b=* 37 | ~(key by (~(gut by a) b ~)) 38 | :: 39 | ++ put 40 | |* [b=* c=* d=*] 41 | %+ ~(put by a) b 42 | %. [c d] 43 | %~ put by 44 | (~(gut by a) b ~) 45 | :: 46 | ++ tap 47 | ::NOTE naive turn-based implementation find-errors ): 48 | =< $ 49 | =+ b=`_?>(?=(^ a) *(list [x=_p.n.a _?>(?=(^ q.n.a) [y=p v=q]:n.q.n.a)]))`~ 50 | |. ^+ b 51 | ?~ a 52 | b 53 | $(a r.a, b (welp (turn ~(tap by q.n.a) (lead p.n.a)) $(a l.a))) 54 | -- 55 | -- 56 | -------------------------------------------------------------------------------- /desk/lib/default-agent.hoon: -------------------------------------------------------------------------------- 1 | /+ skeleton 2 | |* [agent=* help=*] 3 | ?: ?=(%& help) 4 | ~| %default-agent-helpfully-crashing 5 | skeleton 6 | |_ =bowl:gall 7 | ++ on-init 8 | `agent 9 | :: 10 | ++ on-save 11 | !>(~) 12 | :: 13 | ++ on-load 14 | |= old-state=vase 15 | `agent 16 | :: 17 | ++ on-poke 18 | |= =cage 19 | ~| "unexpected poke to {} with mark {}" 20 | !! 21 | :: 22 | ++ on-watch 23 | |= =path 24 | ~| "unexpected subscription to {} on path {}" 25 | !! 26 | :: 27 | ++ on-leave 28 | |= path 29 | `agent 30 | :: 31 | ++ on-peek 32 | |= =path 33 | ~| "unexpected scry into {} on path {}" 34 | !! 35 | :: 36 | ++ on-agent 37 | |= [=wire =sign:agent:gall] 38 | ^- (quip card:agent:gall _agent) 39 | ?- -.sign 40 | %poke-ack 41 | ?~ p.sign 42 | `agent 43 | %- (slog leaf+"poke failed from {} on wire {}" u.p.sign) 44 | `agent 45 | :: 46 | %watch-ack 47 | ?~ p.sign 48 | `agent 49 | =/ =tank leaf+"subscribe failed from {} on wire {}" 50 | %- (slog tank u.p.sign) 51 | `agent 52 | :: 53 | %kick `agent 54 | %fact 55 | ~| "unexpected subscription update to {} on wire {}" 56 | ~| "with mark {}" 57 | !! 58 | == 59 | :: 60 | ++ on-arvo 61 | |= [=wire =sign-arvo] 62 | ~| "unexpected system response {<-.sign-arvo>} to {} on wire {}" 63 | !! 64 | :: 65 | ++ on-fail 66 | |= [=term =tang] 67 | %- (slog leaf+"error in {}" >term< tang) 68 | `agent 69 | -- 70 | -------------------------------------------------------------------------------- /desk/lib/signatures.hoon: -------------------------------------------------------------------------------- 1 | |% 2 | +$ signature [p=@uvH q=ship r=life] 3 | +$ signatures (set signature) 4 | +$ hash @uvH 5 | ++ jael-scry 6 | |* [=mold our=ship desk=term now=time =path] 7 | .^ mold 8 | %j 9 | (scot %p our) 10 | desk 11 | (scot %da now) 12 | path 13 | == 14 | ++ sign 15 | |= [our=ship now=time =hash] 16 | ^- signature 17 | =+ (jael-scry ,=life our %life now /(scot %p our)) 18 | =+ (jael-scry ,=ring our %vein now /(scot %ud life)) 19 | :+ `@uvH`(sign:as:(nol:nu:crub:crypto ring) hash) 20 | our 21 | life 22 | :: 23 | ++ is-signature-valid 24 | |= [our=ship =signature =hash now=time] 25 | ^- ? 26 | =+ (jael-scry ,lyf=(unit @) our %lyfe now /(scot %p q.signature)) 27 | :: we do not have a public key from ship at this life 28 | :: 29 | ?~ lyf %.y 30 | ?. =(u.lyf r.signature) %.y 31 | =+ %: jael-scry 32 | ,deed=[a=life b=pass c=(unit @uvH)] 33 | our %deed now /(scot %p q.signature)/(scot %ud r.signature) 34 | == 35 | :: if signature is from a past life, skip validation 36 | :: XX: should be visualised on frontend, not great. 37 | ?. =(a.deed r.signature) %.y 38 | :: verify signature from ship at life 39 | :: 40 | =/ them 41 | (com:nu:crub:crypto b.deed) 42 | =(`hash (sure:as.them p.signature)) 43 | :: 44 | ++ are-signatures-valid 45 | |= [our=ship =signatures =hash now=time] 46 | ^- ? 47 | =/ signature-list ~(tap in signatures) 48 | |- 49 | ?~ signature-list 50 | %.y 51 | ?: (is-signature-valid our i.signature-list hash now) 52 | $(signature-list t.signature-list) 53 | %.n 54 | -- 55 | -------------------------------------------------------------------------------- /desk/mar/hoon.hoon: -------------------------------------------------------------------------------- 1 | :::: /hoon/hoon/mar 2 | :: 3 | /? 310 4 | :: 5 | =, eyre 6 | |_ own=@t 7 | :: 8 | ++ grow :: convert to 9 | |% 10 | ++ mime `^mime`[/text/x-hoon (as-octs:mimes:html own)] :: convert to %mime 11 | ++ elem :: convert to %html 12 | ;div:pre(urb_codemirror "", mode "hoon"):"{(trip own)}" 13 | :: =+ gen-id="src-{<`@ui`(mug own)>}" 14 | :: ;div 15 | :: ;textarea(id "{gen-id}"):"{(trip own)}" 16 | :: ;script:""" 17 | :: CodeMirror.fromTextArea( 18 | :: window[{}], 19 | :: \{lineNumbers:true, readOnly:true} 20 | :: ) 21 | :: """ 22 | :: == 23 | ++ hymn 24 | :: ;html:(head:title:"Source" "+{elem}") 25 | ;html 26 | ;head 27 | ;title:"Source" 28 | ;script@"//cdnjs.cloudflare.com/ajax/libs/codemirror/4.3.0/codemirror.js"; 29 | ;script@"/lib/syntax/hoon.js"; 30 | ;link(rel "stylesheet", href "//cdnjs.cloudflare.com/ajax/libs/". 31 | "codemirror/4.3.0/codemirror.min.css"); 32 | ;link/"/lib/syntax/codemirror.css"(rel "stylesheet"); 33 | == 34 | ;body 35 | ;textarea#src:"{(trip own)}" 36 | ;script:'CodeMirror.fromTextArea(src, {lineNumbers:true, readOnly:true})' 37 | == 38 | == 39 | ++ txt 40 | (to-wain:format own) 41 | -- 42 | ++ grab 43 | |% :: convert from 44 | ++ mime |=([p=mite q=octs] q.q) 45 | ++ noun @t :: clam from %noun 46 | ++ txt of-wain:format 47 | -- 48 | ++ grad %txt 49 | -- 50 | -------------------------------------------------------------------------------- /desk/sur/docket.hoon: -------------------------------------------------------------------------------- 1 | |% 2 | :: 3 | +$ version 4 | [major=@ud minor=@ud patch=@ud] 5 | :: 6 | +$ glob (map path mime) 7 | :: 8 | +$ url cord 9 | :: $glob-location: How to retrieve a glob 10 | :: 11 | +$ glob-reference 12 | [hash=@uvH location=glob-location] 13 | :: 14 | +$ glob-location 15 | $% [%http =url] 16 | [%ames =ship] 17 | == 18 | :: $href: Where a tile links to 19 | :: 20 | +$ href 21 | $% [%glob base=term =glob-reference] 22 | [%site =path] 23 | == 24 | :: $chad: State of a docket 25 | :: 26 | +$ chad 27 | $~ [%install ~] 28 | $% :: Done 29 | [%glob =glob] 30 | [%site ~] 31 | :: Waiting 32 | [%install ~] 33 | [%suspend glob=(unit glob)] 34 | :: Error 35 | [%hung err=cord] 36 | == 37 | :: 38 | :: $charge: A realized $docket 39 | :: 40 | +$ charge 41 | $: =docket 42 | =chad 43 | == 44 | :: 45 | :: $clause: A key and value, as part of a docket 46 | :: 47 | :: Only used to parse $docket 48 | :: 49 | +$ clause 50 | $% [%title title=@t] 51 | [%info info=@t] 52 | [%color color=@ux] 53 | [%glob-http url=cord hash=@uvH] 54 | [%glob-ames =ship hash=@uvH] 55 | [%image =url] 56 | [%site =path] 57 | [%base base=term] 58 | [%version =version] 59 | [%website website=url] 60 | [%license license=cord] 61 | == 62 | :: 63 | :: $docket: A description of JS bundles for a desk 64 | :: 65 | +$ docket 66 | $: %1 67 | title=@t 68 | info=@t 69 | color=@ux 70 | =href 71 | image=(unit url) 72 | =version 73 | website=url 74 | license=cord 75 | == 76 | :: 77 | +$ charge-update 78 | $% [%initial initial=(map desk charge)] 79 | [%add-charge =desk =charge] 80 | [%del-charge =desk] 81 | == 82 | -- 83 | -------------------------------------------------------------------------------- /desk/app/clockstep.hoon: -------------------------------------------------------------------------------- 1 | /- cw=clockwork 2 | /+ dbug 3 | |% 4 | +$ versioned-state 5 | $% state-0 6 | == 7 | +$ state-0 8 | $: %0 9 | start-time=@da 10 | count=@ud 11 | stop=$~(%.y ?) 12 | == 13 | +$ card card:agent:gall 14 | -- 15 | %- agent:dbug 16 | =| state-0 17 | =* state - 18 | ^- agent:gall 19 | =< 20 | |_ =bowl:gall 21 | +* this . 22 | hd ~(. +> bowl) 23 | :: 24 | ++ on-leave |~(* `this) 25 | ++ on-fail |~(* `this) 26 | ++ on-save !>(state) 27 | ++ on-load |= old-state=vase 28 | =/ prev !<(state-0 old-state) 29 | [~ this(state prev)] 30 | ++ on-init [~ this] 31 | ++ on-peek |=(=(pole knot) ~) 32 | ++ on-poke 33 | |= [=mark =vase] 34 | ?. .=(src.bowl our.bowl) [~ this] 35 | ?. ?=(%noun mark) [~ this] 36 | ?+ q.vase [~ this] 37 | [%start @da] 38 | :- :~((timer-card +.q.vase)) 39 | this(stop %.n, start-time +.q.vase, count 0) 40 | %stop 41 | [~ this(stop %.y)] 42 | == 43 | :: 44 | ++ on-watch 45 | |= =(pole knot) 46 | ~& ["clockstep: on-watch" pole] 47 | :: Only allow %tick subscriptions from our own %clockwork agent 48 | ?. .=(src.bowl our.bowl) !! 49 | ?. .=(/gall/clockwork sap.bowl) !! 50 | ?. ?=([%tick ~] pole) !! [~ this] 51 | ++ on-agent |=([=wire =sign:agent:gall] [~ this]) 52 | ++ on-arvo 53 | |= [=(pole knot) =sign-arvo] 54 | ?. ?=(%behn -.sign-arvo) [~ this] 55 | ?+ pole [~ this] 56 | [%delta ~] 57 | ?: stop [~ this] 58 | ?: (gth (add start-time (mul delta:cw +(count))) now.bowl) 59 | :_ this(count +(count)) 60 | ~[fact-card:hd (timer-card:hd (add start-time (mul delta:cw count)))] 61 | =/ new-count (div (sub now.bowl start-time) delta:cw) 62 | :_ this(count new-count) 63 | ~[fact-card:hd (timer-card:hd (add start-time (mul delta:cw new-count)))] 64 | == 65 | -- 66 | |_ =bowl:gall 67 | ++ timer-card 68 | |= =time ^- card 69 | [%pass /delta %arvo %b %wait (add delta:cw time)] 70 | ++ fact-card ^- card 71 | [%give %fact ~[/tick] [%noun !>(count)]] 72 | -- 73 | -------------------------------------------------------------------------------- /desk/lib/clockwork.hoon: -------------------------------------------------------------------------------- 1 | /- *clockwork 2 | |% 3 | :: sm: supermajority 4 | ++ sm 5 | |= a=@ud 6 | ^- @ud 7 | +(-:(dvr (mul a 2) 3)) 8 | :: 9 | :: vs: vote-store utilities 10 | ++ vs 11 | |_ =vote-store 12 | ++ valid-qcs 13 | |= ref=referendum 14 | ^- (list qc) :: there should only be one but w/e 15 | ~& checking-qcs=[stage.ref round.ref height.ref] 16 | %+ skim ~(tap by vote-store) 17 | |= i=qc ^- ? 18 | :: ~& > qc=[stage.i round.i height.i ~(wyt in +.i)] 19 | ?& %+ gte ~(wyt in quorum.i) (sm (lent nodes)) 20 | .=(height.ref height.i) 21 | .=(round.ref round.i) 22 | .=(stage.ref stage.i) 23 | == 24 | :: ++ majority-qcs 25 | :: |= nodes=(list node) 26 | :: %+ skim ~(tap by vote-store) 27 | :: |= i=qc ^- ? 28 | :: %+ gte ~(wyt in +.i) (sm (lent nodes)) 29 | ++ most-recent 30 | |= =height 31 | %+ roll ~(tap by vote-store) 32 | |= [i=qc acc=(unit qc)] 33 | ?. (valid:qcu i) acc 34 | ?. =(height height.i) acc 35 | ?~ acc (some i) 36 | ?: (more-recent:qcu i u.acc) (some i) acc 37 | ++ latest-by 38 | |= leader=node 39 | :: ~& vote-store 40 | ^- (unit qc) 41 | %+ roll ~(tap by vote-store) 42 | |= [i=qc acc=(unit qc)] 43 | :: ~& "checking mint" 44 | ?. =(mint.bloc.i leader) acc 45 | :: ~& "checking height" 46 | :: ~& [our-height=height their-height=height.i] 47 | :: ?. =(height height.i) acc 48 | :: ~& "checking acc" 49 | ?~ acc (some i) 50 | :: ~& "checking recency" 51 | ?: (more-recent:qcu i u.acc) (some i) acc 52 | :: 53 | ++ future-blocs 54 | |= =height 55 | ^- (list qc) 56 | %+ sort 57 | %+ skim ~(tap by vote-store) 58 | |= i=qc ^- ? 59 | ?& %+ gte ~(wyt in quorum.i) (sm (lent nodes)) 60 | (gte height.i height) 61 | .=(%2 stage.i) 62 | == 63 | |= [a=qc b=qc] (lth height.a height.b) 64 | -- 65 | :: qcu: qc utilities 66 | ++ qcu 67 | |% 68 | ++ as-recent 69 | |= [a=qc b=qc] 70 | ^- ? 71 | ?: (gte round.a round.b) %.y 72 | ?& .=(round.a round.b) 73 | (gte stage.a stage.b) 74 | == 75 | ++ more-recent 76 | |= [a=qc b=qc] 77 | ^- ? 78 | ?: (gth round.a round.b) %.y 79 | ?& .=(round.a round.b) 80 | (gth stage.a stage.b) 81 | == 82 | ++ valid 83 | |= =qc ^- ? 84 | %+ gte ~(wyt in quorum.qc) (sm (lent nodes)) 85 | -- 86 | -- 87 | -------------------------------------------------------------------------------- /desk/sur/clockwork.hoon: -------------------------------------------------------------------------------- 1 | /+ *mip 2 | |% 3 | +$ signature [p=@uvH q=ship r=life] 4 | +$ action 5 | $% [%start ts=@da] 6 | [%broadcast =qc] 7 | [%txn =txn] 8 | [%faucet =addr] 9 | :: [%vote s=signature vote] 10 | == 11 | +$ voted-bloc 12 | $: =bloc 13 | =quorum 14 | == 15 | +$ history ((mop @ud voted-bloc) lth) 16 | ++ hon ((on @ud voted-bloc) lth) 17 | +$ bloc-update 18 | $% [%blocs =history] 19 | [%reset =reset-id] 20 | == 21 | +$ reset-id @ 22 | :: named to avoid conflict with stdlib block 23 | +$ bloc 24 | $: mint=node 25 | txns=(list txn) 26 | ts=@da 27 | =height 28 | =round 29 | last=quorum 30 | == 31 | :: address to nonce to transaction 32 | +$ mempool (mip @ux @ud txn) 33 | :: for the testnet, transactions are not validated 34 | :: and %ledger will ignore invalid ones 35 | +$ txn ^ 36 | :: +$ signed-bloc (pair signature bloc) 37 | :: +$ node $| @p |=(p=@p (lte p ~fipfes)) 38 | +$ node @p 39 | +$ height @ud 40 | +$ round @ud 41 | :: +$ step $? 42 | :: %new-height 43 | :: %propose 44 | :: %prevote 45 | :: %precommit 46 | :: %commit 47 | :: == 48 | :: named to avoid conflict with stdlib step 49 | +$ steppe $~(%1 $?(%1 %2 %3 %4)) :: stage of the app, see above 50 | +$ stage $?(%2 %1) :: voting stage 51 | ++ delta ~s4 :: time between steps 52 | ++ addendum-delta ~s2 53 | +$ referendum [=height =round =stage] 54 | +$ vote 55 | $: =bloc 56 | referendum 57 | == 58 | :: +$ raw-signed-vote @ 59 | :: +$ signed-vote [signature=@ =node =vote] :: signatures are a jam of [signed-msg msg] so we can cue the vote out of it 60 | :: +$ signed-vote signature 61 | +$ quorum (set signature) 62 | +$ qc [vote =quorum] :: provisional qc, no guarantees of majority 63 | +$ vote-store (jug vote signature) 64 | :: constants 65 | ++ nodes ^- (lest node) 66 | :~ ~woldeg 67 | ~sartyr 68 | ~mocbel 69 | ~posdeg 70 | ~firdun 71 | ~tomdys 72 | ~siddef 73 | ~sibnus 74 | ~holnes 75 | ~livpub 76 | ~micdyt 77 | ~wanlur 78 | ~davbel 79 | ~hosdys 80 | ~ridlyd 81 | ~sabbus 82 | ~firbex 83 | ~fipdel 84 | ~matwet 85 | ~matdel 86 | ~bilreg 87 | ~racwet 88 | ~roswet 89 | ~batbex 90 | ~fodwet 91 | ~wittyv 92 | ~mosdef 93 | ~matfen 94 | ~hobdem 95 | ~pocwet 96 | == 97 | ++ primary ~woldeg 98 | +$ addr @ux 99 | :: functions 100 | :: ++ quorum 101 | :: |% 102 | :: ++ shape 103 | :: |= =qc 104 | :: ^- ? 105 | :: ?~ qc .n 106 | :: =/ one n.qc 107 | :: %+ ~(all by qc) 108 | :: |= [=node =vote] 109 | :: ^- ? =(one vote) 110 | :: -- 111 | -- 112 | -------------------------------------------------------------------------------- /desk/sur/dice.hoon: -------------------------------------------------------------------------------- 1 | :: dice: structures for Azimuth L2 rollers 2 | :: 3 | /+ naive, ethereum 4 | :: 5 | |% 6 | +$ owner [=proxy:naive =address:naive] 7 | +$ owners (jug owner ship) 8 | +$ sponsors (map ship [residents=(set ship) requests=(set ship)]) 9 | +$ history (map address:ethereum (tree hist-tx)) 10 | +$ events (list event-log:rpc:ethereum) 11 | +$ net ?(%mainnet %ropsten %goerli %local %default) 12 | +$ snap-state [%0 =id:block:jael nas=^state:naive =owners =sponsors] 13 | :: 14 | +$ config 15 | $% [%frequency frequency=@dr] 16 | [%fallback gas=@ud] 17 | [%setkey pk=@] 18 | [%endpoint endpoint=@t =net] 19 | [%resend-time time=@dr] 20 | [%update-rate rate=@dr] 21 | [%slice slice=@dr] 22 | [%quota quota=@ud] 23 | == 24 | :: 25 | +$ indices 26 | $: own=owners 27 | spo=sponsors 28 | == 29 | :: 30 | +$ azimuth-config 31 | $: refresh-rate=@dr 32 | == 33 | :: 34 | +$ roller-config 35 | $: next-batch=time 36 | frequency=@dr 37 | resend-time=@dr 38 | update-rate=@dr 39 | contract=@ux 40 | chain-id=@ 41 | slice=@dr 42 | quota=@ud 43 | == 44 | :: 45 | +$ keccak @ux 46 | :: 47 | +$ status 48 | ?(%unknown %pending %sending %confirmed %failed %cancelled) 49 | :: 50 | +$ tx-status 51 | $: =status 52 | pointer=(unit l1-tx-pointer) 53 | == 54 | :: 55 | +$ l1-tx-pointer 56 | $: =address:ethereum 57 | nonce=@ud 58 | == 59 | :: 60 | +$ l2-tx 61 | $? %transfer-point 62 | %spawn 63 | %configure-keys 64 | %escape 65 | %cancel-escape 66 | %adopt 67 | %reject 68 | %detach 69 | %set-management-proxy 70 | %set-spawn-proxy 71 | %set-transfer-proxy 72 | == 73 | :: 74 | +$ update 75 | $% [%tx =pend-tx =status] 76 | :: 77 | $: %point 78 | =diff:naive 79 | =ship 80 | new=point:naive 81 | old=(unit point:naive) 82 | to=owner 83 | from=(unit owner) 84 | == == 85 | :: 86 | +$ hist-tx [p=time q=roll-tx] 87 | +$ roll-tx [=ship =status hash=keccak type=l2-tx] 88 | +$ pend-tx [force=? =address:naive =time =raw-tx:naive] 89 | +$ send-tx 90 | $: next-gas-price=@ud 91 | sent=? 92 | :: TODO: make txs as (list pend-tx)? 93 | :: 94 | txs=(list [=address:naive force=? =raw-tx:naive]) 95 | == 96 | +$ part-tx 97 | $% [%raw raw=octs] 98 | [%don =tx:naive] 99 | [%ful raw=octs =tx:naive] ::TODO redundant? 100 | == 101 | :: 102 | +$ rpc-send-roll 103 | $: endpoint=@t 104 | contract=address:ethereum 105 | chain-id=@ 106 | pk=@ 107 | :: 108 | nonce=@ud 109 | fallback-gas-price=@ud 110 | next-gas-price=@ud 111 | txs=(list raw-tx:naive) 112 | == 113 | :: 114 | +$ roller-data 115 | [chain-id=@ =points:naive history=(tree hist-tx) =owners =sponsors] 116 | :: 117 | -- 118 | -------------------------------------------------------------------------------- /desk/lib/token.hoon: -------------------------------------------------------------------------------- 1 | /- *token 2 | |% 3 | :: wrapping/unwrapping 4 | :: 5 | ++ wrap-block 6 | |= [keys=acru:ames =block] 7 | ^- raw-signed-block 8 | =/ =raw-block (jam block) 9 | =/ =hashed-block [(shax raw-block) raw-block] 10 | %- sign:as:keys (jam hashed-block) 11 | ++ unwrap-block 12 | |= raw-signed-block=@ 13 | ^- block 14 | =/ =signed-block ;;([@ @] (cue raw-signed-block)) 15 | =/ =raw-hashed-block +.signed-block 16 | =/ =hashed-block ;;([@ @] (cue raw-hashed-block)) 17 | =/ =raw-block +.hashed-block 18 | =/ =block ;;(block (cue raw-block)) 19 | block 20 | ++ unwrap-block-verbose 21 | |= raw-signed-block=@ 22 | ^- block 23 | =/ signed-block ((soft [@ @]) (cue raw-signed-block)) 24 | ?~ signed-block ~&(["raw-signed-block invalid" raw-signed-block] !!) 25 | =/ =raw-hashed-block +.u.signed-block 26 | =/ hashed-block ((soft [@ @]) (cue raw-hashed-block)) 27 | ?~ hashed-block ~&(["raw-hashed-block invalid" raw-hashed-block] !!) 28 | =/ =raw-block +.u.hashed-block 29 | =/ block ((soft block) (cue raw-block)) 30 | ?~ block ~&(["raw-block invalid" raw-block] !!) 31 | u.block 32 | :: 33 | ++ process-txn 34 | |= [=txn shared=shared-state pool=@udtoken] 35 | ^- txn-result 36 | =/ src src.txn 37 | ?: ?=(?(%pawn %earl) (clan:title src)) 38 | [%bad-rank src (clan:title src)] 39 | =/ bid bid.txn 40 | =/ ubal (~(get by ledger.shared) src) 41 | ?~ ubal [%src-no-bal src] 42 | =/ bal u.ubal 43 | ?: (gte bid bal) 44 | [%bid-gte-bal src bid bal] 45 | =. bal (sub bal bid) 46 | =. pool (add pool bid) 47 | ?- -.act.txn 48 | :: 49 | %spend 50 | =/ des des.act.txn 51 | ?: ?=(?(%pawn %earl) (clan:title des)) 52 | [%bad-rank-des src des (clan:title des)] 53 | =/ amt amt.act.txn 54 | ?: (gte amt bal) 55 | [%amt-gte-bal src amt bal] 56 | =/ bal (sub bal amt) 57 | =. ledger.shared (~(put by ledger.shared) des amt) 58 | =. ledger.shared (~(put by ledger.shared) src bal) 59 | [%success shared pool] 60 | :: 61 | %join 62 | ?: ?=(%king (clan:title src)) 63 | [%bad-rank-val src (clan:title src)] 64 | ?: (~(has in validators.shared) src) 65 | [%already-val src] 66 | =. validators.shared (~(put in validators.shared) src) 67 | [%success shared pool] 68 | :: 69 | %leave 70 | ?. (~(has in validators.shared) src) 71 | [%not-val src] 72 | =. validators.shared (~(del in validators.shared) src) 73 | [%success shared pool] 74 | :: 75 | %claim 76 | ?. (~(has in claimants.shared) src) 77 | [%no-claim src] 78 | =. claimants.shared (~(del in claimants.shared) src) 79 | =/ air (mul (bex 16) yarvin-scale) 80 | ?. (~(has by ledger.shared) src) 81 | =. ledger.shared (~(put by ledger.shared) src air) 82 | [%success shared pool] 83 | =/ bal (~(got by ledger.shared) src) 84 | =. ledger.shared (~(put by ledger.shared) src (add bal air)) 85 | [%success shared pool] 86 | :: 87 | %null 88 | [%success shared pool] 89 | == 90 | -- -------------------------------------------------------------------------------- /desk/lib/verb.hoon: -------------------------------------------------------------------------------- 1 | :: Print what your agent is doing. 2 | :: 3 | /- verb 4 | :: 5 | |= [loud=? =agent:gall] 6 | =| bowl-print=_| 7 | ^- agent:gall 8 | |^ !. 9 | |_ =bowl:gall 10 | +* this . 11 | ag ~(. agent bowl) 12 | :: 13 | ++ on-init 14 | ^- (quip card:agent:gall agent:gall) 15 | %- (print bowl |.("{}: on-init")) 16 | =^ cards agent on-init:ag 17 | [[(emit-event %on-init ~) cards] this] 18 | :: 19 | ++ on-save 20 | ^- vase 21 | %- (print bowl |.("{}: on-save")) 22 | on-save:ag 23 | :: 24 | ++ on-load 25 | |= old-state=vase 26 | ^- (quip card:agent:gall agent:gall) 27 | %- (print bowl |.("{}: on-load")) 28 | =^ cards agent (on-load:ag old-state) 29 | [[(emit-event %on-load ~) cards] this] 30 | :: 31 | ++ on-poke 32 | |= [=mark =vase] 33 | ^- (quip card:agent:gall agent:gall) 34 | %- (print bowl |.("{}: on-poke with mark {}")) 35 | ?: ?=(%verb mark) 36 | ?- !<(?(%loud %bowl) vase) 37 | %loud `this(loud !loud) 38 | %bowl `this(bowl-print !bowl-print) 39 | == 40 | =^ cards agent (on-poke:ag mark vase) 41 | [[(emit-event %on-poke mark) cards] this] 42 | :: 43 | ++ on-watch 44 | |= =path 45 | ^- (quip card:agent:gall agent:gall) 46 | %- (print bowl |.("{}: on-watch on path {}")) 47 | =^ cards agent 48 | ?: ?=([%verb %events ~] path) 49 | [~ agent] 50 | (on-watch:ag path) 51 | [[(emit-event %on-watch path) cards] this] 52 | :: 53 | ++ on-leave 54 | |= =path 55 | ^- (quip card:agent:gall agent:gall) 56 | %- (print bowl |.("{}: on-leave on path {}")) 57 | ?: ?=([%verb %event ~] path) 58 | [~ this] 59 | =^ cards agent (on-leave:ag path) 60 | [[(emit-event %on-leave path) cards] this] 61 | :: 62 | ++ on-peek 63 | |= =path 64 | ^- (unit (unit cage)) 65 | %- (print bowl |.("{}: on-peek on path {}")) 66 | (on-peek:ag path) 67 | :: 68 | ++ on-agent 69 | |= [=wire =sign:agent:gall] 70 | ^- (quip card:agent:gall agent:gall) 71 | %- (print bowl |.("{}: on-agent on wire {}, {<-.sign>}")) 72 | =^ cards agent (on-agent:ag wire sign) 73 | [[(emit-event %on-agent wire -.sign) cards] this] 74 | :: 75 | ++ on-arvo 76 | |= [=wire =sign-arvo] 77 | ^- (quip card:agent:gall agent:gall) 78 | %- %+ print bowl |. 79 | "{}: on-arvo on wire {}, {<[- +<]:sign-arvo>}" 80 | =^ cards agent (on-arvo:ag wire sign-arvo) 81 | [[(emit-event %on-arvo wire [- +<]:sign-arvo) cards] this] 82 | :: 83 | ++ on-fail 84 | |= [=term =tang] 85 | ^- (quip card:agent:gall agent:gall) 86 | %- (print bowl |.("{}: on-fail with term {}")) 87 | =^ cards agent (on-fail:ag term tang) 88 | [[(emit-event %on-fail term) cards] this] 89 | -- 90 | :: 91 | ++ print 92 | |= [=bowl:gall render=(trap tape)] 93 | ^+ same 94 | =? . bowl-print 95 | %- (slog >bowl< ~) 96 | . 97 | ?. loud same 98 | %- (slog [%leaf $:render] ~) 99 | same 100 | :: 101 | ++ emit-event 102 | |= =event:verb 103 | ^- card:agent:gall 104 | [%give %fact ~[/verb/events] %verb-event !>(event)] 105 | -- 106 | -------------------------------------------------------------------------------- /desk/app/pki-store.hoon: -------------------------------------------------------------------------------- 1 | /- *pki-store, 2 | dice 3 | /+ dbug, 4 | default-agent, 5 | verb, 6 | naive, 7 | azimuth 8 | :: 9 | |% 10 | +$ versioned-state $%(state-zero) 11 | :: 12 | +$ state-zero 13 | $: %zero 14 | =pki-store 15 | fake=_| 16 | == 17 | +$ card card:agent:gall 18 | +$ sign sign:agent:gall 19 | -- 20 | :: 21 | %+ verb & 22 | %- agent:dbug 23 | =| state-zero 24 | =* state - 25 | ^- agent:gall 26 | |_ =bowl:gall 27 | +* this . 28 | def ~(. (default-agent this %|) bowl) 29 | ++ on-init 30 | ~> %bout.[0 '%pki-store +on-init'] 31 | ^- (quip card _this) 32 | :_ this 33 | :~ [%pass /pki-store %agent [our.bowl %azimuth] %watch /event] 34 | == 35 | :: 36 | ++ on-save 37 | ^- vase 38 | !>(state) 39 | :: 40 | ++ on-load 41 | |= old-state=vase 42 | ^- (quip card _this) 43 | ?> ?=([%zero *] q.old-state) 44 | `this(state !<(state-zero old-state)) 45 | :: 46 | ++ on-poke 47 | |= [=mark =vase] 48 | |^ 49 | ^- (quip card _this) 50 | ?. ?=(%noun mark) `this 51 | ?: ?=(%set-fake q.vase) 52 | ~& > pki-store-setting-fake=[src.bowl] 53 | =/ fake-store populate-fake-store 54 | :_ %= this 55 | fake .y 56 | pki-store fake-store 57 | == 58 | :~ [%pass /pki-store %agent [our.bowl %azimuth] %leave ~] 59 | [%give %fact ~[/pki-diffs] %pki-snapshot !>(fake-store)] 60 | == 61 | `this 62 | ++ populate-fake-store ^+ pki-store 63 | =/ store *^pki-store 64 | :: =/ ships (gulf ~zod ~fipfes) 65 | :: =/ ships (gulf ~zod ~fes) 66 | =/ ships (gulf ~zod ~wes) 67 | |- 68 | ?~ ships store 69 | =+ .^([=life =pass (unit @ux)] %j /(scot %p our.bowl)/deed/(scot %da now.bowl)/(scot %p i.ships)/1) 70 | %= $ 71 | store (~(put bi store) i.ships life pass) 72 | ships t.ships 73 | == 74 | -- 75 | :: 76 | ++ on-watch 77 | |= =path 78 | ~> %bout.[0 '%pki-store +on-watch'] 79 | ~& path 80 | ^- (quip card _this) 81 | :: this is the only valid path 82 | ?> =(path /pki-diffs) 83 | :_ this 84 | :~ [%give %fact ~[/pki-diffs] %pki-snapshot !>(pki-store)] 85 | == 86 | :: 87 | ++ on-leave 88 | |= path 89 | ^- (quip card _this) 90 | !! 91 | :: 92 | ++ on-peek 93 | |= path 94 | ^- (unit (unit cage)) 95 | !! 96 | :: 97 | ++ on-agent 98 | |= [=wire =sign] 99 | ~> %bout.[0 '%pki-store %on-agent'] 100 | ~& pki-store=[wire -.sign] 101 | ^- (quip card _this) 102 | ?. ?=([%pki-store ~] wire) 103 | (on-agent:def wire sign) 104 | ?+ -.sign (on-agent:def wire sign) 105 | :: 106 | %kick 107 | :_ this 108 | :~ [%pass /pki-store %agent [our.bowl %azimuth] %watch /event] 109 | == 110 | %watch-ack 111 | [~ this] 112 | :: 113 | %fact 114 | ?+ p.cage.sign (on-agent:def wire sign) 115 | :: 116 | %naive-state 117 | =/ snapshot !<([=^state:naive * *] q.cage.sign) 118 | =/ points points:state:snapshot 119 | =/ entries=(list pki-entry) 120 | %+ turn ~(tap by points) 121 | |= [=ship =point:naive] 122 | ^- pki-entry 123 | :: if crypt.keys doesn't work, try auth.keys 124 | =+ keys.net.point 125 | =/ crypt (as-octs:mimes:html crypt) 126 | =/ auth (as-octs:mimes:html auth) 127 | =/ =pass (pass-from-eth.azimuth crypt auth suite) 128 | [ship life pass] 129 | =| new-store=^pki-store 130 | =/ new-store 131 | |- 132 | ^+ new-store 133 | ?~ entries new-store 134 | =+ i.entries 135 | %= $ 136 | entries t.entries 137 | new-store (~(put bi new-store) ship life pass) 138 | == 139 | :_ this(pki-store new-store) 140 | :~ [%give %fact ~[/pki-diffs] %pki-snapshot !>(new-store)] 141 | == 142 | :: 143 | %naive-diffs 144 | =/ diff !<(diff:naive q.cage.sign) 145 | ?. ?=([%point =ship %keys =keys:naive] diff) 146 | [~ this] 147 | =/ =pki-entry [ship.diff life.keys.diff auth.keys.diff] 148 | =+ pki-entry 149 | :_ this(pki-store (~(put bi pki-store) ship life pass)) 150 | :~ [%give %fact ~[/pki-diffs] %pki-diff !>(pki-entry)] 151 | == 152 | == 153 | == 154 | :: 155 | ++ on-arvo 156 | |= [=wire =sign-arvo] 157 | ^- (quip card _this) 158 | !! 159 | :: 160 | ++ on-fail 161 | |= [=term =tang] 162 | ~> %bout.[0 '%pki-store +on-fail'] 163 | ^- (quip card _this) 164 | ~& term 165 | (mean tang) 166 | -- 167 | -------------------------------------------------------------------------------- /desk/lib/dbug.hoon: -------------------------------------------------------------------------------- 1 | :: dbug: agent wrapper for generic debugging tools 2 | :: 3 | :: usage: %-(agent:dbug your-agent) 4 | :: 5 | |% 6 | +$ poke 7 | $% [%bowl ~] 8 | [%state grab=cord] 9 | [%incoming =about] 10 | [%outgoing =about] 11 | == 12 | :: 13 | +$ about 14 | $@ ~ 15 | $% [%ship =ship] 16 | [%path =path] 17 | [%wire =wire] 18 | [%term =term] 19 | == 20 | :: 21 | ++ agent 22 | |= =agent:gall 23 | ^- agent:gall 24 | !. 25 | |_ =bowl:gall 26 | +* this . 27 | ag ~(. agent bowl) 28 | :: 29 | ++ on-poke 30 | |= [=mark =vase] 31 | ^- (quip card:agent:gall agent:gall) 32 | ?. ?=(%dbug mark) 33 | =^ cards agent (on-poke:ag mark vase) 34 | [cards this] 35 | =/ dbug 36 | !<(poke vase) 37 | =; =tang 38 | ((%*(. slog pri 1) tang) [~ this]) 39 | ?- -.dbug 40 | %bowl [(sell !>(bowl))]~ 41 | :: 42 | %state 43 | =? grab.dbug =('' grab.dbug) '-' 44 | =; product=^vase 45 | [(sell product)]~ 46 | =/ state=^vase 47 | :: if the underlying app has implemented a /dbug/state scry endpoint, 48 | :: use that vase in place of +on-save's. 49 | :: 50 | =/ result=(each ^vase tang) 51 | (mule |.(q:(need (need (on-peek:ag /x/dbug/state))))) 52 | ?:(?=(%& -.result) p.result on-save:ag) 53 | %+ slap 54 | (slop state !>([bowl=bowl ..zuse])) 55 | (ream grab.dbug) 56 | :: 57 | %incoming 58 | =; =tang 59 | ?^ tang tang 60 | [%leaf "no matching subscriptions"]~ 61 | %+ murn 62 | %+ sort ~(tap by sup.bowl) 63 | |= [[* a=[=ship =path]] [* b=[=ship =path]]] 64 | (aor [path ship]:a [path ship]:b) 65 | |= [=duct [=ship =path]] 66 | ^- (unit tank) 67 | =; relevant=? 68 | ?. relevant ~ 69 | `>[path=path from=ship duct=duct]< 70 | ?: ?=(~ about.dbug) & 71 | ?- -.about.dbug 72 | %ship =(ship ship.about.dbug) 73 | %path ?=(^ (find path.about.dbug path)) 74 | %wire %+ lien duct 75 | |=(=wire ?=(^ (find wire.about.dbug wire))) 76 | %term !! 77 | == 78 | :: 79 | %outgoing 80 | =; =tang 81 | ?^ tang tang 82 | [%leaf "no matching subscriptions"]~ 83 | %+ murn 84 | %+ sort ~(tap by wex.bowl) 85 | |= [[[a=wire *] *] [[b=wire *] *]] 86 | (aor a b) 87 | |= [[=wire =ship =term] [acked=? =path]] 88 | ^- (unit tank) 89 | =; relevant=? 90 | ?. relevant ~ 91 | `>[wire=wire agnt=[ship term] path=path ackd=acked]< 92 | ?: ?=(~ about.dbug) & 93 | ?- -.about.dbug 94 | %ship =(ship ship.about.dbug) 95 | %path ?=(^ (find path.about.dbug path)) 96 | %wire ?=(^ (find wire.about.dbug wire)) 97 | %term =(term term.about.dbug) 98 | == 99 | == 100 | :: 101 | ++ on-peek 102 | |= =path 103 | ^- (unit (unit cage)) 104 | ?. ?=([@ %dbug *] path) 105 | (on-peek:ag path) 106 | ?+ path [~ ~] 107 | [%u %dbug ~] ``noun+!>(&) 108 | [%x %dbug %state ~] ``noun+!>(on-save:ag) 109 | [%x %dbug %subscriptions ~] ``noun+!>([wex sup]:bowl) 110 | == 111 | :: 112 | ++ on-init 113 | ^- (quip card:agent:gall agent:gall) 114 | =^ cards agent on-init:ag 115 | [cards this] 116 | :: 117 | ++ on-save on-save:ag 118 | :: 119 | ++ on-load 120 | |= old-state=vase 121 | ^- (quip card:agent:gall agent:gall) 122 | =^ cards agent (on-load:ag old-state) 123 | [cards this] 124 | :: 125 | ++ on-watch 126 | |= =path 127 | ^- (quip card:agent:gall agent:gall) 128 | =^ cards agent (on-watch:ag path) 129 | [cards this] 130 | :: 131 | ++ on-leave 132 | |= =path 133 | ^- (quip card:agent:gall agent:gall) 134 | =^ cards agent (on-leave:ag path) 135 | [cards this] 136 | :: 137 | ++ on-agent 138 | |= [=wire =sign:agent:gall] 139 | ^- (quip card:agent:gall agent:gall) 140 | =^ cards agent (on-agent:ag wire sign) 141 | [cards this] 142 | :: 143 | ++ on-arvo 144 | |= [=wire =sign-arvo] 145 | ^- (quip card:agent:gall agent:gall) 146 | =^ cards agent (on-arvo:ag wire sign-arvo) 147 | [cards this] 148 | :: 149 | ++ on-fail 150 | |= [=term =tang] 151 | ^- (quip card:agent:gall agent:gall) 152 | =^ cards agent (on-fail:ag term tang) 153 | [cards this] 154 | -- 155 | -- 156 | -------------------------------------------------------------------------------- /desk/sur/token.hoon: -------------------------------------------------------------------------------- 1 | |% 2 | :: 3 | :: Part 1: Essential Blockchain Types 4 | :: 5 | +$ chain (list raw-signed-block=@) 6 | :: 7 | :: every crypto step (sign or hash) is followed by a 8 | :: serialization (jam). atoms are given faces indicating 9 | :: what they should deserialize (cue) to. 10 | :: 11 | :: jammed signed block 12 | +$ raw-signed-block @ 13 | :: signature on hash and jammed hashed block 14 | +$ signed-block [sign=@ raw-hashed-block=@] 15 | :: jammed hashed block 16 | +$ raw-hashed-block @ 17 | :: hash and jammed block 18 | +$ hashed-block [hash=@uvH raw-block=@] 19 | :: jammed block 20 | +$ raw-block @ 21 | :: block: data fields comprising a block 22 | +$ block 23 | $: stmp=@da :: timestamp (deterministic in case of slash) 24 | mint=@p :: minter address 25 | life=@ud 26 | hght=@ud :: block height 27 | prev=@uvH :: parent block hash 28 | slsh=? :: whether to slash mint 29 | text=@t :: 256-char arbitrary metadata 30 | txns=(list raw-signed-txn) :: all transactions 31 | == 32 | :: 33 | :: jammed signed-txn 34 | +$ raw-signed-txn @ 35 | :: 36 | :: signed-txn: verifiable modification of shared-state 37 | +$ signed-txn 38 | $: sig=@ :: signature 39 | txn=@ 40 | == 41 | :: txn: txn data that gets signed 42 | +$ txn 43 | $: src=@p :: who is transacting 44 | liv=@ud :: revision number of src 45 | tim=@da :: timestamp 46 | tid=@ud :: transaction ID per-ship (nonce) 47 | txn-data 48 | == 49 | :: txn-data: user-entered data to process into full txn 50 | +$ txn-data 51 | $: bid=@udtoken :: claimable by validator for inclusion in a block 52 | txt=@t :: arbitrary metadata (max size enforced by protocol) 53 | act=chain-action :: modification of shared-state 54 | == 55 | :: chain-action: modification of shared-state 56 | +$ chain-action 57 | $% [%spend des=@p amt=@udtoken] :: spend money 58 | [%join ~] :: become validator 59 | [%leave ~] :: stop validating 60 | [%claim ~] :: claim airdrop tokens 61 | [%null ~] :: do nothing 62 | == 63 | :: txn-result: result of applying txn 64 | +$ txn-result 65 | $% [%success =shared-state pool=@udtoken] 66 | [%bad-rank src=@p =rank:title] 67 | [%bad-rank-des src=@p des=@p =rank:title] 68 | [%bad-rank-val src=@p =rank:title] 69 | [%src-no-bal src=@p] 70 | [%bid-gte-bal src=@p bid=@udtoken bal=@udtoken] 71 | [%amt-gte-bal src=@p amt=@udtoken bal=@udtoken] 72 | [%already-val src=@p] 73 | [%not-val src=@p] 74 | [%no-claim src=@p] 75 | == 76 | :: shared-state: total state derivable from chain 77 | +$ shared-state 78 | $: ledger=(map @p @udtoken) :: network-wide $TOKEN balance 79 | claimants=(set @p) :: validators that can claim tokens 80 | validators=(set @p) :: eligible validators for election 81 | blacklist=(map @p @ud) :: slashed validators in timeout 82 | == 83 | 84 | :: 85 | :: Part 2: Protocol Configuration 86 | :: 87 | ++ block-time `@dr`~m10 88 | :: max number of transactions per block 89 | ++ max-txns `@ud`1.024 90 | :: blacklist duration (in blocks) 91 | ++ decay-rate `@ud`1.024 92 | :: num yarvins per token 93 | ++ yarvin-scale `@ud`(pow 2 32) 94 | :: max character length of txt field in txn 95 | ++ max-txt-chars `@ud`256 96 | :: initial shared-state, including airdrop to stars 97 | :: ++ bootstrap-state 98 | :: ^- shared-state :+ 99 | :: :: ledger: initial airdrop to stars 100 | :: ^- (map @p @udtoken) 101 | :: %- molt 102 | :: %+ turn (gulf ~marzod ~fipfes) 103 | :: |= p=@ 104 | :: ^- [@p @udtoken] 105 | :: [p (mul (bex 16) yarvin-scale)] 106 | :: :: validators: genesis block author 107 | :: ^- (set @p) 108 | :: (silt ~[~woldeg]) 109 | :: :: blacklist: stars in time-out (initially empty) 110 | :: ^- (map @p @ud) ~ 111 | :: 112 | :: Part 3: Implementation-Specific Types 113 | :: 114 | :: ++ bootstrap-fakezod 115 | :: ^- shared-state :+ 116 | :: ^- (map @p @udtoken) 117 | :: %- molt 118 | :: %+ turn (gulf ~zod ~fes) 119 | :: |= p=@ 120 | :: ^- [@p @udtoken] 121 | :: [p (mul (bex 16) yarvin-scale)] 122 | :: ^- (set @p) 123 | :: (silt ~[~zod]) 124 | :: ^- (map @p @ud) ~ 125 | :: 126 | :: Part 4: Agent Actions 127 | +$ token-action 128 | $% 129 | :: protocol actions 130 | [%local-txn =txn-data] :: send txn to agent from client 131 | [%remote-txn msg=@] :: send txn to validators from agent 132 | [%genesis ~] :: mint genesis block 133 | :: debug actions 134 | [%set-dbug dbug=?] :: toggle dbug flag 135 | [%set-shared-state val=shared-state] :: force shared state to input 136 | == 137 | -- 138 | -------------------------------------------------------------------------------- /desk/lib/docket.hoon: -------------------------------------------------------------------------------- 1 | /- *docket 2 | |% 3 | :: 4 | ++ mime 5 | |% 6 | +$ draft 7 | $: title=(unit @t) 8 | info=(unit @t) 9 | color=(unit @ux) 10 | glob-http=(unit [=url hash=@uvH]) 11 | glob-ames=(unit [=ship hash=@uvH]) 12 | base=(unit term) 13 | site=(unit path) 14 | image=(unit url) 15 | version=(unit version) 16 | website=(unit url) 17 | license=(unit cord) 18 | == 19 | :: 20 | ++ finalize 21 | |= =draft 22 | ^- (unit docket) 23 | ?~ title.draft ~ 24 | ?~ info.draft ~ 25 | ?~ color.draft ~ 26 | ?~ version.draft ~ 27 | ?~ website.draft ~ 28 | ?~ license.draft ~ 29 | =/ href=(unit href) 30 | ?^ site.draft `[%site u.site.draft] 31 | ?~ base.draft ~ 32 | ?^ glob-http.draft 33 | `[%glob u.base hash.u.glob-http %http url.u.glob-http]:draft 34 | ?~ glob-ames.draft 35 | ~ 36 | `[%glob u.base hash.u.glob-ames %ames ship.u.glob-ames]:draft 37 | ?~ href ~ 38 | =, draft 39 | :- ~ 40 | :* %1 41 | u.title 42 | u.info 43 | u.color 44 | u.href 45 | image 46 | u.version 47 | u.website 48 | u.license 49 | == 50 | :: 51 | ++ from-clauses 52 | =| =draft 53 | |= cls=(list clause) 54 | ^- (unit docket) 55 | =* loop $ 56 | ?~ cls (finalize draft) 57 | =* clause i.cls 58 | =. draft 59 | ?- -.clause 60 | %title draft(title `title.clause) 61 | %info draft(info `info.clause) 62 | %color draft(color `color.clause) 63 | %glob-http draft(glob-http `[url hash]:clause) 64 | %glob-ames draft(glob-ames `[ship hash]:clause) 65 | %base draft(base `base.clause) 66 | %site draft(site `path.clause) 67 | %image draft(image `url.clause) 68 | %version draft(version `version.clause) 69 | %website draft(website `website.clause) 70 | %license draft(license `license.clause) 71 | == 72 | loop(cls t.cls) 73 | :: 74 | ++ to-clauses 75 | |= d=docket 76 | ^- (list clause) 77 | %- zing 78 | :~ :~ title+title.d 79 | info+info.d 80 | color+color.d 81 | version+version.d 82 | website+website.d 83 | license+license.d 84 | == 85 | ?~ image.d ~ ~[image+u.image.d] 86 | ?: ?=(%site -.href.d) ~[site+path.href.d] 87 | =/ ref=glob-reference glob-reference.href.d 88 | :~ base+base.href.d 89 | ?- -.location.ref 90 | %http [%glob-http url.location.ref hash.ref] 91 | %ames [%glob-ames ship.location.ref hash.ref] 92 | == == == 93 | :: 94 | ++ spit-clause 95 | |= =clause 96 | ^- tape 97 | %+ weld " {(trip -.clause)}+" 98 | ?+ -.clause "'{(trip +.clause)}'" 99 | %color (scow %ux color.clause) 100 | %site (spud path.clause) 101 | :: 102 | %glob-http 103 | "['{(trip url.clause)}' {(scow %uv hash.clause)}]" 104 | :: 105 | %glob-ames 106 | "[{(scow %p ship.clause)} {(scow %uv hash.clause)}]" 107 | :: 108 | %version 109 | =, version.clause 110 | "[{(scow %ud major)} {(scow %ud minor)} {(scow %ud patch)}]" 111 | == 112 | :: 113 | ++ spit-docket 114 | |= dock=docket 115 | ^- tape 116 | ;: welp 117 | ":~\0a" 118 | `tape`(zing (join "\0a" (turn (to-clauses dock) spit-clause))) 119 | "\0a==" 120 | == 121 | -- 122 | :: 123 | ++ enjs 124 | =, enjs:format 125 | |% 126 | :: 127 | ++ charge-update 128 | |= u=^charge-update 129 | ^- json 130 | %+ frond -.u 131 | ^- json 132 | ?- -.u 133 | %del-charge s+desk.u 134 | :: 135 | %initial 136 | %- pairs 137 | %+ turn ~(tap by initial.u) 138 | |=([=desk c=^charge] [desk (charge c)]) 139 | :: 140 | %add-charge 141 | %- pairs 142 | :~ desk+s+desk.u 143 | charge+(charge charge.u) 144 | == 145 | == 146 | :: 147 | ++ num 148 | |= a=@u 149 | ^- ^tape 150 | =/ p=json (numb a) 151 | ?> ?=(%n -.p) 152 | (trip p.p) 153 | :: 154 | ++ version 155 | |= v=^version 156 | ^- json 157 | :- %s 158 | %- crip 159 | "{(num major.v)}.{(num minor.v)}.{(num patch.v)}" 160 | :: 161 | ++ merge 162 | |= [a=json b=json] 163 | ^- json 164 | ?> &(?=(%o -.a) ?=(%o -.b)) 165 | [%o (~(uni by p.a) p.b)] 166 | :: 167 | ++ href 168 | |= h=^href 169 | %+ frond -.h 170 | ?- -.h 171 | %site s+(spat path.h) 172 | %glob 173 | %- pairs 174 | :~ base+s+base.h 175 | glob-reference+(glob-reference glob-reference.h) 176 | == 177 | == 178 | :: 179 | ++ glob-reference 180 | |= ref=^glob-reference 181 | %- pairs 182 | :~ hash+s+(scot %uv hash.ref) 183 | location+(glob-location location.ref) 184 | == 185 | :: 186 | ++ glob-location 187 | |= loc=^glob-location 188 | ^- json 189 | %+ frond -.loc 190 | ?- -.loc 191 | %http s+url.loc 192 | %ames s+(scot %p ship.loc) 193 | == 194 | :: 195 | ++ charge 196 | |= c=^charge 197 | %+ merge (docket docket.c) 198 | %- pairs 199 | :~ chad+(chad chad.c) 200 | == 201 | :: 202 | ++ docket 203 | |= d=^docket 204 | ^- json 205 | %- pairs 206 | :~ title+s+title.d 207 | info+s+info.d 208 | color+s+(scot %ux color.d) 209 | href+(href href.d) 210 | image+?~(image.d ~ s+u.image.d) 211 | version+(version version.d) 212 | license+s+license.d 213 | website+s+website.d 214 | == 215 | :: 216 | ++ chad 217 | |= c=^chad 218 | %+ frond -.c 219 | ?+ -.c ~ 220 | %hung s+err.c 221 | == 222 | -- 223 | -- 224 | -------------------------------------------------------------------------------- /desk/app/ledger.hoon: -------------------------------------------------------------------------------- 1 | /- cw=clockwork, lg=ledger, ch=chain, pki=pki-store 2 | /+ default-agent, dbug, *mip 3 | |% 4 | +$ versioned-state 5 | $% state-0 6 | == 7 | +$ state-0 [=history:cw =pki-store:pki] 8 | +$ card card:agent:gall 9 | -- 10 | =| state-0 11 | =* state - 12 | =< 13 | %- agent:dbug 14 | ^- agent:gall 15 | |_ =bowl:gall 16 | +* this . 17 | def ~(. (default-agent this %.n) bowl) 18 | cor ~(. +> [bowl ~]) 19 | ++ on-init 20 | =^ cards state 21 | abet:init:cor 22 | [cards this] 23 | ++ on-watch 24 | |= =path 25 | ^- (quip card _this) 26 | =^ cards state 27 | abet:(watch:cor path) 28 | [cards this] 29 | ++ on-agent 30 | |= [=wire =sign:agent:gall] 31 | ^- (quip card _this) 32 | =^ cards state 33 | abet:(agent:cor wire sign) 34 | [cards this] 35 | ++ on-poke 36 | |= [=mark =vase] 37 | ^- (quip card _this) 38 | =^ cards state 39 | abet:(poke:cor mark vase) 40 | [cards this] 41 | ++ on-peek peek:cor 42 | ++ on-save !>(state) 43 | ++ on-load 44 | |= =vase 45 | ^- (quip card _this) 46 | =^ cards state 47 | abet:(load:cor vase) 48 | [cards this] 49 | ++ on-leave on-leave:def 50 | ++ on-arvo on-arvo:def 51 | ++ on-fail on-fail:def 52 | -- 53 | |_ [=bowl:gall cards=(list card)] 54 | ++ abet [(flop cards) state] 55 | ++ cor . 56 | ++ emit |=(=card cor(cards [card cards])) 57 | ++ emil |=(caz=(list card) cor(cards (welp (flop caz) cards))) 58 | ++ give |=(=gift:agent:gall (emit %give gift)) 59 | ++ init 60 | ^+ cor 61 | =. cor watch-pki 62 | watch-blocs 63 | ++ load 64 | |= =vase 65 | ^+ cor 66 | =/ old !<(state-0 vase) 67 | =. state old 68 | cor 69 | ++ peek 70 | |= =(pole knot) 71 | ^- (unit (unit cage)) 72 | ?> ?=(^ pole) 73 | ?+ pole [~ ~] 74 | [%x %balances ~] ``balances+!>((balance-from-history history ~)) 75 | == 76 | ++ poke 77 | |= [=mark =vase] 78 | ^+ cor 79 | cor 80 | :: ?+ mark ~|(bad-poke+mark !!) 81 | :: == 82 | ++ watch 83 | |= =(pole knot) 84 | ^+ cor 85 | ?+ pole ~|(bad-watch-path+`path`pole !!) 86 | [%balances ~] 87 | ?> =(src.bowl our.bowl) 88 | (give %fact ~ balances+!>(balances)) 89 | == 90 | ++ agent 91 | |= [=(pole knot) =sign:agent:gall] 92 | ^+ cor 93 | ?+ pole ~|(bad-agent-wire+pole !!) 94 | [%blocs ~] 95 | ?+ -.sign !! 96 | %kick watch-blocs 97 | %watch-ack 98 | ?~ p.sign 99 | cor 100 | ((slog leaf+"failed subscription to blocs" u.p.sign) cor) 101 | %fact 102 | (take-update !<(bloc-update:cw q.cage.sign)) 103 | == 104 | [%pki-diffs ~] 105 | ?+ -.sign !! 106 | %kick watch-pki 107 | %watch-ack 108 | ?~ p.sign 109 | cor 110 | ((slog leaf+"failed subscription to pki" u.p.sign) cor) 111 | %fact 112 | ?+ p.cage.sign !! 113 | %pki-snapshot 114 | (take-pki !<(pki-store:pki q.cage.sign)) 115 | %pki-diff 116 | (take-pki-diff !<(pki-entry:pki q.cage.sign)) 117 | == 118 | == 119 | == 120 | ++ balances 121 | |= =internal-balances:lg 122 | %- ~(urn by internal-balances) 123 | |= [k=@ v=[balance=@ud nonce=@ud faucet=?]] 124 | balance.v 125 | ++ take-update 126 | |= update=bloc-update:cw 127 | ^+ cor 128 | ?- -.update 129 | %reset 130 | take-reset 131 | %blocs 132 | =. history (uni:hon:cw history history.update) 133 | (give %fact ~[/balances] balances+!>((balance-from-history history history.update))) 134 | == 135 | ++ take-reset 136 | ^+ cor 137 | =. history ~ 138 | cor 139 | ++ balance-from-history 140 | |= [old=history:cw new=history:cw] 141 | ^- balances:lg 142 | =/ his=(list [@ud voted-bloc:cw]) (tap:hon:cw (uni:hon:cw old new)) 143 | =/ =internal-balances:lg ~ 144 | |- 145 | ~+ 146 | ?~ his (balances internal-balances) 147 | %= $ 148 | his t.his 149 | internal-balances 150 | =- +.- 151 | %^ spin txns.bloc.i.his 152 | internal-balances 153 | |= [=txn:cw br=(map addr:ch [balance=@ud nonce=@ud faucet=?])] 154 | ^- [* (map @ux [@ud @ud ?])] 155 | :: is it structured like a transaction? 156 | ?. ?=(txn-signed:ch txn) [txn br] 157 | :: is it signed correctly? 158 | =/ keys (com:nu:crub:crypto who.txn) 159 | ?. (safe:as:keys -.txn (jam +.txn)) [txn br] 160 | :: is the nonce sequential? 161 | =/ prior (prior-balance br who.txn) 162 | ?. =(nonce.prior nonce.txn) [txn br] 163 | :: is it for %ledger instead of another app? 164 | ?. ?=(txn-ledger:lg txn) 165 | [txn (~(put by br) who.txn [balance.prior +(nonce.prior) faucet.prior])] 166 | =/ cmd=ledger-cmd:lg cmd.txn 167 | ?- cmd 168 | [%send target=@ amount=@] 169 | :: do they have the tokens they want to send? 170 | ?: (gth amount.cmd balance.prior) [txn br] 171 | =/ deducted 172 | %+ ~(put by br) who.txn 173 | [(sub balance.prior amount.cmd) +(nonce.prior) faucet.prior] 174 | =/ target-prior (~(gut by br) target.cmd [balance=0 nonce=0 faucet=%.n]) 175 | :- txn 176 | %+ ~(put by deducted) target.cmd 177 | [(add balance.target-prior amount.cmd) nonce.target-prior faucet.target-prior] 178 | == 179 | == 180 | ++ take-pki 181 | |= p=pki-store:pki 182 | ^+ cor 183 | cor(pki-store p) 184 | ++ take-pki-diff 185 | |= p=pki-entry:pki 186 | ^+ cor 187 | cor(pki-store (~(put bi pki-store) ship.p life.p pass.p)) 188 | ++ watch-pki 189 | (emit %pass /pki-diffs %agent [our.bowl %pki-store] %watch /pki-diffs) 190 | ++ watch-blocs 191 | (emit %pass /blocs %agent [our.bowl %chain] %watch /blocs) 192 | ++ node-keys (turn nodes:cw latest-key) 193 | ++ latest-key 194 | |= =ship 195 | ^- pass 196 | =/ top (~(rep in (~(key bi pki-store) ship)) max) 197 | =/ key (~(get bi pki-store) ship top) 198 | ?~ key !! 199 | u.key 200 | ++ prior-balance 201 | |= [ib=internal-balances:lg =addr:ch] 202 | ?~ (find ~[addr] node-keys) 203 | (~(gut by ib) addr [balance=0 nonce=0 faucet=%.n]) 204 | (~(gut by ib) addr [balance=(bex 64) nonce=0 faucet=%.y]) 205 | -- 206 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | `%chain` is a research project into achieving Byzantine fault-tolerant state machine replication (BFT-SMR) within the context of an Urbit application. If successful, this project will result in an application `%chain` that integrates well with other Urbit applications and improves the utility of Urbit ID. 2 | 3 | `%chain` is a young project and some aspects of it are difficult to document due to liability to change. We will here highlight the overall goals and strategy of the project, and encourage readers to inspect the repo or reach out to developers with specific questions. 4 | ## Goals 5 | 6 | The final goal of `%chain` is to build a blockchain with an indefinite lifespan. By building on top of Urbit OS, which aims to be finally specified as a frozen standard, `%chain` similarly aims standardize its protocol as an Urbit application that does not need to update in order to survive. This is simultaneously the farthest-reaching goal of the project and also the most foundational guiding principle. 7 | 8 | There are some other goals in mind for the `%chain` project that are worth considering. 9 | 10 | * Establish a canonical Urbit blockchain called `%chain`. Provide developers with a source of shared truth that can be trusted to also be the source of shared truth for other Urbit applications. Establish a commanding network effect within the Urbit ecosystem. 11 | * Establish a canonical Urbit currency called `$TOKEN`. Provide the market with a fungible token that is broadly accepted as a form of payment by Urbit users, can easily be integrated into any Urbit application, and whose value can be expected to correlate with the degree of economic activity on Urbit. 12 | * Leverage Urbit ID for sybil resistance. This includes restricting validation rights to higher-level nodes such as stars and galaxies. There may be a case in which the sybil resistance properties of planets is applicable, such as in spam resistance for fee-less payment systems. 13 | * Provide an upside to address space holders. Treat investors in Urbit ID as first-class citizens of the Urbit economy and seek to maximize the correlation between `$TOKEN` value and address space value. 14 | * Integrate Urbit ID as a native blockchain account. Allow tokens to be sent directly to and from an Urbit ID, in addition to a public key account as is normal in blockchain networks elsewhere. 15 | * Make it easy for Urbit users to run full nodes on their own ships and independently verify the state of the network. 16 | 17 | The above goals should be considered core goals of the project and will not be changed unless in light of severe feasibility constraints. There are some other project goals that are more loosely held, and are worth mentioning. 18 | 19 | * Establish a canonical Urbit-native DNS alternative. Allow users to register, buy, sell and renew arbitrary names on `%chain`. 20 | * For example, it should be possible to register a trademark such that one can query it and resolve to a registered Urbit ID under that trademark. It should also be possible for a developer to attest the Hoon definition of a mark file on chain, to avoid the need for ad-hoc social consensus around marks. 21 | * Provide a plausible new home for the Urbit PKI, such that it no longer needs to live on Ethereum. Offer a way to simplify the core Urbit codebase and reduce external dependencies. 22 | * Allow users and developers to mint and distribute novel tokens of their own creation, both of the fungible and non-fungible varieties, and integrate these tokens into their own applications. 23 | * Allow users and developers to create DAOs on-chain, defined as a set of `@p`s and a denotation of privileges between them, in order to create social networks that are more fault-tolerant than federated groups and forums. 24 | * Integrate `%chain` with other blockchain environments, such as Cosmos Hub, and enable users to bridge assets into `%chain` from other networks and vice versa. 25 | * Create a smart contracting platform that integrates with Urbit applications. Allow developers to write smart contracts in Hoon (or any Nock-compiled language) and publish them to `%chain`. 26 | 27 | The feasibility of each of these goals will need to be held in tension with the overall goal of permanent standardization. For example, a PKI integration may not be possible if it necessitates a constant compatibility layer with Ethereum that is liable to change. For a different example, a smart contracting platform may incur a never-ending arms race against attackers and competitors, which could prevent standardization. 28 | 29 | ## Strategy 30 | 31 | The `%chain` project's strategy has rapidly shifted since its inception and is liable to continue to change. The goals outlined above can be looked at as a guidestone, and the Kelvin Zero objective as the north star. 32 | 33 | There does not yet exist a BFT-SMR network on Urbit. Some attempts have been made to reach or approximate this goal, but as of this writing none of them are active. There is a project called Nockchain that aims to build a blockchain with a great degree of compatibility with Urbit applications, but it is not itself an Urbit application, nor is it running natively on the Urbit network. 34 | 35 | The opinion of the `%chain` developers is that BFT-SMR, normally considered an incredibly difficult problem domain, is well-suited to Urbit's application model. In particular, programmer overhead for messaging, broadcast, discovery, sybil resistance, cryptography, and much more is handled natively by Urbit OS. There is still an inherent perniciousness to the details of consensus algorithms, but the overhead is drastically reduced in any case. 36 | 37 | We will begin by creating a reference implementation for two BFT consensus algorithms, `%clockwork` and `%frontier`, to investigate the suitability of two competing approaches to BFT-SMR within the context of an Urbit application. 38 | * `%clockwork` is inspired by the Tendermint protocol and aims to carefully keep a set of nodes in sync with each other as state transformations are voted on throughout a network, providing instant finality when a change is finally accepted. 39 | * `%frontier` is inspired by the Avalanche protocol and allows nodes to keep a local state that is continuously updated by polling the network, with a guarantee to converge towards metastability at a dominant polling result. 40 | 41 | Both protocols will assume that every validator is either a star or a galaxy. To begin, the assumption may also be made that only planets, stars, and galaxies can participate and create transactions -- this will delay the need to implement fee/reward mechanisms too early. 42 | 43 | We will try one or both of our consensus algorithms with a test network that implements a payments system and a cryptocurrency `$TOKEN` live on Urbit. We will then iterate on this live test network continuously until the network is proven seaworthy enough for an official launch. 44 | 45 | Upon official launch, a Kelvin version will be assigned to the `%chain` codebase, and a steadfast commitment to the Kelvin versioning discipline will be maintained until the protocol is frozen as a standard. 46 | -------------------------------------------------------------------------------- /desk/app/token.hoon: -------------------------------------------------------------------------------- 1 | /- *pki-store, 2 | *token 3 | /+ dbug, 4 | default-agent, 5 | verb 6 | :: 7 | |% 8 | :: 9 | +$ versioned-state $%(state-zero) 10 | :: 11 | +$ state-zero 12 | $: %zero 13 | dbug=? :: safety rails on dev pokes 14 | :: dbug default to %.y during early testing 15 | our-life=@ud 16 | keys=acru:ames 17 | =pki-store 18 | =chain 19 | pend=(set @) :: txn queue 20 | ltid=@ud :: last used txn id 21 | next=@p :: next-validator 22 | pubs=(set @p) :: publishers that we sub to 23 | shared=shared-state 24 | == 25 | :: 26 | :: boilerplate 27 | :: 28 | +$ card card:agent:gall 29 | -- 30 | :: 31 | %+ verb & 32 | %- agent:dbug 33 | =| state-zero 34 | =* state - 35 | :: 36 | ^- agent:gall 37 | :: 38 | |_ =bowl:gall 39 | +* this . 40 | def ~(. (default-agent this %|) bowl) 41 | ++ on-init 42 | ^- (quip card _this) 43 | ~> %bout.[0 '%token +on-init'] 44 | :: =. shared bootstrap-state 45 | =. pubs (silt ~[~woldeg]) 46 | :_ this 47 | %+ weld 48 | :: subscribe to private keys from jael 49 | ^- (list card) 50 | :~ [%pass /token/private-keys %arvo %j %private-keys ~] 51 | :: subscribe to pki-store updates 52 | [%pass /token/pki-store %agent [our.bowl %pki-store] %watch /pki-diffs] 53 | == 54 | :: subscribe to block alerts from pubs 55 | ^- (list card) 56 | %+ turn ~(tap in pubs) 57 | |= pub=@p 58 | [%pass /token/block-alerts %agent [pub %token] %watch /block-alerts] 59 | :: 60 | ++ on-save 61 | ^- vase 62 | ~> %bout.[0 '%token +on-save'] 63 | !>(state) 64 | :: 65 | ++ on-load 66 | |= =vase 67 | ~> %bout.[0 '%token +on-load'] 68 | ^- (quip card _this) 69 | ?> ?=([%zero *] q.vase) 70 | `this(state !<(state-zero vase)) 71 | :: 72 | ++ on-poke 73 | |= [=mark =vase] 74 | ~> %bout.[0 '%token +on-poke'] 75 | ~& mark 76 | ^- (quip card _this) 77 | ?> ?=(%token-action mark) 78 | =/ action !<(token-action vase) 79 | ~& -.action 80 | ?- -.action :: ~|(%bad-mark !!) 81 | :: 82 | :: receive txn from client 83 | %local-txn 84 | =. ltid +(ltid) 85 | =/ =txn 86 | :* src=our.bowl 87 | liv=our-life 88 | tim=now.bowl 89 | tid=ltid 90 | txn-data.action 91 | == 92 | =/ msg=@ (sign:as:keys (jam txn)) 93 | :: alert validators of new txn 94 | ~& "checkpoint" 95 | =/ cards=(list card) 96 | =/ =cage [%token-action !>([%remote-txn msg])] 97 | ^- (list card) 98 | %+ turn ~(tap in validators.shared) 99 | |= val=@p 100 | :* %pass /token/remote-txn/(scot %p our.bowl)/(scot %ud tid.txn) 101 | %agent [val %token] %poke cage 102 | == 103 | [cards this] 104 | :: 105 | :: receive a remote txn 106 | %remote-txn 107 | :: todo: query pki 108 | :: currently using our own signature 109 | :: 110 | :: verify signature 111 | =/ ver (sure:as:keys msg.action) 112 | ?~ ver ~&("failed signature" [~ this]) 113 | :: verify structure of txn 114 | =/ des ((soft txn) (cue u.ver)) 115 | ?~ des ~&("failed deserialization" [~ this]) 116 | =. pend (~(put in pend) msg.action) 117 | ~& ["queue updated" pend] 118 | [~ this] 119 | :: 120 | :: mint genesis block 121 | %genesis 122 | ?> =(~ chain) 123 | =/ genesis 124 | %- jam 125 | ^- block 126 | :* stmp=now.bowl 127 | mint=our.bowl 128 | life=our-life 129 | hght=0 130 | prev=(shax ~) 131 | slsh=%.n 132 | text='' 133 | txns=~ 134 | == 135 | =/ =hashed-block [(shax genesis) genesis] 136 | =/ signed-block (sign:as:keys (jam hashed-block)) 137 | :_ this(chain ~[genesis], next our.bowl) 138 | :~ [%pass /block/0 %grow /block/0 token-block+signed-block] 139 | [%pass /block/0 %arvo %b %wait `@da`(add now.bowl block-time)] 140 | [%give %fact ~[/block-alerts] %token-block-alert !>(0)] 141 | == 142 | :: 143 | %set-dbug 144 | [~ this(dbug dbug.action)] 145 | :: 146 | %set-shared-state 147 | ?> dbug 148 | [~ this(shared val.action)] 149 | == 150 | :: 151 | ++ on-peek 152 | |= pat=path 153 | ~> %bout.[0 '%token +on-peek'] 154 | ^- (unit (unit cage)) 155 | [~ ~] 156 | :: 157 | ++ on-agent 158 | |= [=wire =sign:agent:gall] 159 | ~> %bout.[0 '%token +on-agent'] 160 | ~& [wire -.sign] 161 | ^- (quip card _this) 162 | ?+ wire ~&([%bad-wire wire] !!) 163 | :: 164 | :: remote transactions 165 | [%token %remote-txn @ @ ~] 166 | ?+ -.sign ~&([%bad-sign -.sign] !!) 167 | [%poke-ack] 168 | [~ this] 169 | == 170 | :: 171 | :: block alerts 172 | [%token %block-alerts ~] 173 | ?+ -.sign ~&([%bad-sign -.sign] !!) 174 | :: 175 | %fact 176 | ?> =(p.cage.sign %token-block-alert) 177 | =/ tid !<(@ud q.cage.sign) 178 | :_ this 179 | :~ :* %pass /get-block %arvo %g %keen | 180 | src.bowl 181 | /g/x/(scot %da now.bowl)/token//block/(scot %ud tid) 182 | == == 183 | %watch-ack 184 | [~ this] 185 | == 186 | :: 187 | :: subscription responses to %pki-store 188 | [%token %pki-store ~] 189 | ?+ -.sign ~&([%bad-sign -.sign] !!) 190 | :: 191 | %fact 192 | ?+ p.cage.sign ~&([%bad-mark p.cage.sign] !!) 193 | %pki-snapshot 194 | =/ new-pki-store !<(^pki-store q.cage.sign) 195 | [~ this(pki-store new-pki-store)] 196 | %pki-diff 197 | =/ entry !<(pki-entry q.cage.sign) 198 | =+ entry 199 | =/ new-pki-store (~(put bi pki-store) ship life pass) 200 | [~ this(pki-store new-pki-store)] 201 | == 202 | :: 203 | :: resub to pki-store on kick 204 | %kick 205 | :_ this 206 | :~ :* %pass /token/pki-store %agent 207 | [our.bowl %pki-store] %watch 208 | /pki-diffs 209 | == == 210 | :: 211 | %watch-ack 212 | [~ this] 213 | == 214 | == 215 | :: 216 | ++ on-arvo 217 | |= [=wire sign=sign-arvo] 218 | ~> %bout.[0 '%token +on-arvo'] 219 | ~& [wire -.sign -.+.sign] 220 | ^- (quip card _this) 221 | ?+ wire ~|(%bad-wire !!) 222 | [%get-block ~] 223 | ?+ sign ~|(%bad-arvo-sign !!) 224 | [%ames %tune *] 225 | :: remote scry request handler 226 | =/ roar roar.sign 227 | ~& roar 228 | ?~ roar ~|(%empty-roar !!) 229 | :: verify remote scry response is marked %token-block 230 | ?~ q.dat.u.roar ~&("empty scry response" [~ this]) 231 | ?> =(%token-block p.u.q.dat.u.roar) 232 | =/ signed-block ((soft @) q.u.q.dat.u.roar) 233 | ?~ signed-block ~&("page is not atom" [~ this]) 234 | ~& ["signed-block" u.signed-block] 235 | =/ hashed-block ;;([@ @] (cue +:;;([@ @] (cue u.signed-block)))) 236 | ~& ["hashed block" hashed-block] 237 | ?. =(-.hashed-block (shax +.hashed-block)) 238 | ~&("hash does not match block" [~ this]) 239 | =/ block ;;(block (cue +.hashed-block)) 240 | =+ block 241 | =/ keys=(unit pass) (~(get bi pki-store) mint life) 242 | ?~ keys ~&("could not find keys" [~ this]) 243 | =/ crub=acru:ames (com:nu:crub:crypto u.keys) 244 | =/ ver (sure:as:crub u.signed-block) 245 | ?~ ver ~&("failed signature" [~ this]) 246 | :: verify block 247 | :: todo 248 | =. chain [u.signed-block chain] 249 | [~ this] 250 | == 251 | :: 252 | [%token %private-keys ~] 253 | ?> ?=([%jael %private-keys *] sign) 254 | =/ life life.sign 255 | =/ vein vein.sign 256 | =/ private-key=ring (~(got by vein) life) 257 | :- ~ 258 | %= this 259 | our-life life.sign 260 | keys (nol:nu:crub:crypto private-key) 261 | == 262 | == 263 | :: 264 | ++ on-watch 265 | |= pat=path 266 | ~> %bout.[0 '%token +on-watch'] 267 | ^- (quip card _this) 268 | :: we are expecting watches on /block-alerts 269 | :: but have nothing to say 270 | [~ this] 271 | :: 272 | ++ on-fail 273 | ~> %bout.[0 '%token +on-fail'] 274 | on-fail:def 275 | :: 276 | ++ on-leave 277 | ~> %bout.[0 '%token +on-leave'] 278 | on-leave:def 279 | -- 280 | -------------------------------------------------------------------------------- /desk/lib/style.css: -------------------------------------------------------------------------------- 1 | /** style.css 2 | * ~2024.4.1 3 | * 4 | * styling resets 5 | * and 6 | * utility classes 7 | * 8 | **/ 9 | 10 | :root { 11 | --x: 4px; 12 | } 13 | * { 14 | box-sizing: border-box; 15 | font: inherit; 16 | color: inherit; 17 | } 18 | form, a, input, p, li, ul, ol, div, button, h1, h2, h3, h4, h5, h6 { 19 | margin: 0; 20 | line-height: 1; 21 | } 22 | html { 23 | height: 100%; 24 | font-size: 18px; 25 | } 26 | body { 27 | margin: 0; 28 | font-family: sans-serif; 29 | font-feature-settings: normal; 30 | font-variation-settings: normal; 31 | letter-spacing: 0.024em; 32 | line-height: 1; 33 | background-color: var(--b0); 34 | color: var(--f1); 35 | min-height: 100%; 36 | } 37 | a { 38 | cursor: pointer; 39 | text-decoration: none; 40 | font: inherit; 41 | } 42 | button, input, textarea, iframe { 43 | border: unset; 44 | } 45 | img { 46 | max-width: 100%; 47 | } 48 | .break { 49 | word-break: break-word; 50 | } 51 | .action { 52 | touch-action: manipulation; 53 | } 54 | .hidden, 55 | .folded { 56 | display: none !important; 57 | } 58 | .jc { 59 | justify-content: center; 60 | } 61 | .jb { 62 | justify-content: space-between; 63 | } 64 | .ja { 65 | justify-content: space-around; 66 | } 67 | .js { 68 | justify-content: start; 69 | } 70 | .je { 71 | justify-content: end; 72 | } 73 | .js { 74 | justify-content: start; 75 | } 76 | .as { 77 | align-items: start; 78 | } 79 | .af { 80 | align-items: stretch; 81 | } 82 | .ae { 83 | align-items: end; 84 | } 85 | .ac { 86 | align-items: center; 87 | } 88 | .wfc { 89 | width: fit-content; 90 | } 91 | .wf { 92 | width: 100%; 93 | } 94 | .mw-page { 95 | max-width: 650px; 96 | } 97 | .hf { 98 | height: 100%; 99 | } 100 | .hfc { 101 | height: fit-content; 102 | } 103 | .mono { 104 | font-family: monospace; 105 | /* font-variation-settings: "xtab" 500; */ 106 | font-size: 0.85em; 107 | } 108 | .bold { 109 | font-weight: bold; 110 | } 111 | .strike { 112 | text-decoration: line-through; 113 | } 114 | .pre { 115 | white-space: pre; 116 | } 117 | .pre-line { 118 | white-space: pre-line; 119 | } 120 | .tl { 121 | text-align: left; 122 | } 123 | .tc { 124 | text-align: center; 125 | } 126 | .tr { 127 | text-align: right; 128 | } 129 | .block { 130 | display: block; 131 | } 132 | .fc { 133 | display: flex; 134 | flex-direction: column; 135 | } 136 | .fcr { 137 | display: flex; 138 | flex-direction: column-reverse; 139 | } 140 | .fr { 141 | display: flex; 142 | flex-direction: row; 143 | } 144 | .frw { 145 | display: flex; 146 | flex-direction: row; 147 | flex-wrap: wrap; 148 | } 149 | .basis-full { 150 | flex-basis: 100%; 151 | } 152 | .basis-half { 153 | flex-basis: 50%; 154 | flex-shrink: 0; 155 | } 156 | .basis-none { 157 | flex-basis: 0%; 158 | flex-shrink: 1; 159 | } 160 | .shrink-0 { 161 | flex-shrink: 0; 162 | } 163 | .relative { 164 | position: relative; 165 | } 166 | .absolute { 167 | position: absolute; 168 | } 169 | .fixed { 170 | position: fixed; 171 | } 172 | .sticky { 173 | position: sticky; 174 | } 175 | .z-2 { 176 | z-index: -20; 177 | } 178 | .z-1 { 179 | z-index: -10; 180 | } 181 | .z0 { 182 | z-index: 0; 183 | } 184 | .z1 { 185 | z-index: 10; 186 | } 187 | .z2 { 188 | z-index: 20; 189 | } 190 | .grow { 191 | flex-grow: 1; 192 | } 193 | .g1 { 194 | gap: 4px; 195 | } 196 | .g2 { 197 | gap: 8px; 198 | } 199 | .g3 { 200 | gap: 12px; 201 | } 202 | .g4 { 203 | gap: 16px; 204 | } 205 | .g5 { 206 | gap: 20px; 207 | } 208 | .g6 { 209 | gap: 24px; 210 | } 211 | .g7 { 212 | gap: 28px; 213 | } 214 | .p-1 { 215 | padding: 0px 4px; 216 | } 217 | .p0 { 218 | padding: 0; 219 | } 220 | .p1 { 221 | padding: 4px; 222 | } 223 | .p2 { 224 | padding: 8px; 225 | } 226 | .p3 { 227 | padding: 12px; 228 | } 229 | .p4 { 230 | padding: 16px; 231 | } 232 | .p-page { 233 | padding-top: 30px; 234 | padding-bottom: 200px; 235 | padding-left: 12px; 236 | padding-right: 12px; 237 | } 238 | .ma { 239 | margin: auto; 240 | } 241 | .scroll-y { 242 | overflow-y: auto; 243 | } 244 | .scroll-x { 245 | overflow-x: auto; 246 | } 247 | .scroll-hidden { 248 | overflow: hidden; 249 | } 250 | .loader { 251 | position: relative; 252 | } 253 | .loading { 254 | position: absolute; 255 | top: 50%; 256 | left: 50%; 257 | transform: translate(-50%, -50%); 258 | pointer-events: none; 259 | } 260 | .loader .loading { 261 | opacity: 0; 262 | transition: opacity 300ms; 263 | } 264 | .htmx-request .loader .loading, 265 | .loader.htmx-request .loading { 266 | opacity: 1; 267 | } 268 | .loader .loaded { 269 | opacity: 1; 270 | transition: opacity 300ms; 271 | } 272 | .htmx-request .loader .loaded, 273 | .loader.htmx-request .loaded { 274 | opacity: 0; 275 | } 276 | .f1 { 277 | color: var(--f1); 278 | } 279 | .f2 { 280 | color: var(--f2); 281 | } 282 | .f3 { 283 | color: var(--f3); 284 | } 285 | .f-success { 286 | color: var(--f-success); 287 | } 288 | .f-error { 289 | color: var(--f-error); 290 | } 291 | .b0 { 292 | background-color: var(--b0); 293 | } 294 | .b1 { 295 | background-color: var(--b1); 296 | } 297 | .b2 { 298 | background-color: var(--b2); 299 | } 300 | .b3 { 301 | background-color: var(--b3); 302 | } 303 | .b-success { 304 | background-color: var(--b-success); 305 | } 306 | .b-error { 307 | background-color: var(--b-error); 308 | } 309 | .s-2 { 310 | font-size: 0.7em; 311 | } 312 | .s-1 { 313 | font-size: 0.85em; 314 | } 315 | .s0 { 316 | font-size: 1em; 317 | } 318 | .s1 { 319 | font-size: 1.15em; 320 | } 321 | .s2 { 322 | font-size: 1.3em; 323 | } 324 | .s3 { 325 | font-size: 1.45em; 326 | } 327 | .s4 { 328 | font-size: 1.6em; 329 | } 330 | .border { 331 | border: 1.2px solid var(--f3); 332 | } 333 | .border-2 { 334 | border: 1px solid var(--f4); 335 | } 336 | .br1 { 337 | border-radius: 3px; 338 | } 339 | .br2 { 340 | border-radius: 6px; 341 | } 342 | input, 343 | select { 344 | outline: none; 345 | border-radius: 0; 346 | background-color: inherit; 347 | color: inherit; 348 | font: inherit; 349 | line-height: inherit; 350 | } 351 | textarea { 352 | display: block; 353 | outline: none; 354 | resize: none; 355 | border-radius: 0; 356 | border: 0; 357 | background-color: inherit; 358 | color: inherit; 359 | } 360 | button { 361 | cursor: pointer; 362 | background-color: inherit; 363 | color: inherit; 364 | } 365 | .hover:hover { 366 | filter: invert(20%); 367 | } 368 | .toggled { 369 | filter: invert(100%); 370 | } 371 | .hover.toggled:hover { 372 | filter: invert(100%); 373 | } 374 | .active, 375 | .selected { 376 | filter: invert(10%); 377 | } 378 | .hover.active:hover, 379 | .hover.selected:hover { 380 | filter: invert(25%); 381 | } 382 | .numbered > *:before { 383 | content: counter(line); 384 | display: inline-block; 385 | border-right: 1px solid var(--f3); 386 | padding: 0 .5em; 387 | margin-right: .5em; 388 | color: var(--f3); 389 | min-width: 34px; 390 | text-align: right; 391 | } 392 | .numbered > * { 393 | display: block; 394 | counter-increment: line; 395 | } 396 | .prose h1 { 397 | font-size: 1.45rem; 398 | margin: 1rem 0; 399 | } 400 | .prose h2 { 401 | font-size: 1.3rem; 402 | margin: 1rem 0; 403 | } 404 | .prose h3 { 405 | font-size: 1.15rem; 406 | margin: 1rem 0; 407 | } 408 | .prose h1, .prose h2, .prose h3 { 409 | font-weight: bold; 410 | } 411 | .prose p { 412 | margin-bottom: 1rem; 413 | line-height: 1.3; 414 | } 415 | .prose img { 416 | max-width: 100%; 417 | display: block; 418 | max-height: 350px; 419 | } 420 | .prose details { 421 | margin-bottom: 1rem; 422 | } 423 | .prose a { 424 | text-decoration: underline; 425 | } 426 | .prose mono { 427 | font-size: 1em; 428 | } 429 | .prose pre { 430 | font-variation-settings: "xtab" 500; 431 | font-size: 0.8em; 432 | overflow-x: auto; 433 | width: 100%; 434 | display: block; 435 | padding: 8px; 436 | } 437 | .prose code { 438 | white-space: pre; 439 | overflow-x: auto; 440 | width: 100%; 441 | display: block; 442 | padding: 8px; 443 | } 444 | .prose ul, 445 | .prose ol { 446 | padding-left: 19px; 447 | line-height: 1.2; 448 | margin-bottom: 1rem; 449 | } 450 | .prose ul p, 451 | .prose ol p { 452 | margin-bottom: 0; 453 | line-height: 1.4; 454 | } 455 | .prose ul ul, 456 | .prose ol ul, 457 | .prose ul ol, 458 | .prose ol ol { 459 | margin-bottom: 0; 460 | } 461 | summary { 462 | user-select: none; 463 | cursor: pointer; 464 | } 465 | -------------------------------------------------------------------------------- /desk/mar/txt.hoon: -------------------------------------------------------------------------------- 1 | :: 2 | :::: /hoon/txt/mar 3 | :: 4 | /? 310 5 | :: 6 | =, clay 7 | =, differ 8 | =, format 9 | =, mimes:html 10 | |_ txt=wain 11 | :: 12 | ++ grab :: convert from 13 | |% 14 | ++ mime |=((pair mite octs) (to-wain q.q)) 15 | ++ noun wain :: clam from %noun 16 | -- 17 | ++ grow 18 | => v=. 19 | |% 20 | ++ mime => v [/text/plain (as-octs (of-wain txt))] 21 | ++ elem => v ;pre: {(trip (of-wain txt))} 22 | -- 23 | ++ grad 24 | |% 25 | ++ form %txt-diff 26 | ++ diff 27 | |= tyt=wain 28 | ^- (urge cord) 29 | (lusk txt tyt (loss txt tyt)) 30 | :: 31 | ++ pact 32 | |= dif=(urge cord) 33 | ~| [%pacting dif] 34 | ^- wain 35 | (lurk txt dif) 36 | :: 37 | ++ join 38 | |= [ali=(urge cord) bob=(urge cord)] 39 | ^- (unit (urge cord)) 40 | |^ 41 | =. ali (clean ali) 42 | =. bob (clean bob) 43 | |- ^- (unit (urge cord)) 44 | ?~ ali `bob 45 | ?~ bob `ali 46 | ?- -.i.ali 47 | %& 48 | ?- -.i.bob 49 | %& 50 | ?: =(p.i.ali p.i.bob) 51 | %+ bind $(ali t.ali, bob t.bob) 52 | |=(cud=(urge cord) [i.ali cud]) 53 | ?: (gth p.i.ali p.i.bob) 54 | %+ bind $(p.i.ali (sub p.i.ali p.i.bob), bob t.bob) 55 | |=(cud=(urge cord) [i.bob cud]) 56 | %+ bind $(ali t.ali, p.i.bob (sub p.i.bob p.i.ali)) 57 | |=(cud=(urge cord) [i.ali cud]) 58 | :: 59 | %| 60 | ?: =(p.i.ali (lent p.i.bob)) 61 | %+ bind $(ali t.ali, bob t.bob) 62 | |=(cud=(urge cord) [i.bob cud]) 63 | ?: (gth p.i.ali (lent p.i.bob)) 64 | %+ bind $(p.i.ali (sub p.i.ali (lent p.i.bob)), bob t.bob) 65 | |=(cud=(urge cord) [i.bob cud]) 66 | ~ 67 | == 68 | :: 69 | %| 70 | ?- -.i.bob 71 | %| 72 | ?. =(i.ali i.bob) 73 | ~ 74 | %+ bind $(ali t.ali, bob t.bob) 75 | |=(cud=(urge cord) [i.ali cud]) 76 | :: 77 | %& 78 | ?: =(p.i.bob (lent p.i.ali)) 79 | %+ bind $(ali t.ali, bob t.bob) 80 | |=(cud=(urge cord) [i.ali cud]) 81 | ?: (gth p.i.bob (lent p.i.ali)) 82 | %+ bind $(ali t.ali, p.i.bob (sub p.i.bob (lent p.i.ali))) 83 | |=(cud=(urge cord) [i.ali cud]) 84 | ~ 85 | == 86 | == 87 | ++ clean :: clean 88 | |= wig=(urge cord) 89 | ^- (urge cord) 90 | ?~ wig ~ 91 | ?~ t.wig wig 92 | ?: ?=(%& -.i.wig) 93 | ?: ?=(%& -.i.t.wig) 94 | $(wig [[%& (add p.i.wig p.i.t.wig)] t.t.wig]) 95 | [i.wig $(wig t.wig)] 96 | ?: ?=(%| -.i.t.wig) 97 | $(wig [[%| (welp p.i.wig p.i.t.wig) (welp q.i.wig q.i.t.wig)] t.t.wig]) 98 | [i.wig $(wig t.wig)] 99 | -- 100 | :: 101 | ++ mash 102 | |= $: [als=ship ald=desk ali=(urge cord)] 103 | [bos=ship bod=desk bob=(urge cord)] 104 | == 105 | ^- (urge cord) 106 | |^ 107 | =. ali (clean ali) 108 | =. bob (clean bob) 109 | |- ^- (urge cord) 110 | ?~ ali bob 111 | ?~ bob ali 112 | ?- -.i.ali 113 | %& 114 | ?- -.i.bob 115 | %& 116 | ?: =(p.i.ali p.i.bob) 117 | [i.ali $(ali t.ali, bob t.bob)] 118 | ?: (gth p.i.ali p.i.bob) 119 | [i.bob $(p.i.ali (sub p.i.ali p.i.bob), bob t.bob)] 120 | [i.ali $(ali t.ali, p.i.bob (sub p.i.bob p.i.ali))] 121 | :: 122 | %| 123 | ?: =(p.i.ali (lent p.i.bob)) 124 | [i.bob $(ali t.ali, bob t.bob)] 125 | ?: (gth p.i.ali (lent p.i.bob)) 126 | [i.bob $(p.i.ali (sub p.i.ali (lent p.i.bob)), bob t.bob)] 127 | =/ [fic=(unce cord) ali=(urge cord) bob=(urge cord)] 128 | (resolve ali bob) 129 | [fic $(ali ali, bob bob)] 130 | :: ~ :: here, alice is good for a while, but not for the whole 131 | == :: length of bob's changes 132 | :: 133 | %| 134 | ?- -.i.bob 135 | %| 136 | =/ [fic=(unce cord) ali=(urge cord) bob=(urge cord)] 137 | (resolve ali bob) 138 | [fic $(ali ali, bob bob)] 139 | :: 140 | %& 141 | ?: =(p.i.bob (lent p.i.ali)) 142 | [i.ali $(ali t.ali, bob t.bob)] 143 | ?: (gth p.i.bob (lent p.i.ali)) 144 | [i.ali $(ali t.ali, p.i.bob (sub p.i.bob (lent p.i.ali)))] 145 | =/ [fic=(unce cord) ali=(urge cord) bob=(urge cord)] 146 | (resolve ali bob) 147 | [fic $(ali ali, bob bob)] 148 | == 149 | == 150 | :: 151 | ++ annotate :: annotate conflict 152 | |= $: ali=(list @t) 153 | bob=(list @t) 154 | bas=(list @t) 155 | == 156 | ^- (list @t) 157 | %- zing 158 | ^- (list (list @t)) 159 | %- flop 160 | ^- (list (list @t)) 161 | :- :_ ~ 162 | %^ cat 3 '<<<<<<<<<<<<' 163 | %^ cat 3 ' ' 164 | %^ cat 3 `@t`(scot %p bos) 165 | %^ cat 3 '/' 166 | bod 167 | 168 | :- bob 169 | :- ~['------------'] 170 | :- bas 171 | :- ~['++++++++++++'] 172 | :- ali 173 | :- :_ ~ 174 | %^ cat 3 '>>>>>>>>>>>>' 175 | %^ cat 3 ' ' 176 | %^ cat 3 `@t`(scot %p als) 177 | %^ cat 3 '/' 178 | ald 179 | ~ 180 | :: 181 | ++ clean :: clean 182 | |= wig=(urge cord) 183 | ^- (urge cord) 184 | ?~ wig ~ 185 | ?~ t.wig wig 186 | ?: ?=(%& -.i.wig) 187 | ?: ?=(%& -.i.t.wig) 188 | $(wig [[%& (add p.i.wig p.i.t.wig)] t.t.wig]) 189 | [i.wig $(wig t.wig)] 190 | ?: ?=(%| -.i.t.wig) 191 | $(wig [[%| (welp p.i.wig p.i.t.wig) (welp q.i.wig q.i.t.wig)] t.t.wig]) 192 | [i.wig $(wig t.wig)] 193 | :: 194 | ++ resolve 195 | |= [ali=(urge cord) bob=(urge cord)] 196 | ^- [fic=[%| p=(list cord) q=(list cord)] ali=(urge cord) bob=(urge cord)] 197 | =- [[%| bac (annotate alc boc bac)] ali bob] 198 | |- ^- $: $: bac=(list cord) 199 | alc=(list cord) 200 | boc=(list cord) 201 | == 202 | ali=(urge cord) 203 | bob=(urge cord) 204 | == 205 | ?~ ali [[~ ~ ~] ali bob] 206 | ?~ bob [[~ ~ ~] ali bob] 207 | ?- -.i.ali 208 | %& 209 | ?- -.i.bob 210 | %& [[~ ~ ~] ali bob] :: no conflict 211 | %| 212 | =+ lob=(lent p.i.bob) 213 | ?: =(lob p.i.ali) 214 | [[p.i.bob p.i.bob q.i.bob] t.ali t.bob] 215 | ?: (lth lob p.i.ali) 216 | [[p.i.bob p.i.bob q.i.bob] [[%& (sub p.i.ali lob)] t.ali] t.bob] 217 | =+ wat=(scag (sub lob p.i.ali) p.i.bob) 218 | =+ ^= res 219 | %= $ 220 | ali t.ali 221 | bob [[%| (scag (sub lob p.i.ali) p.i.bob) ~] t.bob] 222 | == 223 | :* :* (welp bac.res wat) 224 | (welp alc.res wat) 225 | (welp boc.res q.i.bob) 226 | == 227 | ali.res 228 | bob.res 229 | == 230 | == 231 | :: 232 | %| 233 | ?- -.i.bob 234 | %& 235 | =+ loa=(lent p.i.ali) 236 | ?: =(loa p.i.bob) 237 | [[p.i.ali q.i.ali p.i.ali] t.ali t.bob] 238 | ?: (lth loa p.i.bob) 239 | [[p.i.ali q.i.ali p.i.ali] t.ali [[%& (sub p.i.bob loa)] t.bob]] 240 | =+ wat=(slag (sub loa p.i.bob) p.i.ali) 241 | =+ ^= res 242 | %= $ 243 | ali [[%| (scag (sub loa p.i.bob) p.i.ali) ~] t.ali] 244 | bob t.bob 245 | == 246 | :* :* (welp bac.res wat) 247 | (welp alc.res q.i.ali) 248 | (welp boc.res wat) 249 | == 250 | ali.res 251 | bob.res 252 | == 253 | :: 254 | %| 255 | =+ loa=(lent p.i.ali) 256 | =+ lob=(lent p.i.bob) 257 | ?: =(loa lob) 258 | [[p.i.ali q.i.ali q.i.bob] t.ali t.bob] 259 | =+ ^= res 260 | ?: (gth loa lob) 261 | $(ali [[%| (scag (sub loa lob) p.i.ali) ~] t.ali], bob t.bob) 262 | ~& [%scagging loa=loa pibob=p.i.bob slag=(scag loa p.i.bob)] 263 | $(ali t.ali, bob [[%| (scag (sub lob loa) p.i.bob) ~] t.bob]) 264 | :* :* (welp bac.res ?:((gth loa lob) p.i.bob p.i.ali)) 265 | (welp alc.res q.i.ali) 266 | (welp boc.res q.i.bob) 267 | == 268 | ali.res 269 | bob.res 270 | == 271 | == 272 | == 273 | -- 274 | -- 275 | -- 276 | -------------------------------------------------------------------------------- /desk/app/chain.hoon: -------------------------------------------------------------------------------- 1 | /- cw=clockwork, ch=chain, lg=ledger, pki=pki-store 2 | /+ default-agent, dbug, *mip 3 | |% 4 | +$ versioned-state 5 | $% state-0 6 | == 7 | +$ state-0 [=history:cw =pki-store:pki =wallets:ch =sent-txns:ch] 8 | +$ card card:agent:gall 9 | -- 10 | =| state-0 11 | =* state - 12 | =< 13 | %- agent:dbug 14 | ^- agent:gall 15 | |_ =bowl:gall 16 | +* this . 17 | def ~(. (default-agent this %.n) bowl) 18 | cor ~(. +> [bowl ~]) 19 | ++ on-init 20 | =^ cards state 21 | abet:init:cor 22 | [cards this] 23 | ++ on-save !>(state) 24 | ++ on-load 25 | |= =vase 26 | ^- (quip card _this) 27 | =^ cards state 28 | abet:(load:cor vase) 29 | [cards this] 30 | ++ on-agent 31 | |= [=wire =sign:agent:gall] 32 | ^- (quip card _this) 33 | =^ cards state 34 | abet:(agent:cor wire sign) 35 | [cards this] 36 | ++ on-watch 37 | |= =path 38 | ^- (quip card _this) 39 | =^ cards state 40 | abet:(watch:cor path) 41 | [cards this] 42 | ++ on-poke 43 | |= [=mark =vase] 44 | ^- (quip card _this) 45 | =^ cards state 46 | abet:(poke:cor mark vase) 47 | [cards this] 48 | ++ on-peek peek:cor 49 | ++ on-leave on-leave:def 50 | ++ on-arvo on-arvo:def 51 | ++ on-fail on-fail:def 52 | -- 53 | |_ [=bowl:gall cards=(list card)] 54 | ++ abet [(flop cards) state] 55 | ++ cor . 56 | ++ emit |=(=card cor(cards [card cards])) 57 | ++ emil |=(caz=(list card) cor(cards (welp (flop caz) cards))) 58 | ++ give |=(=gift:agent:gall (emit %give gift)) 59 | ++ init 60 | ^+ cor 61 | =. cor watch-pki 62 | watch-blocs 63 | ++ load 64 | |= =vase 65 | ^+ cor 66 | =/ old !<(state-0 vase) 67 | =. state old 68 | cor 69 | ++ peek 70 | |= =(pole knot) 71 | ^- (unit (unit cage)) 72 | ?> ?=(^ pole) 73 | =, pole 74 | ?+ pole [~ ~] 75 | [%x %wallets ~] 76 | ``wallets+!>((~(run by wallets) |=(=wallet:ch pub.wallet))) 77 | [%x %balances ~] 78 | ``balances+!>(.^(balances:lg %gx /(scot %p our.bowl)/ledger/(scot %da now.bowl)/balances/noun)) 79 | [%x %transactions adr=@t ~] 80 | =/ addr (slav %ux adr.pole) 81 | =- ``transactions+!>(~(tap in -)) 82 | ^- (set txn-signed:ch) 83 | =/ nonces (~(key bi sent-txns) addr) 84 | %- ~(run in nonces) 85 | |= nonce=@ud 86 | (~(got bi sent-txns) addr nonce) 87 | [%x %transactions adr=@ %pending ~] 88 | =/ addr (slav %ux adr.pole) 89 | =/ wallet-txns 90 | =- ~(tap in -) 91 | ^- (set txn-signed:ch) 92 | =/ nonces (~(key bi sent-txns) addr) 93 | %- ~(run in nonces) 94 | |= nonce=@ud 95 | (~(got bi sent-txns) addr nonce) 96 | =/ com (committed-nonce addr) 97 | =- ``transactions+!>(-) 98 | %+ skim wallet-txns 99 | |= =txn-signed:ch 100 | (gte nonce.txn-signed com) 101 | == 102 | ++ watch 103 | |= =(pole knot) 104 | ^+ cor 105 | ?+ pole ~|(bad-watch-path+`path`pole !!) 106 | [%blocs ~] 107 | ?> =(src.bowl our.bowl) 108 | (give %fact ~ bloc-update+!>([%blocs history])) 109 | == 110 | ++ agent 111 | |= [=(pole knot) =sign:agent:gall] 112 | ^+ cor 113 | ?+ pole ~|(bad-agent-wire+pole !!) 114 | [%blocs ~] 115 | ?+ -.sign !! 116 | %kick watch-blocs 117 | %watch-ack 118 | ?~ p.sign 119 | cor 120 | ((slog leaf+"failed subscription to blocs" u.p.sign) cor) 121 | %fact 122 | (take-update !<(bloc-update:cw q.cage.sign)) 123 | == 124 | [%pki-diffs ~] 125 | ?+ -.sign !! 126 | %kick watch-pki 127 | %watch-ack 128 | ?~ p.sign 129 | cor 130 | ((slog leaf+"failed subscription to pki" u.p.sign) cor) 131 | %fact 132 | ?+ p.cage.sign !! 133 | %pki-snapshot 134 | (take-pki !<(pki-store:pki q.cage.sign)) 135 | %pki-diff 136 | (take-pki-diff !<(pki-entry:pki q.cage.sign)) 137 | == 138 | == 139 | [%ask-faucet ~] 140 | ?+ -.sign !! 141 | %poke-ack 142 | ?~ p.sign 143 | cor 144 | ((slog leaf+"failed faucet" u.p.sign) cor) 145 | == 146 | [%send-txn ~] 147 | ?+ -.sign !! 148 | %poke-ack 149 | ?~ p.sign 150 | cor 151 | ((slog leaf+"failed send-txn" u.p.sign) cor) 152 | == 153 | == 154 | ++ poke 155 | |= [=mark =vase] 156 | ^+ cor 157 | ?+ mark ~|(bad-poke+mark !!) 158 | %new-wallet 159 | ?> =(src.bowl our.bowl) 160 | =+ !<(name=cord vase) 161 | ?< (~(has by wallets) name) 162 | =/ keys (pit:nu:crub:crypto 512 eny.bowl) 163 | =. wallets (~(put by wallets) name [pub:ex:keys sec:ex:keys]) 164 | cor 165 | %send-tokens 166 | :: convenience poke for %ledger %send transactions 167 | ?> =(src.bowl our.bowl) 168 | =+ !<([name=cord target=addr:ch amount=@ud] vase) 169 | =/ =wallet:ch (~(got by wallets) name) 170 | =/ keys (nol:nu:crub:crypto sec.wallet) 171 | =/ =txn-unsigned:ch 172 | :* pub.wallet 173 | (nonce pub.wallet) 174 | [%ledger 0 [%send target amount]] 175 | == 176 | =/ =txn-signed:ch 177 | [(sigh:as:keys (jam txn-unsigned)) txn-unsigned] 178 | =. sent-txns (~(put bi sent-txns) pub.wallet (nonce pub.wallet) txn-signed) 179 | %- emil 180 | %+ turn validators 181 | |= who=ship 182 | [%pass /send-txn %agent [who %clockwork] %poke noun+!>([%txn txn-signed])] 183 | %send-txn 184 | ?> =(src.bowl our.bowl) 185 | =+ !<([name=cord =txn-stub:ch] vase) 186 | =/ =wallet:ch (~(got by wallets) name) 187 | =/ keys (nol:nu:crub:crypto sec.wallet) 188 | =/ =txn-unsigned:ch 189 | :* pub.wallet 190 | (nonce pub.wallet) 191 | txn-stub 192 | == 193 | =/ =txn-signed:ch 194 | [(sigh:as:keys (jam txn-unsigned)) txn-unsigned] 195 | =. sent-txns (~(put bi sent-txns) pub.wallet (nonce pub.wallet) txn-signed) 196 | %- emil 197 | %+ turn validators 198 | |= who=ship 199 | [%pass /send-txn %agent [who %clockwork] %poke noun+!>([%txn txn-signed])] 200 | %ask-faucet 201 | ?> =(src.bowl our.bowl) 202 | =+ !<(name=cord vase) 203 | =/ =wallet:ch (~(got by wallets) name) 204 | (emit %pass /ask-faucet %agent [primary:cw %clockwork] %poke noun+!>([%faucet pub.wallet])) 205 | == 206 | ++ take-update 207 | |= update=bloc-update:cw 208 | ^+ cor 209 | ?- -.update 210 | %reset 211 | take-reset 212 | %blocs 213 | ?. (all:hon:cw history.update verify-bloc) cor 214 | =. history (uni:hon:cw history history.update) 215 | (give %fact ~[/blocs] bloc-update+!>([%blocs history.update])) 216 | == 217 | ++ take-reset 218 | ^+ cor 219 | ?> =(src.bowl primary:cw) 220 | =. history ~ 221 | =. sent-txns ~ 222 | (give %fact ~[/blocs] bloc-update+!>([%reset ~])) 223 | ++ verify-bloc 224 | |= [height=@ud =bloc:cw =quorum:cw] 225 | ^- ? 226 | =- (gte (lent -) needed-validators) 227 | %+ skim ~(tap in quorum) 228 | |= =signature:cw 229 | ?~ (find ~[q.signature] nodes:cw) %.n 230 | =/ vote [bloc height.bloc round.bloc %2] 231 | =/ key (~(get bi pki-store) q.signature r.signature) 232 | ?~ key %.n 233 | =/ keys (com:nu:crub:crypto u.key) 234 | (safe:as:keys p.signature (jam vote)) 235 | ++ take-pki 236 | |= p=pki-store:pki 237 | ^+ cor 238 | cor(pki-store p) 239 | ++ take-pki-diff 240 | |= p=pki-entry:pki 241 | ^+ cor 242 | cor(pki-store (~(put bi pki-store) ship.p life.p pass.p)) 243 | ++ watch-pki 244 | (emit %pass /pki-diffs %agent [our.bowl %pki-store] %watch /pki-diffs) 245 | ++ watch-blocs 246 | %- emil 247 | %+ turn validators 248 | |= who=ship 249 | [%pass /blocs %agent [who %clockwork] %watch /blocs] 250 | ++ validators 251 | ^- (list ship) 252 | ~+ 253 | ?^ (find ~[our.bowl] nodes:cw) 254 | ~[our.bowl primary:cw] 255 | :: seed with @p to broadcast txns to the same validators every time 256 | :: otherwise it may be possible to send nonces out of order 257 | =/ rng ~(. og our.bowl) 258 | =/ vals=(list ship) ~[primary:cw] 259 | =/ nods=(list ship) nodes:cw 260 | |- 261 | ?: (gte (lent vals) needed-validators) 262 | vals 263 | =^ next rng (rads:rng (lent nods)) 264 | $(vals [(snag next nods) vals], nods (oust [next 1] nods)) 265 | ++ needed-validators +((div (lent nodes:cw) 3)) 266 | ++ latest-key 267 | |= =ship 268 | ^- pass 269 | =/ top (~(rep in (~(key bi pki-store) ship)) max) 270 | =/ key (~(get bi pki-store) ship top) 271 | ?~ key !! 272 | u.key 273 | ++ nonce 274 | |= =addr:ch 275 | =/ nonces (~(key bi sent-txns) addr) 276 | ?~ nonces 0 277 | +((~(rep in `(set @ud)`nonces) max)) 278 | ++ committed-nonce 279 | |= =addr:ch 280 | ^- @ud 281 | =/ next 0 282 | ~+ 283 | =/ his=(list [@ud voted-bloc:cw]) (tap:hon:cw history) 284 | |- 285 | ?~ his next 286 | %= $ 287 | his t.his 288 | next 289 | =- +.- 290 | %^ spin txns.bloc.i.his 291 | next 292 | |= [txn=* n=@ud] 293 | ^- [* @ud] 294 | :: is it structured like a transaction? 295 | ?. ?=(txn-signed:ch txn) [txn next] 296 | :: is it from this wallet? 297 | ?. =(who.txn addr) [txn next] 298 | :: is it signed correctly? 299 | =/ keys (com:nu:crub:crypto addr) 300 | ?. (safe:as:keys -.txn (jam +.txn)) [txn next] 301 | :: is the nonce sequential? 302 | ?. =(nonce.txn next) [txn next] 303 | [txn +(next)] 304 | == 305 | -- 306 | -------------------------------------------------------------------------------- /desk/app/chain-ui.hoon: -------------------------------------------------------------------------------- 1 | :: %chain-ui 2 | :: 3 | :: interface for the %chain testnet 4 | :: 5 | /- ch=chain, lg=ledger 6 | /+ default-agent, dbug 7 | /* style-css %css /lib/style/css 8 | |% 9 | +$ versioned-state 10 | $% state-0 11 | == 12 | +$ state-0 [fauceted-wallets=(set cord)] 13 | +$ card card:agent:gall 14 | -- 15 | =| state-0 16 | =* state - 17 | =< 18 | %- agent:dbug 19 | ^- agent:gall 20 | |_ =bowl:gall 21 | +* this . 22 | def ~(. (default-agent this %.n) bowl) 23 | cor ~(. +> [bowl ~]) 24 | ++ on-init 25 | =^ cards state 26 | abet:init:cor 27 | [cards this] 28 | ++ on-save !>(state) 29 | ++ on-load 30 | |= =vase 31 | ^- (quip card _this) 32 | =^ cards state 33 | abet:(load:cor vase) 34 | [cards this] 35 | ++ on-poke 36 | |= [=mark =vase] 37 | ^- (quip card _this) 38 | =^ cards state 39 | abet:(poke:cor mark vase) 40 | [cards this] 41 | ++ on-watch 42 | |= =path 43 | `this 44 | ++ on-leave 45 | |=(path `..on-init) 46 | ++ on-peek 47 | |=(path ~) 48 | ++ on-arvo 49 | |= [=wire =sign-arvo] 50 | [~ this] 51 | ++ on-agent 52 | |= [=wire =sign:agent:gall] 53 | ^- (quip card _this) 54 | =^ cards state 55 | abet:(agent:cor wire sign) 56 | [cards this] 57 | ++ on-fail on-fail:def 58 | -- 59 | |_ [=bowl:gall cards=(list card)] 60 | ++ abet [(flop cards) state] 61 | ++ cor . 62 | ++ emit |=(=card cor(cards [card cards])) 63 | ++ emil |=(caz=(list card) cor(cards (welp (flop caz) cards))) 64 | ++ give |=(=gift:agent:gall (emit %give gift)) 65 | ++ init 66 | ^+ cor 67 | %- emit 68 | [%pass /bind-site %arvo %e %connect [~ /apps/chain] dap.bowl] 69 | ++ load 70 | |= =vase 71 | ^+ cor 72 | =/ old !<(state-0 vase) 73 | =. state old 74 | cor 75 | ++ wallets 76 | .^((map cord @ux) %gx /(scot %p our.bowl)/chain/(scot %da now.bowl)/wallets/noun) 77 | ++ balance 78 | |= addr=@ux 79 | ^- (unit @ud) 80 | =+ .^(=balances:lg %gx /(scot %p our.bowl)/chain/(scot %da now.bowl)/balances/noun) 81 | (~(get by balances) addr) 82 | ++ transactions 83 | |= addr=@ux 84 | ^- (list txn-signed:ch) 85 | =/ r .^((list txn-signed:ch) %gx /(scot %p our.bowl)/chain/(scot %da now.bowl)/transactions/[(scot %ux addr)]/noun) 86 | r 87 | ++ pending-transactions 88 | |= addr=@ux 89 | ^- (list txn-signed:ch) 90 | =/ r .^((list txn-signed:ch) %gx /(scot %p our.bowl)/chain/(scot %da now.bowl)/transactions/[(scot %ux addr)]/pending/noun) 91 | r 92 | ++ agent 93 | |= [=(pole knot) =sign:agent:gall] 94 | ^+ cor 95 | ?+ pole ~|(bad-agent-wire+pole !!) 96 | [%send-tokens id=@ta ~] 97 | %- emil 98 | %^ http-cards 99 | id.pole 100 | ~ 101 | (crip (en-xml:html lazy-loader)) 102 | [%faucet id=@ta ~] 103 | %- emil 104 | %^ http-cards 105 | id.pole 106 | ~ 107 | (crip (en-xml:html lazy-loader)) 108 | [%new-wallet id=@ta ~] 109 | %- emil 110 | %^ http-cards 111 | id.pole 112 | ~ 113 | (crip (en-xml:html lazy-loader)) 114 | == 115 | ++ lazy-loader 116 | ;div 117 | =hx-get "" 118 | =hx-trigger "load" 119 | =hx-target "main" 120 | =hx-select "main" 121 | =hx-swap "outerHTML" 122 | ; loading... 123 | == 124 | ++ poke 125 | |= [=mark =vase] 126 | ^+ cor 127 | :: 128 | ?> =(mark %handle-http-request) 129 | ?> =(our src):bowl 130 | =+ !<(req=(pair @ta inbound-request:eyre) vase) 131 | =/ purl :: parsed url with query params 132 | :: 133 | ^- [pax=path pam=(map @t @t)] 134 | =+ %+ rash url.request.q.req 135 | ;~ plug 136 | ;~(pfix fas (more fas smeg:de-purl:html)) 137 | yque:de-purl:html 138 | == 139 | [->+.- (molt +.-)] 140 | =/ body :: parsed form-encoded body 141 | :: 142 | %- malt 143 | %+ fall 144 | %+ rush 145 | q:(fall body.request.q.req [p=0 q='']) 146 | yquy:de-purl:html 147 | ~ 148 | =/ pams :: combined params from purl, body, & headers 149 | :: 150 | %- ~(uni by (malt header-list.request.q.req)) 151 | (~(uni by pam.purl) body) 152 | =/ route 153 | %- (pole knot) 154 | :- (crip (cass (trip method.request.q.req))) 155 | pax.purl 156 | ?+ route 157 | (emil (http-cards p.req ['X-Status' '400']~ 'Route not found')) 158 | :: 159 | [%get ~] 160 | %- emil 161 | %^ http-cards 162 | p.req 163 | ~ 164 | %- html-cord 165 | %- lift 166 | ;main.fc.g5 167 | ;+ part-header 168 | ;+ (part-wallet-links '') 169 | ;+ form-new-wallet 170 | ;+ part-footer 171 | == 172 | [%get wallet-name=@t ~] 173 | =/ uddr (~(get by wallets) wallet-name.route) 174 | %- emil 175 | %^ http-cards 176 | p.req 177 | ~ 178 | %- html-cord 179 | %- lift 180 | ;main.fc.g5 181 | ;+ part-header 182 | ;+ (part-wallet-links wallet-name.route) 183 | ;+ form-new-wallet 184 | ;* 185 | ?~ uddr 186 | ;= 187 | ;div: invalid wallet name 188 | == 189 | =/ amount (balance u.uddr) 190 | ;= 191 | ;+ (part-current-wallet wallet-name.route u.uddr) 192 | ;+ (form-send-tokens wallet-name.route) 193 | ;+ part-refresher 194 | ;+ ?~ amount 195 | ;div#wallet-data.fc.g5 196 | ;+ (form-faucet wallet-name.route) 197 | == 198 | ;div#wallet-data.fc.g5 199 | ;+ (part-current-balance u.amount) 200 | ;+ (part-txn-history u.uddr) 201 | == 202 | == 203 | ;+ part-footer 204 | == 205 | [%post %new-wallet ~] 206 | =/ name (~(got by pams) 'name') 207 | %- emit 208 | [%pass /new-wallet/[p.req] %agent [our.bowl %chain] %poke %new-wallet !>(name)] 209 | [%post %faucet ~] 210 | =/ name (~(got by pams) 'name') 211 | =. fauceted-wallets (~(put in fauceted-wallets) name) 212 | %- emit 213 | [%pass /faucet/[p.req] %agent [our.bowl %chain] %poke %ask-faucet !>(name)] 214 | [%post %send-tokens wallet-name=@t ~] 215 | %- emit 216 | =/ target (slav %ux (~(got by pams) 'txn-target')) 217 | =/ amount (slav %ud (~(got by pams) 'txn-amount')) 218 | :* 219 | %pass 220 | /send-tokens/[p.req] 221 | %agent 222 | [our.bowl %chain] 223 | %poke 224 | %send-tokens 225 | !>([wallet-name.route target amount]) 226 | == 227 | :: 228 | == 229 | ++ http-cards 230 | |= [id=@ta headers=(list [@t @t]) body=@t] 231 | =/ rath [/http-response/[id]]~ 232 | =/ page (as-octs:mimes:html body) 233 | =/ status (slav %ud (~(gut by (malt headers)) 'X-Status' '200')) 234 | :~ 235 | [%give %fact rath %http-response-header !>([status headers])] 236 | [%give %fact rath %http-response-data !>(`page)] 237 | [%give %kick rath ~] 238 | == 239 | ++ theme-dark 240 | :: 241 | %- trip 242 | ''' 243 | :root { 244 | --b0: #222; 245 | --b1: #333; 246 | --b2: #444; 247 | --b3: #555; 248 | --be: #752; 249 | --b-success: #351; 250 | --f1: #ccc; 251 | --f2: #999; 252 | --f3: #777; 253 | --f4: #555; 254 | --f-error: #531; 255 | --f-success: lightgreen; 256 | --link: lightblue; 257 | --hover: 115%; 258 | } 259 | ''' 260 | :: 261 | ++ theme-light 262 | :: 263 | %- trip 264 | ''' 265 | :root { 266 | --f1: #333; 267 | --f2: #555; 268 | --f3: #777; 269 | --f4: #999; 270 | --f-error: #953; 271 | --f-success: #351; 272 | --b0: #eee; 273 | --b1: #ccc; 274 | --b2: #bbb; 275 | --b3: #888; 276 | --b-error: #ca8; 277 | --b-success: #8c8; 278 | --link: blue; 279 | --hover: 87%; 280 | } 281 | ''' 282 | :: 283 | ++ theme-system 284 | :: 285 | """ 286 | {theme-light} 287 | @media (prefers-color-scheme: dark) \{ 288 | {theme-dark} 289 | } 290 | """ 291 | :: 292 | ++ form-new-wallet 293 | ;div 294 | ;button.p2.wfc.border.br1.b1.hover 295 | =onclick "$('#generator').toggleClass('hidden');$(this).toggleClass('toggled');" 296 | ; + new wallet 297 | == 298 | ;form#generator.hidden.fr.br1.g1.p1 299 | =hx-post "/apps/chain/new-wallet" 300 | =hx-swap "outerHTML" 301 | =hx-target "#wallet-links" 302 | =hx-confirm "Create new wallet?" 303 | ;input.border.p2.br1.grow.s0 304 | =autocomplete "off" 305 | =required "" 306 | =type "text" 307 | =name "name" 308 | =placeholder "wallet name" 309 | ; 310 | == 311 | ;button.p2.border.b1.br1.wfc.s0 312 | ; create 313 | == 314 | == 315 | == 316 | :: 317 | ++ part-current-wallet 318 | |= [name=@t addr=@ux] 319 | ;div.fc 320 | ;h2.bold.s1.border-2.br1.p2: {(trip name)} 321 | ;+ (print-addr addr) 322 | == 323 | ++ form-faucet 324 | |= name=cord 325 | ?: (~(has in fauceted-wallets) name) 326 | ;div.p4.border.fc.ac.jc.g4 327 | ; Loading up your wallet. Please be patient. 328 | == 329 | ;div.p4.border.fc.ac.jc.g4 330 | ;div: no balance in the ledger 331 | ;form 332 | =hx-post "/apps/chain/faucet" 333 | ;input.hidden 334 | =type "text" 335 | =name "name" 336 | =value (trip name) 337 | ; 338 | == 339 | ;button.p3.b1.br1.hover.border 340 | ; Initialize wallet 341 | == 342 | == 343 | == 344 | ++ part-current-balance 345 | |= amount=@ud 346 | ;div.fr.jc.jb.p4.br1.s1 347 | ;div: Balance 348 | ;div.mono.bold.s2: $TOKEN {(scow %ud amount)} 349 | == 350 | ++ part-header 351 | ;header.p4.fr.ac.jb 352 | ;a/"/apps/chain" 353 | ;h1.s3: %chain 354 | == 355 | ;span.border.p1.br1.fr.g3 356 | ;span.f3: test net v1 357 | ;span.bold: SECT 358 | == 359 | == 360 | ++ part-refresher 361 | ;div.loader 362 | =hx-get "" 363 | =hx-trigger "every 5s" 364 | =hx-swap "outerHTML" 365 | =hx-target "#wallet-data" 366 | =hx-select "#wallet-data" 367 | ;span.loaded.mono(style "opacity: 0;"): loading 368 | ;span.loading.mono: loading 369 | == 370 | ++ form-send-tokens 371 | |= name=@t 372 | ;form.fc.g2.p3.border.br1 373 | =hx-post "/apps/chain/send-tokens/{(trip name)}" 374 | ;label.fr.ac.g2 375 | ;span.mono: amount 376 | ;input.border.p1.br1.grow 377 | =type "text" 378 | =name "txn-amount" 379 | =required "" 380 | =title "@ud (12.312)" 381 | =autocomplete "off" 382 | =pattern (trip '[0-9]{1,3}(\\.[0-9]{3})*') 383 | =placeholder "12.345" 384 | ; 385 | == 386 | == 387 | ;label.fr.ac.g2 388 | ;span.mono: target 389 | ;input.border.p1.br1.grow 390 | =type "text" 391 | =name "txn-target" 392 | =autocomplete "off" 393 | =required "" 394 | =title "@ux (0x12.42a4)" 395 | =pattern (trip '0x[a-z0-9]{1,4}(\\.[a-z0-9]{4})*') 396 | =placeholder "0x1ab2" 397 | ; 398 | == 399 | == 400 | ;button.loader.p3.bold.s1.b1.br1.hover.wfc 401 | ;span.loaded: Send 402 | ;span.loading: ... 403 | == 404 | == 405 | ++ part-txn-history 406 | |= addr=@ux 407 | ;div.fc.g4 408 | ;+ 409 | =/ x (lent (pending-transactions addr)) 410 | ?: =(0 x) ;/("") 411 | ;div.f3.mono: {} pending transactions 412 | :: 413 | ;* 414 | %+ turn 415 | %+ sort (transactions addr) 416 | |= [a=txn-signed:ch b=txn-signed:ch] 417 | (gth nonce.a nonce.b) 418 | |= txn=txn-signed:ch 419 | =/ cmd 420 | %- ledger-cmd:lg 421 | cmd.txn 422 | ;div.fc 423 | ;+ (print-addr target.cmd) 424 | ;div.fr.jb.as.border-2.br1.p2 425 | ;span.f2: #{(scow %ud nonce.txn)} 426 | ;span.mono: $TOKEN {(scow %ud amount.cmd)} 427 | == 428 | == 429 | == 430 | ++ print-addr 431 | |= addr=@ux 432 | ;div.break.p2.border-2.br1.b1 433 | ;span: {(scow %ux addr)} 434 | == 435 | ++ part-wallet-links 436 | |= current=cord 437 | ;div#wallet-links.fr.g2.ac.js 438 | ;* 439 | %+ turn ~(tap by wallets) 440 | |= [name=cord pub=@ux] 441 | =/ tog ?:(=(name current) "toggled" "") 442 | ;a 443 | =class "p2 br1 border b1 hover loader {tog}" 444 | =href "/apps/chain/{(trip name)}" 445 | ;span.loaded: {(trip name)} 446 | == 447 | == 448 | ++ part-footer 449 | ;footer.p4.br1.prose.f3.tc 450 | =style "margin-top: 100px; margin-bottom: 100px;" 451 | sponsored by [Chorus One](https://chorus.one) 452 | and [Red Horizon](https://redhorizon.com). 453 | == 454 | ++ lift 455 | |= in=manx 456 | =/ theme %system 457 | =/ colors 458 | ?: =(theme %light) theme-light 459 | ?: =(theme %dark) theme-dark 460 | theme-system 461 | :: 462 | ;html 463 | ;head 464 | ;title: %chain - testnet 465 | ;script(src "https://code.jquery.com/jquery-3.7.1.js"); 466 | ;script(src "https://unpkg.com/htmx.org@1.9.11"); 467 | ;script(src "https://unpkg.com/htmx.org@1.9.11/dist/ext/response-targets.js"); 468 | ;style: {(trip style-css)} 469 | ;style: {colors} 470 | == 471 | ;body.mw-page.ma.p2.fc.g3 472 | ;+ in 473 | == 474 | == 475 | ++ html-cord 476 | |= in=manx 477 | %- crip 478 | %+ welp "" 479 | (en-xml:html in) 480 | -- 481 | -------------------------------------------------------------------------------- /desk/lib/azimuth.hoon: -------------------------------------------------------------------------------- 1 | :: azimuth: constants and utilities 2 | :: 3 | /+ ethereum 4 | :: 5 | => => [azimuth-types ethereum-types .] 6 | |% 7 | +$ complete-ship 8 | $: state=point 9 | history=(list diff-point) ::TODO maybe block/event nr? :: newest first 10 | keys=(map life pass) 11 | == 12 | :: 13 | ++ fleet (map @p complete-ship) 14 | :: 15 | ++ eth-type 16 | |% 17 | ++ point 18 | :~ [%bytes-n 32] :: encryptionKey 19 | [%bytes-n 32] :: authenticationKey 20 | %bool :: hasSponsor 21 | %bool :: active 22 | %bool :: escapeRequested 23 | %uint :: sponsor 24 | %uint :: escapeRequestedTo 25 | %uint :: cryptoSuiteVersion 26 | %uint :: keyRevisionNumber 27 | %uint :: continuityNumber 28 | == 29 | ++ deed 30 | :~ %address :: owner 31 | %address :: managementProxy 32 | %address :: spawnProxy 33 | %address :: votingProxy 34 | %address :: transferProxy 35 | == 36 | -- 37 | :: 38 | ++ eth-noun 39 | |% 40 | +$ point 41 | $: encryption-key=octs 42 | authentication-key=octs 43 | has-sponsor=? 44 | active=? 45 | escape-requested=? 46 | sponsor=@ud 47 | escape-to=@ud 48 | crypto-suite=@ud 49 | key-revision=@ud 50 | continuity-number=@ud 51 | == 52 | +$ deed 53 | $: owner=address 54 | management-proxy=address 55 | spawn-proxy=address 56 | voting-proxy=address 57 | transfer-proxy=address 58 | == 59 | -- 60 | :: 61 | ++ function 62 | |% 63 | ++ azimuth 64 | $% [%points who=@p] 65 | [%rights who=@p] 66 | [%get-spawned who=@p] 67 | [%dns-domains ind=@ud] 68 | == 69 | -- 70 | :: 71 | :: # diffs 72 | :: 73 | ++ update 74 | $% [%full ships=(map ship point) dns=dnses heard=events] 75 | [%difs dis=(list (pair event-id diff-azimuth))] 76 | == 77 | :: 78 | :: # constants 79 | :: 80 | :: contract addresses 81 | ++ contracts mainnet-contracts 82 | ++ mainnet-contracts 83 | |% 84 | :: azimuth: data contract 85 | :: 86 | ++ azimuth 87 | 0x223c.067f.8cf2.8ae1.73ee.5caf.ea60.ca44.c335.fecb 88 | :: 89 | ++ ecliptic 90 | 0x33ee.cbf9.0847.8c10.6146.26a9.d304.bfe1.8b78.dd73 91 | :: 92 | ++ linear-star-release 93 | 0x86cd.9cd0.992f.0423.1751.e376.1de4.5cec.ea5d.1801 94 | :: 95 | ++ conditional-star-release 96 | 0x8c24.1098.c3d3.498f.e126.1421.633f.d579.86d7.4aea 97 | :: 98 | ++ delegated-sending 99 | 0xf790.8ab1.f1e3.52f8.3c5e.bc75.051c.0565.aeae.a5fb 100 | :: 101 | ++ naive 102 | 0xeb70.029c.fb3c.53c7.78ea.f68c.d28d.e725.390a.1fe9 103 | :: 104 | :: launch: block number of azimuth deploy 105 | :: 106 | ++ launch 6.784.800 107 | :: 108 | :: public: block number of azimuth becoming independent 109 | :: 110 | ++ public 7.033.765 111 | :: 112 | ++ chain-id 1 113 | -- 114 | :: 115 | :: Testnet contract addresses 116 | :: 117 | ++ goerli-contracts 118 | |% 119 | ++ azimuth 120 | 0xbb61.fa68.3e4b.9104.18e2.7b00.a143.8a93.6234.df52 121 | :: 122 | ++ ecliptic 123 | 0xe129.0a32.9014.5e63.e6a8.ec1e.f661.6906.856d.0c8f 124 | :: 125 | ++ linear-star-release 126 | 0x0 127 | :: 128 | ++ conditional-star-release 129 | 0x0 130 | :: 131 | ++ delegated-sending 132 | 0x0 133 | :: 134 | ++ naive 135 | 0x56e3.7137.cdaf.c026.a732.e8e8.40cd.621e.d50b.d210 136 | :: 137 | ++ launch 7.834.742 138 | ++ public 7.834.800 139 | ++ chain-id 5 140 | -- 141 | :: 142 | :: Local contract addresses 143 | :: 144 | :: These addresses are only reproducible if you use the deploy 145 | :: script in bridge 146 | :: 147 | ++ local-contracts 148 | |% 149 | ++ ecliptic 150 | 0x56db.68f2.9203.ff44.a803.faa2.404a.44ec.bb7a.7480 151 | ++ azimuth 152 | 0x863d.9c2e.5c4c.1335.96cf.ac29.d552.55f0.d0f8.6381 153 | ++ delegated-sending 154 | 0xb71c.0b6c.ee1b.cae5.6dfe.95cd.9d3e.41dd.d7ea.fc43 155 | ++ linear-star-release 156 | 0x3c3.dc12.be65.8158.d1d7.f9e6.6e08.ec40.99c5.68e4 157 | ++ conditional-star-release 158 | 0x35eb.3b10.2d9c.1b69.ac14.69c1.b1fe.1799.850c.d3eb 159 | ++ naive 160 | 0x6bb8.8a9b.bd82.be7a.997f.eb01.929c.6ec7.8988.fe12 161 | ++ launch 0 162 | ++ public 0 163 | ++ chain-id 1.337 164 | -- 165 | :: 166 | :: ++ azimuth 0x863d.9c2e.5c4c.1335.96cf.ac29.d552.55f0.d0f8.6381 :: local bridge 167 | :: hashes of ship event signatures 168 | ++ azimuth-events 169 | |% 170 | :: 171 | :: OwnerChanged(uint32,address) 172 | ++ owner-changed 173 | 0x16d0.f539.d49c.6cad.822b.767a.9445.bfb1. 174 | cf7e.a6f2.a6c2.b120.a7ea.4cc7.660d.8fda 175 | :: 176 | :: Activated(uint32) 177 | ++ activated 178 | 0xe74c.0380.9d07.69e1.b1f7.06cc.8414.258c. 179 | d1f3.b6fe.020c.d15d.0165.c210.ba50.3a0f 180 | :: 181 | :: Spawned(uint32,uint32) 182 | ++ spawned 183 | 0xb2d3.a6e7.a339.f5c8.ff96.265e.2f03.a010. 184 | a854.1070.f374.4a24.7090.9644.1508.1546 185 | :: 186 | :: EscapeRequested(uint32,uint32) 187 | ++ escape-requested 188 | 0xb4d4.850b.8f21.8218.141c.5665.cba3.79e5. 189 | 3e9b.b015.b51e.8d93.4be7.0210.aead.874a 190 | :: 191 | :: EscapeCanceled(uint32,uint32) 192 | ++ escape-canceled 193 | 0xd653.bb0e.0bb7.ce83.93e6.24d9.8fbf.17cd. 194 | a590.2c83.28ed.0cd0.9988.f368.90d9.932a 195 | :: 196 | :: EscapeAccepted(uint32,uint32) 197 | ++ escape-accepted 198 | 0x7e44.7c9b.1bda.4b17.4b07.96e1.00bf.7f34. 199 | ebf3.6dbb.7fe6.6549.0b1b.fce6.246a.9da5 200 | :: 201 | :: LostSponsor(uint32,uint32) 202 | ++ lost-sponsor 203 | 0xd770.4f9a.2519.3dbd.0b0c.b4a8.09fe.ffff. 204 | a7f1.9d1a.ae88.17a7.1346.c194.4482.10d5 205 | :: 206 | :: ChangedKeys(uint32,bytes32,bytes32,uint32,uint32) 207 | ++ changed-keys 208 | 0xaa10.e7a0.117d.4323.f1d9.9d63.0ec1.69be. 209 | bb3a.988e.8957.70e3.5198.7e01.ff54.23d5 210 | :: 211 | :: BrokeContinuity(uint32,uint32) 212 | ++ broke-continuity 213 | 0x2929.4799.f1c2.1a37.ef83.8e15.f79d.d91b. 214 | cee2.df99.d63c.d1c1.8ac9.68b1.2951.4e6e 215 | :: 216 | :: ChangedSpawnProxy(uint32,address) 217 | ++ changed-spawn-proxy 218 | 0x9027.36af.7b3c.efe1.0d9e.840a.ed0d.687e. 219 | 35c8.4095.122b.2505.1a20.ead8.866f.006d 220 | :: 221 | :: ChangedTransferProxy(uint32,address) 222 | ++ changed-transfer-proxy 223 | 0xcfe3.69b7.197e.7f0c.f067.93ae.2472.a9b1. 224 | 3583.fecb.ed2f.78df.a14d.1f10.796b.847c 225 | :: 226 | :: ChangedManagementProxy(uint32,address) 227 | ++ changed-management-proxy 228 | 0xab9c.9327.cffd.2acc.168f.afed.be06.139f. 229 | 5f55.cb84.c761.df05.e051.1c25.1e2e.e9bf 230 | :: 231 | :: ChangedVotingProxy(uint32,address) 232 | ++ changed-voting-proxy 233 | 0xcbd6.269e.c714.57f2.c7b1.a227.74f2.46f6. 234 | c5a2.eae3.795e.d730.0db5.1768.0c61.c805 235 | :: 236 | :: ChangedDns(string,string,string) 237 | ++ changed-dns 238 | 0xfafd.04ad.e1da.ae2e.1fdb.0fc1.cc6a.899f. 239 | d424.063e.d5c9.2120.e67e.0730.53b9.4898 240 | -- 241 | -- 242 | :: 243 | :: logic 244 | :: 245 | |% 246 | ++ pass-from-eth 247 | |= [enc=octs aut=octs sut=@ud] 248 | ^- pass 249 | %^ cat 3 'b' 250 | ?. &(=(1 sut) =(p.enc 32) =(p.aut 32)) 251 | (cat 8 0 0) 252 | (cat 8 q.aut q.enc) 253 | :: 254 | ++ point-from-eth 255 | |= [who=@p point:eth-noun deed:eth-noun] 256 | ^- point 257 | :: 258 | :: ownership 259 | :: 260 | :+ :* owner 261 | management-proxy 262 | voting-proxy 263 | transfer-proxy 264 | == 265 | :: 266 | :: network state 267 | :: 268 | ?. active ~ 269 | :- ~ 270 | :* key-revision 271 | :: 272 | (pass-from-eth encryption-key authentication-key crypto-suite) 273 | :: 274 | continuity-number 275 | :: 276 | [has-sponsor `@p`sponsor] 277 | :: 278 | ?. escape-requested ~ 279 | ``@p`escape-to 280 | == 281 | :: 282 | :: spawn state 283 | :: 284 | ?. ?=(?(%czar %king) (clan:title who)) ~ 285 | :- ~ 286 | :* spawn-proxy 287 | ~ ::TODO call getSpawned to fill this 288 | == 289 | :: 290 | ++ event-log-to-point-diff 291 | =, azimuth-events 292 | =, abi:ethereum 293 | |= log=event-log:rpc:ethereum 294 | ^- (unit (pair ship diff-point)) 295 | ~? ?=(~ mined.log) %processing-unmined-event 296 | :: 297 | ?: =(i.topics.log owner-changed) 298 | =/ [who=@ wer=address] 299 | (decode-topics t.topics.log ~[%uint %address]) 300 | `[who %owner wer] 301 | :: 302 | ?: =(i.topics.log activated) 303 | =/ who=@ 304 | (decode-topics t.topics.log ~[%uint]) 305 | `[who %activated who] 306 | :: 307 | ?: =(i.topics.log spawned) 308 | =/ [pre=@ who=@] 309 | (decode-topics t.topics.log ~[%uint %uint]) 310 | `[pre %spawned who] 311 | :: 312 | ?: =(i.topics.log escape-requested) 313 | =/ [who=@ wer=@] 314 | (decode-topics t.topics.log ~[%uint %uint]) 315 | `[who %escape `wer] 316 | :: 317 | ?: =(i.topics.log escape-canceled) 318 | =/ who=@ (decode-topics t.topics.log ~[%uint]) 319 | `[who %escape ~] 320 | :: 321 | ?: =(i.topics.log escape-accepted) 322 | =/ [who=@ wer=@] 323 | (decode-topics t.topics.log ~[%uint %uint]) 324 | `[who %sponsor & wer] 325 | :: 326 | ?: =(i.topics.log lost-sponsor) 327 | =/ [who=@ pos=@] 328 | (decode-topics t.topics.log ~[%uint %uint]) 329 | `[who %sponsor | pos] 330 | :: 331 | ?: =(i.topics.log changed-keys) 332 | =/ who=@ (decode-topics t.topics.log ~[%uint]) 333 | =/ [enc=octs aut=octs sut=@ud rev=@ud] 334 | %+ decode-results data.log 335 | ~[[%bytes-n 32] [%bytes-n 32] %uint %uint] 336 | `[who %keys rev (pass-from-eth enc aut sut)] 337 | :: 338 | ?: =(i.topics.log broke-continuity) 339 | =/ who=@ (decode-topics t.topics.log ~[%uint]) 340 | =/ num=@ (decode-results data.log ~[%uint]) 341 | `[who %continuity num] 342 | :: 343 | ?: =(i.topics.log changed-management-proxy) 344 | =/ [who=@ sox=address] 345 | (decode-topics t.topics.log ~[%uint %address]) 346 | `[who %management-proxy sox] 347 | :: 348 | ?: =(i.topics.log changed-voting-proxy) 349 | =/ [who=@ tox=address] 350 | (decode-topics t.topics.log ~[%uint %address]) 351 | `[who %voting-proxy tox] 352 | :: 353 | ?: =(i.topics.log changed-spawn-proxy) 354 | =/ [who=@ sox=address] 355 | (decode-topics t.topics.log ~[%uint %address]) 356 | `[who %spawn-proxy sox] 357 | :: 358 | ?: =(i.topics.log changed-transfer-proxy) 359 | =/ [who=@ tox=address] 360 | (decode-topics t.topics.log ~[%uint %address]) 361 | `[who %transfer-proxy tox] 362 | :: 363 | :: warn about unimplemented events, but ignore 364 | :: the ones we know are harmless. 365 | ~? ?! .= i.topics.log 366 | :: OwnershipTransferred(address,address) 367 | 0x8be0.079c.5316.5914.1344.cd1f.d0a4.f284. 368 | 1949.7f97.22a3.daaf.e3b4.186f.6b64.57e0 369 | [%unimplemented-event i.topics.log] 370 | ~ 371 | :: 372 | ++ apply-point-diff 373 | |= [pot=point dif=diff-point] 374 | ^- point 375 | ?- -.dif 376 | %full new.dif 377 | :: 378 | %activated 379 | %_ pot 380 | net `[0 0 0 &^(^sein:title who.dif) ~] 381 | kid ?. ?=(?(%czar %king) (clan:title who.dif)) ~ 382 | `[0x0 ~] 383 | == 384 | :: 385 | :: ownership 386 | :: 387 | %owner pot(owner.own new.dif) 388 | %transfer-proxy pot(transfer-proxy.own new.dif) 389 | %management-proxy pot(management-proxy.own new.dif) 390 | %voting-proxy pot(voting-proxy.own new.dif) 391 | :: 392 | :: networking 393 | :: 394 | ?(%keys %continuity %sponsor %escape) 395 | ?> ?=(^ net.pot) 396 | ?- -.dif 397 | %keys 398 | pot(life.u.net life.dif, pass.u.net pass.dif) 399 | :: 400 | %sponsor 401 | %= pot 402 | sponsor.u.net new.dif 403 | escape.u.net ?:(has.new.dif ~ escape.u.net.pot) 404 | == 405 | :: 406 | %continuity pot(continuity-number.u.net new.dif) 407 | %escape pot(escape.u.net new.dif) 408 | == 409 | :: 410 | :: spawning 411 | :: 412 | ?(%spawned %spawn-proxy) 413 | ?> ?=(^ kid.pot) 414 | ?- -.dif 415 | %spawned 416 | =- pot(spawned.u.kid -) 417 | (~(put in spawned.u.kid.pot) who.dif) 418 | :: 419 | %spawn-proxy pot(spawn-proxy.u.kid new.dif) 420 | == 421 | == 422 | :: 423 | ++ parse-id 424 | |= id=@t 425 | ^- azimuth:function 426 | |^ 427 | ~| id 428 | %+ rash id 429 | ;~ pose 430 | (function %points 'points' shipname) 431 | (function %get-spawned 'getSpawned' shipname) 432 | (function %dns-domains 'dnsDomains' dem:ag) 433 | == 434 | :: 435 | ++ function 436 | |* [tag=@tas fun=@t rul=rule] 437 | ;~(plug (cold tag (jest fun)) (ifix [pal par] rul)) 438 | :: 439 | ++ shipname 440 | ;~(pfix sig fed:ag) 441 | -- 442 | :: 443 | ++ function-to-call 444 | |% 445 | ++ azimuth 446 | |= cal=azimuth:function 447 | ^- [id=@t dat=call-data:rpc:ethereum] 448 | ?- -.cal 449 | %points 450 | :- (crip "points({(scow %p who.cal)})") 451 | ['points(uint32)' ~[uint+`@`who.cal]] 452 | :: 453 | %rights 454 | :- (crip "rights({(scow %p who.cal)})") 455 | ['rights(uint32)' ~[uint+`@`who.cal]] 456 | :: 457 | %get-spawned 458 | :- (crip "getSpawned({(scow %p who.cal)})") 459 | ['getSpawned(uint32)' ~[uint+`@`who.cal]] 460 | :: 461 | %dns-domains 462 | :- (crip "dnsDomains({(scow %ud ind.cal)})") 463 | ['dnsDomains(uint256)' ~[uint+ind.cal]] 464 | == 465 | -- 466 | -- 467 | -------------------------------------------------------------------------------- /desk/app/clockwork.hoon: -------------------------------------------------------------------------------- 1 | /- *clockwork, pki=pki-store, ch=chain 2 | /+ lib=clockwork, 3 | dbug, 4 | *mip 5 | =, crypto 6 | |% 7 | +$ versioned-state 8 | $% state-0 9 | == 10 | +$ state-0 11 | $: %0 12 | $= local :: local variables from spec 13 | $: 14 | =height 15 | =bloc 16 | qc=(unit qc) :: quorum certificate 17 | =mempool 18 | == 19 | :: global state, this should sync among nodes 20 | robin=(lest node) :: node order, round-robin 21 | =history 22 | =vote-store 23 | :: keys 24 | our-life=@ud 25 | keys=acru:ames 26 | =pki-store:pki 27 | faucet-nonce=@ud 28 | == 29 | +$ card card:agent:gall 30 | -- 31 | %- agent:dbug 32 | =| state-0 33 | =* state - 34 | ^- agent:gall 35 | =< 36 | |_ =bowl:gall 37 | +* this . 38 | hd ~(. +> bowl) 39 | :: 40 | ++ on-init 41 | ~& > "%chain initialized" 42 | :_ this(robin nodes) 43 | :- clockstep-watch-card:hd 44 | pki-cards:hd 45 | :: 46 | ++ on-leave 47 | |= =path 48 | [~ this] 49 | ++ on-fail 50 | |= [=term =tang] 51 | %- (slog leaf+"error in {}" >term< tang) 52 | [~ this] 53 | ++ on-save !>(state) 54 | ++ on-load 55 | |= old-state=vase 56 | :: dev 57 | :: :_ this(robin nodes) 58 | :: :- clockstep-watch-card:hd 59 | :: :- fake-pki-card:hd pki-cards:hd 60 | :: prod 61 | :- ~ this(state !<(state-0 old-state)) 62 | :: 63 | ++ on-watch 64 | |= =(pole knot) 65 | ?+ pole ~|(bad-watch-path+`path`pole !!) 66 | [%blocs ~] 67 | :_ this 68 | ~[[%give %fact ~ bloc-update+!>([%blocs history])]] 69 | == 70 | ++ on-poke 71 | |= [=mark =vase] 72 | |^ 73 | :: check various conditions for testing 74 | ?. ?=(%noun mark) [~ this] 75 | ?: ?=(%keys q.vase) 76 | ~& `signature`[(sigh:as:keys 1) our.bowl our-life] 77 | [~ this] 78 | ?: ?=(%reset q.vase) :_ this nuke-cards:hd 79 | ?: ?=(%sprint q.vase) :_ this dbug-cards:hd 80 | ?: ?=(%print q.vase) 81 | =/ his (bap:hon history) 82 | ?~ his ~& >>> "no blocs found" [~ this] 83 | ~& >> last-bloc=i.his [~ this] 84 | ?: ?=(%nuke q.vase) 85 | ~& >>> "nuking state" 86 | ~& >> history=history 87 | ?> =(src.bowl primary) 88 | =. state *state-0 89 | :: this relies on depth-first move order 90 | :: reevaluate when breadth-first is close 91 | :_ this(robin nodes) [stop-card:hd pki-leave-card pki-cards:hd] 92 | :: TODO pause poke? 93 | :: actual checks 94 | :: throw away unrecognized pokes 95 | =/ uaction ((soft action) q.vase) 96 | ?~ uaction [~ this] 97 | =/ action u.uaction 98 | ?- -.action 99 | %start (handle-start +.action) 100 | %broadcast (handle-broadcast +.action) 101 | %txn (handle-txn +.action) 102 | %faucet (handle-faucet +.action) 103 | == 104 | ++ handle-start 105 | |= ts=@da 106 | ?> =(src.bowl primary) 107 | ~& handling-start=ts 108 | ?. =(*bloc bloc.local) [~ this] 109 | ~& "bootstrapping" 110 | =/ init-bloc=bloc [our.bowl ~ ts height.local 0 ~] 111 | =. bloc.local init-bloc 112 | =. qc.local ~ 113 | ?. .=(src.bowl i.robin) [~ this] 114 | :_ this 115 | :- (start-timer-card:hd ts) 116 | (bootstrap-cards:hd ts) 117 | ++ handle-broadcast 118 | |= =qc ^- (quip card _this) 119 | ~& handling-broadcast=[from=src.bowl h=height.qc r=round.qc s=stage.qc] 120 | ?: (lth height.qc height.local) 121 | ~& bail-height-below-current=[src=height.qc our=height.local] 122 | [~ this] 123 | =/ =vote -.qc 124 | =/ sigs=(list signature) ~(tap in quorum.qc) 125 | |- 126 | ?~ sigs [~ this] 127 | =/ sig i.sigs 128 | =/ pass (~(get bi pki-store) q.sig r.sig) 129 | ?~ pass $(sigs t.sigs) 130 | =/ msg (jam vote) 131 | =/ keys (com:nu:crub u.pass) 132 | ?. (safe:as:keys p.sig msg) 133 | $(sigs t.sigs) 134 | $(sigs t.sigs, vote-store (~(put ju vote-store) vote sig)) 135 | ++ handle-txn 136 | |= =txn 137 | ?> (gte (bex 10) (met 3 (jam txn))) 138 | ?. ?=(txn-signed:ch txn) [~ this] 139 | [~ this(mempool.local (~(put bi mempool.local) who.txn nonce.txn txn))] 140 | ++ handle-faucet 141 | |= =addr 142 | =/ =txn-unsigned:ch 143 | :* (latest-key our.bowl) 144 | faucet-nonce 145 | %ledger 146 | 0 147 | [%send addr (bex 16)] 148 | == 149 | =/ =txn-signed:ch [(sigh:as:keys (jam txn-unsigned)) txn-unsigned] 150 | ~& >>> [txn-signed] 151 | =. faucet-nonce +(faucet-nonce) 152 | (handle-txn txn-signed) 153 | -- 154 | ++ on-peek |=(=(pole knot) ~) 155 | ++ on-agent 156 | |= [=(pole knot) =sign:agent:gall] 157 | |^ 158 | :: ~> %bout.[0 '%clockwork +on-agent'] 159 | ?+ pole [~ this] 160 | [%tick ~] 161 | ?: ?=(%kick -.sign) :_ this :~(clockstep-watch-card:hd) 162 | ?. ?=(%fact -.sign) [~ this] (handle-tick (@ud q.q.cage.sign)) 163 | [%pki-store ~] 164 | ?+ -.sign [~ this] 165 | %kick :_ this :~(pki-watch-card:hd) 166 | %fact 167 | ?+ p.cage.sign ~&([%bad-mark p.cage.sign] [~ this]) 168 | %pki-snapshot 169 | ~& >> "pki-snapshot-received" 170 | =/ new-pki-store !<(pki-store:pki q.cage.sign) 171 | [~ this(pki-store new-pki-store)] 172 | %pki-diff 173 | =/ entry !<(pki-entry:pki q.cage.sign) 174 | =+ entry 175 | =/ new-pki-store (~(put bi pki-store) ship life pass) 176 | [~ this(pki-store new-pki-store)] 177 | == 178 | == 179 | == 180 | :: Main agent logic 181 | ++ handle-tick 182 | |= count=@ud ^- (quip card _this) 183 | =/ [=round rem=@] 184 | :: ?: =(count 0) 185 | :: [0 0] 186 | (dvr (dec count) 4) 187 | =/ =steppe (steppe +(rem)) 188 | =/ leader=node (snag (mod round (lent robin)) `(list node)`robin) 189 | ~& >>> timer-pinged-at=[count=count height=height.local round=round steppe=steppe] 190 | ~& > current-time=[m s f]:(yell now.bowl) 191 | ~& >> nexttimer-at=[m s f]:(yell (add now.bowl delta)) :: uhm 192 | ?- steppe 193 | %1 194 | ~& >> leader=leader 195 | :: In step 1 only the leader votes 196 | ?. .=(our.bowl leader) bail 197 | :: If we are the leader we look for a qc in our vote store at the current height 198 | :: that is more recent (i.e. same height, higher round OR stage) 199 | :: than our local state qc. If we find one, we vote for that and update our local 200 | :: bloc and state. 201 | :: If not, we propose our current local bloc with txns from our mempool 202 | =/ most-recent (~(most-recent vs:lib vote-store) height.local) 203 | ~& most-recent=most-recent 204 | =. state 205 | ?~ most-recent 206 | %= state 207 | txns.bloc.local (pick-txns-from mempool.local) 208 | round.bloc.local round 209 | == 210 | %= state 211 | bloc.local bloc.u.most-recent 212 | qc.local (some u.most-recent) 213 | == 214 | :: :_ increment-step 215 | :_ this 216 | %- broadcast-cards:hd 217 | =/ =vote [bloc.local height.local round %1] 218 | :: ~& > leader-vote=[bloc.local height=height.local round=round] 219 | =/ sig=(set signature) (silt ~[[(sigh:as:keys (jam vote)) our.bowl our-life]]) 220 | [vote sig] 221 | :: 222 | %2 223 | :: In step 2 all nodes come to vote. 224 | :: Nodes look for the latest vote by the leader (i.e. what happened on step 1) 225 | =/ lbl=(unit qc) (~(latest-by vs:lib vote-store) leader) 226 | :: If the leader didn't vote on step 1 (which really shouldn't happen!) we bail 227 | :: bail meaning incrementing the step and doing nothing 228 | ?~ lbl ~& "no recent vote from leader found" bail 229 | :: We compare the bloc sent by the leader with our local bloc 230 | :: If the leader's bloc is not at all more recent (in height and (round or stage)) 231 | :: we bail as nothing new was received 232 | ?. =(height.u.lbl height.local) 233 | ~& "received bloc at incorrect height" 234 | bail 235 | =/ received-new=? 236 | ?~ qc.local %.y 237 | (as-recent:qcu:lib u.lbl u.qc.local) 238 | ~& > received-new=received-new 239 | ?. received-new 240 | ~& "did not receive new bloc from leader" 241 | bail 242 | :: If we correctly received a new bloc from the leader we save that to local state 243 | :: and vote for it 244 | =. state 245 | %= state 246 | bloc.local bloc.u.lbl 247 | qc.local lbl 248 | == 249 | :_ this 250 | =/ =vote [bloc.u.lbl height.u.lbl round %1] 251 | ~& >> voting=[height.local round %1] 252 | (vote-and-broadcast u.lbl vote) 253 | :: 254 | %3 255 | :: In step 2 we should have received votes from 2/3 of the nodes for some bloc 256 | :: in the current height and round, and stage %1. We check for that. 257 | =/ valid (~(valid-qcs vs:lib vote-store) height.local round %1) 258 | :: If that's not the case we bail 259 | ?~ valid ~& "no valid qcs at stage 1" bail 260 | :: If good we update our state, and send a stage %2 (final vote). 261 | =. state 262 | %= state 263 | bloc.local bloc.i.valid 264 | qc.local (some i.valid) 265 | == 266 | :_ this 267 | =/ vote [bloc.i.valid height.local round %2] 268 | ~& >> voting=[height.local round %2] 269 | (vote-and-broadcast i.valid vote) 270 | %4 271 | :: Same as above, we should have received 2/3 of stage %2 votes for something 272 | =/ valid (~(valid-qcs vs:lib vote-store) height.local round %2) 273 | :: If we didn't find a valid quorum we increment the step 274 | :: and schedule the final addendum cleanup stage 275 | ?~ valid ~& "no valid qcs at stage 2" schedule-addendum 276 | :: If all good we commit the bloc to history, reset local bloc and qc, 277 | :: increment height 278 | :: then broadcast the qc of the committed bloc to sync everyone's vote store 279 | =/ init-bloc [our.bowl ~ now.bowl +(height.local) round quorum.i.valid] 280 | =. state 281 | %= state 282 | history 283 | ~& > ~ 284 | ~& > bloc-commited=[h=height.local r=round.bloc.i.valid who=mint.bloc.i.valid txns=txns.bloc.i.valid] 285 | ~& > ~ 286 | %^ put:hon history 287 | height.bloc.i.valid 288 | `voted-bloc`[bloc.i.valid quorum.i.valid] 289 | mempool.local (trim-mempool mempool.local txns.bloc.i.valid) 290 | height.local +(height.local) 291 | bloc.local init-bloc 292 | qc.local ~ 293 | == 294 | :: :_ increment-step 295 | :_ this 296 | :* addendum-card:hd 297 | bloc-fact-card:hd 298 | (broadcast-cards:hd i.valid) 299 | == 300 | == 301 | ++ vote-and-broadcast 302 | |= [p=qc =vote] ^- (list card) 303 | =/ =signature [(sigh:as:keys (jam vote)) our.bowl our-life] 304 | %+ roll `(list @p)`nodes |= [i=@p acc=(list card)] 305 | %+ weld acc 306 | :~ (broadcast-card p i) 307 | (vote-card signature vote i) 308 | == 309 | ++ schedule-addendum 310 | :_ this 311 | :~ addendum-card:hd 312 | == 313 | ++ bail 314 | ~& "bail" 315 | [~ this] 316 | -- 317 | ++ on-arvo 318 | |= [=(pole knot) =sign-arvo] 319 | ^- (quip card _this) 320 | |^ 321 | ?: ?=(%jael -.sign-arvo) (update-keys +.sign-arvo) 322 | ?. ?=(%behn -.sign-arvo) [~ this] 323 | ?. ?=([%addendum ~] pole) [~ this] handle-addendum 324 | :: %jael 325 | ++ update-keys 326 | |= g=gift:jael 327 | :: ~& updating-keys=g 328 | ^- (quip card _this) 329 | ?. ?=(%private-keys -.g) [~ this] 330 | =/ vein vein.g 331 | =/ private-key (~(get by vein) life.g) 332 | ?~ private-key ~& >>> "private key not found" [~ this] 333 | :- ~ 334 | %= this 335 | our-life life.g 336 | keys (nol:nu:crub u.private-key) 337 | == 338 | :: %final stage of bloc syncing 339 | ++ handle-addendum 340 | ~& >> addendum-phase=[m s f]:(yell now.bowl) 341 | ^- (quip card _this) 342 | :: In the addendum stage we look in our vote store for valid qcs of stage %2 of a height 343 | :: greater than our local height 344 | =/ valid (~(future-blocs vs:lib vote-store) height.local) 345 | :: We then iterate through them and do what we did in step %4; commit bloc to history, 346 | :: increment height, reset our local bloc/qc and broadcast the committed bloc 347 | =| new-cards=(list card) 348 | |- 349 | ?~ valid [new-cards this] 350 | =/ init-bloc [our.bowl ~ now.bowl +(height.local) round quorum.i.valid] 351 | %= $ 352 | history 353 | ~& > ~ 354 | ~& > bloc-commited=[h=height.local r=round.bloc.i.valid who=mint.bloc.i.valid txns=txns.bloc.i.valid] 355 | ~& > ~ 356 | %^ put:hon history 357 | height.bloc.i.valid 358 | [bloc.i.valid quorum.i.valid] 359 | height.local +(height.local) 360 | :: bloc.local init-bloc 361 | qc.local ~ 362 | mempool.local (trim-mempool mempool.local txns.bloc.i.valid) 363 | new-cards (weld new-cards (broadcast-cards:hd i.valid)) 364 | valid t.valid 365 | == 366 | :: ++ increment-round 367 | :: %= this 368 | :: round +(round) 369 | :: robin shuffle-robin 370 | :: step %1 371 | :: == 372 | :: ++ shuffle-robin ^+ robin 373 | :: :: argh hoon list types 374 | :: =/ shuffled (snoc t.robin i.robin) 375 | :: ?~ shuffled robin shuffled 376 | -- 377 | -- 378 | |_ =bowl:gall 379 | :::: cards 380 | :: clockstep 381 | ++ clockstep-watch-card 382 | [%pass /tick %agent [our.bowl %clockstep] %watch /tick] 383 | ++ start-timer-card 384 | |= ts=@da 385 | [%pass /wire %agent [our.bowl %clockstep] %poke [%noun !>([%start ts])]] 386 | :: pki 387 | ++ pki-cards 388 | ^- (list card) 389 | :~ [%pass /private-keys %arvo %j %private-keys ~] 390 | pki-watch-card 391 | == 392 | ++ pki-watch-card 393 | :: subscribe to pki-store updates 394 | [%pass /pki-store %agent [our.bowl %pki-store] %watch /pki-diffs] 395 | ++ pki-leave-card 396 | [%pass /pki-store %agent [our.bowl %pki-store] %leave ~] 397 | ++ broadcast-cards 398 | |= p=qc ^- (list card) 399 | %+ turn nodes |= s=@p (broadcast-card p s) 400 | ++ broadcast-card 401 | |= [p=qc sip=ship] ^- card 402 | [%pass /wire %agent [sip %clockwork] %poke [%noun !>([%broadcast p])]] 403 | ++ vote-card 404 | |= [s=signature =vote sip=@p] 405 | =/ p [vote (silt ~[s])] 406 | [%pass /wire %agent [sip %clockwork] %poke [%noun !>([%broadcast p])]] 407 | :: 408 | ++ bootstrap-cards 409 | |= ts=@da 410 | %+ turn nodes |= sip=@p 411 | [%pass /wire %agent [sip %clockwork] %poke [%noun !>([%start ts])]] 412 | ++ dbug-cards 413 | %+ turn nodes |= sip=@p 414 | [%pass /wire %agent [sip %clockwork] %poke [%noun !>(%print)]] 415 | :: TODO don't do this poke 416 | ++ fake-pki-card 417 | [%pass /wire %agent [our.bowl %pki-store] %poke [%noun !>(%set-fake)]] 418 | ++ stop-card 419 | [%pass /wire %agent [our.bowl %clockstep] %poke [%noun !>(%stop)]] 420 | ++ nuke-cards 421 | :- [%give %fact ~[/blocs] bloc-update+!>([%reset ~])] 422 | %+ turn nodes |= sip=@p 423 | [%pass /wire %agent [sip %clockwork] %poke [%noun !>(%nuke)]] 424 | ++ addendum-card ^- card 425 | [%pass /addendum %arvo %b %wait (add now.bowl addendum-delta)] :: TODO time this properly 426 | ++ bloc-fact-card ^- card 427 | =/ update 428 | :: ?: (lth ~(wyt by history) 2) 429 | history 430 | :: (lot:hon history `(sub ~(wyt by history) 2) `~(wyt by history)) 431 | [%give %fact ~[/blocs] bloc-update+!>([%blocs update])] 432 | ++ pick-txns-from 433 | |= =mempool 434 | ^- (list txn) 435 | :: number of transactions in a bloc 436 | =/ needed 1.024 437 | =/ count 0 438 | =/ txns=(list txn) ~ 439 | |- 440 | ?~ mempool txns 441 | ?: =(count needed) txns 442 | =/ addr=@ux 443 | =/ addrs ~(key by `^mempool`mempool) 444 | ?~ addrs !! 445 | -:~(get to addrs) 446 | =/ nonces 447 | (scag (sub needed count) (sort ~(tap in (~(key bi `^mempool`mempool) addr)) lth)) 448 | =/ new-txns=(list txn) 449 | %+ turn nonces 450 | |= nonce=@ud 451 | (~(got bi `^mempool`mempool) addr nonce) 452 | %= $ 453 | count (add count (lent nonces)) 454 | txns `(list txn)`(weld new-txns txns) 455 | mempool (~(del by `^mempool`mempool) addr) 456 | == 457 | ++ trim-mempool 458 | |= [=mempool txns=(list txn)] 459 | ^- ^mempool 460 | ?~ txns mempool 461 | ?. ?=(txn-signed:ch i.txns) $(txns t.txns) 462 | $(mempool (~(del bi mempool) who.i.txns nonce.i.txns), txns t.txns) 463 | ++ latest-key 464 | |= =ship 465 | ^- pass 466 | =/ top (~(rep in (~(key bi pki-store) ship)) max) 467 | =/ key (~(get bi pki-store) ship top) 468 | ?~ key !! 469 | u.key 470 | -- 471 | -------------------------------------------------------------------------------- /desk/lib/tiny.hoon: -------------------------------------------------------------------------------- 1 | !. 2 | => %a50 3 | ~% %a.50 ~ ~ 4 | |% 5 | :: Types 6 | :: 7 | +$ ship @p 8 | +$ life @ud 9 | +$ rift @ud 10 | +$ pass @ 11 | +$ bloq @ 12 | +$ step _`@u`1 13 | +$ bite $@(bloq [=bloq =step]) 14 | +$ octs [p=@ud q=@] 15 | +$ mold $~(* $-(* *)) 16 | ++ unit |$ [item] $@(~ [~ u=item]) 17 | ++ list |$ [item] $@(~ [i=item t=(list item)]) 18 | ++ lest |$ [item] [i=item t=(list item)] 19 | ++ tree |$ [node] $@(~ [n=node l=(tree node) r=(tree node)]) 20 | ++ pair |$ [head tail] [p=head q=tail] 21 | ++ map 22 | |$ [key value] 23 | $| (tree (pair key value)) 24 | |=(a=(tree (pair)) ?:(=(~ a) & ~(apt by a))) 25 | :: 26 | ++ set 27 | |$ [item] 28 | $| (tree item) 29 | |=(a=(tree) ?:(=(~ a) & ~(apt in a))) 30 | :: 31 | ++ jug |$ [key value] (map key (set value)) 32 | :: 33 | :: Bits 34 | :: 35 | ++ dec :: decrement 36 | ~/ %dec 37 | |= a=@ 38 | ~_ leaf+"decrement-underflow" 39 | ?< =(0 a) 40 | =+ b=0 41 | |- ^- @ 42 | ?: =(a +(b)) b 43 | $(b +(b)) 44 | :: 45 | ++ add :: plus 46 | ~/ %add 47 | |= [a=@ b=@] 48 | ^- @ 49 | ?: =(0 a) b 50 | $(a (dec a), b +(b)) 51 | :: 52 | ++ sub :: subtract 53 | ~/ %sub 54 | |= [a=@ b=@] 55 | ~_ leaf+"subtract-underflow" 56 | :: difference 57 | ^- @ 58 | ?: =(0 b) a 59 | $(a (dec a), b (dec b)) 60 | :: 61 | ++ mul :: multiply 62 | ~/ %mul 63 | |: [a=`@`1 b=`@`1] 64 | ^- @ 65 | =+ c=0 66 | |- 67 | ?: =(0 a) c 68 | $(a (dec a), c (add b c)) 69 | :: 70 | ++ div :: divide 71 | ~/ %div 72 | |: [a=`@`1 b=`@`1] 73 | ^- @ 74 | ~_ leaf+"divide-by-zero" 75 | ?< =(0 b) 76 | =+ c=0 77 | |- 78 | ?: (lth a b) c 79 | $(a (sub a b), c +(c)) 80 | :: 81 | ++ dvr :: divide w/remainder 82 | ~/ %dvr 83 | |: [a=`@`1 b=`@`1] 84 | ^- [p=@ q=@] 85 | [(div a b) (mod a b)] 86 | :: 87 | ++ mod :: modulus 88 | ~/ %mod 89 | |: [a=`@`1 b=`@`1] 90 | ^- @ 91 | ?< =(0 b) 92 | (sub a (mul b (div a b))) 93 | :: 94 | ++ bex :: binary exponent 95 | ~/ %bex 96 | |= a=bloq 97 | ^- @ 98 | ?: =(0 a) 1 99 | (mul 2 $(a (dec a))) 100 | :: 101 | ++ lsh :: left-shift 102 | ~/ %lsh 103 | |= [a=bite b=@] 104 | =/ [=bloq =step] ?^(a a [a *step]) 105 | (mul b (bex (mul (bex bloq) step))) 106 | :: 107 | ++ rsh :: right-shift 108 | ~/ %rsh 109 | |= [a=bite b=@] 110 | =/ [=bloq =step] ?^(a a [a *step]) 111 | (div b (bex (mul (bex bloq) step))) 112 | :: 113 | ++ con :: binary or 114 | ~/ %con 115 | |= [a=@ b=@] 116 | =+ [c=0 d=0] 117 | |- ^- @ 118 | ?: ?&(=(0 a) =(0 b)) d 119 | %= $ 120 | a (rsh 0 a) 121 | b (rsh 0 b) 122 | c +(c) 123 | d %+ add d 124 | %+ lsh [0 c] 125 | ?& =(0 (end 0 a)) 126 | =(0 (end 0 b)) 127 | == 128 | == 129 | :: 130 | ++ dis :: binary and 131 | ~/ %dis 132 | |= [a=@ b=@] 133 | =| [c=@ d=@] 134 | |- ^- @ 135 | ?: ?|(=(0 a) =(0 b)) d 136 | %= $ 137 | a (rsh 0 a) 138 | b (rsh 0 b) 139 | c +(c) 140 | d %+ add d 141 | %+ lsh [0 c] 142 | ?| =(0 (end 0 a)) 143 | =(0 (end 0 b)) 144 | == 145 | == 146 | :: 147 | ++ mix :: binary xor 148 | ~/ %mix 149 | |= [a=@ b=@] 150 | ^- @ 151 | =+ [c=0 d=0] 152 | |- 153 | ?: ?&(=(0 a) =(0 b)) d 154 | %= $ 155 | a (rsh 0 a) 156 | b (rsh 0 b) 157 | c +(c) 158 | d (add d (lsh [0 c] =((end 0 a) (end 0 b)))) 159 | == 160 | :: 161 | ++ lth :: less 162 | ~/ %lth 163 | |= [a=@ b=@] 164 | ^- ? 165 | ?& !=(a b) 166 | |- 167 | ?| =(0 a) 168 | ?& !=(0 b) 169 | $(a (dec a), b (dec b)) 170 | == == == 171 | :: 172 | ++ lte :: less or equal 173 | ~/ %lte 174 | |= [a=@ b=@] 175 | |(=(a b) (lth a b)) 176 | :: 177 | ++ gte :: greater or equal 178 | ~/ %gte 179 | |= [a=@ b=@] 180 | ^- ? 181 | !(lth a b) 182 | :: 183 | ++ gth :: greater 184 | ~/ %gth 185 | |= [a=@ b=@] 186 | ^- ? 187 | !(lte a b) 188 | :: 189 | ++ swp :: naive rev bloq order 190 | ~/ %swp 191 | |= [a=bloq b=@] 192 | (rep a (flop (rip a b))) 193 | :: 194 | ++ met :: measure 195 | ~/ %met 196 | |= [a=bloq b=@] 197 | ^- @ 198 | =+ c=0 199 | |- 200 | ?: =(0 b) c 201 | $(b (rsh a b), c +(c)) 202 | :: 203 | ++ end :: tail 204 | ~/ %end 205 | |= [a=bite b=@] 206 | =/ [=bloq =step] ?^(a a [a *step]) 207 | (mod b (bex (mul (bex bloq) step))) 208 | :: 209 | ++ cat :: concatenate 210 | ~/ %cat 211 | |= [a=bloq b=@ c=@] 212 | (add (lsh [a (met a b)] c) b) 213 | :: 214 | ++ cut :: slice 215 | ~/ %cut 216 | |= [a=bloq [b=step c=step] d=@] 217 | (end [a c] (rsh [a b] d)) 218 | :: 219 | ++ can :: assemble 220 | ~/ %can 221 | |= [a=bloq b=(list [p=step q=@])] 222 | ^- @ 223 | ?~ b 0 224 | (add (end [a p.i.b] q.i.b) (lsh [a p.i.b] $(b t.b))) 225 | :: 226 | ++ cad :: assemble specific 227 | ~/ %cad 228 | |= [a=bloq b=(list [p=step q=@])] 229 | ^- [=step @] 230 | :_ (can a b) 231 | |- 232 | ?~ b 233 | 0 234 | (add p.i.b $(b t.b)) 235 | :: 236 | ++ rep :: assemble fixed 237 | ~/ %rep 238 | |= [a=bite b=(list @)] 239 | =/ [=bloq =step] ?^(a a [a *step]) 240 | =| i=@ud 241 | |- ^- @ 242 | ?~ b 0 243 | %+ add $(i +(i), b t.b) 244 | (lsh [bloq (mul step i)] (end [bloq step] i.b)) 245 | :: 246 | ++ rip :: disassemble 247 | ~/ %rip 248 | |= [a=bite b=@] 249 | ^- (list @) 250 | ?: =(0 b) ~ 251 | [(end a b) $(b (rsh a b))] 252 | :: 253 | :: 254 | :: Lists 255 | :: 256 | ++ lent :: length 257 | ~/ %lent 258 | |= a=(list) 259 | ^- @ 260 | =+ b=0 261 | |- 262 | ?~ a b 263 | $(a t.a, b +(b)) 264 | :: 265 | ++ slag :: suffix 266 | ~/ %slag 267 | |* [a=@ b=(list)] 268 | |- ^+ b 269 | ?: =(0 a) b 270 | ?~ b ~ 271 | $(b t.b, a (dec a)) 272 | :: 273 | ++ snag :: index 274 | ~/ %snag 275 | |* [a=@ b=(list)] 276 | |- ^+ ?>(?=(^ b) i.b) 277 | ?~ b 278 | ~_ leaf+"snag-fail" 279 | !! 280 | ?: =(0 a) i.b 281 | $(b t.b, a (dec a)) 282 | :: 283 | ++ homo :: homogenize 284 | |* a=(list) 285 | ^+ =< $ 286 | |@ ++ $ ?:(*? ~ [i=(snag 0 a) t=$]) 287 | -- 288 | a 289 | :: 290 | ++ flop :: reverse 291 | ~/ %flop 292 | |* a=(list) 293 | => .(a (homo a)) 294 | ^+ a 295 | =+ b=`_a`~ 296 | |- 297 | ?~ a b 298 | $(a t.a, b [i.a b]) 299 | :: 300 | ++ welp :: concatenate 301 | ~/ %welp 302 | =| [* *] 303 | |@ 304 | ++ $ 305 | ?~ +<- 306 | +<-(. +<+) 307 | +<-(+ $(+<- +<->)) 308 | -- 309 | :: 310 | ++ reap :: replicate 311 | ~/ %reap 312 | |* [a=@ b=*] 313 | |- ^- (list _b) 314 | ?~ a ~ 315 | [b $(a (dec a))] 316 | :: 317 | :: Modular arithmetic 318 | :: 319 | ++ fe :: modulo bloq 320 | |_ a=bloq 321 | ++ rol |= [b=bloq c=@ d=@] ^- @ :: roll left 322 | =+ e=(sit d) 323 | =+ f=(bex (sub a b)) 324 | =+ g=(mod c f) 325 | (sit (con (lsh [b g] e) (rsh [b (sub f g)] e))) 326 | ++ sum |=([b=@ c=@] (sit (add b c))) :: wrapping add 327 | ++ sit |=(b=@ (end a b)) :: enforce modulo 328 | -- 329 | :: 330 | :: Hashes 331 | :: 332 | ++ muk :: standard murmur3 333 | ~% %muk ..muk ~ 334 | =+ ~(. fe 5) 335 | |= [syd=@ len=@ key=@] 336 | =. syd (end 5 syd) 337 | =/ pad (sub len (met 3 key)) 338 | =/ data (welp (rip 3 key) (reap pad 0)) 339 | =/ nblocks (div len 4) :: intentionally off-by-one 340 | =/ h1 syd 341 | =+ [c1=0xcc9e.2d51 c2=0x1b87.3593] 342 | =/ blocks (rip 5 key) 343 | =/ i nblocks 344 | =. h1 =/ hi h1 |- 345 | ?: =(0 i) hi 346 | =/ k1 (snag (sub nblocks i) blocks) :: negative array index 347 | =. k1 (sit (mul k1 c1)) 348 | =. k1 (rol 0 15 k1) 349 | =. k1 (sit (mul k1 c2)) 350 | =. hi (mix hi k1) 351 | =. hi (rol 0 13 hi) 352 | =. hi (sum (sit (mul hi 5)) 0xe654.6b64) 353 | $(i (dec i)) 354 | =/ tail (slag (mul 4 nblocks) data) 355 | =/ k1 0 356 | =/ tlen (dis len 3) 357 | =. h1 358 | ?+ tlen h1 :: fallthrough switch 359 | %3 =. k1 (mix k1 (lsh [0 16] (snag 2 tail))) 360 | =. k1 (mix k1 (lsh [0 8] (snag 1 tail))) 361 | =. k1 (mix k1 (snag 0 tail)) 362 | =. k1 (sit (mul k1 c1)) 363 | =. k1 (rol 0 15 k1) 364 | =. k1 (sit (mul k1 c2)) 365 | (mix h1 k1) 366 | %2 =. k1 (mix k1 (lsh [0 8] (snag 1 tail))) 367 | =. k1 (mix k1 (snag 0 tail)) 368 | =. k1 (sit (mul k1 c1)) 369 | =. k1 (rol 0 15 k1) 370 | =. k1 (sit (mul k1 c2)) 371 | (mix h1 k1) 372 | %1 =. k1 (mix k1 (snag 0 tail)) 373 | =. k1 (sit (mul k1 c1)) 374 | =. k1 (rol 0 15 k1) 375 | =. k1 (sit (mul k1 c2)) 376 | (mix h1 k1) 377 | == 378 | =. h1 (mix h1 len) 379 | |^ (fmix32 h1) 380 | ++ fmix32 381 | |= h=@ 382 | =. h (mix h (rsh [0 16] h)) 383 | =. h (sit (mul h 0x85eb.ca6b)) 384 | =. h (mix h (rsh [0 13] h)) 385 | =. h (sit (mul h 0xc2b2.ae35)) 386 | =. h (mix h (rsh [0 16] h)) 387 | h 388 | -- 389 | :: 390 | ++ mug :: mug with murmur3 391 | ~/ %mug 392 | |= a=* 393 | |^ ?@ a (mum 0xcafe.babe 0x7fff a) 394 | =/ b (cat 5 $(a -.a) $(a +.a)) 395 | (mum 0xdead.beef 0xfffe b) 396 | :: 397 | ++ mum 398 | |= [syd=@uxF fal=@F key=@] 399 | =/ wyd (met 3 key) 400 | =| i=@ud 401 | |- ^- @F 402 | ?: =(8 i) fal 403 | =/ haz=@F (muk syd wyd key) 404 | =/ ham=@F (mix (rsh [0 31] haz) (end [0 31] haz)) 405 | ?.(=(0 ham) ham $(i +(i), syd +(syd))) 406 | -- 407 | :: 408 | ++ gor :: mug order 409 | ~/ %gor 410 | |= [a=* b=*] 411 | ^- ? 412 | =+ [c=(mug a) d=(mug b)] 413 | ?: =(c d) 414 | (dor a b) 415 | (lth c d) 416 | :: 417 | ++ mor :: more mug order 418 | ~/ %mor 419 | |= [a=* b=*] 420 | ^- ? 421 | =+ [c=(mug (mug a)) d=(mug (mug b))] 422 | ?: =(c d) 423 | (dor a b) 424 | (lth c d) 425 | :: 426 | ++ dor :: tree order 427 | ~/ %dor 428 | |= [a=* b=*] 429 | ^- ? 430 | ?: =(a b) & 431 | ?. ?=(@ a) 432 | ?: ?=(@ b) | 433 | ?: =(-.a -.b) 434 | $(a +.a, b +.b) 435 | $(a -.a, b -.b) 436 | ?. ?=(@ b) & 437 | (lth a b) 438 | :: 439 | ++ por :: parent order 440 | ~/ %por 441 | |= [a=@p b=@p] 442 | ^- ? 443 | ?: =(a b) & 444 | =| i=@ 445 | |- 446 | ?: =(i 2) 447 | :: second two bytes 448 | (lte a b) 449 | :: first two bytes 450 | =+ [c=(end 3 a) d=(end 3 b)] 451 | ?: =(c d) 452 | $(a (rsh 3 a), b (rsh 3 b), i +(i)) 453 | (lth c d) 454 | :: 455 | :: Maps 456 | :: 457 | ++ by 458 | ~/ %by 459 | =| a=(tree (pair)) :: (map) 460 | =* node ?>(?=(^ a) n.a) 461 | |@ 462 | ++ get 463 | ~/ %get 464 | |* b=* 465 | => .(b `_?>(?=(^ a) p.n.a)`b) 466 | |- ^- (unit _?>(?=(^ a) q.n.a)) 467 | ?~ a 468 | ~ 469 | ?: =(b p.n.a) 470 | `q.n.a 471 | ?: (gor b p.n.a) 472 | $(a l.a) 473 | $(a r.a) 474 | :: 475 | ++ put 476 | ~/ %put 477 | |* [b=* c=*] 478 | |- ^+ a 479 | ?~ a 480 | [[b c] ~ ~] 481 | ?: =(b p.n.a) 482 | ?: =(c q.n.a) 483 | a 484 | a(n [b c]) 485 | ?: (gor b p.n.a) 486 | =+ d=$(a l.a) 487 | ?> ?=(^ d) 488 | ?: (mor p.n.a p.n.d) 489 | a(l d) 490 | d(r a(l r.d)) 491 | =+ d=$(a r.a) 492 | ?> ?=(^ d) 493 | ?: (mor p.n.a p.n.d) 494 | a(r d) 495 | d(l a(r l.d)) 496 | :: 497 | ++ del 498 | ~/ %del 499 | |* b=* 500 | |- ^+ a 501 | ?~ a 502 | ~ 503 | ?. =(b p.n.a) 504 | ?: (gor b p.n.a) 505 | a(l $(a l.a)) 506 | a(r $(a r.a)) 507 | |- ^- [$?(~ _a)] 508 | ?~ l.a r.a 509 | ?~ r.a l.a 510 | ?: (mor p.n.l.a p.n.r.a) 511 | l.a(r $(l.a r.l.a)) 512 | r.a(l $(r.a l.r.a)) 513 | :: 514 | ++ apt 515 | =< $ 516 | ~/ %apt 517 | =| [l=(unit) r=(unit)] 518 | |. ^- ? 519 | ?~ a & 520 | ?& ?~(l & &((gor p.n.a u.l) !=(p.n.a u.l))) 521 | ?~(r & &((gor u.r p.n.a) !=(u.r p.n.a))) 522 | ?~ l.a & 523 | &((mor p.n.a p.n.l.a) !=(p.n.a p.n.l.a) $(a l.a, l `p.n.a)) 524 | ?~ r.a & 525 | &((mor p.n.a p.n.r.a) !=(p.n.a p.n.r.a) $(a r.a, r `p.n.a)) 526 | == 527 | -- 528 | :: 529 | ++ on :: ordered map 530 | ~/ %on 531 | |* [key=mold val=mold] 532 | => |% 533 | +$ item [key=key val=val] 534 | -- 535 | :: 536 | ~% %comp +>+ ~ 537 | |= compare=$-([key key] ?) 538 | ~% %core + ~ 539 | |% 540 | :: 541 | ++ apt 542 | ~/ %apt 543 | |= a=(tree item) 544 | =| [l=(unit key) r=(unit key)] 545 | |- ^- ? 546 | ?~ a %.y 547 | ?& ?~(l %.y (compare key.n.a u.l)) 548 | ?~(r %.y (compare u.r key.n.a)) 549 | ?~(l.a %.y &((mor key.n.a key.n.l.a) $(a l.a, l `key.n.a))) 550 | ?~(r.a %.y &((mor key.n.a key.n.r.a) $(a r.a, r `key.n.a))) 551 | == 552 | :: 553 | ++ get 554 | ~/ %get 555 | |= [a=(tree item) b=key] 556 | ^- (unit val) 557 | ?~ a ~ 558 | ?: =(b key.n.a) 559 | `val.n.a 560 | ?: (compare b key.n.a) 561 | $(a l.a) 562 | $(a r.a) 563 | :: 564 | ++ has 565 | ~/ %has 566 | |= [a=(tree item) b=key] 567 | ^- ? 568 | !=(~ (get a b)) 569 | :: 570 | ++ put 571 | ~/ %put 572 | |= [a=(tree item) =key =val] 573 | ^- (tree item) 574 | ?~ a [n=[key val] l=~ r=~] 575 | ?: =(key.n.a key) a(val.n val) 576 | ?: (compare key key.n.a) 577 | =/ l $(a l.a) 578 | ?> ?=(^ l) 579 | ?: (mor key.n.a key.n.l) 580 | a(l l) 581 | l(r a(l r.l)) 582 | =/ r $(a r.a) 583 | ?> ?=(^ r) 584 | ?: (mor key.n.a key.n.r) 585 | a(r r) 586 | r(l a(r l.r)) 587 | -- 588 | :: 589 | :: Sets 590 | :: 591 | ++ in 592 | ~/ %in 593 | =| a=(tree) :: (set) 594 | |@ 595 | ++ put 596 | ~/ %put 597 | |* b=* 598 | |- ^+ a 599 | ?~ a 600 | [b ~ ~] 601 | ?: =(b n.a) 602 | a 603 | ?: (gor b n.a) 604 | =+ c=$(a l.a) 605 | ?> ?=(^ c) 606 | ?: (mor n.a n.c) 607 | a(l c) 608 | c(r a(l r.c)) 609 | =+ c=$(a r.a) 610 | ?> ?=(^ c) 611 | ?: (mor n.a n.c) 612 | a(r c) 613 | c(l a(r l.c)) 614 | :: 615 | ++ del 616 | ~/ %del 617 | |* b=* 618 | |- ^+ a 619 | ?~ a 620 | ~ 621 | ?. =(b n.a) 622 | ?: (gor b n.a) 623 | a(l $(a l.a)) 624 | a(r $(a r.a)) 625 | |- ^- [$?(~ _a)] 626 | ?~ l.a r.a 627 | ?~ r.a l.a 628 | ?: (mor n.l.a n.r.a) 629 | l.a(r $(l.a r.l.a)) 630 | r.a(l $(r.a l.r.a)) 631 | :: 632 | ++ apt 633 | =< $ 634 | ~/ %apt 635 | =| [l=(unit) r=(unit)] 636 | |. ^- ? 637 | ?~ a & 638 | ?& ?~(l & (gor n.a u.l)) 639 | ?~(r & (gor u.r n.a)) 640 | ?~(l.a & ?&((mor n.a n.l.a) $(a l.a, l `n.a))) 641 | ?~(r.a & ?&((mor n.a n.r.a) $(a r.a, r `n.a))) 642 | == 643 | -- 644 | :: 645 | :: Jugs 646 | :: 647 | ++ ju 648 | =| a=(tree (pair * (tree))) :: (jug) 649 | |@ 650 | ++ get 651 | |* b=* 652 | =+ c=(~(get by a) b) 653 | ?~(c ~ u.c) 654 | :: 655 | ++ del 656 | |* [b=* c=*] 657 | ^+ a 658 | =+ d=(get b) 659 | =+ e=(~(del in d) c) 660 | ?~ e 661 | (~(del by a) b) 662 | (~(put by a) b e) 663 | :: 664 | ++ put 665 | |* [b=* c=*] 666 | ^+ a 667 | =+ d=(get b) 668 | (~(put by a) b (~(put in d) c)) 669 | -- 670 | -- 671 | -------------------------------------------------------------------------------- /desk/lib/naive.hoon: -------------------------------------------------------------------------------- 1 | /+ tiny 2 | !. 3 | => => tiny 4 | :: Laconic bit 5 | :: 6 | =| lac=? 7 | :: Constants 8 | :: 9 | |% 10 | :: Transfers on L1 to this address count as depositing to L2 11 | :: 12 | ++ deposit-address 0x1111.1111.1111.1111.1111.1111.1111.1111.1111.1111 13 | ++ log-names 14 | |% 15 | :: Generated with (keccak-256:keccak:crypto (as-octs:mimes:html name)) 16 | :: 17 | :: OwnerChanged(uint32,address) 18 | ++ owner-changed 19 | 0x16d0.f539.d49c.6cad.822b.767a.9445.bfb1. 20 | cf7e.a6f2.a6c2.b120.a7ea.4cc7.660d.8fda 21 | :: 22 | :: Activated(uint32) 23 | ++ activated 24 | 0xe74c.0380.9d07.69e1.b1f7.06cc.8414.258c. 25 | d1f3.b6fe.020c.d15d.0165.c210.ba50.3a0f 26 | :: 27 | :: Spawned(uint32,uint32) 28 | ++ spawned 29 | 0xb2d3.a6e7.a339.f5c8.ff96.265e.2f03.a010. 30 | a854.1070.f374.4a24.7090.9644.1508.1546 31 | :: 32 | :: OwnershipTransferred(address,address) 33 | ++ ownership-transferred 34 | 0x8be0.079c.5316.5914.1344.cd1f.d0a4.f284. 35 | 1949.7f97.22a3.daaf.e3b4.186f.6b64.57e0 36 | :: 37 | :: EscapeRequested(uint32,uint32) 38 | ++ escape-requested 39 | 0xb4d4.850b.8f21.8218.141c.5665.cba3.79e5. 40 | 3e9b.b015.b51e.8d93.4be7.0210.aead.874a 41 | :: 42 | :: EscapeCanceled(uint32,uint32) 43 | ++ escape-canceled 44 | 0xd653.bb0e.0bb7.ce83.93e6.24d9.8fbf.17cd. 45 | a590.2c83.28ed.0cd0.9988.f368.90d9.932a 46 | :: 47 | :: EscapeAccepted(uint32,uint32) 48 | ++ escape-accepted 49 | 0x7e44.7c9b.1bda.4b17.4b07.96e1.00bf.7f34. 50 | ebf3.6dbb.7fe6.6549.0b1b.fce6.246a.9da5 51 | :: 52 | :: LostSponsor(uint32,uint32) 53 | ++ lost-sponsor 54 | 0xd770.4f9a.2519.3dbd.0b0c.b4a8.09fe.ffff. 55 | a7f1.9d1a.ae88.17a7.1346.c194.4482.10d5 56 | :: 57 | :: ChangedKeys(uint32,bytes32,bytes32,uint32,uint32) 58 | ++ changed-keys 59 | 0xaa10.e7a0.117d.4323.f1d9.9d63.0ec1.69be. 60 | bb3a.988e.8957.70e3.5198.7e01.ff54.23d5 61 | :: 62 | :: BrokeContinuity(uint32,uint32) 63 | ++ broke-continuity 64 | 0x2929.4799.f1c2.1a37.ef83.8e15.f79d.d91b. 65 | cee2.df99.d63c.d1c1.8ac9.68b1.2951.4e6e 66 | :: 67 | :: ChangedSpawnProxy(uint32,address) 68 | ++ changed-spawn-proxy 69 | 0x9027.36af.7b3c.efe1.0d9e.840a.ed0d.687e. 70 | 35c8.4095.122b.2505.1a20.ead8.866f.006d 71 | :: 72 | :: ChangedTransferProxy(uint32,address) 73 | ++ changed-transfer-proxy 74 | 0xcfe3.69b7.197e.7f0c.f067.93ae.2472.a9b1. 75 | 3583.fecb.ed2f.78df.a14d.1f10.796b.847c 76 | :: 77 | :: ChangedManagementProxy(uint32,address) 78 | ++ changed-management-proxy 79 | 0xab9c.9327.cffd.2acc.168f.afed.be06.139f. 80 | 5f55.cb84.c761.df05.e051.1c25.1e2e.e9bf 81 | :: 82 | :: ChangedVotingProxy(uint32,address) 83 | ++ changed-voting-proxy 84 | 0xcbd6.269e.c714.57f2.c7b1.a227.74f2.46f6. 85 | c5a2.eae3.795e.d730.0db5.1768.0c61.c805 86 | :: 87 | :: ChangedDns(string,string,string) 88 | ++ changed-dns 89 | 0xfafd.04ad.e1da.ae2e.1fdb.0fc1.cc6a.899f. 90 | d424.063e.d5c9.2120.e67e.0730.53b9.4898 91 | :: 92 | :: ApprovalForAll(address,address,bool) 93 | ++ approval-for-all 94 | 0x1730.7eab.39ab.6107.e889.9845.ad3d.59bd. 95 | 9653.f200.f220.9204.89ca.2b59.3769.6c31 96 | -- 97 | -- => 98 | :: Types 99 | |% 100 | :: ethereum address, 20 bytes. 101 | :: 102 | +$ address @ux 103 | +$ nonce @ud 104 | +$ dominion ?(%l1 %l2 %spawn) 105 | +$ keys [=life suite=@ud auth=@ crypt=@] 106 | ++ orm ((on ship point) por) 107 | ++ point 108 | $: :: domain 109 | :: 110 | =dominion 111 | :: 112 | :: ownership 113 | :: 114 | $= own 115 | $: owner=[=address =nonce] 116 | spawn-proxy=[=address =nonce] 117 | management-proxy=[=address =nonce] 118 | voting-proxy=[=address =nonce] 119 | transfer-proxy=[=address =nonce] 120 | == 121 | :: 122 | :: networking 123 | :: 124 | $= net 125 | $: rift=@ud 126 | =keys 127 | sponsor=[has=? who=@p] 128 | escape=(unit @p) 129 | == 130 | == 131 | :: 132 | ++ diff 133 | $% [%nonce =ship =proxy =nonce] 134 | [%tx =raw-tx err=(unit @tas)] 135 | [%operator owner=address operator=address approved=?] 136 | [%dns domains=(list @t)] 137 | $: %point =ship 138 | $% [%rift =rift] 139 | [%keys =keys] 140 | [%sponsor sponsor=(unit @p)] 141 | [%escape to=(unit @p)] 142 | [%owner =address] 143 | [%spawn-proxy =address] 144 | [%management-proxy =address] 145 | [%voting-proxy =address] 146 | [%transfer-proxy =address] 147 | [%dominion =dominion] 148 | == == == 149 | :: 150 | +$ state 151 | $: %0 152 | =points 153 | =operators 154 | dns=(list @t) 155 | == 156 | +$ points (tree [ship point]) 157 | +$ operators (jug address address) 158 | +$ effects (list diff) 159 | +$ proxy ?(%own %spawn %manage %vote %transfer) 160 | +$ roll (list raw-tx) 161 | +$ raw-tx [sig=@ raw=octs =tx] 162 | +$ tx [from=[=ship =proxy] skim-tx] 163 | +$ skim-tx 164 | $% [%transfer-point =address reset=?] 165 | [%spawn =ship =address] 166 | [%configure-keys encrypt=@ auth=@ crypto-suite=@ breach=?] 167 | [%escape parent=ship] 168 | [%cancel-escape parent=ship] 169 | [%adopt =ship] 170 | [%reject =ship] 171 | [%detach =ship] 172 | [%set-management-proxy =address] 173 | [%set-spawn-proxy =address] 174 | [%set-transfer-proxy =address] 175 | == 176 | :: 177 | +$ event-log 178 | $: address=@ux 179 | data=@ux 180 | topics=(lest @ux) 181 | == 182 | +$ input 183 | $: block=@ud 184 | $% [%bat batch=@] 185 | [%log =event-log] 186 | == == 187 | :: ECDSA verifier. 188 | :: 189 | :: Must keccak `dat` and recover the ethereum address which signed. 190 | :: Must not crash. `v` will normally be between 0 and 3; if it is not, 191 | :: should produce null. 192 | :: 193 | +$ verifier $-([dat=octs v=@ r=@ s=@] (unit address)) 194 | -- => 195 | :: 196 | |% 197 | ++ debug 198 | |* [meg=@t *] 199 | ?: lac 200 | +<+ 201 | ~> %slog.[0 meg] 202 | +<+ 203 | :: 204 | ++ parse-roll 205 | |= batch=@ 206 | =| =roll 207 | =| pos=@ud 208 | =/ las (met 0 batch) 209 | |- ^+ roll 210 | ?: (gte pos las) 211 | (flop roll) 212 | =/ parse-result (parse-raw-tx pos batch) 213 | :: Parsing failed, abort batch 214 | :: 215 | ?~ parse-result 216 | (debug %parse-failed ~) 217 | =^ =raw-tx pos u.parse-result 218 | $(roll [raw-tx roll]) 219 | :: 220 | ++ parse-raw-tx 221 | |= [pos=@ud batch=@] 222 | ^- (unit [raw-tx pos=@ud]) 223 | |^ 224 | =^ sig pos (take 3 65) 225 | =/ res=(unit [=tx pos=@ud]) parse-tx 226 | ?~ res ~ 227 | =/ dif (sub pos.u.res pos) 228 | =/ len =>((dvr dif 8) ?>(=(0 q) p)) 229 | :- ~ :_ pos.u.res 230 | [sig [len (cut 0 [pos dif] batch)] tx.u.res] 231 | :: 232 | ++ parse-tx 233 | ^- (unit [tx pos=@ud]) 234 | =^ from-proxy=@ pos (take 0 3) 235 | ?. ?=(?(%0 %1 %2 %3 %4) from-proxy) (debug %bad-proxy ~) 236 | =/ =proxy 237 | ?- from-proxy 238 | %0 %own 239 | %1 %spawn 240 | %2 %manage 241 | %3 %vote 242 | %4 %transfer 243 | == 244 | =^ pad pos (take 0 5) 245 | =^ from-ship=ship pos (take 3 4) 246 | =- ?~ res 247 | ~ 248 | `[[[from-ship proxy] skim-tx.u.res] pos.u.res] 249 | ^- res=(unit [=skim-tx pos=@ud]) 250 | =^ op pos (take 0 7) 251 | ?+ op (debug %strange-opcode ~) 252 | %0 253 | =^ reset=@ pos (take 0) 254 | =^ =address pos (take 3 20) 255 | `[[%transfer-point address =(0 reset)] pos] 256 | :: 257 | %1 258 | =^ pad=@ pos (take 0) 259 | =^ =ship pos (take 3 4) 260 | =^ =address pos (take 3 20) 261 | `[[%spawn ship address] pos] 262 | :: 263 | %2 264 | =^ breach=@ pos (take 0) 265 | =^ encrypt=@ pos (take 3 32) 266 | =^ auth=@ pos (take 3 32) 267 | =^ crypto-suite=@ pos (take 3 4) 268 | `[[%configure-keys encrypt auth crypto-suite =(0 breach)] pos] 269 | :: 270 | %3 =^(res pos take-ship `[[%escape res] pos]) 271 | %4 =^(res pos take-ship `[[%cancel-escape res] pos]) 272 | %5 =^(res pos take-ship `[[%adopt res] pos]) 273 | %6 =^(res pos take-ship `[[%reject res] pos]) 274 | %7 =^(res pos take-ship `[[%detach res] pos]) 275 | %8 =^(res pos take-address `[[%set-management-proxy res] pos]) 276 | %9 =^(res pos take-address `[[%set-spawn-proxy res] pos]) 277 | %10 =^(res pos take-address `[[%set-transfer-proxy res] pos]) 278 | == 279 | :: 280 | :: Take a bite 281 | :: 282 | ++ take 283 | |= =bite 284 | ^- [@ @ud] 285 | =/ =step 286 | ?@ bite (bex bite) 287 | (mul step.bite (bex bloq.bite)) 288 | [(cut 0 [pos step] batch) (add pos step)] 289 | :: Encode ship and address 290 | :: 291 | ++ take-address 292 | ^- [address @ud] 293 | =^ pad=@ pos (take 0) 294 | =^ =address pos (take 3 20) 295 | [address pos] 296 | :: Encode escape-related txs 297 | :: 298 | ++ take-ship 299 | ^- [ship @ud] 300 | =^ pad=@ pos (take 0) 301 | =^ other=ship pos (take 3 4) 302 | [other pos] 303 | -- 304 | :: 305 | ++ proxy-from-point 306 | |= [=proxy point] 307 | ^- [=address =nonce] 308 | ?- proxy 309 | %own owner.own 310 | %spawn spawn-proxy.own 311 | %manage management-proxy.own 312 | %vote voting-proxy.own 313 | %transfer transfer-proxy.own 314 | == 315 | :: 316 | ++ verify-sig-and-nonce 317 | |= [=verifier chain-t=@t =state =raw-tx] 318 | ^- ? 319 | |^ 320 | =/ point (get-point state ship.from.tx.raw-tx) 321 | ?> ?=(^ point) :: we never parse more than four bytes for a ship 322 | =/ need=[=address =nonce] 323 | (proxy-from-point proxy.from.tx.raw-tx u.point) 324 | :: We include a domain separator to avoid letting signatures be 325 | :: accidentally reused with other applications. We include the name 326 | :: UrbitID, a signature format version number, and the EIP-155 chain 327 | :: ID. 328 | :: 329 | :: We also include a nonce so that a transaction cannot be 330 | :: rebroadcast. 331 | :: 332 | =/ prepared-data=octs 333 | %: cad 3 334 | 14^'UrbitIDV1Chain' 335 | (met 3 chain-t)^chain-t 336 | 1^':' 337 | 4^nonce.need 338 | raw.raw-tx 339 | ~ 340 | == 341 | :: Wallets which support personal_sign include this preamble to avoid 342 | :: letting personal_sign be used to sign ethereum transactions 343 | :: 344 | =/ signed-data=octs 345 | =/ len (ud-to-ascii p.prepared-data) 346 | %: cad 3 347 | 26^'\19Ethereum Signed Message:\0a' 348 | (met 3 len)^len 349 | prepared-data 350 | ~ 351 | == 352 | =/ dress (verify-sig sig.raw-tx signed-data) 353 | ?~ dress 354 | | 355 | =(address.need u.dress) 356 | :: Verify signature and produce signer address 357 | :: 358 | ++ verify-sig 359 | |= [sig=@ txdata=octs] 360 | ^- (unit address) 361 | |^ 362 | :: Reversed of the usual r-s-v order because Ethereum integers are 363 | :: big-endian 364 | :: 365 | =^ v sig (take 3) 366 | =^ s sig (take 3 32) 367 | =^ r sig (take 3 32) 368 | :: In Ethereum, v is generally 27 + recid, and verifier expects a 369 | :: recid. Old versions of geth used 0 + recid, so most software 370 | :: now supports either format. See: 371 | :: 372 | :: https://github.com/ethereum/go-ethereum/issues/2053 373 | :: 374 | =? v (gte v 27) (sub v 27) 375 | (verifier txdata v r s) 376 | :: 377 | ++ take 378 | |= =bite 379 | [(end bite sig) (rsh bite sig)] 380 | -- 381 | -- 382 | :: ASCII-decimal encode 383 | :: 384 | ++ ud-to-ascii 385 | |= n=@ud 386 | ?~ n '0' 387 | =| l=(list @) 388 | |- ^- @t 389 | ?~ n (rep 3 l) 390 | =+ (dvr n 10) 391 | $(n p, l [(add '0' q) l]) 392 | :: 393 | ++ ship-rank 394 | |= =ship 395 | ^- ?(%0 %1 %2 %3 %4) 396 | ?: (lth ship 0x100) %0 397 | ?: (lth ship 0x1.0000) %1 398 | ?: (lth ship 0x1.0000.0000) %2 399 | ?: (lth ship 0x1.0000.0000.0000.0000) %3 400 | %4 401 | :: 402 | ++ sein :: autoboss 403 | |= who=ship 404 | ^- ship 405 | =/ mir (ship-rank who) 406 | ?- mir 407 | %0 who 408 | %1 (end 3 who) 409 | %2 (end 4 who) 410 | %3 (end 5 who) 411 | %4 (end 4 who) 412 | == 413 | :: 414 | :: Produces null only if ship is not a galaxy, star, or planet 415 | :: 416 | ++ get-point 417 | |= [=state =ship] 418 | ^- (unit point) 419 | =/ existing (get:orm points.state ship) 420 | ?^ existing 421 | `u.existing 422 | =| =point 423 | =. who.sponsor.net.point (sein ship) 424 | ?+ (ship-rank ship) (debug %strange-point ~) 425 | %0 `point(dominion %l1) 426 | ?(%1 %2) 427 | =/ existing-parent $(ship (sein ship)) 428 | ?~ existing-parent ~ 429 | :- ~ 430 | %= point 431 | dominion 432 | ?- dominion.u.existing-parent 433 | %l1 %l1 434 | %l2 %l2 435 | %spawn %l2 436 | == 437 | == 438 | == 439 | -- => 440 | |% 441 | :: Receive log from L1 transaction 442 | :: 443 | ++ receive-log 444 | |= [=state log=event-log] 445 | ^- [effects ^state] 446 | =* log-name i.topics.log 447 | ?: =(log-name activated:log-names) `state 448 | ?: =(log-name spawned:log-names) `state 449 | ?: =(log-name ownership-transferred:log-names) `state 450 | ?: =(log-name changed-dns:log-names) 451 | ?> ?=(~ t.topics.log) 452 | =/ words (rip 8 data.log) 453 | :: This is only true if each domain is <= 32 bytes 454 | :: 455 | ?. ?=([c=@ @ b=@ @ a=@ @ @ @ @ ~] words) `state 456 | =* one &5.words 457 | =* two &3.words 458 | =* tri &1.words 459 | =/ domains ~[(swp 3 one) (swp 3 two) (swp 3 tri)] 460 | :- [%dns domains]~ 461 | state(dns domains) 462 | :: 463 | ?: =(log-name approval-for-all:log-names) 464 | ?> ?=([@ @ ~] t.topics.log) 465 | =* owner i.t.topics.log 466 | =* operator i.t.t.topics.log 467 | =/ approved !=(0 data.log) 468 | :- [%operator owner operator approved]~ 469 | =- state(operators -) 470 | ?: approved 471 | (~(put ju operators.state) owner operator) 472 | (~(del ju operators.state) owner operator) 473 | :: 474 | :: The rest of the logs modify a particular ship, specified in the 475 | :: second topic. We fetch it, and insert the modification back into 476 | :: our state. 477 | :: 478 | ?> ?=([@ *] t.topics.log) 479 | =* ship=@ i.t.topics.log 480 | =/ the-point (get-point state ship) 481 | ?> ?=(^ the-point) 482 | =* point u.the-point 483 | :: 484 | :: Important to fully no-op on failure so we don't insert an entry 485 | :: into points.state 486 | :: 487 | =- ?~ res 488 | `state 489 | [effects.u.res state(points (put:orm points.state ship new-point.u.res))] 490 | ^- res=(unit [=effects new-point=^point]) 491 | :: 492 | ?: =(log-name changed-spawn-proxy:log-names) 493 | ?. ?=(%l1 -.point) ~ 494 | ?> ?=([@ ~] t.t.topics.log) 495 | =* to i.t.t.topics.log 496 | :: Depositing to L2 is represented by a spawn proxy change on L1, 497 | :: but it doesn't change the actual spawn proxy. 498 | :: 499 | ?: =(deposit-address to) 500 | :+ ~ [%point ship %dominion %spawn]~ 501 | point(dominion %spawn) 502 | :+ ~ [%point ship %spawn-proxy to]~ 503 | point(address.spawn-proxy.own to) 504 | :: 505 | ?: =(log-name escape-accepted:log-names) 506 | ?> ?=([@ ~] t.t.topics.log) 507 | =* parent=@ i.t.t.topics.log 508 | =/ parent-point (get-point state parent) 509 | ?> ?=(^ parent-point) 510 | ?: ?=(%l2 -.u.parent-point) ~ 511 | :+ ~ [%point ship %sponsor `parent]~ 512 | point(escape.net ~, sponsor.net [%& parent]) 513 | :: 514 | ?: =(log-name lost-sponsor:log-names) 515 | ?> ?=([@ ~] t.t.topics.log) 516 | =* parent=@ i.t.t.topics.log 517 | :: If the sponsor we lost was not our actual sponsor, we didn't 518 | :: actually lose anything. 519 | :: 520 | ?. =(parent who.sponsor.net.point) ~ 521 | :: 522 | =/ parent-point (get-point state parent) 523 | ?> ?=(^ parent-point) 524 | :: 525 | :: We can detach even if the child is on L2, as long as the parent 526 | :: is on L1. 527 | :: 528 | ?: ?=(%l2 -.u.parent-point) ~ 529 | :+ ~ [%point ship %sponsor ~]~ 530 | point(has.sponsor.net %|) 531 | :: 532 | :: The rest can be done by any ship on L1, even if their spawn proxy 533 | :: is set to L2 534 | :: 535 | ?: ?=(%l2 -.point) ~ 536 | :: 537 | ?: =(log-name escape-requested:log-names) 538 | ?> ?=([@ ~] t.t.topics.log) 539 | =* parent=@ i.t.t.topics.log 540 | =/ parent-point (get-point state parent) 541 | ?> ?=(^ parent-point) 542 | :+ ~ [%point ship %escape `parent]~ 543 | point(escape.net `parent) 544 | :: 545 | ?: =(log-name escape-canceled:log-names) 546 | ?> ?=([@ ~] t.t.topics.log) 547 | =* parent=@ i.t.t.topics.log 548 | =/ parent-point (get-point state parent) 549 | ?> ?=(^ parent-point) 550 | :+ ~ [%point ship %escape ~]~ 551 | point(escape.net ~) 552 | :: 553 | ?: =(log-name broke-continuity:log-names) 554 | ?> ?=(~ t.t.topics.log) 555 | =* rift=@ data.log 556 | :+ ~ [%point ship %rift rift]~ 557 | point(rift.net rift) 558 | :: 559 | ?: =(log-name changed-keys:log-names) 560 | ?> ?=(~ t.t.topics.log) 561 | =/ =keys 562 | :* life=(cut 8 [0 1] data.log) 563 | suite=(cut 8 [1 1] data.log) 564 | auth=(cut 8 [2 1] data.log) 565 | crypt=(cut 8 [3 1] data.log) 566 | == 567 | :+ ~ [%point ship %keys keys]~ 568 | point(keys.net keys) 569 | :: 570 | ?: =(log-name owner-changed:log-names) 571 | ?> ?=([@ ~] t.t.topics.log) 572 | =* to i.t.t.topics.log 573 | :: Depositing to L2 is represented by an ownership change on L1, 574 | :: but it doesn't change who actually owns the ship. 575 | :: 576 | ?: =(deposit-address to) 577 | :+ ~ [%point ship %dominion %l2]~ 578 | point(dominion %l2) 579 | :+ ~ [%point ship %owner to]~ 580 | point(address.owner.own to) 581 | :: 582 | ?: =(log-name changed-transfer-proxy:log-names) 583 | ?> ?=([@ ~] t.t.topics.log) 584 | =* to i.t.t.topics.log 585 | :+ ~ [%point ship %transfer-proxy to]~ 586 | point(address.transfer-proxy.own to) 587 | :: 588 | ?: =(log-name changed-management-proxy:log-names) 589 | ?> ?=([@ ~] t.t.topics.log) 590 | =* to i.t.t.topics.log 591 | :+ ~ [%point ship %management-proxy to]~ 592 | point(address.management-proxy.own to) 593 | :: 594 | ?: =(log-name changed-voting-proxy:log-names) 595 | ?> ?=([@ ~] t.t.topics.log) 596 | =* to i.t.t.topics.log 597 | :+ ~ [%point ship %voting-proxy to]~ 598 | point(address.voting-proxy.own to) 599 | :: 600 | (debug %unknown-log ~) 601 | :: 602 | :: Receive batch of L2 transactions 603 | :: 604 | ++ receive-batch 605 | |= [=verifier chain-id=@ud =state batch=@] 606 | =/ chain-t (ud-to-ascii chain-id) 607 | =/ =roll (parse-roll batch) 608 | |- ^- [effects ^state] 609 | ?~ roll 610 | [~ state] 611 | :: Verify signature, else skip tx 612 | :: 613 | ?. (verify-sig-and-nonce verifier chain-t state i.roll) 614 | %+ debug %l2-sig-failed 615 | =^ effects state $(roll t.roll) 616 | :_ state 617 | [[%tx i.roll `%sig-or-nonce-failed] effects] 618 | :: Increment nonce, even if it later fails 619 | :: 620 | =^ effects-1 points.state (increment-nonce state from.tx.i.roll) 621 | :: Process tx 622 | :: 623 | =^ effects-2 state 624 | =/ tx-result=(unit [=effects =^state]) (receive-tx state tx.i.roll) 625 | ?~ tx-result 626 | %+ debug %l2-tx-failed 627 | [[%tx i.roll `%tx-failed]~ state] 628 | [[[%tx i.roll ~] effects.u.tx-result] state.u.tx-result] 629 | =^ effects-3 state $(roll t.roll) 630 | [:(welp effects-1 effects-2 effects-3) state] 631 | :: 632 | ++ increment-nonce 633 | |= [=state =ship =proxy] 634 | =/ point (get-point state ship) 635 | ?> ?=(^ point) :: we only parsed 4 bytes 636 | =* own own.u.point 637 | =^ nonce u.point 638 | ?- proxy 639 | %own 640 | :- nonce.owner.own 641 | u.point(nonce.owner.own +(nonce.owner.own)) 642 | :: 643 | %spawn 644 | :- nonce.spawn-proxy.own 645 | u.point(nonce.spawn-proxy.own +(nonce.spawn-proxy.own)) 646 | :: 647 | %manage 648 | :- nonce.management-proxy.own 649 | u.point(nonce.management-proxy.own +(nonce.management-proxy.own)) 650 | :: 651 | %vote 652 | :- nonce.voting-proxy.own 653 | u.point(nonce.voting-proxy.own +(nonce.voting-proxy.own)) 654 | :: 655 | %transfer 656 | :- nonce.transfer-proxy.own 657 | u.point(nonce.transfer-proxy.own +(nonce.transfer-proxy.own)) 658 | == 659 | :: 660 | :- [%nonce ship proxy nonce]~ 661 | (put:orm points.state ship u.point) 662 | :: 663 | :: Receive an individual L2 transaction 664 | :: 665 | ++ receive-tx 666 | |= [=state =tx] 667 | |^ 668 | ^- (unit [effects ^state]) 669 | ?- +<.tx 670 | %spawn (process-spawn +>.tx) 671 | %transfer-point (w-point process-transfer-point ship.from.tx +>.tx) 672 | %configure-keys (w-point process-configure-keys ship.from.tx +>.tx) 673 | %escape (w-point-esc process-escape ship.from.tx +>.tx) 674 | %cancel-escape (w-point-esc process-cancel-escape ship.from.tx +>.tx) 675 | %adopt (w-point-esc process-adopt ship.tx +>.tx) 676 | %reject (w-point-esc process-reject ship.tx +>.tx) 677 | %detach (w-point-esc process-detach ship.tx +>.tx) 678 | %set-spawn-proxy 679 | (w-point-spawn process-set-spawn-proxy ship.from.tx +>.tx) 680 | :: 681 | %set-transfer-proxy 682 | (w-point process-set-transfer-proxy ship.from.tx +>.tx) 683 | :: 684 | %set-management-proxy 685 | (w-point process-set-management-proxy ship.from.tx +>.tx) 686 | == 687 | :: 688 | ++ w-point 689 | |* [fun=$-([ship point *] (unit [effects point])) =ship rest=*] 690 | ^- (unit [effects ^state]) 691 | =/ point (get-point state ship) 692 | ?~ point (debug %strange-ship ~) 693 | ?. ?=(%l2 -.u.point) (debug %ship-not-on-l2 ~) 694 | :: Important to fully no-op on failure so we don't insert an entry 695 | :: into points.state 696 | :: 697 | =/ res=(unit [=effects new-point=^point]) (fun u.point rest) 698 | ?~ res 699 | ~ 700 | `[effects.u.res state(points (put:orm points.state ship new-point.u.res))] 701 | :: 702 | ++ w-point-esc 703 | |* [fun=$-([ship point *] (unit [effects point])) =ship rest=*] 704 | ^- (unit [effects ^state]) 705 | =/ point (get-point state ship) 706 | ?~ point (debug %strange-ship ~) 707 | =/ res=(unit [=effects new-point=^point]) (fun u.point rest) 708 | ?~ res 709 | ~ 710 | `[effects.u.res state(points (put:orm points.state ship new-point.u.res))] 711 | :: 712 | ++ w-point-spawn 713 | |* [fun=$-([ship point *] (unit [effects point])) =ship rest=*] 714 | ^- (unit [effects ^state]) 715 | =/ point (get-point state ship) 716 | ?~ point (debug %strange-ship ~) 717 | ?: ?=(%l1 -.u.point) (debug %ship-on-l2 ~) 718 | =/ res=(unit [=effects new-point=^point]) (fun u.point rest) 719 | ?~ res 720 | ~ 721 | `[effects.u.res state(points (put:orm points.state ship new-point.u.res))] 722 | :: 723 | ++ process-transfer-point 724 | |= [=point to=address reset=?] 725 | =* ship ship.from.tx 726 | :: Assert from owner or transfer prxoy 727 | :: 728 | ?. |(=(%own proxy.from.tx) =(%transfer proxy.from.tx)) 729 | (debug %bad-permission ~) 730 | :: Execute transfer 731 | :: 732 | =/ effects-1 733 | ~[[%point ship %owner to] [%point ship %transfer-proxy *address]] 734 | =: address.owner.own.point to 735 | address.transfer-proxy.own.point *address 736 | == 737 | :: Execute reset if requested 738 | :: 739 | ?. reset 740 | `[effects-1 point] 741 | :: 742 | =^ effects-2 net.point 743 | ?: =([0 0 0] +.keys.net.point) 744 | `net.point 745 | =/ =keys [+(life.keys.net.point) 0 0 0] 746 | :- [%point ship %keys keys]~ 747 | [rift.net.point keys sponsor.net.point escape.net.point] 748 | =^ effects-3 rift.net.point 749 | ?: =(0 life.keys.net.point) 750 | `rift.net.point 751 | :- [%point ship %rift +(rift.net.point)]~ 752 | +(rift.net.point) 753 | =/ effects-4 754 | :~ [%point ship %spawn-proxy *address] 755 | [%point ship %management-proxy *address] 756 | [%point ship %voting-proxy *address] 757 | [%point ship %transfer-proxy *address] 758 | == 759 | =: address.spawn-proxy.own.point *address 760 | address.management-proxy.own.point *address 761 | address.voting-proxy.own.point *address 762 | address.transfer-proxy.own.point *address 763 | == 764 | `[:(welp effects-1 effects-2 effects-3 effects-4) point] 765 | :: 766 | ++ process-spawn 767 | |= [=ship to=address] 768 | ^- (unit [effects ^state]) 769 | =/ parent=^ship (sein ship) 770 | :: Assert parent is on L2 771 | :: 772 | =/ parent-point (get-point state parent) 773 | ?~ parent-point ~ 774 | ?. ?=(?(%l2 %spawn) -.u.parent-point) ~ 775 | :: Assert from owner or spawn proxy 776 | :: 777 | ?. ?& =(parent ship.from.tx) 778 | |(=(%own proxy.from.tx) =(%spawn proxy.from.tx)) 779 | == 780 | (debug %bad-permission ~) 781 | :: Assert child not already spawned 782 | :: 783 | ?^ (get:orm points.state ship) (debug %spawn-exists ~) 784 | :: Assert one-level-down 785 | :: 786 | ?. =(+((ship-rank parent)) (ship-rank ship)) (debug %bad-rank ~) 787 | :: 788 | =/ [=effects new-point=point] 789 | =/ point=(unit point) (get-point state ship) 790 | ?> ?=(^ point) :: only parsed 4 bytes 791 | :: If spawning to self, just do it 792 | :: 793 | ?: ?| ?& =(%own proxy.from.tx) 794 | =(to address.owner.own.u.parent-point) 795 | == 796 | ?& =(%spawn proxy.from.tx) 797 | =(to address.spawn-proxy.own.u.parent-point) 798 | == 799 | == 800 | :- ~[[%point ship %dominion %l2] [%point ship %owner to]] 801 | u.point(address.owner.own to) 802 | :: Else spawn to parent and set transfer proxy 803 | :: 804 | :- :~ [%point ship %dominion %l2] 805 | [%point ship %owner address.owner.own.u.parent-point] 806 | [%point ship %transfer-proxy to] 807 | == 808 | %= u.point 809 | address.owner.own address.owner.own.u.parent-point 810 | address.transfer-proxy.own to 811 | == 812 | `[effects state(points (put:orm points.state ship new-point))] 813 | :: 814 | ++ process-configure-keys 815 | |= [=point crypt=@ auth=@ suite=@ breach=?] 816 | =* ship ship.from.tx 817 | :: 818 | ?. |(=(%own proxy.from.tx) =(%manage proxy.from.tx)) 819 | (debug %bad-permission ~) 820 | :: 821 | =^ rift-effects rift.net.point 822 | ?. breach 823 | `rift.net.point 824 | [[%point ship %rift +(rift.net.point)]~ +(rift.net.point)] 825 | :: 826 | =^ keys-effects keys.net.point 827 | ?: =(+.keys.net.point [suite auth crypt]) 828 | `keys.net.point 829 | =/ =keys 830 | [+(life.keys.net.point) suite auth crypt] 831 | [[%point ship %keys keys]~ keys] 832 | :: 833 | `[(welp rift-effects keys-effects) point] 834 | :: 835 | ++ process-escape 836 | |= [=point parent=ship] 837 | =* ship ship.from.tx 838 | ?. |(=(%own proxy.from.tx) =(%manage proxy.from.tx)) 839 | (debug %bad-permission ~) 840 | :: 841 | ?. =(+((ship-rank parent)) (ship-rank ship)) 842 | (debug %bad-rank ~) 843 | :: 844 | :+ ~ [%point ship %escape `parent]~ 845 | point(escape.net `parent) 846 | :: 847 | ++ process-cancel-escape 848 | |= [=point parent=ship] 849 | =* ship ship.from.tx 850 | ?. |(=(%own proxy.from.tx) =(%manage proxy.from.tx)) 851 | (debug %bad-permission ~) 852 | :: 853 | :+ ~ [%point ship %escape ~]~ 854 | point(escape.net ~) 855 | :: 856 | ++ process-adopt 857 | |= [=point =ship] 858 | =* parent ship.from.tx 859 | ?. |(=(%own proxy.from.tx) =(%manage proxy.from.tx)) 860 | (debug %bad-permission ~) 861 | :: 862 | ?. =(escape.net.point `parent) (debug %no-adopt ~) 863 | :+ ~ [%point ship %sponsor `parent]~ 864 | point(escape.net ~, sponsor.net [%& parent]) 865 | :: 866 | ++ process-reject 867 | |= [=point =ship] 868 | =* parent ship.from.tx 869 | ?. |(=(%own proxy.from.tx) =(%manage proxy.from.tx)) 870 | (debug %bad-permission ~) 871 | :: 872 | ?. =(escape.net.point `parent) (debug %no-reject ~) 873 | :+ ~ [%point ship %escape ~]~ 874 | point(escape.net ~) 875 | :: 876 | ++ process-detach 877 | |= [=point =ship] 878 | =* parent ship.from.tx 879 | ?. |(=(%own proxy.from.tx) =(%manage proxy.from.tx)) 880 | (debug %bad-permission ~) 881 | :: 882 | ?. =(who.sponsor.net.point parent) (debug %no-detach ~) 883 | :+ ~ [%point ship %sponsor ~]~ 884 | point(has.sponsor.net %|) 885 | :: 886 | ++ process-set-management-proxy 887 | |= [=point =address] 888 | ?. |(=(%own proxy.from.tx) =(%manage proxy.from.tx)) 889 | (debug %bad-permission ~) 890 | :: 891 | :+ ~ [%point ship.from.tx %management-proxy address]~ 892 | point(address.management-proxy.own address) 893 | :: 894 | ++ process-set-spawn-proxy 895 | |= [=point =address] 896 | ?. |(=(%own proxy.from.tx) =(%spawn proxy.from.tx)) 897 | (debug %bad-permission ~) 898 | :: 899 | ?: (gte (ship-rank ship.from.tx) 2) 900 | (debug %spawn-proxy-planet ~) 901 | :: 902 | :+ ~ [%point ship.from.tx %spawn-proxy address]~ 903 | point(address.spawn-proxy.own address) 904 | :: 905 | ++ process-set-transfer-proxy 906 | |= [=point =address] 907 | ?. |(=(%own proxy.from.tx) =(%transfer proxy.from.tx)) 908 | (debug %bad-permission ~) 909 | :: 910 | :+ ~ [%point ship.from.tx %transfer-proxy address]~ 911 | point(address.transfer-proxy.own address) 912 | -- 913 | -- 914 | :: 915 | :: State transition function 916 | :: 917 | |= [=verifier chain-id=@ud =state =input] 918 | ^- [effects ^state] 919 | ?: ?=(%log +<.input) 920 | :: Received log from L1 transaction 921 | :: 922 | (receive-log state event-log.input) 923 | :: Received L2 batch 924 | :: 925 | :: %+ debug %batch 926 | (receive-batch verifier chain-id state batch.input) 927 | --------------------------------------------------------------------------------