on main help sign in
270 files changed+29093−650
since splitsnapshots
unifiedsplit
.gitignore+2 .vscode/settings.json+58 .vscode/tasks.json+13 README.md+47−21 base-desk/lib/agentio.hoon+137 base-desk/lib/azimuth.hoon+466 base-desk/lib/azimuthio.hoon+146 base-desk/lib/bip/b158.hoon+249 base-desk/lib/bip/b173.hoon+144 base-desk/lib/bip/b174.hoon+184 base-desk/lib/bip32.hoon+243 base-desk/lib/bip39.hoon+46 base-desk/lib/bip39/english.hoon+2052 base-desk/lib/bitcoin-utils.hoon+177 base-desk/lib/cram.hoon+61 base-desk/lib/dbug.hoon+161 base-desk/lib/default-agent.hoon+69 base-desk/lib/der.hoon+210 base-desk/lib/dill.hoon+94 base-desk/lib/docket.hoon+223 base-desk/lib/ethereum.hoon+1006 base-desk/lib/ethio.hoon+289 base-desk/lib/hark-store.hoon+255 base-desk/lib/jose.hoon+222 base-desk/lib/keygen.hoon+112 base-desk/lib/language-server/build.hoon+61 base-desk/lib/language-server/complete.hoon+387 base-desk/lib/language-server/easy-print.hoon+484 base-desk/lib/language-server/json.hoon+301 base-desk/lib/language-server/parser.hoon+72 base-desk/lib/language-server/rune-snippet.hoon+532 base-desk/lib/mip.hoon+55 base-desk/lib/naive.hoon+926 base-desk/lib/noun-diff.hoon+213 base-desk/lib/ph/io.hoon+531 base-desk/lib/ph/util.hoon+125 base-desk/lib/pill.hoon+620 base-desk/lib/pkcs.hoon+378 base-desk/lib/primitive-rsa.hoon+84 base-desk/lib/ring.hoon+478 base-desk/lib/server.hoon+159 base-desk/lib/shoe.hoon+568 base-desk/lib/sink.hoon+26 base-desk/lib/skeleton.hoon+51 base-desk/lib/sole.hoon+163 base-desk/lib/sss.hoon+445 base-desk/lib/story.hoon+88 base-desk/lib/strand.hoon+1 base-desk/lib/strandio.hoon+918 base-desk/lib/test.hoon+103 base-desk/lib/tiny.hoon+670 base-desk/lib/verb.hoon+182 base-desk/mar/atom.hoon+18 base-desk/mar/belt.hoon+20 base-desk/mar/bill.hoon+34 base-desk/mar/blit.hoon+20 base-desk/mar/css.hoon+25 base-desk/mar/docket-0.hoon+25 base-desk/mar/hoon.hoon+303 base-desk/mar/htm.hoon+6 base-desk/mar/html.hoon+22 base-desk/mar/httr.hoon+24 base-desk/mar/hymn.hoon+17 base-desk/mar/js.hoon+25 base-desk/mar/json.hoon+26 base-desk/mar/json/rpc/response.hoon+42 base-desk/mar/kelvin.hoon+28 base-desk/mar/language-server/rpc/notification.hoon+18 base-desk/mar/language-server/rpc/request.hoon+16 base-desk/mar/language-server/rpc/response.hoon+17 base-desk/mar/mime.hoon+32 base-desk/mar/noun.hoon+22 base-desk/mar/path.hoon+11 base-desk/mar/png.hoon+12 base-desk/mar/purl.hoon+18 base-desk/mar/ship.hoon+20 base-desk/mar/sole/action.hoon+52 base-desk/mar/sole/effect.hoon+82 base-desk/mar/story-diff.hoon+16 base-desk/mar/story.hoon+65 base-desk/mar/svg.hoon+12 base-desk/mar/tang.hoon+30 base-desk/mar/tape.hoon+12 base-desk/mar/thread-done.hoon+11 base-desk/mar/thread-fail.hoon+11 base-desk/mar/txt-diff.hoon+16 base-desk/mar/txt.hoon+274 base-desk/mar/udon.hoon+27 base-desk/mar/umd.hoon+28 base-desk/mar/urb.hoon+18 base-desk/mar/urbit.hoon+17 base-desk/mar/woff2.hoon+12 base-desk/mar/xml.hoon+21 base-desk/sources.txt+3 base-desk/sur/aquarium.hoon+89 base-desk/sur/asn1.hoon+80 base-desk/sur/bitcoin.hoon+84 base-desk/sur/docket.hoon+82 base-desk/sur/hark-store.hoon+159 base-desk/sur/hood.hoon+401 base-desk/sur/json/rpc.hoon+28 base-desk/sur/keygen.hoon+23 base-desk/sur/language-server.hoon+114 base-desk/sur/ring.hoon+47 base-desk/sur/settings.hoon+44 base-desk/sur/sole.hoon+88 base-desk/sur/spider.hoon+27 base-desk/sur/sss.hoon+39 base-desk/sur/story.hoon+9 base-desk/sur/verb.hoon+48 bin/commit.sh+24 bin/get_glob.sh+19 bin/install.sh+82 bin/make_glob.py+208 config/ignore_files_on_install.txt+4 desk/app/astrolabe.hoon+345 desk/desk.bill+2−1 desk/desk.docket-0+6−5 desk/desk.seal+7 desk/doc.toc+15 desk/doc/overview.udon+26 desk/doc/usr/astrolabe.udon+107 desk/doc/usr/azimuth.udon+51 desk/doc/usr/comet.udon+10 desk/doc/usr/galaxy.udon+36 desk/doc/usr/keys.udon+63 desk/doc/usr/l2.udon+60 desk/doc/usr/moon.udon+8 desk/doc/usr/patpee.udon+104 desk/doc/usr/phonemes.udon+45 desk/doc/usr/planet.udon+9 desk/doc/usr/sigil-input.udon+27 desk/doc/usr/sigil.udon+22 desk/doc/usr/star.udon+21 desk/doc/usr/test.udon+24 desk/doc/usr/urbit-id.udon+118 desk/lib/astrolabe.hoon+234 desk/lib/search.hoon+373 desk/lib/state.hoon+21 desk/mar/astrolabe/point-set.hoon+13 desk/mar/astrolabe/point.hoon+14 desk/mar/ico.hoon+12 desk/mar/seal.hoon+12 desk/mar/webmanifest.hoon+12 desk/sur/astrolabe.hoon+58 desk/sys.kelvin+1−1 desk/tests/lib/state.hoon+59 docs-dev-desk/lib/docs.hoon+205 docs-dev-desk/lib/gemtext.hoon+190 docs-dev-desk/mar/clue.hoon+28 docs-dev-desk/mar/docu.hoon+23 docs-dev-desk/mar/elem.hoon+18 docs-dev-desk/mar/gmi-diff.hoon+13 docs-dev-desk/mar/gmi.hoon+37 docs-dev-desk/mar/toc.hoon+16 docs-dev-desk/mar/x-htm.hoon+12 docs-dev-desk/sur/docs.hoon+9 docs-dev-desk/sur/gemtext.hoon+10 flake.lock+27 flake.nix+73 install.sh−39 ui/.env+3 ui/.env.local−2 ui/index.html+7−3 ui/package-lock.json+401−55 ui/package.json+28−7 ui/public/android-chrome-192x192.png ui/public/android-chrome-512x512.png ui/public/apple-touch-icon.png ui/public/favicon-16x16.png ui/public/favicon-32x32.png ui/public/favicon.ico ui/public/sigil-example.png ui/public/site.webmanifest+1 ui/scraps/tirrel-graph-main.js+198 ui/src/App.svelte+63−13 ui/src/actions/docLinks.ts+26 ui/src/actions/symbolPartClick.ts+27 ui/src/actions/tooltip.ts+73 ui/src/assets/astrolabe-tile.svg+23 ui/src/assets/astrolabe.svg+206 ui/src/assets/up-arrow.svg+1 ui/src/assets/x.svg+1 ui/src/components/CollapsibleContent.svelte+18 ui/src/components/ExtensionWindow.svelte+25 ui/src/components/HomeScreenTiles.svelte+42 ui/src/components/SearchBar.svelte−35 ui/src/components/SearchResults.svelte−63 ui/src/components/ShipListing.svelte+37−11 ui/src/components/ShipListings.svelte+19 ui/src/components/ShipView.svelte−58 ui/src/components/Sigil.svelte−36 ui/src/components/StarChart.svelte+233 ui/src/components/ValidationProblems.svelte+6−2 ui/src/components/buttons/CloseButton.svelte+4 ui/src/components/buttons/Hamburger.svelte+5 ui/src/components/buttons/InlineSelect.svelte+16 ui/src/components/buttons/ToggleButton.svelte+11 ui/src/components/common/ChartLink.svelte+11 ui/src/components/common/EthAddressLink.svelte+37 ui/src/components/common/GoldBadge.svelte+10 ui/src/components/common/Legil.svelte+47 ui/src/components/common/LoadingSpinner.svelte+8 ui/src/components/common/ShipLink.svelte+10 ui/src/components/common/Sigil.svelte+65 ui/src/components/common/Tooltip.svelte+37 ui/src/components/common/TooltipAndDocLink.svelte+14 ui/src/components/docs/Doc.svelte+50 ui/src/components/docs/DocContent.svelte+37 ui/src/components/docs/DocHome.svelte+76 ui/src/components/docs/DocLink.svelte+26 ui/src/components/docs/HelpModal.svelte+25 ui/src/components/extensions/AppIcon.svelte+61 ui/src/components/extensions/AppsShipViewExtension.svelte+56 ui/src/components/extensions/GroupsShipViewExtension.svelte+15 ui/src/components/extensions/ProfileShipViewExtension.svelte+52 ui/src/components/pals/PalStatusIndicator.svelte+191 ui/src/components/pals/PalTagger.svelte+40 ui/src/components/pals/PalsShipViewExtension.svelte+34 ui/src/components/search/SearchBar.svelte+152 ui/src/components/SearchResultNavButtons.svelte → ui/src/components/search/SearchResultNavButtons.svelte ui/src/components/search/SearchResults.svelte+147 ui/src/components/search/SearchResultsNavButtons.svelte+54 ui/src/components/search/SearchSettings.svelte+25 ui/src/components/search/sigil/ClanSelect.svelte+44 ui/src/components/search/sigil/ClanSelectOption.svelte+17 ui/src/components/search/sigil/GeonSelector.svelte+30 ui/src/components/search/sigil/MiniFakeSigil.svelte+25 ui/src/components/search/sigil/SigilInput.svelte+104 ui/src/components/search/sigil/Symbol.svelte+79 ui/src/components/search/sigil/SymbolInput.svelte+105 ui/src/components/search/sigil/SymbolInputModeSelector.svelte+168 ui/src/components/search/sigil/SymbolInputModeSelectorButton.svelte+33 ui/src/components/search/sigil/SymbolInputNavButtons.svelte+30 ui/src/components/ship_view/AzimuthDetails.svelte+90 ui/src/components/ship_view/ShipChain.svelte+11 ui/src/components/ship_view/ShipChildrenTabs.svelte+136 ui/src/components/ship_view/ShipView.svelte+130 ui/src/fake_data/fake-contacts.ts+6−1 ui/src/lib/api.ts+102 ui/src/lib/apps.ts+177 ui/src/lib/colors.ts+17 ui/src/lib/graph.ts+422 ui/src/lib/id.ts+430−147 ui/src/lib/link.ts+15−2 ui/src/lib/pals.ts+91 ui/src/lib/ship.ts+114 ui/src/lib/sigil.ts+387 ui/src/lib/utils.ts+58−4 ui/src/main.ts+5−2 ui/src/routes/HelpPage.svelte+26 ui/src/routes/Home.svelte+191−7 ui/src/routes/ShipViewPage.svelte−26 ui/src/routes/SigilPage.svelte+61 ui/src/stores/docs.ts+44 ui/src/stores/keys.ts+68 ui/src/stores/pageName.ts+12 ui/src/stores/searchStores.ts+66 ui/src/stores/store.ts+66−24 ui/src/styles/docs.scss+49 ui/src/styles/styles.scss+13 ui/src/styles/tailwind-output.css+1556−74 ui/src/styles/tippy.css+5 ui/src/types/id.ts+1 ui/src/types/sigil.ts+148 ui/src/types/store.ts+66−4 ui/svelte.config.js+2−2 ui/tailwind.config.cjs+38−3 ui/tsconfig.json+9 ui/vite.config.ts+22−2
.gitignore+2
@@ -1,2 +1,4 @@
11# OS X
22.DS_Store
3+extras
4+globs
.vscode/settings.jsonnew file+58
@@ -0,0 +1,58 @@
1+{
2+ "saveEditorLayout.list": [
3+ {
4+ "name": "gall agent",
5+ "orientation": 0,
6+ "documents": [
7+ {
8+ "fsPath": "/Users/john/ws/urbit-apps/astrolabe/desk/sur/astrolabe.hoon",
9+ "column": 1
10+ },
11+ {
12+ "fsPath": "/Users/john/ws/urbit-apps/astrolabe/desk/app/astrolabe.hoon",
13+ "column": 1
14+ },
15+ {
16+ "fsPath": "/Users/john/ws/urbit-apps/astrolabe/extras/scraps/json-lib.hoon",
17+ "column": 2
18+ },
19+ {
20+ "fsPath": "/Users/john/ws/urbit-apps/astrolabe/base-desk/lib/naive.hoon",
21+ "column": 3
22+ },
23+ {
24+ "fsPath": "/Users/john/ws/urbit-apps/astrolabe/extras/scraps/scry thoughts.txt",
25+ "column": 3
26+ },
27+ {
28+ "fsPath": "/Users/john/ws/urbit-apps/astrolabe/desk/mar/astrolabe/point.hoon",
29+ "column": 4
30+ },
31+ {
32+ "fsPath": "/Users/john/ws/urbit-apps/astrolabe/install.sh",
33+ "column": 5
34+ },
35+ {
36+ "fsPath": "/Users/john/ws/urbit-apps/astrolabe/desk/lib/astrolabe.hoon",
37+ "column": 5
38+ }
39+ ]
40+ },
41+ {
42+ "name": "ui",
43+ "orientation": 0,
44+ "documents": [
45+ {
46+ "fsPath": "/Users/john/ws/urbit-apps/astrolabe/ui/src/components/ShipView.svelte",
47+ "column": 1
48+ }
49+ ]
50+ }
51+ ],
52+ "grammarly.selectors": [
53+ {
54+ "language": "markdown",
55+ "scheme": "file"
56+ }
57+ ]
58+}
.vscode/tasks.jsonnew file+13
@@ -0,0 +1,13 @@
1+{
2+ "version": "2.0.0",
3+ "tasks": [
4+ {
5+ "type": "npm",
6+ "script": "install:desk",
7+ "path": "ui",
8+ "problemMatcher": [],
9+ "label": "npm: install:desk - ui",
10+ "detail": "dotenv -c local npm run _install:desk"
11+ }
12+ ]
13+}
README.md+47−21
@@ -21,30 +21,56 @@ Astrolabe is built primarily using [Svelte], [Typescript], and [Tailwind CSS]. [
2121
2222To get started using Astrolabe first you need to run `npm install` inside the `ui` directory.
2323
24−To develop you'll need a running ship to point to. To do so you first need to add a `.env.local` file to the `ui` directory. This file will not be committed. Adding `VITE_SHIP_URL={URL}` where **{URL}** is the URL of the ship you would like to point to, will allow you to run `npm run dev`. This will proxy all requests to the ship except for those powering the interface, allowing you to see live data.
24+To develop you'll need a running ship to point to. If it's running somewhere other than `http://localhost:8081`, make a copy of `.env` in the `ui` directory and name it `.env.local`. This file will not be committed. Change `VITE_SHIP_URL` to the URL of the ship you would like to point to.
2525
26−Regardless of what you run to develop, Vite will hot-reload code changes as you work so you don't have to constantly refresh.
27−
28−### Deploying
29−
30−To deploy, run `npm run build` in the `ui` directory which will bundle all the code and assets into the `dist/` folder. This can then be made into a glob by doing the following:
26+Once your URL is correctly configured, you can run `npm run dev`. This will proxy all requests to the ship except for those powering the interface, allowing you to see live data.
3127
32−1. Create or launch an urbit using the -F flag
33−2. On that urbit, if you don't already have a desk to run from, run `|merge %work our %base` to create a new desk and mount it with `|mount %work`.
34−3. Now the `%work` desk is accessible through the host OS's filesystem as a directory of that urbit's pier ie `~/zod/work`.
35−4. From the `ui` directory you can run `rsync -avL --delete dist/ ~/zod/work/astrolabe` where `~/zod` is your fake urbit's pier.
36−5. Once completed you can then run `|commit %work` on your urbit and you should see your files logged back out from the dojo.
37−6. Now run `=dir /=garden` to switch to the garden desk directory
38−7. You can now run `-make-glob %work /astrolabe` which will take the folder where you just added files and create a glob which can be thought of as a sort of bundle. It will be output to `~/zod/.urb/put`.
39−8. If you navigate to `~/zod/.urb/put` you should see a file that looks like this `glob-0v5.fdf99.nph65.qecq3.ncpjn.q13mb.glob`. The characters between `glob-` and `.glob` are a hash of the glob's contents.
40−9. Now that we have the glob it can be uploaded to any publicly available HTTP endpoint that can serve files. This allows the glob to distributed over HTTP.
41−10. Once you've uploaded the glob, you should then update the corresponding entry in the docket file at `desk/desk.docket-0`. Both the full URL and the hash should be updated to match the glob we just created, on the line that looks like this:
42−
43−```hoon
44− glob-http+['https://bootstrap.urbit.org/glob-0v5.fdf99.nph65.qecq3.ncpjn.q13mb.glob' 0v5.fdf99.nph65.qecq3.ncpjn.q13mb]
45−```
28+Regardless of what you run to develop, Vite will hot-reload code changes as you work so you don't have to constantly refresh.
4629
47−11. This can now be safely committed and deployed.
30+# Deploying
31+
32+1. Spin up a comet or distribution ship.
33+2. Mount an `%astrolabe` desk. In Dojo:
34+ 1. `|merge %astrolabe our %base` to create a new desk.
35+ 2. `|mount %astrolabe` to mount it.
36+ 3. Set `ASTROLABE_DESK` in `.env.local` if the path to your desk is different.
37+3. Create and upload `glob-http`, if applicable (see below)
38+4. Bump the `version` in `desk.docket-0`.
39+3. Install the desk
40+ 1. From the `ui` folder: `npm run install:desk`
41+ 2. (first time only, on dev ship): `|install our %astrolabe`
42+ 2. From the distribution ship's dojo: `:treaty|unpublish %astrolabe`
43+ 2. From middleman or distribution ship's dojo: `|commit %astrolabe`
44+ 3. (if using a comet as a middleman) `|public %astrolabe`
45+ 4. (if using a comet as a middleman) from the actual distribution ship: `|install ~comet-name %astrolabe` or `|resume %astrolabe`
46+ 5. (if using a comet as a middleman) from the actual distribution ship: `|pause %astrolabe`
47+4. Build UI and upload `glob-ames`
48+5. Publish the desk from dojo: `:treaty|publish %astrolabe`
49+
50+## Deploying with `glob-ames` glob
51+Initial Setup:
52+1. Put the line `glob-ames+[~dister-midlev-mindyr 0v0]` in `desk.docket-0` if it's not there, where `~dister-midlevi-mindyr` is the `@p` of the distribution ship.
53+
54+Every Time:
55+4. Build the UI with `npm run build` in the `ui` directory which will bundle all the code and assets into the `dist/` folder.
56+5. Upload the `dist/` folder as a glob to your distribution ship. Example url: https://distribution.urbit-ship.com/docket/upload
57+
58+## Deploying with `glob-http` glob
59+Initial Setup:
60+1. Spin up a globber ship (comet or fakezod) (or just reuse your dev ship for this).
61+2. Mount an `%globber` desk. In Dojo:
62+ 1. `|merge %globber our %base` to create a new desk.
63+ 2. `|mount %globber` to mount it.
64+ 3. Set `GLOBBER_DESK` in `.env.local` if the path to your globber desk is different.
65+
66+Every Time:
67+3. From the `ui` directory, run `npm run release` to build the ui, make the glob, and copy it to the `globs` folder. The command will also print out the glob hash/id.
68+4. Copy the string printed by the last step, and paste it into `desk.docket-0`.
69+5. Upload the glob in `/globs/` to any publicly available HTTP endpoint that can serve files. This allows the glob to be distributed over HTTP.
70+6. Once you've uploaded the glob, paste the url into `desk/desk.docket-0`. Both the full URL and the hash should be updated to match the glob we just created, on the line that looks like this:
71+ ```hoon
72+ glob-http+['https://bootstrap.urbit.org/glob-0v5.fdf99.nph65.qecq3.ncpjn.q13mb.glob' 0v5.fdf99.nph65.qecq3.ncpjn.q13mb]
73+ ```
4874
4975[svelte]: https://svelte.dev/
5076[typescript]: https://www.typescriptlang.org/
base-desk/lib/agentio.hoonnew file+137
@@ -0,0 +1,137 @@
1+=>
2+ |%
3+ ++ card card:agent:gall
4+ --
5+::
6+|_ =bowl:gall
7+++ scry
8+ |= [desk=@tas =path]
9+ %+ weld
10+ /(scot %p our.bowl)/[desk]/(scot %da now.bowl)
11+ path
12+::
13+++ pass
14+ |_ =wire
15+ ++ poke
16+ |= [=dock =cage]
17+ [%pass wire %agent dock %poke cage]
18+ ::
19+ ++ poke-our
20+ |= [app=term =cage]
21+ ^- card
22+ (poke [our.bowl app] cage)
23+ ::
24+ ++ poke-self
25+ |= =cage
26+ ^- card
27+ (poke-our dap.bowl cage)
28+ ::
29+ ++ arvo
30+ |= =note-arvo
31+ ^- card
32+ [%pass wire %arvo note-arvo]
33+ ::
34+ ++ watch
35+ |= [=dock =path]
36+ [%pass (watch-wire path) %agent dock %watch path]
37+ ::
38+ ++ watch-our
39+ |= [app=term =path]
40+ (watch [our.bowl app] path)
41+ ::
42+ ++ watch-wire
43+ |= =path
44+ ^+ wire
45+ ?. ?=(~ wire)
46+ wire
47+ agentio-watch+path
48+ ::
49+ ++ leave
50+ |= =dock
51+ [%pass wire %agent dock %leave ~]
52+ ::
53+ ++ leave-our
54+ |= app=term
55+ (leave our.bowl app)
56+ ::
57+ ++ leave-path
58+ |= [=dock =path]
59+ =. wire
60+ (watch-wire path)
61+ (leave dock)
62+ ::
63+ ++ wait
64+ |= p=@da
65+ (arvo %b %wait p)
66+ ::
67+ ++ rest
68+ |= p=@da
69+ (arvo %b %rest p)
70+ ::
71+ ++ warp
72+ |= [wer=ship =riff:clay]
73+ (arvo %c %warp wer riff)
74+ ::
75+ ++ warp-our
76+ |= =riff:clay
77+ (warp our.bowl riff)
78+ ::
79+ :: right here, right now
80+ ++ warp-slim
81+ |= [genre=?(%sing %next) =care:clay =path]
82+ =/ =mood:clay
83+ [care r.byk.bowl path]
84+ =/ =rave:clay
85+ ?:(?=(%sing genre) [genre mood] [genre mood])
86+ (warp-our q.byk.bowl `rave)
87+ ::
88+ ++ tire
89+ (arvo %c %tire `~)
90+ ::
91+ ++ connect
92+ |= [=binding:eyre app=term]
93+ (arvo %e %connect binding app)
94+ --
95+::
96+++ fact-kick
97+ |= [=path =cage]
98+ ^- (list card)
99+ :~ (fact cage ~[path])
100+ (kick ~[path])
101+ ==
102+::
103+++ fact-init
104+ |= =cage
105+ ^- card
106+ [%give %fact ~ cage]
107+::
108+++ fact-init-kick
109+ |= =cage
110+ ^- (list card)
111+ :~ (fact cage ~)
112+ (kick ~)
113+ ==
114+::
115+++ fact
116+ |= [=cage paths=(list path)]
117+ ^- card
118+ [%give %fact paths cage]
119+::
120+++ fact-all
121+ |= =cage
122+ ^- (unit card)
123+ =/ paths=(set path)
124+ %- ~(gas in *(set path))
125+ %+ turn ~(tap by sup.bowl)
126+ |=([duct ship =path] path)
127+ ?: =(~ paths) ~
128+ `(fact cage ~(tap in paths))
129+::
130+++ kick
131+ |= paths=(list path)
132+ [%give %kick paths ~]
133+::
134+++ kick-only
135+ |= [=ship paths=(list path)]
136+ [%give %kick paths `ship]
137+--
base-desk/lib/azimuth.hoonnew file+466
@@ -0,0 +1,466 @@
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+--
base-desk/lib/azimuthio.hoonnew file+146
@@ -0,0 +1,146 @@
1+/- rpc=json-rpc
2+/+ ethereum, azimuth, strandio
3+=, strand=strand:strandio
4+=, jael
5+|%
6+++ tract azimuth:contracts:azimuth
7+++ fetch-point
8+ |= [url=@ta who=ship]
9+ =/ m (strand ,point:azimuth)
10+ ^- form:m
11+ =/ =request:rpc:ethereum
12+ :+ %eth-call
13+ =- [from=~ to=tract gas=~ price=~ value=~ data=-]
14+ (encode-call:rpc:ethereum 'points(uint32)' [%uint `@`who]~)
15+ [%label %latest]
16+ ;< jon=json bind:m (request-rpc url `'point' request)
17+ =/ res=cord (so:dejs:format jon)
18+ =/ =point:eth-noun:azimuth
19+ (decode-results:abi:ethereum res point:eth-type:azimuth)
20+ ::
21+ =/ =request:rpc:ethereum
22+ :+ %eth-call
23+ =- [from=~ to=tract gas=~ price=~ value=~ data=-]
24+ (encode-call:rpc:ethereum 'rights(uint32)' [%uint `@`who]~)
25+ [%label %latest]
26+ ;< jon=json bind:m (request-rpc url `'deed' request)
27+ =/ res=cord (so:dejs:format jon)
28+ =/ =deed:eth-noun:azimuth
29+ (decode-results:abi:ethereum res deed:eth-type:azimuth)
30+ ::
31+ (pure:m (point-from-eth:azimuth who point deed))
32+::
33+++ request-rpc
34+ |= [url=@ta id=(unit @t) req=request:rpc:ethereum]
35+ =/ m (strand ,json)
36+ ^- form:m
37+ %+ (retry json) `10
38+ =/ m (strand ,(unit json))
39+ ^- form:m
40+ |^
41+ =/ =request:http
42+ :* method=%'POST'
43+ url=url
44+ header-list=['Content-Type'^'application/json' ~]
45+ ^= body
46+ %- some %- as-octs:mimes:html
47+ %- en:json:html
48+ (request-to-json:rpc:ethereum id req)
49+ ==
50+ ;< ~ bind:m (send-request:strandio request)
51+ ;< rep=(unit client-response:iris) bind:m
52+ take-maybe-response:strandio
53+ ?~ rep
54+ (pure:m ~)
55+ (parse-response u.rep)
56+ ::
57+ ++ parse-response
58+ |= =client-response:iris
59+ =/ m (strand ,(unit json))
60+ ^- form:m
61+ ?> ?=(%finished -.client-response)
62+ ?~ full-file.client-response
63+ (pure:m ~)
64+ =/ body=@t q.data.u.full-file.client-response
65+ =/ jon=(unit json) (de:json:html body)
66+ ?~ jon
67+ (pure:m ~)
68+ =, dejs-soft:format
69+ =/ array=(unit (list response:rpc))
70+ ((ar parse-one-response) u.jon)
71+ ?~ array
72+ =/ res=(unit response:rpc) (parse-one-response u.jon)
73+ ?~ res
74+ (strand-fail:strandio %request-rpc-parse-error >id< ~)
75+ ?: ?=(%error -.u.res)
76+ (strand-fail:strandio %request-rpc-error >id< >+.res< ~)
77+ ?. ?=(%result -.u.res)
78+ (strand-fail:strandio %request-rpc-fail >u.res< ~)
79+ (pure:m `res.u.res)
80+ (strand-fail:strandio %request-rpc-batch >%not-implemented< ~)
81+ :: (pure:m `[%batch u.array])
82+ ::
83+ ++ parse-one-response
84+ |= =json
85+ ^- (unit response:rpc)
86+ =/ res=(unit [@t ^json])
87+ %. json
88+ =, dejs-soft:format
89+ (ot id+so result+some ~)
90+ ?^ res `[%result u.res]
91+ ~| parse-one-response=json
92+ :+ ~ %error %- need
93+ %. json
94+ =, dejs-soft:format
95+ (ot id+so error+(ot code+no message+so ~) ~)
96+ --
97+::
98+++ retry
99+ |* result=mold
100+ |= [crash-after=(unit @ud) computation=_*form:(strand (unit result))]
101+ =/ m (strand ,result)
102+ =| try=@ud
103+ |- ^- form:m
104+ =* loop $
105+ ?: =(crash-after `try)
106+ (strand-fail:strandio %retry-too-many ~)
107+ ;< ~ bind:m (backoff:strandio try ~m1)
108+ ;< res=(unit result) bind:m computation
109+ ?^ res
110+ (pure:m u.res)
111+ loop(try +(try))
112+::
113+++ get-latest-block
114+ |= url=@ta
115+ =/ m (strand ,block)
116+ ^- form:m
117+ ;< =json bind:m (request-rpc url `'block number' %eth-block-number ~)
118+ (get-block-by-number url (parse-eth-block-number:rpc:ethereum json))
119+::
120+++ get-block-by-number
121+ |= [url=@ta =number:block]
122+ =/ m (strand ,block)
123+ ^- form:m
124+ |^
125+ ;< =json bind:m
126+ (request-rpc url `'block by number' %eth-get-block-by-number number |)
127+ =/ =block (parse-block json)
128+ ?. =(number number.id.block)
129+ (strand-fail:strandio %reorg-detected >number< >block< ~)
130+ (pure:m block)
131+ ::
132+ ++ parse-block
133+ |= =json
134+ ^- block
135+ =< [[&1 &2] |2]
136+ ^- [@ @ @]
137+ ~| json
138+ %. json
139+ =, dejs:format
140+ %- ot
141+ :~ hash+parse-hex-result:rpc:ethereum
142+ number+parse-hex-result:rpc:ethereum
143+ 'parentHash'^parse-hex-result:rpc:ethereum
144+ ==
145+ --
146+--
base-desk/lib/bip/b158.hoonnew file+249
@@ -0,0 +1,249 @@
1+/- bc=bitcoin
2+/+ bcu=bitcoin-utils
3+|%
4+++ params
5+ |%
6+ ++ p 19
7+ ++ m 784.931
8+ --
9+::
10+++ siphash
11+ |= [k=byts m=byts]
12+ ^- byts
13+ |^
14+ ?> =(wid.k 16)
15+ ?> (lte (met 3 dat.k) wid.k)
16+ ?> (lte (met 3 dat.m) wid.m)
17+ =. k (flim:sha k)
18+ =. m (flim:sha m)
19+ (flim:sha (fin (comp m (init dat.k))))
20+ :: Initialise internal state
21+ ::
22+ ++ init
23+ |= k=@
24+ ^- [@ @ @ @]
25+ =/ k0=@ (end [6 1] k)
26+ =/ k1=@ (cut 6 [1 1] k)
27+ :^ (mix k0 0x736f.6d65.7073.6575)
28+ (mix k1 0x646f.7261.6e64.6f6d)
29+ (mix k0 0x6c79.6765.6e65.7261)
30+ (mix k1 0x7465.6462.7974.6573)
31+ ::
32+ :: Compression rounds
33+ ++ comp
34+ |= [m=byts v=[v0=@ v1=@ v2=@ v3=@]]
35+ ^- [@ @ @ @]
36+ =/ len=@ud (div wid.m 8)
37+ =/ last=@ (lsh [3 7] (mod wid.m 256))
38+ =| i=@ud
39+ =| w=@
40+ |-
41+ =. w (cut 6 [i 1] dat.m)
42+ ?: =(i len)
43+ =. v3.v (mix v3.v (mix last w))
44+ =. v (rnd (rnd v))
45+ =. v0.v (mix v0.v (mix last w))
46+ v
47+ %= $
48+ v =. v3.v (mix v3.v w)
49+ =. v (rnd (rnd v))
50+ =. v0.v (mix v0.v w)
51+ v
52+ i (add i 1)
53+ ==
54+ ::
55+ :: Finalisation rounds
56+ ++ fin
57+ |= v=[v0=@ v1=@ v2=@ v3=@]
58+ ^- byts
59+ =. v2.v (mix v2.v 0xff)
60+ =. v (rnd (rnd (rnd (rnd v))))
61+ :- 8
62+ :(mix v0.v v1.v v2.v v3.v)
63+ ::
64+ :: Sipround
65+ ++ rnd
66+ |= [v0=@ v1=@ v2=@ v3=@]
67+ ^- [@ @ @ @]
68+ =. v0 (~(sum fe 6) v0 v1)
69+ =. v2 (~(sum fe 6) v2 v3)
70+ =. v1 (~(rol fe 6) 0 13 v1)
71+ =. v3 (~(rol fe 6) 0 16 v3)
72+ =. v1 (mix v1 v0)
73+ =. v3 (mix v3 v2)
74+ =. v0 (~(rol fe 6) 0 32 v0)
75+ =. v2 (~(sum fe 6) v2 v1)
76+ =. v0 (~(sum fe 6) v0 v3)
77+ =. v1 (~(rol fe 6) 0 17 v1)
78+ =. v3 (~(rol fe 6) 0 21 v3)
79+ =. v1 (mix v1 v2)
80+ =. v3 (mix v3 v0)
81+ =. v2 (~(rol fe 6) 0 32 v2)
82+ [v0 v1 v2 v3]
83+ --
84+:: +str: bit streams
85+:: read is from the front
86+:: write appends to the back
87+::
88+++ str
89+ |%
90+ ++ read-bit
91+ |= s=bits:bc
92+ ^- [bit=@ub rest=bits:bc]
93+ ?> (gth wid.s 0)
94+ :* ?:((gth wid.s (met 0 dat.s)) 0b0 0b1)
95+ [(dec wid.s) (end [0 (dec wid.s)] dat.s)]
96+ ==
97+ ::
98+ ++ read-bits
99+ |= [n=@ s=bits:bc]
100+ ^- [bits:bc rest=bits:bc]
101+ =| bs=bits:bc
102+ |-
103+ ?: =(n 0) [bs s]
104+ =^ b s (read-bit s)
105+ $(n (dec n), bs (write-bits bs [1 b]))
106+ ::
107+ ++ write-bits
108+ |= [s1=bits:bc s2=bits:bc]
109+ ^- bits:bc
110+ [(add wid.s1 wid.s2) (can 0 ~[s2 s1])]
111+ --
112+:: +gol: Golomb-Rice encoding/decoding
113+::
114+++ gol
115+ |%
116+ :: +en: encode x and append to end of s
117+ :: - s: bits stream
118+ :: - x: number to add to the stream
119+ :: - p: golomb-rice p param
120+ ::
121+ ++ en
122+ |= [s=bits:bc x=@ p=@]
123+ ^- bits:bc
124+ =+ q=(rsh [0 p] x)
125+ =+ unary=[+(q) (lsh [0 1] (dec (bex q)))]
126+ =+ r=[p (end [0 p] x)]
127+ %+ write-bits:str s
128+ (write-bits:str unary r)
129+ ::
130+ ++ de
131+ |= [s=bits:bc p=@]
132+ ^- [delta=@ rest=bits:bc]
133+ |^ ?> (gth wid.s 0)
134+ =^ q s (get-q s)
135+ =^ r s (read-bits:str p s)
136+ [(add dat.r (lsh [0 p] q)) s]
137+ ::
138+ ++ get-q
139+ |= s=bits:bc
140+ =| q=@
141+ =^ first-bit s (read-bit:str s)
142+ |-
143+ ?: =(0 first-bit) [q s]
144+ =^ b s (read-bit:str s)
145+ $(first-bit b, q +(q))
146+ --
147+ --
148+:: +hsh
149+::
150+++ hsh
151+ |%
152+ :: +to-range
153+ :: - item: scriptpubkey to hash
154+ :: - f: N*M
155+ :: - k: key for siphash (end of blockhash, reversed)
156+ ::
157+ ++ to-range
158+ |= [item=byts f=@ k=byts]
159+ ^- @
160+ (rsh [0 64] (mul f (swp 3 dat:(siphash k item))))
161+ :: +set-construct: return sorted hashes of scriptpubkeys
162+ ::
163+ ++ set-construct
164+ |= [items=(list byts) k=byts f=@]
165+ ^- (list @)
166+ %+ sort
167+ %+ turn items
168+ |= item=byts
169+ (to-range item f k)
170+ lth
171+ --
172+::
173+++ parse-filter
174+ |= filter=hexb:bc
175+ ^- [n=@ux gcs-set=bits:bc]
176+ =/ n n:(de:csiz:bcu filter)
177+ =/ lead=@ ?:(=(1 wid.n) 1 +(wid.n))
178+ :- dat.n
179+ [(mul 8 (sub wid.filter lead)) `@ub`dat:(drop:byt:bcu lead filter)]
180+:: +to-key: blockhash (little endian) to key for siphash
181+::
182+++ to-key
183+ |= blockhash=tape
184+ ^- byts
185+ %+ take:byt:bcu 16
186+ %- flip:byt:bcu
187+ (from-cord:hxb:bcu (crip blockhash))
188+:: +match: whether block filter matches *any* target scriptpubkeys
189+:: - filter: full block filter, with leading N
190+:: - k: key for siphash (end of blockhash, reversed)
191+:: - targets: scriptpubkeys to match
192+::
193+++ match
194+ |= [filter=hexb:bc k=byts targets=(list byts)]
195+ ^- ?
196+ =/ [p=@ m=@] [p:params m:params]
197+ =/ [n=@ux gcs-set=bits:bc] (parse-filter filter)
198+ =+ target-hs=(set-construct:hsh targets k (mul n m))
199+ =+ last-val=0
200+ |-
201+ ?~ target-hs %.n
202+ ?: =(last-val i.target-hs)
203+ %.y
204+ ?: (gth last-val i.target-hs)
205+ $(target-hs t.target-hs)
206+ :: last-val is less than target: check next val in GCS, if any
207+ ::
208+ ?: (lth wid.gcs-set p) %.n
209+ =^ delta gcs-set
210+ (de:gol gcs-set p)
211+ $(last-val (add delta last-val))
212+:: +all-match: returns all target byts that match
213+:: - filter: full block filter, with leading N
214+:: - targets: scriptpubkeys to match
215+::
216+++ all-match
217+ |= [filter=hexb:bc blockhash=hexb:bc targets=(list [address:bc byts])]
218+ ^- (set [address:bc hexb:bc])
219+ =/ k (to-key (trip (to-cord:hxb:bcu blockhash)))
220+ %- ~(gas in *(set [address:bc hexb:bc]))
221+ =/ [p=@ m=@] [p:params m:params]
222+ =/ [n=@ux gcs-set=bits:bc] (parse-filter filter)
223+ =/ target-map=(map @ [address:bc hexb:bc])
224+ %- ~(gas by *(map @ [address:bc hexb:bc]))
225+ %+ turn targets
226+ |= [a=address:bc t=hexb:bc]
227+ [(to-range:hsh t (mul n m) k) a t]
228+ =+ target-hs=(sort ~(tap in ~(key by target-map)) lth)
229+ =+ last-val=0
230+ =| matches=(list @)
231+ |-
232+ ?~ target-hs
233+ (murn matches ~(get by target-map))
234+ ?: =(last-val i.target-hs)
235+ %= $
236+ target-hs t.target-hs
237+ matches [last-val matches]
238+ ==
239+ ?: (gth last-val i.target-hs)
240+ $(target-hs t.target-hs)
241+ :: last-val is less than target: get next val in GCS, if any
242+ ::
243+ ?: (lth wid.gcs-set p)
244+ (murn matches ~(get by target-map))
245+ =^ delta gcs-set
246+ (de:gol gcs-set p)
247+ $(last-val (add delta last-val))
248+::
249+--
base-desk/lib/bip/b173.hoonnew file+144
@@ -0,0 +1,144 @@
1+:: BIP173: Bech32 Addresses
2+:: https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki
3+::
4+:: Heavily copies:
5+:: https://github.com/bitcoinjs/bech32/blob/master/index.js
6+::
7+/- sur=bitcoin
8+/+ bcu=bitcoin-utils
9+=, sur
10+=, bcu
11+|%
12+++ prefixes
13+ ^- (map network tape)
14+ (my [[%main "bc"] [%testnet "tb"] [%regtest "bcrt"] ~])
15+++ charset "qpzry9x8gf2tvdw0s3jn54khce6mua7l"
16++$ raw-decoded [hrp=tape data=(list @) checksum=(list @)]
17+:: below is a port of: https://github.com/bitcoinjs/bech32/blob/master/index.js
18+::
19+++ polymod
20+ |= values=(list @)
21+ |^ ^- @
22+ =/ gen=(list @ux)
23+ ~[0x3b6a.57b2 0x2650.8e6d 0x1ea1.19fa 0x3d42.33dd 0x2a14.62b3]
24+ =/ chk=@ 1
25+ |- ?~ values chk
26+ =/ top (rsh [0 25] chk)
27+ =. chk
28+ (mix i.values (lsh [0 5] (dis chk 0x1ff.ffff)))
29+ $(values t.values, chk (update-chk chk top gen))
30+::
31+ ++ update-chk
32+ |= [chk=@ top=@ gen=(list @ux)]
33+ =/ is (gulf 0 4)
34+ |- ?~ is chk
35+ ?: =(1 (dis 1 (rsh [0 i.is] top)))
36+ $(is t.is, chk (mix chk (snag i.is gen)))
37+ $(is t.is)
38+ --
39+::
40+++ expand-hrp
41+ |= hrp=tape
42+ ^- (list @)
43+ =/ front (turn hrp |=(p=@tD (rsh [0 5] p)))
44+ =/ back (turn hrp |=(p=@tD (dis 31 p)))
45+ (zing ~[front ~[0] back])
46+::
47+++ verify-checksum
48+ |= [hrp=tape data-and-checksum=(list @)]
49+ ^- ?
50+ %- |=(a=@ =(1 a))
51+ %- polymod
52+ (weld (expand-hrp hrp) data-and-checksum)
53+::
54+++ checksum
55+ |= [hrp=tape data=(list @)]
56+ ^- (list @)
57+ :: xor 1 with the polymod
58+ ::
59+ =/ pmod=@
60+ %+ mix 1
61+ %- polymod
62+ (zing ~[(expand-hrp hrp) data (reap 6 0)])
63+ %+ turn (gulf 0 5)
64+ |=(i=@ (dis 31 (rsh [0 (mul 5 (sub 5 i))] pmod)))
65+::
66+++ charset-to-value
67+ |= c=@tD
68+ ^- (unit @)
69+ (find ~[c] charset)
70+++ value-to-charset
71+ |= value=@
72+ ^- (unit @tD)
73+ ?: (gth value 31) ~
74+ `(snag value charset)
75+::
76+++ is-valid
77+ |= [bech=tape last-1-pos=@] ^- ?
78+ ?& ?|(=((cass bech) bech) =((cuss bech) bech)) :: to upper or to lower is same as bech
79+ (gte last-1-pos 1)
80+ (lte (add last-1-pos 7) (lent bech))
81+ (lte (lent bech) 90)
82+ (levy bech |=(c=@tD (gte c 33)))
83+ (levy bech |=(c=@tD (lte c 126)))
84+ ==
85+:: data should be 5bit words
86+::
87+++ encode-raw
88+ |= [hrp=tape data=(list @)]
89+ ^- cord
90+ =/ combined=(list @)
91+ (weld data (checksum hrp data))
92+ %- crip
93+ (zing ~[hrp "1" (tape (murn combined value-to-charset))])
94+++ decode-raw
95+ |= body=cord
96+ ^- (unit raw-decoded)
97+ =/ bech (cass (trip body)) :: to lowercase
98+ =/ pos (flop (fand "1" bech))
99+ ?~ pos ~
100+ =/ last-1=@ i.pos
101+ ?. (is-valid bech last-1) :: check bech32 validity (not segwit validity or checksum)
102+ ~
103+ =/ hrp (scag last-1 bech)
104+ =/ encoded-data-and-checksum=(list @)
105+ (slag +(last-1) bech)
106+ =/ data-and-checksum=(list @)
107+ %+ murn encoded-data-and-checksum
108+ charset-to-value
109+ ?. =((lent encoded-data-and-checksum) (lent data-and-checksum)) :: ensure all were in CHARSET
110+ ~
111+ ?. (verify-checksum hrp data-and-checksum)
112+ ~
113+ =/ checksum-pos (sub (lent data-and-checksum) 6)
114+ `[hrp (scag checksum-pos data-and-checksum) (slag checksum-pos data-and-checksum)]
115+:: +from-address: BIP173 bech32 address encoding to hex
116+:: https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki
117+:: expects to drop a leading 5-bit 0 (the witness version)
118+::
119+++ from-address
120+ |= body=cord
121+ ^- hexb
122+ ~| "Invalid bech32 address"
123+ =/ d=(unit raw-decoded) (decode-raw body)
124+ ?> ?=(^ d)
125+ =/ bs=bits (from-atoms:bit 5 data.u.d)
126+ =/ byt-len=@ (div (sub wid.bs 5) 8)
127+ ?> =(5^0b0 (take:bit 5 bs))
128+ ?> ?| =(20 byt-len)
129+ =(32 byt-len)
130+ ==
131+ [byt-len `@ux`dat:(take:bit (mul 8 byt-len) (drop:bit 5 bs))]
132+:: pubkey is the 33 byte ECC compressed public key
133+::
134+++ encode-pubkey
135+ |= [=network pubkey=byts]
136+ ^- (unit cord)
137+ ?. =(33 wid.pubkey)
138+ ~|('pubkey must be a 33 byte ECC compressed public key' !!)
139+ =/ prefix (~(get by prefixes) network)
140+ ?~ prefix ~
141+ :- ~
142+ %+ encode-raw u.prefix
143+ [0v0 (to-atoms:bit 5 [160 `@ub`dat:(hash-160 pubkey)])]
144+--
base-desk/lib/bip/b174.hoonnew file+184
@@ -0,0 +1,184 @@
1+:: BIP174: PSBTs
2+:: https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki
3+::
4+/- sur=bitcoin
5+/+ bcu=bitcoin-utils
6+=, sur
7+=, bcu
8+|%
9+++ en
10+ |%
11+ ++ globals
12+ |= rawtx=hexb
13+ ^- map:psbt
14+ :~ [[1 0x0] rawtx]
15+ ==
16+ ::
17+ ++ input
18+ |= [only-witness=? i=in:psbt]
19+ ^- map:psbt
20+ %+ weld
21+ ?: only-witness ~
22+ ~[[1^0x0 rawtx.i]]
23+ :~ (witness-tx i)
24+ (hdkey %input hdkey.i)
25+ ==
26+ ::
27+ ++ output
28+ |= =out:psbt
29+ ^- map:psbt
30+ ?~ hk.out ~
31+ :~ (hdkey %output u.hk.out)
32+ ==
33+ ::
34+ ++ witness-tx
35+ |= i=in:psbt
36+ ^- keyval:psbt
37+ :- [1 0x1]
38+ %- cat:byt
39+ :~ (flip:byt 8^value.utxo.i)
40+ 1^0x16
41+ 2^0x14
42+ (hash-160 pubkey.hdkey.i)
43+ ==
44+ ::
45+ ++ hdkey
46+ |= [=target:psbt h=^hdkey]
47+ ^- keyval:psbt
48+ =/ typ=@ux
49+ ?- target
50+ %input 0x6
51+ %output 0x2
52+ ==
53+ =/ coin-type=hexb
54+ ?- network.h
55+ %main
56+ 1^0x0
57+ %testnet
58+ 1^0x1
59+ %regtest
60+ 1^0x1
61+ ==
62+ :- (cat:byt ~[1^typ pubkey.h])
63+ %- cat:byt
64+ :~ fprint.h
65+ 1^`@ux`bipt.h 3^0x80
66+ coin-type 3^0x80
67+ 4^0x80
68+ 1^`@ux`chyg.h 3^0x0
69+ (flip:byt 4^idx.h)
70+ ==
71+ ::
72+ ++ keyval-byts
73+ |= kv=keyval:psbt
74+ ^- hexb
75+ %- cat:byt
76+ :~ 1^wid.key.kv
77+ key.kv
78+ 1^wid.val.kv
79+ val.kv
80+ ==
81+ ::
82+ ++ map-byts
83+ |= m=map:psbt
84+ ^- (unit hexb)
85+ ?~ m ~
86+ :- ~
87+ %- cat:byt
88+ (turn m keyval-byts)
89+ --
90+ ++ base64
91+ |= b=hexb
92+ ^- base64:psbt
93+ %- en:base64:mimes:html
94+ (flip:byt b)
95+:: +encode: make base64 cord of PSBT
96+:: - only-witness: don't include non-witness UTXO
97+::
98+++ encode
99+ |= $: only-witness=?
100+ rawtx=hexb
101+ txid=hexb
102+ inputs=(list in:psbt)
103+ outputs=(list out:psbt)
104+ ==
105+ ^- base64:psbt
106+ =/ sep=(unit hexb) `1^0x0
107+ =/ final=(list (unit hexb))
108+ %+ join sep
109+ %+ turn
110+ %- zing
111+ :~ ~[(globals:en rawtx)]
112+ (turn inputs (cury input:en only-witness))
113+ (turn outputs output:en)
114+ ==
115+ map-byts:en
116+ %- base64:en
117+ ^- byts
118+ %- cat:byt
119+ %+ weld ~[[5 0x70.7362.74ff]]
120+ (murn (snoc final sep) same)
121+::
122+++ parse
123+ |= psbt-base64=cord
124+ ^- (list map:psbt)
125+ =/ todo=hexb
126+ (drop:byt 5 (to-byts psbt-base64))
127+ =| acc=(list map:psbt)
128+ =| m=map:psbt
129+ |-
130+ ?: =(wid.todo 0)
131+ (snoc acc m)
132+ :: 0x0: map separator
133+ ::
134+ ?: =(1^0x0 (take:byt 1 todo))
135+ $(acc (snoc acc m), m *map:psbt, todo (drop:byt 1 todo))
136+ =^ kv todo (next-keyval todo)
137+ $(m (snoc m kv))
138+:: +get-txid: extract txid from a valid PSBT
139+::
140+++ get-txid
141+ |= psbt-base64=cord
142+ ^- hexb
143+ =/ tx=hexb
144+ %- raw-tx
145+ %+ drop:byt 5
146+ (to-byts psbt-base64)
147+ %- flip:byt
148+ (dsha256 tx)
149+:: +raw-tx: extract hex transaction
150+:: looks for key 0x0 in global map
151+:: crashes if tx not in hex
152+::
153+++ raw-tx
154+ |= b=hexb
155+ ^- hexb
156+ |-
157+ ?: =(wid.b 0) !!
158+ ?: =(1^0x0 (take:byt 1 b)) !!
159+ =/ nk (next-keyval b)
160+ ?: =(0x0 dat.key.kv.nk)
161+ val.kv.nk
162+ $(b rest.nk)
163+:: +next-keyval: returns next key-val in a PSBT map
164+:: input first byte must be a map key length
165+::
166+++ next-keyval
167+ |= b=hexb
168+ ^- [kv=keyval:psbt rest=hexb]
169+ =/ klen dat:(take:byt 1 b)
170+ =/ k (take:byt klen (drop:byt 1 b))
171+ =/ vlen dat:(take:byt 1 (drop:byt (add 1 klen) b))
172+ =/ v (take:byt vlen (drop:byt (add 2 klen) b))
173+ ?> ?&((gth wid.k 0) (gth wid.v 0))
174+ :- [k v]
175+ (drop:byt ;:(add 2 klen vlen) b)
176+::
177+++ to-byts
178+ |= psbt-base64=cord
179+ ^- hexb
180+ ~| "Invalid PSBT"
181+ =+ p=(de:base64:mimes:html psbt-base64)
182+ ?~ p !!
183+ (flip:byt u.p)
184+--
base-desk/lib/bip32.hoonnew file+243
@@ -0,0 +1,243 @@
1+:: bip32 implementation in hoon
2+::
3+:: to use, call one of the core initialization arms.
4+:: using the produced core, derive as needed and take out the data you want.
5+::
6+::NOTE tested to be correct against
7+:: https://en.bitcoin.it/wiki/BIP_0032_TestVectors
8+::
9+=, hmac:crypto
10+=, secp:crypto
11+=+ ecc=secp256k1
12+::
13+:: prv: private key
14+:: pub: public key
15+:: cad: chain code
16+:: dep: depth in chain
17+:: ind: index at depth
18+:: pif: parent fingerprint (4 bytes)
19+|_ [prv=@ pub=point.ecc cad=@ dep=@ud ind=@ud pif=@]
20+::
21++$ keyc [key=@ cai=@] :: prv/pub key + chain code
22+::
23+:: elliptic curve operations and values
24+::
25+++ point priv-to-pub.ecc
26+::
27+++ ser-p compress-point.ecc
28+::
29+++ n n:t.ecc
30+::
31+:: core initialization
32+::
33+++ from-seed
34+ |= byts
35+ ^+ +>
36+ =+ der=(hmac-sha512l [12 'dees nioctiB'] [wid dat])
37+ =+ pri=(cut 3 [32 32] der)
38+ +>.$(prv pri, pub (point pri), cad (cut 3 [0 32] der))
39+::
40+++ from-private
41+ |= keyc
42+ +>(prv key, pub (point key), cad cai)
43+::
44+++ from-public
45+ |= keyc
46+ +>(pub (decompress-point.ecc key), cad cai)
47+::
48+++ from-public-point
49+ |= [pon=point.ecc cai=@]
50+ +>(pub pon, cad cai)
51+::
52+++ from-extended
53+ |= t=tape
54+ =+ x=(de-base58check 4 t)
55+ => |%
56+ ++ take
57+ |= b=@ud
58+ ^- [v=@ x=@]
59+ :- (end [3 b] x)
60+ (rsh [3 b] x)
61+ --
62+ =^ k x (take 33)
63+ =^ c x (take 32)
64+ =^ i x (take 4)
65+ =^ p x (take 4)
66+ =^ d x (take 1)
67+ ?> =(0 x) :: sanity check
68+ %. [d i p]
69+ =< set-metadata
70+ =+ v=(swag [1 3] t)
71+ ?: =("prv" v) (from-private k c)
72+ ?: =("pub" v) (from-public k c)
73+ !!
74+::
75+++ set-metadata
76+ |= [d=@ud i=@ud p=@]
77+ +>(dep d, ind i, pif p)
78+::
79+:: derivation
80+::
81+++ derivation-path
82+ ;~ pfix
83+ ;~(pose (jest 'm/') (easy ~))
84+ %+ most fas
85+ ;~ pose
86+ %+ cook
87+ |=(i=@ (add i (bex 31)))
88+ ;~(sfix dem soq)
89+ ::
90+ dem
91+ == ==
92+::
93+++ derive-path
94+ |= t=tape
95+ %- derive-sequence
96+ (scan t derivation-path)
97+::
98+++ derive-sequence
99+ |= j=(list @u)
100+ ?~ j +>
101+ =. +> (derive i.j)
102+ $(j t.j)
103+::
104+++ derive
105+ ?: =(0 prv)
106+ derive-public
107+ derive-private
108+::
109+++ derive-private
110+ |= i=@u
111+ ^+ +>
112+ :: we must have a private key to derive the next one
113+ ?: =(0 prv)
114+ ~| %know-no-private-key
115+ !!
116+ :: derive child at i
117+ =/ [left=@ right=@]
118+ =- [(cut 3 [32 32] -) (cut 3 [0 32] -)]
119+ %+ hmac-sha512l [32 cad]
120+ :- 37
121+ ?: (gte i (bex 31))
122+ :: hardened child
123+ (can 3 ~[4^i 32^prv 1^0])
124+ :: normal child
125+ (can 3 ~[4^i 33^(ser-p (point prv))])
126+ =+ key=(mod (add left prv) n)
127+ :: rare exception, invalid key, go to the next one
128+ ?: |(=(0 key) (gte left n)) $(i +(i))
129+ %_ +>.$
130+ prv key
131+ pub (point key)
132+ cad right
133+ dep +(dep)
134+ ind i
135+ pif fingerprint
136+ ==
137+::
138+++ derive-public
139+ |= i=@u
140+ ^+ +>
141+ :: public keys can't be hardened
142+ ?: (gte i (bex 31))
143+ ~| %cant-derive-hardened-public-key
144+ !!
145+ :: derive child at i
146+ =/ [left=@ right=@]
147+ =- [(cut 3 [32 32] -) (cut 3 [0 32] -)]
148+ %+ hmac-sha512l [32 cad]
149+ 37^(can 3 ~[4^i 33^(ser-p pub)])
150+ :: rare exception, invalid key, go to the next one
151+ ?: (gte left n) $(i +(i)) ::TODO or child key is "point at infinity"
152+ %_ +>.$
153+ pub (add-points.ecc (point left) pub)
154+ cad right
155+ dep +(dep)
156+ ind i
157+ pif fingerprint
158+ ==
159+::
160+:: rendering
161+::
162+++ private-key ?.(=(0 prv) prv ~|(%know-no-private-key !!))
163+++ public-key (ser-p pub)
164+++ chain-code cad
165+++ private-chain [private-key cad]
166+++ public-chain [public-key cad]
167+::
168+++ identity (hash160 public-key)
169+++ fingerprint (cut 3 [16 4] identity)
170+::
171+++ address
172+ |= network=?(%main %regtest %testnet)
173+ ^- @uc
174+ :: removes checksum
175+ ::
176+ %+ rsh [3 4]
177+ %+ en-base58check
178+ [4 (version-bytes network %pub %.n)]
179+ [20 identity]
180+::
181+++ prv-extended
182+ |= network=?(%main %regtest %testnet)
183+ %+ en-b58c-bip32 (version-bytes network %prv %.y)
184+ (build-extended private-key)
185+::
186+++ pub-extended
187+ |= network=?(%main %regtest %testnet)
188+ %+ en-b58c-bip32 (version-bytes network %pub %.y)
189+ (build-extended public-key)
190+::
191+++ build-extended
192+ |= key=@
193+ %+ can 3
194+ :~ 33^key
195+ 32^cad
196+ 4^ind
197+ 4^pif
198+ 1^dep
199+ ==
200+::
201+++ en-b58c-bip32
202+ |= [v=@ k=@]
203+ %- en-base58:mimes:html
204+ (en-base58check [4 v] [74 k])
205+::
206+:: base58check
207+::
208+++ en-base58check
209+ :: v: version bytes
210+ :: d: data
211+ |= [v=byts d=byts]
212+ =+ p=[(add wid.v wid.d) (can 3 ~[d v])]
213+ =- (can 3 ~[4^- p])
214+ %+ rsh [3 28]
215+ (sha-256l:sha 32 (sha-256l:sha p))
216+::
217+++ de-base58check
218+ :: vw: amount of version bytes
219+ |= [vw=@u t=tape]
220+ =+ x=(de-base58:mimes:html t)
221+ =+ hash=(sha-256l:sha 32 (sha-256:sha (rsh [3 4] x)))
222+ ?> =((end [3 4] x) (rsh [3 28] hash))
223+ (cut 3 [vw (sub (met 3 x) (add 4 vw))] x)
224+::
225+++ hash160
226+ |= d=@
227+ (ripemd-160:ripemd:crypto 32 (sha-256:sha d))
228+::
229+++ version-bytes
230+ |= [network=?(%main %regtest %testnet) type=?(%pub %prv) bip32=?]
231+ ^- @ux
232+ |^
233+ ?- type
234+ %pub ?:(bip32 xpub-key pay-to-pubkey)
235+ %prv ?:(bip32 xprv-key private-key)
236+ ==
237+ ::
238+ ++ pay-to-pubkey ?:(=(network %main) 0x0 0x6f)
239+ ++ private-key ?:(=(network %main) 0x80 0xef)
240+ ++ xpub-key ?:(=(network %main) 0x488.b21e 0x435.87cf)
241+ ++ xprv-key ?:(=(network %main) 0x488.ade4 0x435.8394)
242+ --
243+--
base-desk/lib/bip39.hoonnew file+46
@@ -0,0 +1,46 @@
1+:: bip39 implementation in hoon
2+::
3+/+ bip39-english
4+::
5+|%
6+++ from-entropy
7+ |= byts
8+ ^- tape
9+ =. wid (mul wid 8)
10+ ~| [%unsupported-entropy-bit-length wid]
11+ ?> &((gte wid 128) (lte wid 256))
12+ ::
13+ =+ cs=(div wid 32)
14+ =/ check=@
15+ %+ rsh [0 (sub 256 cs)]
16+ (sha-256l:sha (div wid 8) dat)
17+ =/ bits=byts
18+ :- (add wid cs)
19+ %+ can 0
20+ :~ cs^check
21+ wid^dat
22+ ==
23+ ::
24+ =/ pieces
25+ |- ^- (list @)
26+ :- (end [0 11] dat.bits)
27+ ?: (lte wid.bits 11) ~
28+ $(bits [(sub wid.bits 11) (rsh [0 11] dat.bits)])
29+ ::
30+ =/ words=(list tape)
31+ %+ turn pieces
32+ |= ind=@ud
33+ (snag ind `(list tape)`bip39-english)
34+ ::
35+ %+ roll (flop words)
36+ |= [nex=tape all=tape]
37+ ?~ all nex
38+ :(weld all " " nex)
39+::
40+::NOTE always produces a 512-bit result
41+++ to-seed
42+ |= [mnem=tape pass=tape]
43+ ^- @
44+ %- hmac-sha512t:pbkdf:crypto
45+ [(crip mnem) (crip (weld "mnemonic" pass)) 2.048 64]
46+--
base-desk/lib/bip39/english.hoonnew file+2052
@@ -0,0 +1,2052 @@
1+:: english wordlist for use in bip39
2+^- (list tape)
3+:~
4+ "abandon"
5+ "ability"
6+ "able"
7+ "about"
8+ "above"
9+ "absent"
10+ "absorb"
11+ "abstract"
12+ "absurd"
13+ "abuse"
14+ "access"
15+ "accident"
16+ "account"
17+ "accuse"
18+ "achieve"
19+ "acid"
20+ "acoustic"
21+ "acquire"
22+ "across"
23+ "act"
24+ "action"
25+ "actor"
26+ "actress"
27+ "actual"
28+ "adapt"
29+ "add"
30+ "addict"
31+ "address"
32+ "adjust"
33+ "admit"
34+ "adult"
35+ "advance"
36+ "advice"
37+ "aerobic"
38+ "affair"
39+ "afford"
40+ "afraid"
41+ "again"
42+ "age"
43+ "agent"
44+ "agree"
45+ "ahead"
46+ "aim"
47+ "air"
48+ "airport"
49+ "aisle"
50+ "alarm"
51+ "album"
52+ "alcohol"
53+ "alert"
54+ "alien"
55+ "all"
56+ "alley"
57+ "allow"
58+ "almost"
59+ "alone"
60+ "alpha"
61+ "already"
62+ "also"
63+ "alter"
64+ "always"
65+ "amateur"
66+ "amazing"
67+ "among"
68+ "amount"
69+ "amused"
70+ "analyst"
71+ "anchor"
72+ "ancient"
73+ "anger"
74+ "angle"
75+ "angry"
76+ "animal"
77+ "ankle"
78+ "announce"
79+ "annual"
80+ "another"
81+ "answer"
82+ "antenna"
83+ "antique"
84+ "anxiety"
85+ "any"
86+ "apart"
87+ "apology"
88+ "appear"
89+ "apple"
90+ "approve"
91+ "april"
92+ "arch"
93+ "arctic"
94+ "area"
95+ "arena"
96+ "argue"
97+ "arm"
98+ "armed"
99+ "armor"
100+ "army"
101+ "around"
102+ "arrange"
103+ "arrest"
104+ "arrive"
105+ "arrow"
106+ "art"
107+ "artefact"
108+ "artist"
109+ "artwork"
110+ "ask"
111+ "aspect"
112+ "assault"
113+ "asset"
114+ "assist"
115+ "assume"
116+ "asthma"
117+ "athlete"
118+ "atom"
119+ "attack"
120+ "attend"
121+ "attitude"
122+ "attract"
123+ "auction"
124+ "audit"
125+ "august"
126+ "aunt"
127+ "author"
128+ "auto"
129+ "autumn"
130+ "average"
131+ "avocado"
132+ "avoid"
133+ "awake"
134+ "aware"
135+ "away"
136+ "awesome"
137+ "awful"
138+ "awkward"
139+ "axis"
140+ "baby"
141+ "bachelor"
142+ "bacon"
143+ "badge"
144+ "bag"
145+ "balance"
146+ "balcony"
147+ "ball"
148+ "bamboo"
149+ "banana"
150+ "banner"
151+ "bar"
152+ "barely"
153+ "bargain"
154+ "barrel"
155+ "base"
156+ "basic"
157+ "basket"
158+ "battle"
159+ "beach"
160+ "bean"
161+ "beauty"
162+ "because"
163+ "become"
164+ "beef"
165+ "before"
166+ "begin"
167+ "behave"
168+ "behind"
169+ "believe"
170+ "below"
171+ "belt"
172+ "bench"
173+ "benefit"
174+ "best"
175+ "betray"
176+ "better"
177+ "between"
178+ "beyond"
179+ "bicycle"
180+ "bid"
181+ "bike"
182+ "bind"
183+ "biology"
184+ "bird"
185+ "birth"
186+ "bitter"
187+ "black"
188+ "blade"
189+ "blame"
190+ "blanket"
191+ "blast"
192+ "bleak"
193+ "bless"
194+ "blind"
195+ "blood"
196+ "blossom"
197+ "blouse"
198+ "blue"
199+ "blur"
200+ "blush"
201+ "board"
202+ "boat"
203+ "body"
204+ "boil"
205+ "bomb"
206+ "bone"
207+ "bonus"
208+ "book"
209+ "boost"
210+ "border"
211+ "boring"
212+ "borrow"
213+ "boss"
214+ "bottom"
215+ "bounce"
216+ "box"
217+ "boy"
218+ "bracket"
219+ "brain"
220+ "brand"
221+ "brass"
222+ "brave"
223+ "bread"
224+ "breeze"
225+ "brick"
226+ "bridge"
227+ "brief"
228+ "bright"
229+ "bring"
230+ "brisk"
231+ "broccoli"
232+ "broken"
233+ "bronze"
234+ "broom"
235+ "brother"
236+ "brown"
237+ "brush"
238+ "bubble"
239+ "buddy"
240+ "budget"
241+ "buffalo"
242+ "build"
243+ "bulb"
244+ "bulk"
245+ "bullet"
246+ "bundle"
247+ "bunker"
248+ "burden"
249+ "burger"
250+ "burst"
251+ "bus"
252+ "business"
253+ "busy"
254+ "butter"
255+ "buyer"
256+ "buzz"
257+ "cabbage"
258+ "cabin"
259+ "cable"
260+ "cactus"
261+ "cage"
262+ "cake"
263+ "call"
264+ "calm"
265+ "camera"
266+ "camp"
267+ "can"
268+ "canal"
269+ "cancel"
270+ "candy"
271+ "cannon"
272+ "canoe"
273+ "canvas"
274+ "canyon"
275+ "capable"
276+ "capital"
277+ "captain"
278+ "car"
279+ "carbon"
280+ "card"
281+ "cargo"
282+ "carpet"
283+ "carry"
284+ "cart"
285+ "case"
286+ "cash"
287+ "casino"
288+ "castle"
289+ "casual"
290+ "cat"
291+ "catalog"
292+ "catch"
293+ "category"
294+ "cattle"
295+ "caught"
296+ "cause"
297+ "caution"
298+ "cave"
299+ "ceiling"
300+ "celery"
301+ "cement"
302+ "census"
303+ "century"
304+ "cereal"
305+ "certain"
306+ "chair"
307+ "chalk"
308+ "champion"
309+ "change"
310+ "chaos"
311+ "chapter"
312+ "charge"
313+ "chase"
314+ "chat"
315+ "cheap"
316+ "check"
317+ "cheese"
318+ "chef"
319+ "cherry"
320+ "chest"
321+ "chicken"
322+ "chief"
323+ "child"
324+ "chimney"
325+ "choice"
326+ "choose"
327+ "chronic"
328+ "chuckle"
329+ "chunk"
330+ "churn"
331+ "cigar"
332+ "cinnamon"
333+ "circle"
334+ "citizen"
335+ "city"
336+ "civil"
337+ "claim"
338+ "clap"
339+ "clarify"
340+ "claw"
341+ "clay"
342+ "clean"
343+ "clerk"
344+ "clever"
345+ "click"
346+ "client"
347+ "cliff"
348+ "climb"
349+ "clinic"
350+ "clip"
351+ "clock"
352+ "clog"
353+ "close"
354+ "cloth"
355+ "cloud"
356+ "clown"
357+ "club"
358+ "clump"
359+ "cluster"
360+ "clutch"
361+ "coach"
362+ "coast"
363+ "coconut"
364+ "code"
365+ "coffee"
366+ "coil"
367+ "coin"
368+ "collect"
369+ "color"
370+ "column"
371+ "combine"
372+ "come"
373+ "comfort"
374+ "comic"
375+ "common"
376+ "company"
377+ "concert"
378+ "conduct"
379+ "confirm"
380+ "congress"
381+ "connect"
382+ "consider"
383+ "control"
384+ "convince"
385+ "cook"
386+ "cool"
387+ "copper"
388+ "copy"
389+ "coral"
390+ "core"
391+ "corn"
392+ "correct"
393+ "cost"
394+ "cotton"
395+ "couch"
396+ "country"
397+ "couple"
398+ "course"
399+ "cousin"
400+ "cover"
401+ "coyote"
402+ "crack"
403+ "cradle"
404+ "craft"
405+ "cram"
406+ "crane"
407+ "crash"
408+ "crater"
409+ "crawl"
410+ "crazy"
411+ "cream"
412+ "credit"
413+ "creek"
414+ "crew"
415+ "cricket"
416+ "crime"
417+ "crisp"
418+ "critic"
419+ "crop"
420+ "cross"
421+ "crouch"
422+ "crowd"
423+ "crucial"
424+ "cruel"
425+ "cruise"
426+ "crumble"
427+ "crunch"
428+ "crush"
429+ "cry"
430+ "crystal"
431+ "cube"
432+ "culture"
433+ "cup"
434+ "cupboard"
435+ "curious"
436+ "current"
437+ "curtain"
438+ "curve"
439+ "cushion"
440+ "custom"
441+ "cute"
442+ "cycle"
443+ "dad"
444+ "damage"
445+ "damp"
446+ "dance"
447+ "danger"
448+ "daring"
449+ "dash"
450+ "daughter"
451+ "dawn"
452+ "day"
453+ "deal"
454+ "debate"
455+ "debris"
456+ "decade"
457+ "december"
458+ "decide"
459+ "decline"
460+ "decorate"
461+ "decrease"
462+ "deer"
463+ "defense"
464+ "define"
465+ "defy"
466+ "degree"
467+ "delay"
468+ "deliver"
469+ "demand"
470+ "demise"
471+ "denial"
472+ "dentist"
473+ "deny"
474+ "depart"
475+ "depend"
476+ "deposit"
477+ "depth"
478+ "deputy"
479+ "derive"
480+ "describe"
481+ "desert"
482+ "design"
483+ "desk"
484+ "despair"
485+ "destroy"
486+ "detail"
487+ "detect"
488+ "develop"
489+ "device"
490+ "devote"
491+ "diagram"
492+ "dial"
493+ "diamond"
494+ "diary"
495+ "dice"
496+ "diesel"
497+ "diet"
498+ "differ"
499+ "digital"
500+ "dignity"
501+ "dilemma"
502+ "dinner"
503+ "dinosaur"
504+ "direct"
505+ "dirt"
506+ "disagree"
507+ "discover"
508+ "disease"
509+ "dish"
510+ "dismiss"
511+ "disorder"
512+ "display"
513+ "distance"
514+ "divert"
515+ "divide"
516+ "divorce"
517+ "dizzy"
518+ "doctor"
519+ "document"
520+ "dog"
521+ "doll"
522+ "dolphin"
523+ "domain"
524+ "donate"
525+ "donkey"
526+ "donor"
527+ "door"
528+ "dose"
529+ "double"
530+ "dove"
531+ "draft"
532+ "dragon"
533+ "drama"
534+ "drastic"
535+ "draw"
536+ "dream"
537+ "dress"
538+ "drift"
539+ "drill"
540+ "drink"
541+ "drip"
542+ "drive"
543+ "drop"
544+ "drum"
545+ "dry"
546+ "duck"
547+ "dumb"
548+ "dune"
549+ "during"
550+ "dust"
551+ "dutch"
552+ "duty"
553+ "dwarf"
554+ "dynamic"
555+ "eager"
556+ "eagle"
557+ "early"
558+ "earn"
559+ "earth"
560+ "easily"
561+ "east"
562+ "easy"
563+ "echo"
564+ "ecology"
565+ "economy"
566+ "edge"
567+ "edit"
568+ "educate"
569+ "effort"
570+ "egg"
571+ "eight"
572+ "either"
573+ "elbow"
574+ "elder"
575+ "electric"
576+ "elegant"
577+ "element"
578+ "elephant"
579+ "elevator"
580+ "elite"
581+ "else"
582+ "embark"
583+ "embody"
584+ "embrace"
585+ "emerge"
586+ "emotion"
587+ "employ"
588+ "empower"
589+ "empty"
590+ "enable"
591+ "enact"
592+ "end"
593+ "endless"
594+ "endorse"
595+ "enemy"
596+ "energy"
597+ "enforce"
598+ "engage"
599+ "engine"
600+ "enhance"
601+ "enjoy"
602+ "enlist"
603+ "enough"
604+ "enrich"
605+ "enroll"
606+ "ensure"
607+ "enter"
608+ "entire"
609+ "entry"
610+ "envelope"
611+ "episode"
612+ "equal"
613+ "equip"
614+ "era"
615+ "erase"
616+ "erode"
617+ "erosion"
618+ "error"
619+ "erupt"
620+ "escape"
621+ "essay"
622+ "essence"
623+ "estate"
624+ "eternal"
625+ "ethics"
626+ "evidence"
627+ "evil"
628+ "evoke"
629+ "evolve"
630+ "exact"
631+ "example"
632+ "excess"
633+ "exchange"
634+ "excite"
635+ "exclude"
636+ "excuse"
637+ "execute"
638+ "exercise"
639+ "exhaust"
640+ "exhibit"
641+ "exile"
642+ "exist"
643+ "exit"
644+ "exotic"
645+ "expand"
646+ "expect"
647+ "expire"
648+ "explain"
649+ "expose"
650+ "express"
651+ "extend"
652+ "extra"
653+ "eye"
654+ "eyebrow"
655+ "fabric"
656+ "face"
657+ "faculty"
658+ "fade"
659+ "faint"
660+ "faith"
661+ "fall"
662+ "false"
663+ "fame"
664+ "family"
665+ "famous"
666+ "fan"
667+ "fancy"
668+ "fantasy"
669+ "farm"
670+ "fashion"
671+ "fat"
672+ "fatal"
673+ "father"
674+ "fatigue"
675+ "fault"
676+ "favorite"
677+ "feature"
678+ "february"
679+ "federal"
680+ "fee"
681+ "feed"
682+ "feel"
683+ "female"
684+ "fence"
685+ "festival"
686+ "fetch"
687+ "fever"
688+ "few"
689+ "fiber"
690+ "fiction"
691+ "field"
692+ "figure"
693+ "file"
694+ "film"
695+ "filter"
696+ "final"
697+ "find"
698+ "fine"
699+ "finger"
700+ "finish"
701+ "fire"
702+ "firm"
703+ "first"
704+ "fiscal"
705+ "fish"
706+ "fit"
707+ "fitness"
708+ "fix"
709+ "flag"
710+ "flame"
711+ "flash"
712+ "flat"
713+ "flavor"
714+ "flee"
715+ "flight"
716+ "flip"
717+ "float"
718+ "flock"
719+ "floor"
720+ "flower"
721+ "fluid"
722+ "flush"
723+ "fly"
724+ "foam"
725+ "focus"
726+ "fog"
727+ "foil"
728+ "fold"
729+ "follow"
730+ "food"
731+ "foot"
732+ "force"
733+ "forest"
734+ "forget"
735+ "fork"
736+ "fortune"
737+ "forum"
738+ "forward"
739+ "fossil"
740+ "foster"
741+ "found"
742+ "fox"
743+ "fragile"
744+ "frame"
745+ "frequent"
746+ "fresh"
747+ "friend"
748+ "fringe"
749+ "frog"
750+ "front"
751+ "frost"
752+ "frown"
753+ "frozen"
754+ "fruit"
755+ "fuel"
756+ "fun"
757+ "funny"
758+ "furnace"
759+ "fury"
760+ "future"
761+ "gadget"
762+ "gain"
763+ "galaxy"
764+ "gallery"
765+ "game"
766+ "gap"
767+ "garage"
768+ "garbage"
769+ "garden"
770+ "garlic"
771+ "garment"
772+ "gas"
773+ "gasp"
774+ "gate"
775+ "gather"
776+ "gauge"
777+ "gaze"
778+ "general"
779+ "genius"
780+ "genre"
781+ "gentle"
782+ "genuine"
783+ "gesture"
784+ "ghost"
785+ "giant"
786+ "gift"
787+ "giggle"
788+ "ginger"
789+ "giraffe"
790+ "girl"
791+ "give"
792+ "glad"
793+ "glance"
794+ "glare"
795+ "glass"
796+ "glide"
797+ "glimpse"
798+ "globe"
799+ "gloom"
800+ "glory"
801+ "glove"
802+ "glow"
803+ "glue"
804+ "goat"
805+ "goddess"
806+ "gold"
807+ "good"
808+ "goose"
809+ "gorilla"
810+ "gospel"
811+ "gossip"
812+ "govern"
813+ "gown"
814+ "grab"
815+ "grace"
816+ "grain"
817+ "grant"
818+ "grape"
819+ "grass"
820+ "gravity"
821+ "great"
822+ "green"
823+ "grid"
824+ "grief"
825+ "grit"
826+ "grocery"
827+ "group"
828+ "grow"
829+ "grunt"
830+ "guard"
831+ "guess"
832+ "guide"
833+ "guilt"
834+ "guitar"
835+ "gun"
836+ "gym"
837+ "habit"
838+ "hair"
839+ "half"
840+ "hammer"
841+ "hamster"
842+ "hand"
843+ "happy"
844+ "harbor"
845+ "hard"
846+ "harsh"
847+ "harvest"
848+ "hat"
849+ "have"
850+ "hawk"
851+ "hazard"
852+ "head"
853+ "health"
854+ "heart"
855+ "heavy"
856+ "hedgehog"
857+ "height"
858+ "hello"
859+ "helmet"
860+ "help"
861+ "hen"
862+ "hero"
863+ "hidden"
864+ "high"
865+ "hill"
866+ "hint"
867+ "hip"
868+ "hire"
869+ "history"
870+ "hobby"
871+ "hockey"
872+ "hold"
873+ "hole"
874+ "holiday"
875+ "hollow"
876+ "home"
877+ "honey"
878+ "hood"
879+ "hope"
880+ "horn"
881+ "horror"
882+ "horse"
883+ "hospital"
884+ "host"
885+ "hotel"
886+ "hour"
887+ "hover"
888+ "hub"
889+ "huge"
890+ "human"
891+ "humble"
892+ "humor"
893+ "hundred"
894+ "hungry"
895+ "hunt"
896+ "hurdle"
897+ "hurry"
898+ "hurt"
899+ "husband"
900+ "hybrid"
901+ "ice"
902+ "icon"
903+ "idea"
904+ "identify"
905+ "idle"
906+ "ignore"
907+ "ill"
908+ "illegal"
909+ "illness"
910+ "image"
911+ "imitate"
912+ "immense"
913+ "immune"
914+ "impact"
915+ "impose"
916+ "improve"
917+ "impulse"
918+ "inch"
919+ "include"
920+ "income"
921+ "increase"
922+ "index"
923+ "indicate"
924+ "indoor"
925+ "industry"
926+ "infant"
927+ "inflict"
928+ "inform"
929+ "inhale"
930+ "inherit"
931+ "initial"
932+ "inject"
933+ "injury"
934+ "inmate"
935+ "inner"
936+ "innocent"
937+ "input"
938+ "inquiry"
939+ "insane"
940+ "insect"
941+ "inside"
942+ "inspire"
943+ "install"
944+ "intact"
945+ "interest"
946+ "into"
947+ "invest"
948+ "invite"
949+ "involve"
950+ "iron"
951+ "island"
952+ "isolate"
953+ "issue"
954+ "item"
955+ "ivory"
956+ "jacket"
957+ "jaguar"
958+ "jar"
959+ "jazz"
960+ "jealous"
961+ "jeans"
962+ "jelly"
963+ "jewel"
964+ "job"
965+ "join"
966+ "joke"
967+ "journey"
968+ "joy"
969+ "judge"
970+ "juice"
971+ "jump"
972+ "jungle"
973+ "junior"
974+ "junk"
975+ "just"
976+ "kangaroo"
977+ "keen"
978+ "keep"
979+ "ketchup"
980+ "key"
981+ "kick"
982+ "kid"
983+ "kidney"
984+ "kind"
985+ "kingdom"
986+ "kiss"
987+ "kit"
988+ "kitchen"
989+ "kite"
990+ "kitten"
991+ "kiwi"
992+ "knee"
993+ "knife"
994+ "knock"
995+ "know"
996+ "lab"
997+ "label"
998+ "labor"
999+ "ladder"
1000+ "lady"
1001+ "lake"
1002+ "lamp"
1003+ "language"
1004+ "laptop"
1005+ "large"
1006+ "later"
1007+ "latin"
1008+ "laugh"
1009+ "laundry"
1010+ "lava"
1011+ "law"
1012+ "lawn"
1013+ "lawsuit"
1014+ "layer"
1015+ "lazy"
1016+ "leader"
1017+ "leaf"
1018+ "learn"
1019+ "leave"
1020+ "lecture"
1021+ "left"
1022+ "leg"
1023+ "legal"
1024+ "legend"
1025+ "leisure"
1026+ "lemon"
1027+ "lend"
1028+ "length"
1029+ "lens"
1030+ "leopard"
1031+ "lesson"
1032+ "letter"
1033+ "level"
1034+ "liar"
1035+ "liberty"
1036+ "library"
1037+ "license"
1038+ "life"
1039+ "lift"
1040+ "light"
1041+ "like"
1042+ "limb"
1043+ "limit"
1044+ "link"
1045+ "lion"
1046+ "liquid"
1047+ "list"
1048+ "little"
1049+ "live"
1050+ "lizard"
1051+ "load"
1052+ "loan"
1053+ "lobster"
1054+ "local"
1055+ "lock"
1056+ "logic"
1057+ "lonely"
1058+ "long"
1059+ "loop"
1060+ "lottery"
1061+ "loud"
1062+ "lounge"
1063+ "love"
1064+ "loyal"
1065+ "lucky"
1066+ "luggage"
1067+ "lumber"
1068+ "lunar"
1069+ "lunch"
1070+ "luxury"
1071+ "lyrics"
1072+ "machine"
1073+ "mad"
1074+ "magic"
1075+ "magnet"
1076+ "maid"
1077+ "mail"
1078+ "main"
1079+ "major"
1080+ "make"
1081+ "mammal"
1082+ "man"
1083+ "manage"
1084+ "mandate"
1085+ "mango"
1086+ "mansion"
1087+ "manual"
1088+ "maple"
1089+ "marble"
1090+ "march"
1091+ "margin"
1092+ "marine"
1093+ "market"
1094+ "marriage"
1095+ "mask"
1096+ "mass"
1097+ "master"
1098+ "match"
1099+ "material"
1100+ "math"
1101+ "matrix"
1102+ "matter"
1103+ "maximum"
1104+ "maze"
1105+ "meadow"
1106+ "mean"
1107+ "measure"
1108+ "meat"
1109+ "mechanic"
1110+ "medal"
1111+ "media"
1112+ "melody"
1113+ "melt"
1114+ "member"
1115+ "memory"
1116+ "mention"
1117+ "menu"
1118+ "mercy"
1119+ "merge"
1120+ "merit"
1121+ "merry"
1122+ "mesh"
1123+ "message"
1124+ "metal"
1125+ "method"
1126+ "middle"
1127+ "midnight"
1128+ "milk"
1129+ "million"
1130+ "mimic"
1131+ "mind"
1132+ "minimum"
1133+ "minor"
1134+ "minute"
1135+ "miracle"
1136+ "mirror"
1137+ "misery"
1138+ "miss"
1139+ "mistake"
1140+ "mix"
1141+ "mixed"
1142+ "mixture"
1143+ "mobile"
1144+ "model"
1145+ "modify"
1146+ "mom"
1147+ "moment"
1148+ "monitor"
1149+ "monkey"
1150+ "monster"
1151+ "month"
1152+ "moon"
1153+ "moral"
1154+ "more"
1155+ "morning"
1156+ "mosquito"
1157+ "mother"
1158+ "motion"
1159+ "motor"
1160+ "mountain"
1161+ "mouse"
1162+ "move"
1163+ "movie"
1164+ "much"
1165+ "muffin"
1166+ "mule"
1167+ "multiply"
1168+ "muscle"
1169+ "museum"
1170+ "mushroom"
1171+ "music"
1172+ "must"
1173+ "mutual"
1174+ "myself"
1175+ "mystery"
1176+ "myth"
1177+ "naive"
1178+ "name"
1179+ "napkin"
1180+ "narrow"
1181+ "nasty"
1182+ "nation"
1183+ "nature"
1184+ "near"
1185+ "neck"
1186+ "need"
1187+ "negative"
1188+ "neglect"
1189+ "neither"
1190+ "nephew"
1191+ "nerve"
1192+ "nest"
1193+ "net"
1194+ "network"
1195+ "neutral"
1196+ "never"
1197+ "news"
1198+ "next"
1199+ "nice"
1200+ "night"
1201+ "noble"
1202+ "noise"
1203+ "nominee"
1204+ "noodle"
1205+ "normal"
1206+ "north"
1207+ "nose"
1208+ "notable"
1209+ "note"
1210+ "nothing"
1211+ "notice"
1212+ "novel"
1213+ "now"
1214+ "nuclear"
1215+ "number"
1216+ "nurse"
1217+ "nut"
1218+ "oak"
1219+ "obey"
1220+ "object"
1221+ "oblige"
1222+ "obscure"
1223+ "observe"
1224+ "obtain"
1225+ "obvious"
1226+ "occur"
1227+ "ocean"
1228+ "october"
1229+ "odor"
1230+ "off"
1231+ "offer"
1232+ "office"
1233+ "often"
1234+ "oil"
1235+ "okay"
1236+ "old"
1237+ "olive"
1238+ "olympic"
1239+ "omit"
1240+ "once"
1241+ "one"
1242+ "onion"
1243+ "online"
1244+ "only"
1245+ "open"
1246+ "opera"
1247+ "opinion"
1248+ "oppose"
1249+ "option"
1250+ "orange"
1251+ "orbit"
1252+ "orchard"
1253+ "order"
1254+ "ordinary"
1255+ "organ"
1256+ "orient"
1257+ "original"
1258+ "orphan"
1259+ "ostrich"
1260+ "other"
1261+ "outdoor"
1262+ "outer"
1263+ "output"
1264+ "outside"
1265+ "oval"
1266+ "oven"
1267+ "over"
1268+ "own"
1269+ "owner"
1270+ "oxygen"
1271+ "oyster"
1272+ "ozone"
1273+ "pact"
1274+ "paddle"
1275+ "page"
1276+ "pair"
1277+ "palace"
1278+ "palm"
1279+ "panda"
1280+ "panel"
1281+ "panic"
1282+ "panther"
1283+ "paper"
1284+ "parade"
1285+ "parent"
1286+ "park"
1287+ "parrot"
1288+ "party"
1289+ "pass"
1290+ "patch"
1291+ "path"
1292+ "patient"
1293+ "patrol"
1294+ "pattern"
1295+ "pause"
1296+ "pave"
1297+ "payment"
1298+ "peace"
1299+ "peanut"
1300+ "pear"
1301+ "peasant"
1302+ "pelican"
1303+ "pen"
1304+ "penalty"
1305+ "pencil"
1306+ "people"
1307+ "pepper"
1308+ "perfect"
1309+ "permit"
1310+ "person"
1311+ "pet"
1312+ "phone"
1313+ "photo"
1314+ "phrase"
1315+ "physical"
1316+ "piano"
1317+ "picnic"
1318+ "picture"
1319+ "piece"
1320+ "pig"
1321+ "pigeon"
1322+ "pill"
1323+ "pilot"
1324+ "pink"
1325+ "pioneer"
1326+ "pipe"
1327+ "pistol"
1328+ "pitch"
1329+ "pizza"
1330+ "place"
1331+ "planet"
1332+ "plastic"
1333+ "plate"
1334+ "play"
1335+ "please"
1336+ "pledge"
1337+ "pluck"
1338+ "plug"
1339+ "plunge"
1340+ "poem"
1341+ "poet"
1342+ "point"
1343+ "polar"
1344+ "pole"
1345+ "police"
1346+ "pond"
1347+ "pony"
1348+ "pool"
1349+ "popular"
1350+ "portion"
1351+ "position"
1352+ "possible"
1353+ "post"
1354+ "potato"
1355+ "pottery"
1356+ "poverty"
1357+ "powder"
1358+ "power"
1359+ "practice"
1360+ "praise"
1361+ "predict"
1362+ "prefer"
1363+ "prepare"
1364+ "present"
1365+ "pretty"
1366+ "prevent"
1367+ "price"
1368+ "pride"
1369+ "primary"
1370+ "print"
1371+ "priority"
1372+ "prison"
1373+ "private"
1374+ "prize"
1375+ "problem"
1376+ "process"
1377+ "produce"
1378+ "profit"
1379+ "program"
1380+ "project"
1381+ "promote"
1382+ "proof"
1383+ "property"
1384+ "prosper"
1385+ "protect"
1386+ "proud"
1387+ "provide"
1388+ "public"
1389+ "pudding"
1390+ "pull"
1391+ "pulp"
1392+ "pulse"
1393+ "pumpkin"
1394+ "punch"
1395+ "pupil"
1396+ "puppy"
1397+ "purchase"
1398+ "purity"
1399+ "purpose"
1400+ "purse"
1401+ "push"
1402+ "put"
1403+ "puzzle"
1404+ "pyramid"
1405+ "quality"
1406+ "quantum"
1407+ "quarter"
1408+ "question"
1409+ "quick"
1410+ "quit"
1411+ "quiz"
1412+ "quote"
1413+ "rabbit"
1414+ "raccoon"
1415+ "race"
1416+ "rack"
1417+ "radar"
1418+ "radio"
1419+ "rail"
1420+ "rain"
1421+ "raise"
1422+ "rally"
1423+ "ramp"
1424+ "ranch"
1425+ "random"
1426+ "range"
1427+ "rapid"
1428+ "rare"
1429+ "rate"
1430+ "rather"
1431+ "raven"
1432+ "raw"
1433+ "razor"
1434+ "ready"
1435+ "real"
1436+ "reason"
1437+ "rebel"
1438+ "rebuild"
1439+ "recall"
1440+ "receive"
1441+ "recipe"
1442+ "record"
1443+ "recycle"
1444+ "reduce"
1445+ "reflect"
1446+ "reform"
1447+ "refuse"
1448+ "region"
1449+ "regret"
1450+ "regular"
1451+ "reject"
1452+ "relax"
1453+ "release"
1454+ "relief"
1455+ "rely"
1456+ "remain"
1457+ "remember"
1458+ "remind"
1459+ "remove"
1460+ "render"
1461+ "renew"
1462+ "rent"
1463+ "reopen"
1464+ "repair"
1465+ "repeat"
1466+ "replace"
1467+ "report"
1468+ "require"
1469+ "rescue"
1470+ "resemble"
1471+ "resist"
1472+ "resource"
1473+ "response"
1474+ "result"
1475+ "retire"
1476+ "retreat"
1477+ "return"
1478+ "reunion"
1479+ "reveal"
1480+ "review"
1481+ "reward"
1482+ "rhythm"
1483+ "rib"
1484+ "ribbon"
1485+ "rice"
1486+ "rich"
1487+ "ride"
1488+ "ridge"
1489+ "rifle"
1490+ "right"
1491+ "rigid"
1492+ "ring"
1493+ "riot"
1494+ "ripple"
1495+ "risk"
1496+ "ritual"
1497+ "rival"
1498+ "river"
1499+ "road"
1500+ "roast"
1501+ "robot"
1502+ "robust"
1503+ "rocket"
1504+ "romance"
1505+ "roof"
1506+ "rookie"
1507+ "room"
1508+ "rose"
1509+ "rotate"
1510+ "rough"
1511+ "round"
1512+ "route"
1513+ "royal"
1514+ "rubber"
1515+ "rude"
1516+ "rug"
1517+ "rule"
1518+ "run"
1519+ "runway"
1520+ "rural"
1521+ "sad"
1522+ "saddle"
1523+ "sadness"
1524+ "safe"
1525+ "sail"
1526+ "salad"
1527+ "salmon"
1528+ "salon"
1529+ "salt"
1530+ "salute"
1531+ "same"
1532+ "sample"
1533+ "sand"
1534+ "satisfy"
1535+ "satoshi"
1536+ "sauce"
1537+ "sausage"
1538+ "save"
1539+ "say"
1540+ "scale"
1541+ "scan"
1542+ "scare"
1543+ "scatter"
1544+ "scene"
1545+ "scheme"
1546+ "school"
1547+ "science"
1548+ "scissors"
1549+ "scorpion"
1550+ "scout"
1551+ "scrap"
1552+ "screen"
1553+ "script"
1554+ "scrub"
1555+ "sea"
1556+ "search"
1557+ "season"
1558+ "seat"
1559+ "second"
1560+ "secret"
1561+ "section"
1562+ "security"
1563+ "seed"
1564+ "seek"
1565+ "segment"
1566+ "select"
1567+ "sell"
1568+ "seminar"
1569+ "senior"
1570+ "sense"
1571+ "sentence"
1572+ "series"
1573+ "service"
1574+ "session"
1575+ "settle"
1576+ "setup"
1577+ "seven"
1578+ "shadow"
1579+ "shaft"
1580+ "shallow"
1581+ "share"
1582+ "shed"
1583+ "shell"
1584+ "sheriff"
1585+ "shield"
1586+ "shift"
1587+ "shine"
1588+ "ship"
1589+ "shiver"
1590+ "shock"
1591+ "shoe"
1592+ "shoot"
1593+ "shop"
1594+ "short"
1595+ "shoulder"
1596+ "shove"
1597+ "shrimp"
1598+ "shrug"
1599+ "shuffle"
1600+ "shy"
1601+ "sibling"
1602+ "sick"
1603+ "side"
1604+ "siege"
1605+ "sight"
1606+ "sign"
1607+ "silent"
1608+ "silk"
1609+ "silly"
1610+ "silver"
1611+ "similar"
1612+ "simple"
1613+ "since"
1614+ "sing"
1615+ "siren"
1616+ "sister"
1617+ "situate"
1618+ "six"
1619+ "size"
1620+ "skate"
1621+ "sketch"
1622+ "ski"
1623+ "skill"
1624+ "skin"
1625+ "skirt"
1626+ "skull"
1627+ "slab"
1628+ "slam"
1629+ "sleep"
1630+ "slender"
1631+ "slice"
1632+ "slide"
1633+ "slight"
1634+ "slim"
1635+ "slogan"
1636+ "slot"
1637+ "slow"
1638+ "slush"
1639+ "small"
1640+ "smart"
1641+ "smile"
1642+ "smoke"
1643+ "smooth"
1644+ "snack"
1645+ "snake"
1646+ "snap"
1647+ "sniff"
1648+ "snow"
1649+ "soap"
1650+ "soccer"
1651+ "social"
1652+ "sock"
1653+ "soda"
1654+ "soft"
1655+ "solar"
1656+ "soldier"
1657+ "solid"
1658+ "solution"
1659+ "solve"
1660+ "someone"
1661+ "song"
1662+ "soon"
1663+ "sorry"
1664+ "sort"
1665+ "soul"
1666+ "sound"
1667+ "soup"
1668+ "source"
1669+ "south"
1670+ "space"
1671+ "spare"
1672+ "spatial"
1673+ "spawn"
1674+ "speak"
1675+ "special"
1676+ "speed"
1677+ "spell"
1678+ "spend"
1679+ "sphere"
1680+ "spice"
1681+ "spider"
1682+ "spike"
1683+ "spin"
1684+ "spirit"
1685+ "split"
1686+ "spoil"
1687+ "sponsor"
1688+ "spoon"
1689+ "sport"
1690+ "spot"
1691+ "spray"
1692+ "spread"
1693+ "spring"
1694+ "spy"
1695+ "square"
1696+ "squeeze"
1697+ "squirrel"
1698+ "stable"
1699+ "stadium"
1700+ "staff"
1701+ "stage"
1702+ "stairs"
1703+ "stamp"
1704+ "stand"
1705+ "start"
1706+ "state"
1707+ "stay"
1708+ "steak"
1709+ "steel"
1710+ "stem"
1711+ "step"
1712+ "stereo"
1713+ "stick"
1714+ "still"
1715+ "sting"
1716+ "stock"
1717+ "stomach"
1718+ "stone"
1719+ "stool"
1720+ "story"
1721+ "stove"
1722+ "strategy"
1723+ "street"
1724+ "strike"
1725+ "strong"
1726+ "struggle"
1727+ "student"
1728+ "stuff"
1729+ "stumble"
1730+ "style"
1731+ "subject"
1732+ "submit"
1733+ "subway"
1734+ "success"
1735+ "such"
1736+ "sudden"
1737+ "suffer"
1738+ "sugar"
1739+ "suggest"
1740+ "suit"
1741+ "summer"
1742+ "sun"
1743+ "sunny"
1744+ "sunset"
1745+ "super"
1746+ "supply"
1747+ "supreme"
1748+ "sure"
1749+ "surface"
1750+ "surge"
1751+ "surprise"
1752+ "surround"
1753+ "survey"
1754+ "suspect"
1755+ "sustain"
1756+ "swallow"
1757+ "swamp"
1758+ "swap"
1759+ "swarm"
1760+ "swear"
1761+ "sweet"
1762+ "swift"
1763+ "swim"
1764+ "swing"
1765+ "switch"
1766+ "sword"
1767+ "symbol"
1768+ "symptom"
1769+ "syrup"
1770+ "system"
1771+ "table"
1772+ "tackle"
1773+ "tag"
1774+ "tail"
1775+ "talent"
1776+ "talk"
1777+ "tank"
1778+ "tape"
1779+ "target"
1780+ "task"
1781+ "taste"
1782+ "tattoo"
1783+ "taxi"
1784+ "teach"
1785+ "team"
1786+ "tell"
1787+ "ten"
1788+ "tenant"
1789+ "tennis"
1790+ "tent"
1791+ "term"
1792+ "test"
1793+ "text"
1794+ "thank"
1795+ "that"
1796+ "theme"
1797+ "then"
1798+ "theory"
1799+ "there"
1800+ "they"
1801+ "thing"
1802+ "this"
1803+ "thought"
1804+ "three"
1805+ "thrive"
1806+ "throw"
1807+ "thumb"
1808+ "thunder"
1809+ "ticket"
1810+ "tide"
1811+ "tiger"
1812+ "tilt"
1813+ "timber"
1814+ "time"
1815+ "tiny"
1816+ "tip"
1817+ "tired"
1818+ "tissue"
1819+ "title"
1820+ "toast"
1821+ "tobacco"
1822+ "today"
1823+ "toddler"
1824+ "toe"
1825+ "together"
1826+ "toilet"
1827+ "token"
1828+ "tomato"
1829+ "tomorrow"
1830+ "tone"
1831+ "tongue"
1832+ "tonight"
1833+ "tool"
1834+ "tooth"
1835+ "top"
1836+ "topic"
1837+ "topple"
1838+ "torch"
1839+ "tornado"
1840+ "tortoise"
1841+ "toss"
1842+ "total"
1843+ "tourist"
1844+ "toward"
1845+ "tower"
1846+ "town"
1847+ "toy"
1848+ "track"
1849+ "trade"
1850+ "traffic"
1851+ "tragic"
1852+ "train"
1853+ "transfer"
1854+ "trap"
1855+ "trash"
1856+ "travel"
1857+ "tray"
1858+ "treat"
1859+ "tree"
1860+ "trend"
1861+ "trial"
1862+ "tribe"
1863+ "trick"
1864+ "trigger"
1865+ "trim"
1866+ "trip"
1867+ "trophy"
1868+ "trouble"
1869+ "truck"
1870+ "true"
1871+ "truly"
1872+ "trumpet"
1873+ "trust"
1874+ "truth"
1875+ "try"
1876+ "tube"
1877+ "tuition"
1878+ "tumble"
1879+ "tuna"
1880+ "tunnel"
1881+ "turkey"
1882+ "turn"
1883+ "turtle"
1884+ "twelve"
1885+ "twenty"
1886+ "twice"
1887+ "twin"
1888+ "twist"
1889+ "two"
1890+ "type"
1891+ "typical"
1892+ "ugly"
1893+ "umbrella"
1894+ "unable"
1895+ "unaware"
1896+ "uncle"
1897+ "uncover"
1898+ "under"
1899+ "undo"
1900+ "unfair"
1901+ "unfold"
1902+ "unhappy"
1903+ "uniform"
1904+ "unique"
1905+ "unit"
1906+ "universe"
1907+ "unknown"
1908+ "unlock"
1909+ "until"
1910+ "unusual"
1911+ "unveil"
1912+ "update"
1913+ "upgrade"
1914+ "uphold"
1915+ "upon"
1916+ "upper"
1917+ "upset"
1918+ "urban"
1919+ "urge"
1920+ "usage"
1921+ "use"
1922+ "used"
1923+ "useful"
1924+ "useless"
1925+ "usual"
1926+ "utility"
1927+ "vacant"
1928+ "vacuum"
1929+ "vague"
1930+ "valid"
1931+ "valley"
1932+ "valve"
1933+ "van"
1934+ "vanish"
1935+ "vapor"
1936+ "various"
1937+ "vast"
1938+ "vault"
1939+ "vehicle"
1940+ "velvet"
1941+ "vendor"
1942+ "venture"
1943+ "venue"
1944+ "verb"
1945+ "verify"
1946+ "version"
1947+ "very"
1948+ "vessel"
1949+ "veteran"
1950+ "viable"
1951+ "vibrant"
1952+ "vicious"
1953+ "victory"
1954+ "video"
1955+ "view"
1956+ "village"
1957+ "vintage"
1958+ "violin"
1959+ "virtual"
1960+ "virus"
1961+ "visa"
1962+ "visit"
1963+ "visual"
1964+ "vital"
1965+ "vivid"
1966+ "vocal"
1967+ "voice"
1968+ "void"
1969+ "volcano"
1970+ "volume"
1971+ "vote"
1972+ "voyage"
1973+ "wage"
1974+ "wagon"
1975+ "wait"
1976+ "walk"
1977+ "wall"
1978+ "walnut"
1979+ "want"
1980+ "warfare"
1981+ "warm"
1982+ "warrior"
1983+ "wash"
1984+ "wasp"
1985+ "waste"
1986+ "water"
1987+ "wave"
1988+ "way"
1989+ "wealth"
1990+ "weapon"
1991+ "wear"
1992+ "weasel"
1993+ "weather"
1994+ "web"
1995+ "wedding"
1996+ "weekend"
1997+ "weird"
1998+ "welcome"
1999+ "west"
2000+ "wet"
2001+ "whale"
2002+ "what"
2003+ "wheat"
2004+ "wheel"
2005+ "when"
2006+ "where"
2007+ "whip"
2008+ "whisper"
2009+ "wide"
2010+ "width"
2011+ "wife"
2012+ "wild"
2013+ "will"
2014+ "win"
2015+ "window"
2016+ "wine"
2017+ "wing"
2018+ "wink"
2019+ "winner"
2020+ "winter"
2021+ "wire"
2022+ "wisdom"
2023+ "wise"
2024+ "wish"
2025+ "witness"
2026+ "wolf"
2027+ "woman"
2028+ "wonder"
2029+ "wood"
2030+ "wool"
2031+ "word"
2032+ "work"
2033+ "world"
2034+ "worry"
2035+ "worth"
2036+ "wrap"
2037+ "wreck"
2038+ "wrestle"
2039+ "wrist"
2040+ "write"
2041+ "wrong"
2042+ "yard"
2043+ "year"
2044+ "yellow"
2045+ "you"
2046+ "young"
2047+ "youth"
2048+ "zebra"
2049+ "zero"
2050+ "zone"
2051+ "zoo"
2052+==
base-desk/lib/bitcoin-utils.hoonnew file+177
@@ -0,0 +1,177 @@
1+:: lib/bitcoin-utils.hoon
2+:: Utilities for working with BTC data types and transactions
3+::
4+/- *bitcoin
5+~% %bitcoin-utils-lib ..part ~
6+|%
7+::
8+:: TODO: move this bit/byt stuff to zuse
9+:: bit/byte utilities
10+::
11+::
12+:: +blop: munge bit and byt sequences (cat, flip, take, drop)
13+::
14+++ blop
15+ ~/ %blop
16+ |_ =bloq
17+ +$ biyts [wid=@ud dat=@]
18+ ++ cat
19+ |= bs=(list biyts)
20+ ^- biyts
21+ :- (roll (turn bs |=(b=biyts -.b)) add)
22+ (can bloq (flop bs))
23+ :: +flip: flip endianness while preserving lead/trail zeroes
24+ ::
25+ ++ flip
26+ |= b=biyts
27+ ^- biyts
28+ [wid.b (rev bloq b)]
29+ :: +take: take n bloqs from front
30+ :: pads front with extra zeroes if n is longer than input
31+ ::
32+ ++ take
33+ |= [n=@ b=biyts]
34+ ^- biyts
35+ ?: (gth n wid.b)
36+ [n dat.b]
37+ [n (rsh [bloq (sub wid.b n)] dat.b)]
38+ :: +drop: drop n bloqs from front
39+ :: returns 0^0 if n >= width
40+ ::
41+ ++ drop
42+ |= [n=@ b=biyts]
43+ ^- biyts
44+ ?: (gte n wid.b)
45+ 0^0x0
46+ =+ n-take=(sub wid.b n)
47+ [n-take (end [bloq n-take] dat.b)]
48+ --
49+++ byt ~(. blop 3)
50+::
51+++ bit
52+ ~/ %bit
53+ =/ bl ~(. blop 0)
54+ |%
55+ ++ cat cat:bl:bit
56+ ++ flip flip:bl:bit
57+ ++ take take:bl:bit
58+ ++ drop drop:bl:bit
59+ ++ from-atoms
60+ |= [bitwidth=@ digits=(list @)]
61+ ^- bits
62+ %- cat:bit
63+ %+ turn digits
64+ |= a=@
65+ ?> (lte (met 0 a) bitwidth)
66+ [bitwidth `@ub`a]
67+ :: +to-atoms: convert bits to atoms of bitwidth
68+ ::
69+ ++ to-atoms
70+ |= [bitwidth=@ bs=bits]
71+ ^- (list @)
72+ =| res=(list @)
73+ ?> =(0 (mod wid.bs bitwidth))
74+ |-
75+ ?: =(0 wid.bs) res
76+ %= $
77+ res (snoc res dat:(take:bit bitwidth bs))
78+ bs (drop:bit bitwidth bs)
79+ ==
80+ --
81+:: big endian sha256: input and output are both MSB first (big endian)
82+::
83+++ sha256
84+ ~/ %sha256
85+ |= =byts
86+ ^- hexb
87+ %- flip:byt
88+ [32 (shay (flip:byt byts))]
89+::
90+++ dsha256
91+ ~/ %dsha256
92+ |= =byts
93+ (sha256 (sha256 byts))
94+::
95+++ hash-160
96+ ~/ %hash-160
97+ |= val=byts
98+ ^- hexb
99+ =, ripemd:crypto
100+ :- 20
101+ %- ripemd-160
102+ (sha256 val)
103+
104+::
105+:: hxb: hex parsing utilities
106+::
107+++ hxb
108+ ~% %hxb ..blop ~
109+ |%
110+ ++ from-cord
111+ ~/ %from-cord
112+ |= h=@t
113+ ^- hexb
114+ ?: =('' h) 1^0x0
115+ :: Add leading 00
116+ ::
117+ =+ (lsh [3 2] h)
118+ :: Group by 4-size block
119+ ::
120+ =+ (rsh [3 2] -)
121+ :: Parse hex to atom
122+ ::
123+ =/ a (need (de:base16:mimes:html -))
124+ [-.a `@ux`+.a]
125+ ::
126+ ++ to-cord
127+ ~/ %to-cord
128+ |= =hexb
129+ ^- cord
130+ (en:base16:mimes:html hexb)
131+ --
132+::
133+:: +csiz: CompactSize integers (a Bitcoin-specific datatype)
134+:: https://btcinformation.org/en/developer-reference#compactsize-unsigned-integers
135+:: - encode: big endian to little endian
136+:: - decode: little endian to big endian
137+::
138+++ csiz
139+ ~% %csiz ..blop ~
140+ |%
141+ ++ en
142+ ~/ %en
143+ |= a=@
144+ ^- hexb
145+ =/ l=@ (met 3 a)
146+ ?: =(l 0) 1^a
147+ ?: =(l 1) 1^a
148+ ?: =(l 2) (cat:byt ~[1^0xfd (flip:byt 2^a)])
149+ ?: (lte l 4) (cat:byt ~[1^0xfe (flip:byt 4^a)])
150+ ?: (lte l 8) (cat:byt ~[1^0xff (flip:byt 8^a)])
151+ ~|("Cannot encode CompactSize longer than 8 bytes" !!)
152+ ::
153+ ++ de
154+ ~/ %de
155+ |= h=hexb
156+ ^- [n=hexb rest=hexb]
157+ =/ s=@ux dat:(take:byt 1 h)
158+ ?: (lth s 0xfd) [1^s (drop:byt 1 h)]
159+ ~| "Invalid compact-size at start of {<h>}"
160+ =/ len=bloq
161+ ?+ s !!
162+ %0xfd 1
163+ %0xfe 2
164+ %0xff 3
165+ ==
166+ :_ (drop:byt (add 1 (bex len)) h)
167+ %- flip:byt
168+ (take:byt (bex len) (drop:byt 1 h))
169+ :: +dea: atom instead of hexb for parsed CompactSize
170+ ::
171+ ++ dea
172+ |= h=hexb
173+ ^- [a=@ rest=hexb]
174+ => (de h)
175+ [dat.n rest]
176+ --
177+--
base-desk/lib/cram.hoonnew file+61
@@ -0,0 +1,61 @@
1+|%
2+++ static :: freeze .mdh hoon subset
3+ |= gen=hoon ^- [inf=(map term dime) elm=manx]
4+ ?+ -.gen
5+ =/ gen ~(open ap gen)
6+ ?: =(gen ^gen) ~|([%cram-dynamic -.gen] !!)
7+ $(gen gen)
8+ ::
9+ %xray [~ (single (shut gen))]
10+ ^ [(malt (frontmatter p.gen)) (single (shut q.gen))]
11+ ==
12+::
13+++ single :: unwrap one-elem marl
14+ |= xml=marl ^- manx
15+ ?: ?=([* ~] xml) i.xml
16+ ~|(%many-elems !!)
17+::
18+++ shut-mart :: xml attrs
19+ |=([n=mane v=(list beer:hoot)] [n (turn v |=(a=beer:hoot ?^(a !! a)))])
20+::
21+++ shut :: as xml constant
22+ |= gen=hoon ^- marl
23+ ?+ -.gen ~|([%bad-xml -.gen] !!)
24+ %dbug $(gen q.gen)
25+ ::
26+ %xray
27+ [[n.g.p.gen (turn a.g.p.gen shut-mart)] $(gen [%mcts c.p.gen])]~
28+ ::
29+ %mcts
30+ ?~ p.gen ~
31+ =- (weld - $(p.gen t.p.gen))
32+ ?^ -.i.p.gen $(gen [%xray i.p.gen])
33+ ~| [%shut-tuna -.i.p.gen]
34+ ?+ -.i.p.gen !!
35+ %manx ?>(?=(%xray -.p.i.p.gen) $(gen p.i.p.gen))
36+ %marl ?>(?=(%mcts -.p.i.p.gen) $(gen p.i.p.gen))
37+ ==
38+ ==
39+::
40+::
41+++ frontmatter :: parse ~[[%foo 1] [%bar ~s2]]
42+ |= gen=hoon ^- (list [term dime])
43+ ?: ?=([%bust %null] gen) ~
44+ ?: ?=(%dbug -.gen) $(gen q.gen)
45+ ?. ?=(%clsg -.gen) ~|([%bad-frontmatter -.gen] !!)
46+ %+ turn p.gen
47+ |= gen=hoon
48+ ?. ?=(^ -.gen)
49+ =/ gen ~(open ap gen)
50+ ?: =(gen ^gen) ~|([%bad-frontmatter-elem -.gen] !!)
51+ $(gen gen)
52+ =/ hed (as-dime p.gen)
53+ ?. =(%tas p.hed) ~|([%bad-frontmatter-key-type p.hed] !!)
54+ [q.hed (as-dime q.gen)]
55+::
56+++ as-dime :: %foo ~.foo 0vbar etc
57+ |= gen=hoon ^- dime
58+ ?: ?=(%dbug -.gen) $(gen q.gen)
59+ ?. ?=([?(%rock %sand) @ @] gen) ~|([%bad-literal gen] !!)
60+ +.gen
61+--
base-desk/lib/dbug.hoonnew file+161
@@ -0,0 +1,161 @@
1+:: dbug: agent wrapper for generic debugging tools
2+::
3+:: usage: %-(agent:dbug your-agent)
4+::
5+|%
6++$ poke
7+ $% [%skip depth=@ud =poke]
8+ [%bowl ~]
9+ [%state grab=cord]
10+ [%incoming =about]
11+ [%outgoing =about]
12+ ==
13+::
14++$ about
15+ $@ ~
16+ $% [%ship =ship]
17+ [%path =path]
18+ [%wire =wire]
19+ [%term =term]
20+ ==
21+::
22+++ agent
23+ |= =agent:gall
24+ ^- agent:gall
25+ !.
26+ |_ =bowl:gall
27+ +* this .
28+ ag ~(. agent bowl)
29+ ::
30+ ++ on-poke
31+ |= [=mark =vase]
32+ ^- (quip card:agent:gall agent:gall)
33+ ?. ?=(%dbug mark)
34+ =^ cards agent (on-poke:ag mark vase)
35+ [cards this]
36+ =/ dbug !<(poke vase)
37+ =? dbug ?=([%skip %0 *] dbug) poke.dbug
38+ ?: ?=(%skip -.dbug)
39+ =^ cards agent
40+ %+ on-poke:ag %dbug
41+ !>(`poke`dbug(depth (dec depth.dbug)))
42+ [cards this]
43+ =; =tang
44+ ((%*(. slog pri 1) tang) [~ this])
45+ ?- -.dbug
46+ %bowl [(sell !>(bowl))]~
47+ ::
48+ %state
49+ =? grab.dbug =('' grab.dbug) '-'
50+ =; product=^vase
51+ [(sell product)]~
52+ =/ state=^vase
53+ :: if the underlying app has implemented a /dbug/state scry endpoint,
54+ :: use that vase in place of +on-save's.
55+ ::
56+ =/ result=(each ^vase tang)
57+ (mule |.(q:(need (need (on-peek:ag /x/dbug/state)))))
58+ ?:(?=(%& -.result) p.result on-save:ag)
59+ %+ slap
60+ (slop state !>([bowl=bowl ..zuse]))
61+ (ream grab.dbug)
62+ ::
63+ %incoming
64+ =; =tang
65+ ?^ tang tang
66+ [%leaf "no matching subscriptions"]~
67+ %+ murn
68+ %+ sort ~(tap by sup.bowl)
69+ |= [[* a=[=ship =path]] [* b=[=ship =path]]]
70+ (aor [path ship]:a [path ship]:b)
71+ |= [=duct [=ship =path]]
72+ ^- (unit tank)
73+ =; relevant=?
74+ ?. relevant ~
75+ `>[path=path from=ship duct=duct]<
76+ ?: ?=(~ about.dbug) &
77+ ?- -.about.dbug
78+ %ship =(ship ship.about.dbug)
79+ %path ?=(^ (find path.about.dbug path))
80+ %wire %+ lien duct
81+ |=(=wire ?=(^ (find wire.about.dbug wire)))
82+ %term !!
83+ ==
84+ ::
85+ %outgoing
86+ =; =tang
87+ ?^ tang tang
88+ [%leaf "no matching subscriptions"]~
89+ %+ murn
90+ %+ sort ~(tap by wex.bowl)
91+ |= [[[a=wire *] *] [[b=wire *] *]]
92+ (aor a b)
93+ |= [[=wire =ship =term] [acked=? =path]]
94+ ^- (unit tank)
95+ =; relevant=?
96+ ?. relevant ~
97+ `>[wire=wire agnt=[ship term] path=path ackd=acked]<
98+ ?: ?=(~ about.dbug) &
99+ ?- -.about.dbug
100+ %ship =(ship ship.about.dbug)
101+ %path ?=(^ (find path.about.dbug path))
102+ %wire ?=(^ (find wire.about.dbug wire))
103+ %term =(term term.about.dbug)
104+ ==
105+ ==
106+ ::
107+ ++ on-peek
108+ |= =path
109+ ^- (unit (unit cage))
110+ ?. ?=([@ %dbug *] path)
111+ (on-peek:ag path)
112+ ?+ path [~ ~]
113+ [%u %dbug ~] ``noun+!>(&)
114+ [%x %dbug %state ~] ``noun+!>(on-save:ag)
115+ [%x %dbug %subscriptions ~] ``noun+!>([wex sup]:bowl)
116+ ==
117+ ::
118+ ++ on-init
119+ ^- (quip card:agent:gall agent:gall)
120+ =^ cards agent on-init:ag
121+ [cards this]
122+ ::
123+ ++ on-save on-save:ag
124+ ::
125+ ++ on-load
126+ |= old-state=vase
127+ ^- (quip card:agent:gall agent:gall)
128+ =^ cards agent (on-load:ag old-state)
129+ [cards this]
130+ ::
131+ ++ on-watch
132+ |= =path
133+ ^- (quip card:agent:gall agent:gall)
134+ =^ cards agent (on-watch:ag path)
135+ [cards this]
136+ ::
137+ ++ on-leave
138+ |= =path
139+ ^- (quip card:agent:gall agent:gall)
140+ =^ cards agent (on-leave:ag path)
141+ [cards this]
142+ ::
143+ ++ on-agent
144+ |= [=wire =sign:agent:gall]
145+ ^- (quip card:agent:gall agent:gall)
146+ =^ cards agent (on-agent:ag wire sign)
147+ [cards this]
148+ ::
149+ ++ on-arvo
150+ |= [=wire =sign-arvo]
151+ ^- (quip card:agent:gall agent:gall)
152+ =^ cards agent (on-arvo:ag wire sign-arvo)
153+ [cards this]
154+ ::
155+ ++ on-fail
156+ |= [=term =tang]
157+ ^- (quip card:agent:gall agent:gall)
158+ =^ cards agent (on-fail:ag term tang)
159+ [cards this]
160+ --
161+--
base-desk/lib/default-agent.hoonnew file+69
@@ -0,0 +1,69 @@
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 {<dap.bowl>} with mark {<p.cage>}"
20+ !!
21+::
22+++ on-watch
23+ |= =path
24+ ~| "unexpected subscription to {<dap.bowl>} on path {<path>}"
25+ !!
26+::
27+++ on-leave
28+ |= path
29+ `agent
30+::
31+++ on-peek
32+ |= =path
33+ ~| "unexpected scry into {<dap.bowl>} on path {<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 {<dap.bowl>} on wire {<wire>}" u.p.sign)
44+ `agent
45+ ::
46+ %watch-ack
47+ ?~ p.sign
48+ `agent
49+ =/ =tank leaf+"subscribe failed from {<dap.bowl>} on wire {<wire>}"
50+ %- (slog tank u.p.sign)
51+ `agent
52+ ::
53+ %kick `agent
54+ %fact
55+ ~| "unexpected subscription update to {<dap.bowl>} on wire {<wire>}"
56+ ~| "with mark {<p.cage.sign>}"
57+ !!
58+ ==
59+::
60+++ on-arvo
61+ |= [=wire =sign-arvo]
62+ ~| "unexpected system response {<-.sign-arvo>} to {<dap.bowl>} on wire {<wire>}"
63+ !!
64+::
65+++ on-fail
66+ |= [=term =tang]
67+ %- (slog leaf+"error in {<dap.bowl>}" >term< tang)
68+ `agent
69+--
base-desk/lib/der.hoonnew file+210
@@ -0,0 +1,210 @@
1+/- asn1
2+:: |der: distinguished encoding rules for ASN.1
3+::
4+:: DER is a tag-length-value binary encoding for ASN.1, designed
5+:: so that there is only one (distinguished) valid encoding for an
6+:: instance of a type.
7+::
8+|%
9+:: +en:der: encode +spec:asn1 to +octs (kindof)
10+::
11+++ en
12+ =< |= a=spec:asn1
13+ ^- [len=@ud dat=@ux]
14+ =/ b ~(ren raw a)
15+ [(lent b) (rep 3 b)]
16+ |%
17+ :: +raw:en:der: door for encoding +spec:asn1 to list of bytes
18+ ::
19+ ++ raw
20+ |_ pec=spec:asn1
21+ :: +ren:raw:en:der: render +spec:asn1 to tag-length-value bytes
22+ ::
23+ ++ ren
24+ ^- (list @D)
25+ =/ a lem
26+ [tag (weld (len a) a)]
27+ :: +tag:raw:en:der: tag byte
28+ ::
29+ ++ tag
30+ ^- @D
31+ ?- pec
32+ [%int *] 2
33+ [%bit *] 3
34+ [%oct *] 4
35+ [%nul *] 5
36+ [%obj *] 6
37+ [%seq *] 48 :: constructed: (con 0x20 16)
38+ [%set *] 49 :: constructed: (con 0x20 17)
39+ [%con *] ;: con
40+ 0x80 :: context-specifc
41+ ?:(imp.bes.pec 0 0x20) :: implicit?
42+ (dis 0x1f tag.bes.pec) :: 5 bits of custom tag
43+ ==
44+ ==
45+ :: +lem:raw:en:der: element bytes
46+ ::
47+ ++ lem
48+ ^- (list @D)
49+ ?- pec
50+ :: unsigned only, interpreted as positive-signed and
51+ :: rendered in big-endian byte order. negative-signed would
52+ :: be two's complement
53+ ::
54+ [%int *] =/ a (flop (rip 3 int.pec))
55+ ?~ a [0 ~]
56+ ?:((lte i.a 127) a [0 a])
57+ :: padded to byte-width, must be already byte-aligned
58+ ::
59+ [%bit *] =/ a (rip 3 bit.pec)
60+ =/ b ~| %der-invalid-bit
61+ ?. =(0 (mod len.pec 8))
62+ ~|(%der-invalid-bit-alignment !!)
63+ (sub (div len.pec 8) (lent a))
64+ [0 (weld a (reap b 0))]
65+ :: padded to byte-width
66+ ::
67+ [%oct *] =/ a (rip 3 oct.pec)
68+ =/ b ~| %der-invalid-oct
69+ (sub len.pec (lent a))
70+ (weld a (reap b 0))
71+ ::
72+ [%nul *] ~
73+ [%obj *] (rip 3 obj.pec)
74+ ::
75+ [%seq *] %- zing
76+ |- ^- (list (list @))
77+ ?~ seq.pec ~
78+ :- ren(pec i.seq.pec)
79+ $(seq.pec t.seq.pec)
80+ :: presumed to be already deduplicated and sorted
81+ ::
82+ [%set *] %- zing
83+ |- ^- (list (list @))
84+ ?~ set.pec ~
85+ :- ren(pec i.set.pec)
86+ $(set.pec t.set.pec)
87+ :: already constructed
88+ ::
89+ [%con *] con.pec
90+ ==
91+ :: +len:raw:en:der: length bytes
92+ ::
93+ ++ len
94+ |= a=(list @D)
95+ ^- (list @D)
96+ =/ b (lent a)
97+ ?: (lte b 127)
98+ [b ~] :: note: big-endian
99+ [(con 0x80 (met 3 b)) (flop (rip 3 b))]
100+ --
101+ --
102+:: +de:der: decode atom to +spec:asn1
103+::
104+++ de
105+ |= [len=@ud dat=@ux]
106+ ^- (unit spec:asn1)
107+ :: XX refactor into +parse
108+ =/ a (rip 3 dat)
109+ =/ b ~| %der-invalid-len
110+ (sub len (lent a))
111+ (rust `(list @D)`(weld a (reap b 0)) parse)
112+:: +parse:der: DER parser combinator
113+::
114+++ parse
115+ =< ^- $-(nail (like spec:asn1))
116+ ;~ pose
117+ (stag %int (bass 256 (sear int ;~(pfix (tag 2) till))))
118+ (stag %bit (sear bit (boss 256 ;~(pfix (tag 3) till))))
119+ (stag %oct (boss 256 ;~(pfix (tag 4) till)))
120+ (stag %nul (cold ~ ;~(plug (tag 5) (tag 0))))
121+ (stag %obj (^boss 256 ;~(pfix (tag 6) till)))
122+ (stag %seq (sear recur ;~(pfix (tag 48) till)))
123+ (stag %set (sear recur ;~(pfix (tag 49) till)))
124+ (stag %con ;~(plug (sear context next) till))
125+ ==
126+ |%
127+ :: +tag:parse:der: parse tag byte
128+ ::
129+ ++ tag
130+ |=(a=@D (just a))
131+ :: +int:parse:der: sear unsigned big-endian bytes
132+ ::
133+ ++ int
134+ |= a=(list @D)
135+ ^- (unit (list @D))
136+ ?~ a ~
137+ ?: ?=([@ ~] a) `a
138+ ?. =(0 i.a) `a
139+ ?.((gth i.t.a 127) ~ `t.a)
140+ :: +bit:parse:der: convert bytewidth to bitwidth
141+ ::
142+ ++ bit
143+ |= [len=@ud dat=@ux]
144+ ^- (unit [len=@ud dat=@ux])
145+ ?. =(0 (end 3 dat)) ~
146+ :+ ~
147+ (mul 8 (dec len))
148+ (rsh 3 dat)
149+ :: +recur:parse:der: parse bytes for a list of +spec:asn1
150+ ::
151+ ++ recur
152+ |=(a=(list @) (rust a (star parse)))
153+ :: +context:parse:der: decode context-specific tag byte
154+ ::
155+ ++ context
156+ |= a=@D
157+ ^- (unit bespoke:asn1)
158+ ?. =(1 (cut 0 [7 1] a)) ~
159+ :+ ~
160+ =(1 (cut 0 [5 1] a))
161+ (dis 0x1f a)
162+ :: +boss:parse:der: shadowed to count as well
163+ ::
164+ :: Use for parsing +octs more broadly?
165+ ::
166+ ++ boss
167+ |* [wuc=@ tyd=rule]
168+ %+ cook
169+ |= waq=(list @)
170+ :- (lent waq)
171+ (reel waq |=([p=@ q=@] (add p (mul wuc q))))
172+ tyd
173+ :: +till:parse:der: parser combinator for len-prefixed bytes
174+ ::
175+ :: advance until
176+ ::
177+ ++ till
178+ |= tub=nail
179+ ^- (like (list @D))
180+ ?~ q.tub
181+ (fail tub)
182+ :: fuz: first byte - length, or length of the length
183+ ::
184+ =* fuz i.q.tub
185+ :: nex: offset of value bytes from fuz
186+ :: len: length of value bytes
187+ ::
188+ =/ [nex=@ len=@]
189+ :: faz: meaningful bits in fuz
190+ ::
191+ =/ faz (end [0 7] fuz)
192+ ?: =(0 (cut 0 [7 1] fuz))
193+ [0 faz]
194+ [faz (rep 3 (flop (scag faz t.q.tub)))]
195+ ?: ?& !=(0 nex)
196+ !=(nex (met 3 len))
197+ ==
198+ (fail tub)
199+ :: zuf: value bytes
200+ ::
201+ =/ zuf (swag [nex len] t.q.tub)
202+ ?. =(len (lent zuf))
203+ (fail tub)
204+ :: zaf: product nail
205+ ::
206+ =/ zaf [p.p.tub (add +(nex) q.p.tub)]
207+ [zaf `[zuf zaf (slag (add nex len) t.q.tub)]]
208+ --
209+--
210+
base-desk/lib/dill.hoonnew file+94
@@ -0,0 +1,94 @@
1+:: dill: utilities for dill's data structures
2+::
3+=, dill
4+|%
5+++ enjs
6+ |%
7+ ++ blit
8+ |= =blit:dill
9+ ^- json
10+ =, enjs:format
11+ %+ frond -.blit
12+ ?- -.blit
13+ %bel b+&
14+ %clr b+&
15+ %hop ?@ p.blit (numb p.blit)
16+ (pairs 'x'^(numb x.p.blit) 'y'^(numb y.p.blit) ~)
17+ %put a+(turn p.blit |=(c=@c s+(tuft c)))
18+ %nel b+&
19+ %url s+p.blit
20+ %wyp b+&
21+ %mor a+(turn p.blit ^blit)
22+ ::
23+ %sag
24+ %- pairs
25+ :~ 'path'^(path p.blit)
26+ 'file'^s+(en:base64:mimes:html (as-octs:mimes:html (jam q.blit)))
27+ ==
28+ ::
29+ %sav
30+ %- pairs
31+ :~ 'path'^(path p.blit)
32+ 'file'^s+(en:base64:mimes:html (as-octs:mimes:html q.blit))
33+ ==
34+ ::
35+ %klr
36+ :- %a
37+ %+ turn p.blit
38+ |= [=stye text=(list @c)]
39+ %- pairs
40+ :~ 'text'^a+(turn text |=(c=@c s+(tuft c)))
41+ ::
42+ :- 'stye'
43+ %- pairs
44+ |^ :~ 'back'^(color p.q.stye)
45+ 'fore'^(color q.q.stye)
46+ 'deco'^a+(turn ~(tap in p.stye) |=(d=deco ?~(d ~ s+d)))
47+ ==
48+ ++ color
49+ |= =tint
50+ ?@ tint ?~(tint ~ s+tint)
51+ =, tint
52+ (pairs r+(numb r) g+(numb g) b+(numb b) ~)
53+ --
54+ ==
55+ ==
56+ --
57+::
58+++ dejs
59+ |%
60+ ++ belt
61+ |= jon=json
62+ ^- belt:dill
63+ ?: ?=([%s *] jon)
64+ (taft p.jon)
65+ =, dejs:format
66+ %. jon
67+ %- of
68+ |^ :* mod+(ot 'mod'^mod 'key'^bot ~)
69+ txt+(ar (cu taft so))
70+ bol
71+ ==
72+ ::
73+ ++ bol
74+ :~ aro+(su (perk %d %l %r %u ~))
75+ bac+ul
76+ del+ul
77+ hit+(ot 'x'^ni 'y'^ni ~)
78+ ret+ul
79+ ==
80+ ::
81+ ++ bot
82+ |= j=json
83+ ^- bolt:dill
84+ ?+ j !!
85+ [%s *] (taft p.j)
86+ [%o *] ((of bol) j)
87+ ==
88+ ::
89+ ++ mod
90+ |= j=json
91+ ((su (perk %ctl %met %hyp ~)) j)
92+ --
93+ --
94+--
base-desk/lib/docket.hoonnew file+223
@@ -0,0 +1,223 @@
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+--
base-desk/lib/ethereum.hoonnew file+1006
@@ -0,0 +1,1006 @@
1+:: ethereum: utilities
2+::
3+=, ethereum-types
4+|%
5+:: deriving and using ethereum keys
6+::
7+++ key
8+ |%
9+ ++ address-from-pub
10+ =, keccak:crypto
11+ |= pub=@
12+ %+ end [3 20]
13+ %+ keccak-256 64
14+ (rev 3 64 pub)
15+ ::
16+ ++ address-from-prv
17+ (cork pub-from-prv address-from-pub)
18+ ::
19+ ++ pub-from-prv
20+ =, secp256k1:secp:crypto
21+ |= prv=@
22+ %- serialize-point
23+ (priv-to-pub prv)
24+ ::
25+ ++ sign-typed-transaction
26+ |= [tx=typed-transaction:rpc pk=@]
27+ ^- @ux
28+ =- (cat 3 - -.tx)
29+ ?- -.tx
30+ %0x0 (sign-transaction +.tx pk)
31+ %0x2 (sign-transaction-1559 +.tx pk)
32+ ==
33+ ::
34+ ++ sign-transaction
35+ =, crypto
36+ |= [tx=transaction:rpc pk=@]
37+ |^ ^- @ux
38+ :: hash the raw transaction data
39+ =/ hash=@
40+ %- keccak-256:keccak
41+ =+ dat=(encode chain-id.tx 0 0)
42+ =+ wid=(met 3 dat)
43+ [wid (rev 3 wid dat)]
44+ :: sign transaction hash with private key
45+ =+ (ecdsa-raw-sign:secp256k1:secp hash pk)
46+ :: complete transaction is raw data, with r and s
47+ :: taken from the signature, and v as per eip-155
48+ (encode :(add (mul chain-id.tx 2) 35 v) r s)
49+ ::
50+ ++ encode
51+ |= [v=@ r=@ s=@]
52+ %+ encode:rlp %l
53+ tx(to b+20^to.tx, chain-id [v r s ~])
54+ --
55+ ::
56+ ++ sign-transaction-1559
57+ =, crypto
58+ |= [tx=transaction-1559:rpc pk=@]
59+ |^ ^- @ux
60+ =; hash=@
61+ =+ (ecdsa-raw-sign:secp256k1:secp hash pk)
62+ ::NOTE we retrieve y's parity from the v value
63+ (encode-1559 ~ (end 0 v) r s)
64+ :: hash the raw transaction data including leading 0x2
65+ %- keccak-256:keccak
66+ =+ dat=(cat 3 (encode-1559 ~) 0x2)
67+ =+ wid=(met 3 dat)
68+ [wid (rev 3 wid dat)]
69+ ::
70+ ++ encode-1559
71+ |= sig=(unit [y=@ r=@ s=@])
72+ %+ encode:rlp %l
73+ =, tx
74+ :* chain-id
75+ nonce
76+ max-priority-gas-fee
77+ max-gas-fee
78+ gas
79+ b+20^to
80+ value
81+ data
82+ ::
83+ :- %l
84+ %+ turn ~(tap by access-list)
85+ |= [a=address b=(list @ux)]
86+ l+~[b+20^a l+(turn b |=(c=@ux b+32^c))]
87+ ::
88+ ?~ sig ~
89+ ~[y r s]:u.sig
90+ ==
91+ --
92+ --
93+::
94+:: rlp en/decoding
95+::NOTE https://eth.wiki/en/fundamentals/rlp
96+::
97+++ rlp
98+ |%
99+ ::NOTE rlp encoding doesn't really care about leading zeroes,
100+ :: but because we need to disinguish between no-bytes zero
101+ :: and one-byte zero (and also empty list) we end up with
102+ :: this awful type...
103+ +$ item
104+ $@ @
105+ $% [%l l=(list item)]
106+ [%b b=byts]
107+ ==
108+ :: +encode-atoms: encode list of atoms as a %l of %b items
109+ ::
110+ ++ encode-atoms ::NOTE deprecated
111+ |= l=(list @)
112+ ^- @
113+ (encode l+l)
114+ ::
115+ ++ encode
116+ |= in=item
117+ |^ ^- @
118+ ?- in
119+ @
120+ $(in [%b (met 3 in) in])
121+ ::
122+ [%b *]
123+ ?: &(=(1 wid.b.in) (lte dat.b.in 0x7f))
124+ dat.b.in
125+ =- (can 3 ~[b.in [(met 3 -) -]])
126+ (encode-length wid.b.in 0x80)
127+ ::
128+ [%l *]
129+ :: we +can because b+1^0x0 encodes to 0x00
130+ ::
131+ =/ l=(list byts)
132+ %+ turn l.in
133+ |= ni=item
134+ =+ (encode ni)
135+ [(max 1 (met 3 -)) -]
136+ %+ can 3
137+ %- flop
138+ =- [(met 3 -)^- l]
139+ (encode-length (roll (turn l head) add) 0xc0)
140+ ==
141+ ::
142+ ++ encode-length
143+ |= [len=@ off=@]
144+ ?: (lth len 56) (add len off)
145+ =- (cat 3 len -)
146+ :(add (met 3 len) off 55)
147+ --
148+ :: +decode-atoms: decode expecting a %l of %b items, producing atoms within
149+ ::
150+ ++ decode-atoms
151+ |= dat=@
152+ ^- (list @)
153+ =/ i=item (decode dat)
154+ ~| [%unexpected-data i]
155+ ?> ?=(%l -.i)
156+ %+ turn l.i
157+ |= i=item
158+ ~| [%unexpected-list i]
159+ ?> ?=(%b -.i)
160+ dat.b.i
161+ ::
162+ ++ decode
163+ |= dat=@
164+ ^- item
165+ =/ bytes=(list @) (flop (rip 3 dat))
166+ =? bytes ?=(~ bytes) ~[0]
167+ |^ item:decode-head
168+ ::
169+ ++ decode-head
170+ ^- [done=@ud =item]
171+ ?~ bytes
172+ ~| %rlp-unexpected-end
173+ !!
174+ =* byt i.bytes
175+ :: byte in 0x00-0x79 range encodes itself
176+ ::
177+ ?: (lte byt 0x79)
178+ :- 1
179+ [%b 1^byt]
180+ :: byte in 0x80-0xb7 range encodes string length
181+ ::
182+ ?: (lte byt 0xb7)
183+ =+ len=(sub byt 0x80)
184+ :- +(len)
185+ :- %b
186+ len^(get-value 1 len)
187+ :: byte in 0xb8-0xbf range encodes string length length
188+ ::
189+ ?: (lte byt 0xbf)
190+ =+ led=(sub byt 0xb7)
191+ =+ len=(get-value 1 led)
192+ :- (add +(led) len)
193+ :- %b
194+ len^(get-value +(led) len)
195+ :: byte in 0xc0-f7 range encodes list length
196+ ::
197+ ?: (lte byt 0xf7)
198+ =+ len=(sub byt 0xc0)
199+ :- +(len)
200+ :- %l
201+ %. len
202+ decode-list(bytes (slag 1 `(list @)`bytes))
203+ :: byte in 0xf8-ff range encodes list length length
204+ ::
205+ ?: (lte byt 0xff)
206+ =+ led=(sub byt 0xf7)
207+ =+ len=(get-value 1 led)
208+ :- (add +(led) len)
209+ :- %l
210+ %. len
211+ decode-list(bytes (slag +(led) `(list @)`bytes))
212+ ~| [%rip-not-bloq-3 `@ux`byt]
213+ !!
214+ ::
215+ ++ decode-list
216+ |= rem=@ud
217+ ^- (list item)
218+ ?: =(0 rem) ~
219+ =+ ^- [don=@ud =item] ::TODO =/
220+ decode-head
221+ :- item
222+ %= $
223+ rem (sub rem don)
224+ bytes (slag don bytes)
225+ ==
226+ ::
227+ ++ get-value
228+ |= [at=@ud to=@ud]
229+ ^- @
230+ (rep 3 (flop (swag [at to] bytes)))
231+ --
232+ --
233+::
234+:: abi en/decoding
235+::NOTE https://solidity.readthedocs.io/en/develop/abi-spec.html
236+::
237+++ abi
238+ => |%
239+ :: solidity types. integer bitsizes ignored
240+ ++ etyp
241+ $@ $? :: static
242+ %address %bool
243+ %int %uint
244+ %real %ureal
245+ :: dynamic
246+ %bytes %string
247+ ==
248+ $% :: static
249+ [%bytes-n n=@ud]
250+ :: dynamic
251+ [%array-n t=etyp n=@ud]
252+ [%array t=etyp]
253+ ==
254+ ::
255+ :: solidity-style typed data. integer bitsizes ignored
256+ ++ data
257+ $% [%address p=address]
258+ [%string p=tape]
259+ [%bool p=?]
260+ [%int p=@sd]
261+ [%uint p=@ud]
262+ [%real p=@rs]
263+ [%ureal p=@urs]
264+ [%array-n p=(list data)]
265+ [%array p=(list data)]
266+ [%bytes-n p=octs] ::TODO just @, because context knows length?
267+ [%bytes p=octs]
268+ ==
269+ --
270+ =, mimes:html
271+ |%
272+ :: encoding
273+ ::
274+ ++ encode-args
275+ :: encode list of arguments.
276+ ::
277+ |= das=(list data)
278+ ^- tape
279+ (encode-data [%array-n das])
280+ ::
281+ ++ encode-data
282+ :: encode typed data into ABI bytestring.
283+ ::
284+ |= dat=data
285+ ^- tape
286+ ?+ -.dat
287+ ~| [%unsupported-type -.dat]
288+ !!
289+ ::
290+ %array-n
291+ :: enc(X) = head(X[0]) ... head(X[k-1]) tail(X[0]) ... tail(X[k-1])
292+ :: where head and tail are defined for X[i] being of a static type as
293+ :: head(X[i]) = enc(X[i]) and tail(X[i]) = "" (the empty string), or as
294+ :: head(X[i]) = enc(len( head(X[0])..head(X[k-1])
295+ :: tail(X[0])..tail(X[i-1]) ))
296+ :: and tail(X[i]) = enc(X[i]) otherwise.
297+ ::
298+ :: so: if it's a static type, data goes in the head. if it's a dynamic
299+ :: type, a reference goes into the head and data goes into the tail.
300+ ::
301+ :: in the head, we first put a placeholder where references need to go.
302+ =+ hol=(reap 64 'x')
303+ =/ hes=(list tape)
304+ %+ turn p.dat
305+ |= d=data
306+ ?. (is-dynamic-type d) ^$(dat d)
307+ hol
308+ =/ tas=(list tape)
309+ %+ turn p.dat
310+ |= d=data
311+ ?. (is-dynamic-type d) ""
312+ ^$(dat d)
313+ :: once we know the head and tail, we can fill in the references in head.
314+ =- (weld nes `tape`(zing tas))
315+ ^- [@ud nes=tape]
316+ =+ led=(lent (zing hes))
317+ %+ roll hes
318+ |= [t=tape i=@ud nes=tape]
319+ :- +(i)
320+ :: if no reference needed, just put the data.
321+ ?. =(t hol) (weld nes t)
322+ :: calculate byte offset of data we need to reference.
323+ =/ ofs=@ud
324+ =- (div - 2) :: two hex digits per byte.
325+ %+ add led :: count head, and
326+ %- lent %- zing :: count all tail data
327+ (scag i tas) :: preceding ours.
328+ =+ ref=^$(dat [%uint ofs])
329+ :: shouldn't hit this unless we're sending over 2gb of data?
330+ ~| [%weird-ref-lent (lent ref)]
331+ ?> =((lent ref) (lent hol))
332+ (weld nes ref)
333+ ::
334+ %array :: where X has k elements (k is assumed to be of type uint256):
335+ :: enc(X) = enc(k) enc([X[1], ..., X[k]])
336+ :: i.e. it is encoded as if it were an array of static size k, prefixed
337+ :: with the number of elements.
338+ %+ weld $(dat [%uint (lent p.dat)])
339+ $(dat [%array-n p.dat])
340+ ::
341+ %bytes-n
342+ :: enc(X) is the sequence of bytes in X padded with zero-bytes to a
343+ :: length of 32.
344+ :: Note that for any X, len(enc(X)) is a multiple of 32.
345+ ~| [%bytes-n-too-long max=32 actual=p.p.dat]
346+ ?> (lte p.p.dat 32)
347+ (pad-to-multiple (render-hex-bytes p.dat) 64 %right)
348+ ::
349+ %bytes :: of length k (which is assumed to be of type uint256)
350+ :: enc(X) = enc(k) pad_right(X), i.e. the number of bytes is encoded as a
351+ :: uint256 followed by the actual value of X as a byte sequence, followed
352+ :: by the minimum number of zero-bytes such that len(enc(X)) is a
353+ :: multiple of 32.
354+ %+ weld $(dat [%uint p.p.dat])
355+ (pad-to-multiple (render-hex-bytes p.dat) 64 %right)
356+ ::
357+ %string
358+ :: enc(X) = enc(enc_utf8(X)), i.e. X is utf-8 encoded and this value is
359+ :: interpreted as of bytes type and encoded further. Note that the length
360+ :: used in this subsequent encoding is the number of bytes of the utf-8
361+ :: encoded string, not its number of characters.
362+ $(dat [%bytes (lent p.dat) (swp 3 (crip p.dat))])
363+ ::
364+ %uint
365+ :: enc(X) is the big-endian encoding of X, padded on the higher-order
366+ :: (left) side with zero-bytes such that the length is a multiple of 32
367+ :: bytes.
368+ (pad-to-multiple (render-hex-bytes (as-octs p.dat)) 64 %left)
369+ ::
370+ %bool
371+ :: as in the uint8 case, where 1 is used for true and 0 for false
372+ $(dat [%uint ?:(p.dat 1 0)])
373+ ::
374+ %address
375+ :: as in the uint160 case
376+ $(dat [%uint `@ud`p.dat])
377+ ==
378+ ::
379+ ++ is-dynamic-type
380+ |= a=data
381+ ?. ?=(%array-n -.a)
382+ ?=(?(%string %bytes %array) -.a)
383+ &(!=((lent p.a) 0) (lien p.a is-dynamic-type))
384+ ::
385+ :: decoding
386+ ::
387+ ++ decode-topics decode-arguments
388+ ::
389+ ++ decode-results
390+ :: rex: string of hex bytes with leading 0x.
391+ |* [rex=@t tys=(list etyp)]
392+ =- (decode-arguments - tys)
393+ %^ rut 9
394+ (rsh [3 2] rex)
395+ (curr rash hex)
396+ ::
397+ ++ decode-arguments
398+ |* [wos=(list @) tys=(list etyp)]
399+ =/ wos=(list @) wos :: get rid of tmi
400+ =| win=@ud
401+ =< (decode-from 0 tys)
402+ |%
403+ ++ decode-from
404+ |* [win=@ud tys=(list etyp)]
405+ ?~ tys !!
406+ =- ?~ t.tys dat
407+ [dat $(win nin, tys t.tys)]
408+ (decode-one win ~[i.tys])
409+ ::
410+ ++ decode-one
411+ ::NOTE we take (list etyp) even though we only operate on
412+ :: a single etyp as a workaround for urbit/arvo#673
413+ |* [win=@ud tys=(list etyp)]
414+ =- [nin dat]=- ::NOTE ^= regular form broken
415+ ?~ tys !!
416+ =* typ i.tys
417+ =+ wor=(snag win wos)
418+ ?+ typ
419+ ~| [%unsupported-type typ]
420+ !!
421+ ::
422+ ?(%address %bool %uint) :: %int %real %ureal
423+ :- +(win)
424+ ?- typ
425+ %address `@ux`wor
426+ %uint `@ud`wor
427+ %bool =(1 wor)
428+ ==
429+ ::
430+ %string
431+ =+ $(tys ~[%bytes])
432+ [nin (trip (swp 3 q.dat))]
433+ ::
434+ %bytes
435+ :- +(win)
436+ :: find the word index of the actual data.
437+ =/ lic=@ud (div wor 32)
438+ :: learn the bytelength of the data.
439+ =/ len=@ud (snag lic wos)
440+ (decode-bytes-n +(lic) len)
441+ ::
442+ [%bytes-n *]
443+ :- (add win +((div (dec n.typ) 32)))
444+ (decode-bytes-n win n.typ)
445+ ::
446+ [%array *]
447+ :- +(win)
448+ :: find the word index of the actual data.
449+ =. win (div wor 32)
450+ :: read the elements from their location.
451+ %- tail
452+ %^ decode-array-n ~[t.typ] +(win)
453+ (snag win wos)
454+ ::
455+ [%array-n *]
456+ (decode-array-n ~[t.typ] win n.typ)
457+ ==
458+ ::
459+ ++ decode-bytes-n
460+ |= [fro=@ud bys=@ud]
461+ ^- octs
462+ :: parse {bys} bytes from {fro}.
463+ :- bys
464+ %+ rsh
465+ :- 3
466+ =+ (mod bys 32)
467+ ?:(=(0 -) - (sub 32 -))
468+ %+ rep 8
469+ %- flop
470+ =- (swag [fro -] wos)
471+ +((div (dec bys) 32))
472+ ::
473+ ++ decode-array-n
474+ ::NOTE we take (list etyp) even though we only operate on
475+ :: a single etyp as a workaround for urbit/arvo#673
476+ ::NOTE careful! produces lists without type info
477+ =| res=(list)
478+ |* [tys=(list etyp) fro=@ud len=@ud]
479+ ^- [@ud (list)]
480+ ?~ tys !!
481+ ?: =(len 0) [fro (flop `(list)`res)]
482+ =+ (decode-one fro ~[i.tys]) :: [nin=@ud dat=*]
483+ $(res ^+(res [dat res]), fro nin, len (dec len))
484+ --
485+ --
486+::
487+:: communicating with rpc nodes
488+::NOTE https://github.com/ethereum/wiki/wiki/JSON-RPC
489+::
490+++ rpc
491+ :: types
492+ ::
493+ => =, abi
494+ =, format
495+ |%
496+ :: raw call data
497+ ++ call-data
498+ $: function=@t
499+ arguments=(list data)
500+ ==
501+ ::
502+ :: raw transaction data
503+ +$ typed-transaction
504+ $% [%0x0 transaction]
505+ [%0x2 transaction-1559]
506+ ==
507+ ::
508+ +$ transaction
509+ $: nonce=@ud
510+ gas-price=@ud
511+ gas=@ud
512+ to=address
513+ value=@ud
514+ data=@ux
515+ chain-id=@ux
516+ ==
517+ ::
518+ +$ transaction-1559
519+ $: chain-id=@ux
520+ nonce=@ud
521+ max-priority-gas-fee=@ud
522+ max-gas-fee=@ud
523+ gas=@ud
524+ to=address
525+ value=@ud
526+ data=@ux
527+ access-list=(jar address @ux)
528+ ==
529+ ::
530+ :: ethereum json rpc api
531+ ::
532+ :: supported requests.
533+ ++ request
534+ $% [%eth-block-number ~]
535+ [%eth-call cal=call deb=block]
536+ $: %eth-new-filter
537+ fro=(unit block)
538+ tob=(unit block)
539+ adr=(list address)
540+ top=(list ?(@ux (list @ux)))
541+ ==
542+ [%eth-get-block-by-number bon=@ud txs=?]
543+ [%eth-get-filter-logs fid=@ud]
544+ $: %eth-get-logs
545+ fro=(unit block)
546+ tob=(unit block)
547+ adr=(list address)
548+ top=(list ?(@ux (list @ux)))
549+ ==
550+ $: %eth-get-logs-by-hash
551+ has=@
552+ adr=(list address)
553+ top=(list ?(@ux (list @ux)))
554+ ==
555+ [%eth-get-filter-changes fid=@ud]
556+ [%eth-get-transaction-by-hash txh=@ux]
557+ [%eth-get-transaction-count adr=address =block]
558+ [%eth-get-balance adr=address =block]
559+ [%eth-get-transaction-receipt txh=@ux]
560+ [%eth-send-raw-transaction dat=@ux]
561+ ==
562+ ::
563+ ::TODO clean up & actually use
564+ ++ response
565+ $% ::TODO
566+ [%eth-new-filter fid=@ud]
567+ [%eth-get-filter-logs los=(list event-log)]
568+ [%eth-get-logs los=(list event-log)]
569+ [%eth-get-logs-by-hash los=(list event-log)]
570+ [%eth-got-filter-changes los=(list event-log)]
571+ [%eth-transaction-hash haz=@ux]
572+ ==
573+ ::
574+ ++ transaction-result
575+ $: block-hash=(unit @ux)
576+ block-number=(unit @ud)
577+ transaction-index=(unit @ud)
578+ from=@ux
579+ to=(unit @ux)
580+ input=@t
581+ ==
582+ ::
583+ ++ event-log
584+ $: :: null for pending logs
585+ $= mined %- unit
586+ $: input=(unit @ux)
587+ log-index=@ud
588+ transaction-index=@ud
589+ transaction-hash=@ux
590+ block-number=@ud
591+ block-hash=@ux
592+ removed=?
593+ ==
594+ ::
595+ address=@ux
596+ data=@t
597+ :: event data
598+ ::
599+ :: For standard events, the first topic is the event signature
600+ :: hash. For anonymous events, the first topic is the first
601+ :: indexed argument.
602+ :: Note that this does not support the "anonymous event with
603+ :: zero topics" case. This has dubious usability, and using
604+ :: +lest instead of +list saves a lot of ?~ checks.
605+ ::
606+ topics=(lest @ux)
607+ ==
608+ ::
609+ :: data for eth_call.
610+ ++ call
611+ $: from=(unit address)
612+ to=address
613+ gas=(unit @ud)
614+ gas-price=(unit @ud)
615+ value=(unit @ud)
616+ data=tape
617+ ==
618+ ::
619+ :: minimum data needed to construct a read call
620+ ++ proto-read-request
621+ $: id=(unit @t)
622+ to=address
623+ call-data
624+ ==
625+ ::
626+ :: block to operate on.
627+ ++ block
628+ $% [%number n=@ud]
629+ [%label l=?(%earliest %latest %pending)]
630+ ==
631+ --
632+ ::
633+ :: logic
634+ ::
635+ |%
636+ ++ encode-call
637+ |= call-data
638+ ^- tape
639+ ::TODO should this check to see if the data matches the function signature?
640+ =- :(weld "0x" - (encode-args arguments))
641+ %+ scag 8
642+ %+ render-hex-bytes 32
643+ %- keccak-256:keccak:crypto
644+ (as-octs:mimes:html function)
645+ ::
646+ :: building requests
647+ ::
648+ ++ json-request
649+ =, eyre
650+ |= [url=purl jon=json]
651+ ^- hiss
652+ :^ url %post
653+ %- ~(gas in *math)
654+ ~['Content-Type'^['application/json']~]
655+ (some (as-octs (en:json:html jon)))
656+ :: +light-json-request: like json-request, but for %l
657+ ::
658+ :: TODO: Exorcising +purl from our system is a much longer term effort;
659+ :: get the current output types for now.
660+ ::
661+ ++ light-json-request
662+ |= [url=purl:eyre jon=json]
663+ ^- request:http
664+ ::
665+ :* %'POST'
666+ (crip (en-purl:html url))
667+ ~[['content-type' 'application/json']]
668+ (some (as-octs (en:json:html jon)))
669+ ==
670+ ::
671+ ++ batch-read-request
672+ |= req=(list proto-read-request)
673+ ^- json
674+ a+(turn req read-request)
675+ ::
676+ ++ read-request
677+ |= proto-read-request
678+ ^- json
679+ %+ request-to-json id
680+ :+ %eth-call
681+ ^- call
682+ [~ to ~ ~ ~ `tape`(encode-call function arguments)]
683+ [%label %latest]
684+ ::
685+ ++ request-to-json
686+ =, enjs:format
687+ |= [riq=(unit @t) req=request]
688+ ^- json
689+ %- pairs
690+ =; r=[met=@t pas=(list json)]
691+ ::TODO should use request-to-json:rpc:jstd,
692+ :: and probably (fall riq -.req)
693+ :* jsonrpc+s+'2.0'
694+ method+s+met.r
695+ params+a+pas.r
696+ ::TODO would just jamming the req noun for id be a bad idea?
697+ ?~ riq ~
698+ [id+s+u.riq]~
699+ ==
700+ ?- -.req
701+ %eth-block-number
702+ ['eth_blockNumber' ~]
703+ ::
704+ %eth-call
705+ :- 'eth_call'
706+ :~ (eth-call-to-json cal.req)
707+ (block-to-json deb.req)
708+ ==
709+ ::
710+ %eth-new-filter
711+ :- 'eth_newFilter'
712+ :_ ~
713+ :- %o %- ~(gas by *(map @t json))
714+ =- (murn - same)
715+ ^- (list (unit (pair @t json)))
716+ :~ ?~ fro.req ~
717+ `['fromBlock' (block-to-json u.fro.req)]
718+ ::
719+ ?~ tob.req ~
720+ `['toBlock' (block-to-json u.tob.req)]
721+ ::
722+ ::NOTE tmi
723+ ?: =(0 (lent adr.req)) ~
724+ :+ ~ 'address'
725+ ?: =(1 (lent adr.req)) (tape (address-to-hex (snag 0 adr.req)))
726+ :- %a
727+ (turn adr.req (cork address-to-hex tape))
728+ ::
729+ ?~ top.req ~
730+ :+ ~ 'topics'
731+ (topics-to-json top.req)
732+ ==
733+ ::
734+ %eth-get-block-by-number
735+ :- 'eth_getBlockByNumber'
736+ :~ (tape (num-to-hex-minimal bon.req))
737+ b+txs.req
738+ ==
739+ ::
740+ %eth-get-filter-logs
741+ ['eth_getFilterLogs' (tape (num-to-hex fid.req)) ~]
742+ ::
743+ %eth-get-logs
744+ :- 'eth_getLogs'
745+ :_ ~
746+ :- %o %- ~(gas by *(map @t json))
747+ =- (murn - same)
748+ ^- (list (unit (pair @t json)))
749+ :~ ?~ fro.req ~
750+ `['fromBlock' (block-to-json u.fro.req)]
751+ ::
752+ ?~ tob.req ~
753+ `['toBlock' (block-to-json u.tob.req)]
754+ ::
755+ ?: =(0 (lent adr.req)) ~
756+ :+ ~ 'address'
757+ ?: =(1 (lent adr.req)) (tape (address-to-hex (snag 0 adr.req)))
758+ :- %a
759+ (turn adr.req (cork address-to-hex tape))
760+ ::
761+ ?~ top.req ~
762+ :+ ~ 'topics'
763+ (topics-to-json top.req)
764+ ==
765+ ::
766+ %eth-get-logs-by-hash
767+ :- 'eth_getLogs'
768+ :_ ~ :- %o
769+ %- ~(gas by *(map @t json))
770+ =- (murn - same)
771+ ^- (list (unit (pair @t json)))
772+ :~ `['blockHash' (tape (transaction-to-hex has.req))]
773+ ::
774+ ?: =(0 (lent adr.req)) ~
775+ :+ ~ 'address'
776+ ?: =(1 (lent adr.req)) (tape (address-to-hex (snag 0 adr.req)))
777+ :- %a
778+ (turn adr.req (cork address-to-hex tape))
779+ ::
780+ ?~ top.req ~
781+ :+ ~ 'topics'
782+ (topics-to-json top.req)
783+ ==
784+ ::
785+ %eth-get-filter-changes
786+ ['eth_getFilterChanges' (tape (num-to-hex fid.req)) ~]
787+ ::
788+ %eth-get-transaction-count
789+ :- 'eth_getTransactionCount'
790+ :~ (tape (address-to-hex adr.req))
791+ (block-to-json block.req)
792+ ==
793+ ::
794+ %eth-get-balance
795+ :- 'eth_getBalance'
796+ :~ (tape (address-to-hex adr.req))
797+ (block-to-json block.req)
798+ ==
799+ ::
800+ %eth-get-transaction-by-hash
801+ ['eth_getTransactionByHash' (tape (transaction-to-hex txh.req)) ~]
802+ ::
803+ %eth-get-transaction-receipt
804+ ['eth_getTransactionReceipt' (tape (transaction-to-hex txh.req)) ~]
805+ ::
806+ %eth-send-raw-transaction
807+ ['eth_sendRawTransaction' (tape (num-to-hex dat.req)) ~]
808+ ==
809+ ::
810+ ++ eth-call-to-json
811+ =, enjs:format
812+ |= cal=call
813+ ^- json
814+ :- %o %- ~(gas by *(map @t json))
815+ =- (murn - same)
816+ ^- (list (unit (pair @t json)))
817+ :~ ?~ from.cal ~
818+ `['from' (tape (address-to-hex u.from.cal))]
819+ ::
820+ `['to' (tape (address-to-hex to.cal))]
821+ ::
822+ ?~ gas.cal ~
823+ `['gas' (tape (num-to-hex u.gas.cal))]
824+ ::
825+ ?~ gas-price.cal ~
826+ `['gasPrice' (tape (num-to-hex u.gas-price.cal))]
827+ ::
828+ ?~ value.cal ~
829+ `['value' (tape (num-to-hex u.value.cal))]
830+ ::
831+ ?~ data.cal ~
832+ `['data' (tape data.cal)]
833+ ==
834+ ::
835+ ++ block-to-json
836+ |= dob=block
837+ ^- json
838+ ?- -.dob
839+ %number s+(crip '0' 'x' ((x-co:co 1) n.dob))
840+ %label s+l.dob
841+ ==
842+ ::
843+ ++ topics-to-json
844+ |= tos=(list ?(@ux (list @ux)))
845+ ^- json
846+ :- %a
847+ =/ ttj
848+ ;: cork
849+ (cury render-hex-bytes 32)
850+ prefix-hex
851+ tape:enjs:format
852+ ==
853+ %+ turn tos
854+ |= t=?(@ (list @))
855+ ?@ t
856+ ?: =(0 t) ~
857+ (ttj `@`t)
858+ a+(turn t ttj)
859+ ::
860+ :: parsing responses
861+ ::
862+ ::TODO ++ parse-response |= json ^- response
863+ ::
864+ ++ parse-hex-result
865+ |= j=json
866+ ^- @
867+ ?> ?=(%s -.j)
868+ (hex-to-num p.j)
869+ ::
870+ ++ parse-eth-new-filter-res parse-hex-result
871+ ::
872+ ++ parse-eth-block-number parse-hex-result
873+ ::
874+ ++ parse-transaction-hash parse-hex-result
875+ ::
876+ ++ parse-eth-get-transaction-count parse-hex-result
877+ ::
878+ ++ parse-eth-get-balance parse-hex-result
879+ ::
880+ ++ parse-event-logs
881+ (ar:dejs:format parse-event-log)
882+ ::
883+ ++ parse-event-log
884+ =, dejs:format
885+ |= log=json
886+ ^- event-log
887+ =- ((ot -) log)
888+ :~ =- ['logIndex'^(cu - (mu so))]
889+ |= li=(unit @t)
890+ ?~ li ~
891+ =- ``((ou -) log) ::TODO not sure if elegant or hacky.
892+ :~ 'logIndex'^(un (cu hex-to-num so))
893+ 'transactionIndex'^(un (cu hex-to-num so))
894+ 'transactionHash'^(un (cu hex-to-num so))
895+ 'blockNumber'^(un (cu hex-to-num so))
896+ 'blockHash'^(un (cu hex-to-num so))
897+ 'removed'^(uf | bo)
898+ ==
899+ ::
900+ address+(cu hex-to-num so)
901+ data+so
902+ ::
903+ =- topics+(cu - (ar so))
904+ |= r=(list @t)
905+ ^- (lest @ux)
906+ ?> ?=([@t *] r)
907+ :- (hex-to-num i.r)
908+ (turn t.r hex-to-num)
909+ ==
910+ ::
911+ ++ parse-transaction-result
912+ =, dejs:format
913+ |= jon=json
914+ ~| jon=jon
915+ ^- transaction-result
916+ =- ((ot -) jon)
917+ :~ 'blockHash'^_~ :: TODO: fails if maybe-num?
918+ 'blockNumber'^maybe-num
919+ 'transactionIndex'^maybe-num
920+ from+(cu hex-to-num so)
921+ to+maybe-num
922+ input+so
923+ ==
924+ ::
925+ ++ maybe-num
926+ =, dejs:format
927+ =- (cu - (mu so))
928+ |= r=(unit @t)
929+ ?~ r ~
930+ `(hex-to-num u.r)
931+ --
932+::
933+:: utilities
934+::TODO give them better homes!
935+::
936+++ num-to-hex
937+ |= n=@
938+ ^- tape
939+ %- prefix-hex
940+ ?: =(0 n)
941+ "0"
942+ %- render-hex-bytes
943+ (as-octs:mimes:html n)
944+::
945+++ num-to-hex-minimal
946+ |= n=@
947+ ^- tape
948+ %- prefix-hex
949+ ((x-co:co 1) n)
950+::
951+++ address-to-hex
952+ |= a=address
953+ ^- tape
954+ %- prefix-hex
955+ (render-hex-bytes 20 `@`a)
956+::
957+++ address-to-checksum
958+ |= a=address
959+ ^- tape
960+ =/ hexed (render-hex-bytes 20 `@`a)
961+ =/ hash (keccak-256:keccak:crypto (as-octs:mimes:html (crip hexed)))
962+ =| ret=tape
963+ =/ pos 63
964+ |-
965+ ?~ hexed (prefix-hex (flop ret))
966+ =/ char i.hexed
967+ ?: (lth char 58) $(pos (dec pos), ret [char ret], hexed t.hexed)
968+ =/ nib (cut 2 [pos 1] hash)
969+ ?: (lth 7 nib) $(pos (dec pos), ret [(sub char 32) ret], hexed t.hexed)
970+ $(pos (dec pos), ret [char ret], hexed t.hexed)
971+::
972+++ transaction-to-hex
973+ |= h=@
974+ ^- tape
975+ %- prefix-hex
976+ (render-hex-bytes 32 h)
977+::
978+++ prefix-hex
979+ |= a=tape
980+ ^- tape
981+ ['0' 'x' a]
982+::
983+++ render-hex-bytes
984+ :: atom to string of hex bytes without 0x prefix and dots.
985+ |= a=octs
986+ ^- tape
987+ ((x-co:co (mul 2 p.a)) q.a)
988+::
989+++ pad-to-multiple
990+ |= [wat=tape mof=@ud wer=?(%left %right)]
991+ ^- tape
992+ =+ len=(lent wat)
993+ ?: =(0 len) (reap mof '0')
994+ =+ mad=(mod len mof)
995+ ?: =(0 mad) wat
996+ =+ tad=(reap (sub mof mad) '0')
997+ %- weld
998+ ?:(?=(%left wer) [tad wat] [wat tad])
999+::
1000+++ hex-to-num
1001+ |= a=@t
1002+ ~| %non-hex-cord
1003+ ?> =((end [3 2] a) '0x')
1004+ =< ?<(=(0 p) q) %- need
1005+ (de:base16:mimes:html (rsh [3 2] a))
1006+--
base-desk/lib/ethio.hoonnew file+289
@@ -0,0 +1,289 @@
1+:: ethio: Asynchronous Ethereum input/output functions.
2+::
3+/- rpc=json-rpc
4+/+ ethereum, strandio
5+=, ethereum-types
6+=, jael
7+::
8+=> |%
9+ +$ topics (list ?(@ux (list @ux)))
10+ --
11+|%
12+:: +request-rpc: send rpc request, with retry
13+::
14+++ request-rpc
15+ |= [url=@ta id=(unit @t) req=request:rpc:ethereum]
16+ =/ m (strand:strandio ,json)
17+ ^- form:m
18+ ;< res=(list [id=@t =json]) bind:m
19+ (request-batch-rpc-strict url [id req]~)
20+ ?: ?=([* ~] res)
21+ (pure:m json.i.res)
22+ %+ strand-fail:strandio
23+ %unexpected-multiple-results
24+ [>(lent res)< ~]
25+:: +request-batch-rpc-strict: send rpc requests, with retry
26+::
27+:: sends a batch request. produces results for all requests in the batch,
28+:: but only if all of them are successful.
29+::
30+++ request-batch-rpc-strict
31+ |= [url=@ta reqs=(list [id=(unit @t) req=request:rpc:ethereum])]
32+ |^ %+ (retry:strandio results)
33+ `10
34+ attempt-request
35+ ::
36+ +$ results (list [id=@t =json])
37+ ::
38+ ++ attempt-request
39+ =/ m (strand:strandio ,(unit results))
40+ ^- form:m
41+ ;< responses=(list response:rpc) bind:m
42+ (request-batch-rpc-loose url reqs)
43+ =- ?~ err
44+ (pure:m `res)
45+ (pure:m ~)
46+ %+ roll responses
47+ |= $: rpc=response:rpc
48+ [res=results err=(list [id=@t code=@t message=@t])]
49+ ==
50+ ?: ?=(%error -.rpc)
51+ [res [+.rpc err]]
52+ ?. ?=(%result -.rpc)
53+ [res [['' 'ethio-rpc-fail' (crip <rpc>)] err]]
54+ [[+.rpc res] err]
55+ --
56+:: +request-batch-rpc-loose: send rpc requests, with retry
57+::
58+:: sends a batch request. produces results for all requests in the batch,
59+:: including the ones that are unsuccessful.
60+::
61+++ request-batch-rpc-loose
62+ |= [url=@ta reqs=(list [id=(unit @t) req=request:rpc:ethereum])]
63+ |^ %+ (retry:strandio results)
64+ `10
65+ attempt-request
66+ ::
67+ +$ result response:rpc
68+ +$ results (list response:rpc)
69+ ::
70+ ++ attempt-request
71+ =/ m (strand:strandio ,(unit results))
72+ ^- form:m
73+ =/ =request:http
74+ :* method=%'POST'
75+ url=url
76+ header-list=['Content-Type'^'application/json' ~]
77+ ::
78+ ^= body
79+ %- some %- as-octs:mimes:html
80+ %- en:json:html
81+ a+(turn reqs request-to-json:rpc:ethereum)
82+ ==
83+ ;< ~ bind:m
84+ (send-request:strandio request)
85+ ;< rep=(unit client-response:iris) bind:m
86+ take-maybe-response:strandio
87+ ?~ rep
88+ (pure:m ~)
89+ (parse-responses u.rep)
90+ ::
91+ ++ parse-responses
92+ |= =client-response:iris
93+ =/ m (strand:strandio ,(unit results))
94+ ^- form:m
95+ ?> ?=(%finished -.client-response)
96+ ?~ full-file.client-response
97+ (pure:m ~)
98+ =/ body=@t q.data.u.full-file.client-response
99+ =/ jon=(unit json) (de:json:html body)
100+ ?~ jon
101+ (pure:m ~)
102+ =/ array=(unit (list response:rpc))
103+ ((ar:dejs-soft:format parse-one-response) u.jon)
104+ ?~ array
105+ (strand-fail:strandio %rpc-result-incomplete-batch >u.jon< ~)
106+ (pure:m array)
107+ ::
108+ ++ parse-one-response
109+ |= =json
110+ ^- (unit response:rpc)
111+ ?. &(?=([%o *] json) (~(has by p.json) 'error'))
112+ =/ res=(unit [@t ^json])
113+ %. json
114+ =, dejs-soft:format
115+ (ot id+so result+some ~)
116+ ?~ res ~
117+ `[%result u.res]
118+ ~| parse-one-response=json
119+ =/ error=(unit [id=@t ^json code=@ta mssg=@t])
120+ %. json
121+ =, dejs-soft:format
122+ :: A 'result' member is present in the error
123+ :: response when using ganache, even though
124+ :: that goes against the JSON-RPC spec
125+ ::
126+ (ot id+so result+some error+(ot code+no message+so ~) ~)
127+ ?~ error ~
128+ =* err u.error
129+ `[%error id.err code.err mssg.err]
130+ --
131+::
132+:: +read-contract: calls a read function on a contract, produces result hex
133+::
134+++ read-contract
135+ |= [url=@t req=proto-read-request:rpc:ethereum]
136+ =/ m (strand:strandio ,@t)
137+ ;< res=(list [id=@t res=@t]) bind:m
138+ (batch-read-contract-strict url [req]~)
139+ ?: ?=([* ~] res)
140+ (pure:m res.i.res)
141+ %+ strand-fail:strandio
142+ %unexpected-multiple-results
143+ [>(lent res)< ~]
144+:: +batch-read-contract-strict: calls read functions on contracts
145+::
146+:: sends a batch request. produces results for all requests in the batch,
147+:: but only if all of them are successful.
148+::
149+++ batch-read-contract-strict
150+ |= [url=@t reqs=(list proto-read-request:rpc:ethereum)]
151+ |^ =/ m (strand:strandio ,results)
152+ ^- form:m
153+ ;< res=(list [id=@t =json]) bind:m
154+ %+ request-batch-rpc-strict url
155+ (turn reqs proto-to-rpc)
156+ =+ ^- [=results =failures]
157+ (roll res response-to-result)
158+ ?~ failures (pure:m results)
159+ (strand-fail:strandio %batch-read-failed-for >failures< ~)
160+ ::
161+ +$ results (list [id=@t res=@t])
162+ +$ failures (list [id=@t =json])
163+ ::
164+ ++ proto-to-rpc
165+ |= proto-read-request:rpc:ethereum
166+ ^- [(unit @t) request:rpc:ethereum]
167+ :- id
168+ :+ %eth-call
169+ ^- call:rpc:ethereum
170+ [~ to ~ ~ ~ `tape`(encode-call:rpc:ethereum function arguments)]
171+ [%label %latest]
172+ ::
173+ ++ response-to-result
174+ |= [[id=@t =json] =results =failures]
175+ ^+ [results failures]
176+ ?: ?=(%s -.json)
177+ [[id^p.json results] failures]
178+ [results [id^json failures]]
179+ --
180+::
181+::
182+++ get-latest-block
183+ |= url=@ta
184+ =/ m (strand:strandio ,block)
185+ ^- form:m
186+ ;< =json bind:m
187+ (request-rpc url `'block number' %eth-block-number ~)
188+ (get-block-by-number url (parse-eth-block-number:rpc:ethereum json))
189+::
190+++ get-block-by-number
191+ |= [url=@ta =number:block]
192+ =/ m (strand:strandio ,block)
193+ ^- form:m
194+ |^
195+ %+ (retry:strandio ,block) `10
196+ =/ m (strand:strandio ,(unit block))
197+ ^- form:m
198+ ;< =json bind:m
199+ %+ request-rpc url
200+ :- `'block by number'
201+ [%eth-get-block-by-number number |]
202+ (pure:m (parse-block json))
203+ ::
204+ ++ parse-block
205+ |= =json
206+ ^- (unit block)
207+ =< ?~(. ~ `[[&1 &2] |2]:u)
208+ ^- (unit [@ @ @])
209+ ~| json
210+ %. json
211+ =, dejs-soft:format
212+ %- ot
213+ :~ hash+parse-hex
214+ number+parse-hex
215+ 'parentHash'^parse-hex
216+ ==
217+ ::
218+ ++ parse-hex |=(=json `(unit @)`(some (parse-hex-result:rpc:ethereum json)))
219+ --
220+::
221+++ get-tx-by-hash
222+ |= [url=@ta tx-hash=@ux]
223+ =/ m (strand:strandio transaction-result:rpc:ethereum)
224+ ^- form:m
225+ ;< =json bind:m
226+ %+ request-rpc url
227+ :* `'tx by hash'
228+ %eth-get-transaction-by-hash
229+ tx-hash
230+ ==
231+ %- pure:m
232+ (parse-transaction-result:rpc:ethereum json)
233+::
234+++ get-logs-by-hash
235+ |= [url=@ta =hash:block contracts=(list address) =topics]
236+ =/ m (strand:strandio (list event-log:rpc:ethereum))
237+ ^- form:m
238+ ;< =json bind:m
239+ %+ request-rpc url
240+ :* `'logs by hash'
241+ %eth-get-logs-by-hash
242+ hash
243+ contracts
244+ topics
245+ ==
246+ %- pure:m
247+ (parse-event-logs:rpc:ethereum json)
248+::
249+++ get-logs-by-range
250+ |= $: url=@ta
251+ contracts=(list address)
252+ =topics
253+ =from=number:block
254+ =to=number:block
255+ ==
256+ =/ m (strand:strandio (list event-log:rpc:ethereum))
257+ ^- form:m
258+ ;< =json bind:m
259+ %+ request-rpc url
260+ :* `'logs by range'
261+ %eth-get-logs
262+ `number+from-number
263+ `number+to-number
264+ contracts
265+ topics
266+ ==
267+ %- pure:m
268+ (parse-event-logs:rpc:ethereum json)
269+::
270+++ get-next-nonce
271+ |= [url=@ta =address]
272+ =/ m (strand:strandio ,@ud)
273+ ^- form:m
274+ ;< =json bind:m
275+ %^ request-rpc url `'nonce'
276+ [%eth-get-transaction-count address [%label %latest]]
277+ %- pure:m
278+ (parse-eth-get-transaction-count:rpc:ethereum json)
279+::
280+++ get-balance
281+ |= [url=@ta =address]
282+ =/ m (strand:strandio ,@ud)
283+ ^- form:m
284+ ;< =json bind:m
285+ %^ request-rpc url `'balance'
286+ [%eth-get-balance address [%label %latest]]
287+ %- pure:m
288+ (parse-eth-get-balance:rpc:ethereum json)
289+--
base-desk/lib/hark-store.hoonnew file+255
@@ -0,0 +1,255 @@
1+/- sur=hark-store
2+^?
3+=, sur
4+=< [. sur]
5+|%
6+
7+++ enjs
8+ =, enjs:format
9+ |%
10+ ++ update
11+ |= upd=^update
12+ ^- json
13+ %+ frond -.upd
14+ ?+ -.upd a+~
15+ %added (notification +.upd)
16+ %add-note (add-note +.upd)
17+ %timebox (timebox +.upd)
18+ %more (more +.upd)
19+ %read-each (read-each +.upd)
20+ %read-count (place +.upd)
21+ %unread-each (read-each +.upd)
22+ %unread-count (unread-count +.upd)
23+ %saw-place (saw-place +.upd)
24+ %all-stats (all-stats +.upd)
25+ %del-place (place +.upd)
26+ ::%read-note (index +.upd)
27+ ::%note-read (note-read +.upd)
28+ %archived (archived +.upd)
29+ ==
30+ ::
31+ ++ add-note
32+ |= [bi=^bin bo=^body]
33+ %- pairs
34+ :~ bin+(bin bi)
35+ body+(body bo)
36+ ==
37+ ::
38+ ++ saw-place
39+ |= [p=^place t=(unit ^time)]
40+ %- pairs
41+ :~ place+(place p)
42+ time+?~(t ~ (time u.t))
43+ ==
44+ ::
45+ ++ archived
46+ |= [t=^time l=^lid n=^notification]
47+ %- pairs
48+ :~ lid+(lid l)
49+ time+s+(scot %ud t)
50+ notification+(notification n)
51+ ==
52+ ::
53+ ++ note-read
54+ |= *
55+ (pairs ~)
56+ ::
57+ ++ all-stats
58+ |= places=(map ^place ^stats)
59+ ^- json
60+ :- %a
61+ ^- (list json)
62+ %+ turn ~(tap by places)
63+ |= [p=^place s=^stats]
64+ %- pairs
65+ :~ stats+(stats s)
66+ place+(place p)
67+
68+ ==
69+ ::
70+ ++ stats
71+ |= s=^stats
72+ ^- json
73+ %- pairs
74+ :~ each+a+(turn ~(tap in each.s) (cork spat (lead %s)))
75+ last+(time last.s)
76+ count+(numb count.s)
77+ ==
78+ ++ more
79+ |= upds=(list ^update)
80+ ^- json
81+ a+(turn upds update)
82+ ::
83+ ++ place
84+ |= =^place
85+ %- pairs
86+ :~ desk+s+desk.place
87+ path+s+(spat path.place)
88+ ==
89+ ::
90+ ++ bin
91+ |= =^bin
92+ %- pairs
93+ :~ place+(place place.bin)
94+ path+s+(spat path.bin)
95+ ==
96+ ++ notification
97+ |= ^notification
98+ ^- json
99+ %- pairs
100+ :~ time+(time date)
101+ bin+(^bin bin)
102+ body+(bodies body)
103+ ==
104+ ++ bodies
105+ |= bs=(list ^body)
106+ ^- json
107+ a+(turn bs body)
108+ ::
109+ ++ contents
110+ |= cs=(list ^content)
111+ ^- json
112+ a+(turn cs content)
113+ ::
114+ ++ content
115+ |= c=^content
116+ ^- json
117+ %+ frond -.c
118+ ?- -.c
119+ %ship s+(scot %p ship.c)
120+ %text s+cord.c
121+ ==
122+ ::
123+ ++ body
124+ |= ^body
125+ ^- json
126+ %- pairs
127+ :~ title+(contents title)
128+ content+(contents content)
129+ time+(^time time)
130+ link+s+(spat link)
131+ ==
132+ ::
133+ ++ binned-notification
134+ |= [=^bin =^notification]
135+ %- pairs
136+ :~ bin+(^bin bin)
137+ notification+(^notification notification)
138+ ==
139+ ++ lid
140+ |= l=^lid
141+ ^- json
142+ %+ frond -.l
143+ ?- -.l
144+ ?(%seen %unseen) ~
145+ %archive s+(scot %ud time.l)
146+ ==
147+ ::
148+ ++ timebox
149+ |= [li=^lid l=(list ^notification)]
150+ ^- json
151+ %- pairs
152+ :~ lid+(lid li)
153+ notifications+a+(turn l notification)
154+ ==
155+ ::
156+ ++ read-each
157+ |= [p=^place pax=^path]
158+ %- pairs
159+ :~ place+(place p)
160+ path+(path pax)
161+ ==
162+ ::
163+ ++ unread-count
164+ |= [p=^place inc=? count=@ud]
165+ %- pairs
166+ :~ place+(place p)
167+ inc+b+inc
168+ count+(numb count)
169+ ==
170+ --
171+++ dejs
172+ =, dejs:format
173+ |%
174+ ++ ship (su ;~(pfix sig fed:ag))
175+ :: TODO: fix +stab
176+ ::
177+ ++ pa
178+ |= j=json
179+ ^- path
180+ ?> ?=(%s -.j)
181+ ?: =('/' p.j) /
182+ (stab p.j)
183+ ::
184+ ++ place
185+ %- ot
186+ :~ desk+so
187+ path+pa
188+ ==
189+ ::
190+ ++ bin
191+ %- ot
192+ :~ path+pa
193+ place+place
194+ ==
195+ ::
196+ ++ read-each
197+ %- ot
198+ :~ place+place
199+ path+pa
200+ ==
201+ ::
202+ :: parse date as @ud
203+ :: TODO: move to zuse
204+ ++ sd
205+ |= jon=json
206+ ^- @da
207+ ?> ?=(%s -.jon)
208+ `@da`(rash p.jon dem:ag)
209+ ::
210+ ++ lid
211+ %- of
212+ :~ archive+sd
213+ unseen+ul
214+ seen+ul
215+ ==
216+ ::
217+ ++ archive
218+ %- ot
219+ :~ lid+lid
220+ bin+bin
221+ ==
222+ ++ content
223+ %- of
224+ :~ text+so
225+ ship+ship
226+ ==
227+ ::
228+ ++ body
229+ %- ot
230+ :~ title+(ar content)
231+ content+(ar content)
232+ time+di
233+ binned+pa
234+ link+pa
235+ ==
236+ ::
237+ ++ add-note
238+ %- ot
239+ :~ bin+bin
240+ body+body
241+ ==
242+ ::
243+ ++ action
244+ ^- $-(json ^action)
245+ %- of
246+ :~ archive-all+ul
247+ archive+archive
248+ opened+ul
249+ read-count+place
250+ read-each+read-each
251+ read-note+bin
252+ add-note+add-note
253+ ==
254+ --
255+--
base-desk/lib/jose.hoonnew file+222
@@ -0,0 +1,222 @@
1+/+ primitive-rsa, *pkcs
2+=* rsa primitive-rsa
3+|%
4+:: +en-base64url: url-safe base64 encoding, without padding
5+::
6+++ en-base64url
7+ ~(en base64:mimes:html | &)
8+:: +de-base64url: url-safe base64 decoding, without padding
9+::
10+++ de-base64url
11+ ~(de base64:mimes:html | &)
12+:: |octn: encode/decode unsigned atoms as big-endian octet stream
13+::
14+++ octn
15+ |%
16+ ++ en |=(a=@u `octs`[(met 3 a) (swp 3 a)])
17+ ++ de |=(a=octs `@u`(rev 3 p.a q.a))
18+ --
19+:: +eor: explicit sort order comparator
20+::
21+:: Lookup :a and :b in :lit, and pass their indices to :com.
22+::
23+++ eor
24+ |= [com=$-([@ @] ?) lit=(list)]
25+ |= [a=* b=*]
26+ ^- ?
27+ (fall (bind (both (find ~[a] lit) (find ~[b] lit)) com) |)
28+:: +en-json-sort: json encoding with sorted object keys
29+::
30+:: XX move %zuse with sorting optional?
31+::
32+++ en-json-sort :: XX rename
33+ |^ |=([sor=$-(^ ?) val=json] (apex val sor ""))
34+ :: :: ++apex:en-json:html
35+ ++ apex
36+ |= [val=json sor=$-(^ ?) rez=tape]
37+ ^- tape
38+ ?~ val (weld "null" rez)
39+ ?- -.val
40+ %a
41+ :- '['
42+ =. rez [']' rez]
43+ !.
44+ ?~ p.val rez
45+ |-
46+ ?~ t.p.val ^$(val i.p.val)
47+ ^$(val i.p.val, rez [',' $(p.val t.p.val)])
48+ ::
49+ %b (weld ?:(p.val "true" "false") rez)
50+ %n (weld (trip p.val) rez)
51+ %s
52+ :- '"'
53+ =. rez ['"' rez]
54+ =+ viz=(trip p.val)
55+ !.
56+ |- ^- tape
57+ ?~ viz rez
58+ =+ hed=(jesc i.viz)
59+ ?: ?=([@ ~] hed)
60+ [i.hed $(viz t.viz)]
61+ (weld hed $(viz t.viz))
62+ ::
63+ %o
64+ :- '{'
65+ =. rez ['}' rez]
66+ =/ viz
67+ %+ sort ~(tap by p.val)
68+ |=((pair) (sor (head p) (head q)))
69+ ?~ viz rez
70+ !.
71+ |- ^+ rez
72+ ?~ t.viz ^$(val [%s p.i.viz], rez [':' ^$(val q.i.viz)])
73+ =. rez [',' $(viz t.viz)]
74+ ^$(val [%s p.i.viz], rez [':' ^$(val q.i.viz)])
75+ ==
76+ ::
77+ ++ jesc
78+ =+ utf=|=(a=@ ['\\' 'u' ((x-co 4):co a)])
79+ |= a=@ ^- tape
80+ ?+ a ?:(&((gth a 0x1f) !=(a 0x7f)) [a ~] (utf a))
81+ %10 "\\n"
82+ %34 "\\\""
83+ %92 "\\\\"
84+ ==
85+ --
86+:: %/lib/jose
87+::
88+:: |jwk: json representations of cryptographic keys (rfc7517)
89+::
90+:: Url-safe base64 encoding of key parameters in big-endian byte order.
91+:: RSA-only for now
92+::
93+++ jwk
94+ |%
95+ :: |en:jwk: encoding of json cryptographic keys
96+ ::
97+ ++ en
98+ => |%
99+ :: +numb:en:jwk: base64-url encode big-endian number
100+ ::
101+ ++ numb (corl en-base64url en:octn)
102+ --
103+ |%
104+ :: +pass:en:jwk: json encode public key
105+ ::
106+ ++ pass
107+ |= k=key:rsa
108+ ^- json
109+ [%o (my kty+s+'RSA' n+s+(numb n.pub.k) e+s+(numb e.pub.k) ~)]
110+ :: +ring:en:jwk: json encode private key
111+ ::
112+ ++ ring
113+ |= k=key:rsa
114+ ^- json
115+ ~| %rsa-need-ring
116+ ?> ?=(^ sek.k)
117+ :- %o %- my :~
118+ kty+s+'RSA'
119+ n+s+(numb n.pub.k)
120+ e+s+(numb e.pub.k)
121+ d+s+(numb d.u.sek.k)
122+ p+s+(numb p.u.sek.k)
123+ q+s+(numb q.u.sek.k)
124+ ==
125+ --
126+ :: |de:jwk: decoding of json cryptographic keys
127+ ::
128+ ++ de
129+ =, dejs-soft:format
130+ => |%
131+ :: +numb:de:jwk: parse base64-url big-endian number
132+ ::
133+ ++ numb (cu (cork de-base64url (lift de:octn)) so)
134+ --
135+ |%
136+ :: +pass:de:jwk: decode json public key
137+ ::
138+ ++ pass
139+ %+ ci
140+ =/ a (unit @ux)
141+ |= [kty=@t n=a e=a]
142+ ^- (unit key:rsa)
143+ =/ pub (both n e)
144+ ?~(pub ~ `[u.pub ~])
145+ (ot kty+(su (jest 'RSA')) n+numb e+numb ~)
146+ :: +ring:de:jwk: decode json private key
147+ ::
148+ ++ ring
149+ %+ ci
150+ =/ a (unit @ux)
151+ |= [kty=@t n=a e=a d=a p=a q=a]
152+ ^- (unit key:rsa)
153+ =/ pub (both n e)
154+ =/ sek :(both d p q)
155+ ?:(|(?=(~ pub) ?=(~ sek)) ~ `[u.pub sek])
156+ (ot kty+(su (jest 'RSA')) n+numb e+numb d+numb p+numb q+numb ~)
157+ --
158+ :: |thumb:jwk: "thumbprint" json-encoded key (rfc7638)
159+ ::
160+ ++ thumb
161+ |%
162+ :: +pass:thumb:jwk: thumbprint json-encoded public key
163+ ::
164+ ++ pass
165+ |= k=key:rsa
166+ (en-base64url 32 (shax (crip (en-json-sort aor (pass:en k)))))
167+ :: +ring:thumb:jwk: thumbprint json-encoded private key
168+ ::
169+ ++ ring !!
170+ --
171+ --
172+:: |jws: json web signatures (rfc7515)
173+::
174+:: Note: flattened signature form only.
175+::
176+++ jws
177+ |%
178+ :: +sign:jws: sign json value
179+ ::
180+ ++ sign
181+ |= [k=key:rsa pro=json lod=json]
182+ |^ ^- json
183+ =. pro header
184+ =/ protect=cord (encode pro)
185+ =/ payload=cord (encode lod)
186+ :- %o %- my :~
187+ protected+s+protect
188+ payload+s+payload
189+ signature+s+(sign protect payload)
190+ ==
191+ :: +header:sign:jws: set signature algorithm in header
192+ ::
193+ ++ header
194+ ?> ?=([%o *] pro)
195+ ^- json
196+ [%o (~(put by p.pro) %alg s+'RS256')]
197+ :: +encode:sign:jws: encode json for signing
198+ ::
199+ :: Alphabetically sort object keys, url-safe base64 encode
200+ :: the serialized json.
201+ ::
202+ ++ encode
203+ |= jon=json
204+ %- en-base64url
205+ %- as-octt:mimes:html
206+ (en-json-sort aor jon)
207+ :: +sign:sign:jws: compute signature
208+ ::
209+ :: Url-safe base64 encode in big-endian byte order.
210+ ::
211+ ++ sign
212+ |= [protect=cord payload=cord]
213+ =/ msg=@t (rap 3 ~[protect '.' payload])
214+ =/ sig=@ud (~(sign rs256 k) (met 3 msg) msg)
215+ =/ len=@ud (met 3 n.pub.k)
216+ (en-base64url len (rev 3 len sig))
217+ --
218+ :: +verify:jws: verify signature
219+ ::
220+ ++ verify !!
221+ --
222+--
base-desk/lib/keygen.hoonnew file+112
@@ -0,0 +1,112 @@
1+:: urbit-style key generation and derivation functions
2+::
3+/- keygen
4+::
5+/+ ethereum, bip32, bip39
6+::
7+=, keygen
8+::
9+|%
10+++ argon2u
11+ |= [who=ship tic=byts]
12+ ^- @
13+ ~| [%who who (met 3 who)]
14+ :: ?> (lte (met 3 who) 4)
15+ %- (argon2-urbit:argon2:crypto 32)
16+ :- tic
17+ =- [(met 3 -) (swp 3 -)]
18+ %- crip
19+ (weld "urbitkeygen" (a-co:co who))
20+::
21+++ child-node-from-seed
22+ |= [seed=@ typ=tape pass=(unit @t)]
23+ ^- node
24+ =+ sed=(seed:ds 32^seed typ)
25+ =+ nom=(from-entropy:bip39 32^sed)
26+ :+ typ nom
27+ %- wallet:ds
28+ %+ to-seed:bip39 nom
29+ (trip (fall pass ''))
30+::
31+++ derive-network-seed
32+ |= [mngs=@ rev=@ud]
33+ ^- @ux
34+ =+ (seed:ds 64^mngs (weld "network" (a-co:co rev)))
35+ ?: =(0 rev) -
36+ :: hash again to prevent length extension attacks
37+ (sha-256l:sha 32 -)
38+::
39+++ ownership-wallet-from-ticket
40+ |= [who=ship ticket=byts pass=(unit @t)]
41+ ^- node
42+ =+ master-seed=(argon2u who ticket)
43+ (child-node-from-seed master-seed "ownership" pass)
44+::
45+++ full-wallet-from-ticket
46+ :: who: username
47+ :: ticket: password
48+ :: rev: network key revision
49+ :: pass: optional passphrase
50+ ::
51+ |= [who=ship ticket=byts rev=@ud pass=(unit @t)]
52+ ^- vault
53+ =+ master-seed=(argon2u who ticket)
54+ =/ cn :: child node
55+ |= typ=nodetype
56+ (child-node-from-seed master-seed typ pass)
57+ ::
58+ :- ^= ownership ^- node
59+ (cn "ownership")
60+ ::
61+ :- ^= voting ^- node
62+ (cn "voting")
63+ ::
64+ =/ management=node
65+ (cn "management")
66+ :- management=management
67+ ::
68+ :- ^= transfer ^- node
69+ (cn "transfer")
70+ ::
71+ :- ^= spawn ^- node
72+ (cn "spawn")
73+ ::
74+ ^= network ^- uode
75+ =/ mad :: management seed
76+ %+ to-seed:bip39
77+ seed:management
78+ (trip (fall pass ''))
79+ =+ sed=(derive-network-seed mad rev)
80+ [rev sed (urbit:ds sed)]
81+::
82+++ ds :: derive from raw seed
83+ |%
84+ ++ wallet
85+ |= seed=@
86+ ^- ^wallet
87+ =+ => (from-seed:bip32 64^seed)
88+ (derive-path "m/44'/60'/0'/0/0")
89+ :+ [public-key private-key]
90+ (address-from-prv:key:ethereum private-key)
91+ chain-code
92+ ::
93+ ++ urbit
94+ |= seed=@
95+ ^- edkeys
96+ =+ =< [pub=pub:ex sec=sec:ex]
97+ (pit:nu:cric:crypto 256 seed %b ~)
98+ :- ^= auth
99+ :- (rsh 3 (end [3 33] pub))
100+ (rsh 3 (end [3 33] sec))
101+ ^= crypt
102+ :- (rsh [3 33] pub)
103+ (rsh [3 33] sec)
104+ ::
105+ ++ seed
106+ |= [seed=byts salt=tape]
107+ ^- @ux
108+ %- sha-256l:sha
109+ :- (add wid.seed (lent salt))
110+ (cat 3 (crip (flop salt)) dat.seed)
111+ --
112+--
base-desk/lib/language-server/build.hoonnew file+61
@@ -0,0 +1,61 @@
1+/- *language-server
2+::
3+|%
4+++ parse-error
5+ |= =tape
6+ ^- (unit [=path =range])
7+ =/ parse-pair
8+ %+ cook
9+ |=([row=@ud col=@ud] [(dec row) col])
10+ (ifix [sel ser] ;~((glue ace) dem dem))
11+ =/ parse-path
12+ %+ cook
13+ |=(p=path (slag 3 p))
14+ (ifix [fas (jest '::')] (more fas urs:ab))
15+ =/ parse-full
16+ ;~(plug parse-path ;~(sfix ;~((glue dot) parse-pair parse-pair) gar))
17+ (rust tape parse-full)
18+::
19+++ get-errors-from-tang
20+ |= [uri=@t =tang]
21+ ^- (list range)
22+ =/ =path
23+ (uri-to-path uri)
24+ %+ murn tang
25+ |= =tank
26+ ^- (unit range)
27+ ?. ?=([%leaf *] tank)
28+ ~
29+ =/ error
30+ (parse-error p.tank)
31+ ?~ error
32+ ~
33+ ?: =(path path.u.error)
34+ `range.u.error
35+ ~
36+::
37+++ uri-to-path
38+ |= uri=@t
39+ ^- path
40+ =/ pier-root=(set cord)
41+ %- sy
42+ ['app' 'gen' 'lib' 'mar' 'ren' 'sur' 'sys' 'test' ~]
43+ =/ path=(list cord)
44+ (parse-uri uri)
45+ |-
46+ ?< ?=(~ path)
47+ ?: (~(has in pier-root) i.path)
48+ `^path`path
49+ $(path t.path)
50+::
51+++ parse-uri
52+ |= uri=@t
53+ =- (fall - /fail)
54+ %+ rush uri
55+ %+ more
56+ ;~(pose (plus fas) dot)
57+ %+ cook
58+ crip
59+ (star ;~(pose col hep alf))
60+::
61+--
base-desk/lib/language-server/complete.hoonnew file+387
@@ -0,0 +1,387 @@
1+/+ language-server-parser
2+:: Autocomplete for hoon.
3+::
4+=/ debug |
5+|%
6+++ option
7+ |$ [item]
8+ [term=cord detail=item]
9+::
10+:: Like +rose except also produces line number
11+::
12+++ lily
13+ |* [los=tape sab=rule]
14+ =+ vex=(sab [[1 1] los])
15+ ?~ q.vex
16+ [%| p=p.vex(q (dec q.p.vex))]
17+ ?. =(~ q.q.u.q.vex)
18+ [%| p=p.vex(q (dec q.p.vex))]
19+ [%& p=p.u.q.vex]
20+::
21+:: Get all the identifiers accessible if this type is your subject.
22+::
23+++ get-identifiers
24+ |= ty=type
25+ %- flop
26+ |- ^- (list (option type))
27+ ?- ty
28+ %noun ~
29+ %void ~
30+ [%atom *] ~
31+ [%cell *]
32+ %+ weld
33+ $(ty p.ty)
34+ $(ty q.ty)
35+ ::
36+ [%core *]
37+ %- weld
38+ :_ ?. ?=(%gold r.p.q.ty)
39+ ~
40+ $(ty p.ty)
41+ ^- (list (option type))
42+ %- zing
43+ %+ turn ~(tap by q.r.q.ty)
44+ |= [term =tome]
45+ %+ turn
46+ ~(tap by tome)
47+ |= [name=term =hoon]
48+ ^- (pair term type)
49+ ~| term=term
50+ [name ~(play ~(et ut ty) ~[name] ~)]
51+ ::
52+ [%face *]
53+ ?^ p.ty
54+ ~
55+ [p.ty q.ty]~
56+ ::
57+ [%fork *]
58+ %= $
59+ ty
60+ =/ tines ~(tap in p.ty)
61+ ?~ tines
62+ %void
63+ |- ^- type
64+ ?~ t.tines
65+ i.tines
66+ (~(fuse ut $(tines t.tines)) i.tines)
67+ ==
68+ ::
69+ [%hint *] $(ty q.ty)
70+ [%hold *] $(ty ~(repo ut ty))
71+ ==
72+::
73+++ search-exact
74+ |* [sid=term options=(list (option))]
75+ =/ match
76+ %+ skim options
77+ |= [id=cord *]
78+ =(sid id)
79+ ?~ match
80+ ~
81+ [~ i.match]
82+::
83+:: Get all the identifiers that start with sid.
84+::
85+++ search-prefix
86+ |* [sid=cord ids=(list (option))]
87+ ^+ ids
88+ %+ skim ids
89+ |= [id=cord *]
90+ ^- ?(%.y %.n)
91+ =(sid (end [3 (met 3 sid)] id))
92+::
93+:: Get the longest prefix of a list of identifiers.
94+::
95+++ longest-match
96+ |= matches=(list (option))
97+ ^- cord
98+ ?~ matches
99+ ''
100+ =/ n 1
101+ =/ last (met 3 term.i.matches)
102+ |- ^- term
103+ ?: (gth n last)
104+ term.i.matches
105+ =/ prefix (end [3 n] term.i.matches)
106+ ?: |- ^- ?
107+ ?| ?=(~ t.matches)
108+ ?& =(prefix (end [3 n] term.i.t.matches))
109+ $(t.matches t.t.matches)
110+ == ==
111+ $(n +(n))
112+ (end [3 (dec n)] term.i.matches)
113+::
114+:: Run +find-type safely, printing the first line of the stack trace on
115+:: error.
116+::
117+++ find-type-mule
118+ |= [sut=type gen=hoon]
119+ ^- (unit [term type])
120+ =/ res (mule |.((find-type sut gen)))
121+ ?- -.res
122+ %& p.res
123+ %| ((slog (flop (scag 10 p.res))) ~)
124+ ==
125+::
126+:: Get the subject type of the wing where you've put the "magic-spoon".
127+::
128+++ find-type
129+ |= [sut=type gen=hoon]
130+ =* loop $
131+ |^
132+ ^- (unit [term type])
133+ ?- gen
134+ [%cnts [%magic-spoon ~] *] `['' sut]
135+ [%cnts [%magic-spoon @ ~] *] `[i.t.p.gen sut]
136+ [%cnts [%magic-spoon @ *] *]
137+ %= $
138+ sut (~(play ut sut) wing+t.t.p.gen)
139+ t.p.gen t.p.gen(t ~)
140+ ==
141+ ::
142+ [%cnts [%magic-fork @ ~] *]
143+ `['' (~(play ut sut) wing+t.p.gen)]
144+ ::
145+ [^ *] (both p.gen q.gen)
146+ [%brcn *] (grow q.gen)
147+ [%brpt *] (grow q.gen)
148+ [%cnts *]
149+ |- ^- (unit [term type])
150+ =* inner-loop $
151+ ?~ q.gen
152+ ~
153+ %+ replace
154+ loop(gen q.i.q.gen)
155+ |. inner-loop(q.gen t.q.gen)
156+ ::
157+ [%dtkt *] (spec-and-hoon p.gen q.gen)
158+ [%dtls *] loop(gen p.gen)
159+ [%rock *] ~
160+ [%sand *] ~
161+ [%tune *] ~
162+ [%dttr *] (both p.gen q.gen)
163+ [%dtts *] (both p.gen q.gen)
164+ [%dtwt *] loop(gen p.gen)
165+ [%hand *] ~
166+ [%ktbr *] loop(gen p.gen)
167+ [%ktls *] (both p.gen q.gen)
168+ [%ktpm *] loop(gen p.gen)
169+ [%ktsg *] loop(gen p.gen)
170+ [%ktwt *] loop(gen p.gen)
171+ [%note *] loop(gen q.gen)
172+ [%sgzp *] (both p.gen q.gen)
173+ [%sggr *] loop(gen q.gen) :: should check for hoon in p.gen
174+ [%tsgr *] (change p.gen q.gen)
175+ [%tscm *]
176+ %+ replace
177+ loop(gen p.gen)
178+ |.(loop(gen q.gen, sut (~(busk ut sut) p.gen)))
179+ ::
180+ [%wtcl *] (bell p.gen q.gen r.gen)
181+ [%fits *] (both p.gen wing+q.gen)
182+ [%wthx *] loop(gen wing+q.gen)
183+ [%dbug *] loop(gen q.gen)
184+ [%zpcm *] (both p.gen q.gen)
185+ [%lost *] loop(gen p.gen)
186+ [%zpmc *] (both p.gen q.gen)
187+ [%zpts *] loop(gen p.gen)
188+ [%zppt *] (both q.gen r.gen)
189+ [%zpgl *] (spec-and-hoon p.gen q.gen)
190+ [%zpzp *] ~
191+ *
192+ =+ doz=~(open ap gen)
193+ ?: =(doz gen)
194+ ~_ (show [%c 'hoon'] [%q gen])
195+ ~> %mean.'play-open'
196+ !!
197+ loop(gen doz)
198+ ==
199+ ::
200+ ++ replace
201+ |= [a=(unit [term type]) b=(trap (unit [term type]))]
202+ ^- (unit [term type])
203+ ?~(a $:b a)
204+ ::
205+ ++ both
206+ |= [a=hoon b=hoon]
207+ (replace loop(gen a) |.(loop(gen b)))
208+ ::
209+ ++ bell
210+ |= [a=hoon b=hoon c=hoon]
211+ %+ replace loop(gen a)
212+ |. %+ replace loop(gen b, sut (~(gain ut sut) a))
213+ |. loop(gen c, sut (~(lose ut sut) a))
214+ ::
215+ ++ spec-and-hoon
216+ |= [a=spec b=hoon]
217+ (replace (find-type-in-spec sut a) |.(loop(gen b)))
218+ ::
219+ ++ change
220+ |= [a=hoon b=hoon]
221+ (replace loop(gen a) |.(loop(gen b, sut (~(play ut sut) a))))
222+ ::
223+ ++ grow
224+ |= m=(map term tome)
225+ =/ tomes ~(tap by m)
226+ |- ^- (unit [term type])
227+ =* outer-loop $
228+ ?~ tomes
229+ ~
230+ =/ arms ~(tap by q.i.tomes)
231+ |- ^- (unit [term type])
232+ =* inner-loop $
233+ ?~ arms
234+ outer-loop(tomes t.tomes)
235+ %+ replace
236+ loop(gen q.i.arms, sut (~(play ut sut) gen))
237+ |. inner-loop(arms t.arms)
238+ --
239+::
240+:: Not implemented yet. I wonder whether we should modify types found
241+:: in spec mode such that if it's a mold that produces a type, it
242+:: should just display the type and not that it's technically a
243+:: function.
244+::
245+++ find-type-in-spec
246+ |= [sut=type pec=spec]
247+ ^- (unit [term type])
248+ ~
249+::
250+++ get-id-sym
251+ |= [pos=@ud =tape]
252+ %^ get-id pos tape
253+ ^- $-(nail (like (unit @t)))
254+ ;~(sfix (punt sym) (star ;~(pose prn (just `@`10))))
255+::
256+++ get-id-cord
257+ |= [pos=@ud =tape]
258+ %^ get-id pos tape
259+ ^- $-(nail (like (unit @t)))
260+ ;~(sfix (punt (cook crip (star prn))) (star ;~(pose prn (just `@`10))))
261+::
262+++ get-id
263+ |= [pos=@ud txt=tape seek=$-(nail (like (unit @t)))]
264+ ^- [forward=(unit @t) backward=(unit @t) id=(unit @t)]
265+ =/ forward=(unit @t)
266+ (scan (slag pos txt) seek)
267+ =/ backward=(unit @t)
268+ %- (lift |=(t=@t (swp 3 t)))
269+ (scan (flop (scag pos txt)) seek)
270+ =/ id=(unit @t)
271+ ?~ forward
272+ ?~ backward
273+ ~
274+ `u.backward
275+ ?~ backward
276+ `u.forward
277+ `(cat 3 u.backward u.forward)
278+ [forward backward id]
279+::
280+:: Insert magic marker in hoon source at the given position.
281+::
282+++ insert-magic
283+ |= [pos=@ud txt=tape]
284+ ^- [back-pos=@ud fore-pos=@ud txt=tape]
285+ :: Find beg-pos by searching backward to where the current term
286+ :: begins
287+ =+ (get-id-sym pos txt)
288+ =/ back-pos
289+ ?~ backward
290+ pos
291+ (sub pos (met 3 u.backward))
292+ =/ fore-pos
293+ ?~ forward
294+ pos
295+ (add pos (met 3 u.forward))
296+ :+ back-pos fore-pos
297+ :: Insert "magic-spoon" marker so +find-type can identify where to
298+ :: stop.
299+ ::
300+ ;: weld
301+ (scag back-pos txt)
302+ ?: &(?=(~ id) ?=([%'.' *] (slag pos txt)))
303+ "magic-fork"
304+ "magic-spoon"
305+ ?~ id
306+ ""
307+ "."
308+ (slag back-pos txt)
309+ "\0a"
310+ ==
311+::
312+:: Produce the longest possible advance without choosing between
313+:: matches.
314+::
315+:: Takes a +hoon which has already has a magic-spoon marker. Useful if
316+:: you want to handle your own parsing.
317+::
318+++ advance-hoon
319+ |= [sut=type gen=hoon]
320+ %+ bind (find-type-mule sut gen)
321+ |= [id=term typ=type]
322+ =/ matches=(list (option type))
323+ (search-prefix id (get-identifiers typ))
324+ (longest-match matches)
325+::
326+:: Same as +advance-hoon, but takes a position and text directly.
327+::
328+++ advance-tape
329+ |= [sut=type pos=@ud code=tape]
330+ (advance-hoon sut (scan txt:(insert-magic pos code) vest))
331+::
332+:: Produce a list of matches.
333+::
334+:: Takes a +hoon which has already has a magic-spoon marker. Useful if
335+:: you want to handle your own parsing.
336+::
337+++ tab-list-hoon
338+ |= [sut=type gen=hoon]
339+ ^- (unit (list (option type)))
340+ %+ bind (find-type-mule sut gen)
341+ |= [id=term typ=type]
342+ (search-prefix id (get-identifiers typ))
343+::
344+:: Same as +advance-hoon, but takes a position and text directly.
345+::
346+++ tab-list-tape
347+ |= [sut=type pos=@ud code=tape]
348+ ^- (each (unit (list (option type))) [row=@ col=@])
349+ ~? > debug %start-magick
350+ =/ magicked txt:(insert-magic pos code)
351+ ~? > debug %start-parsing
352+ =/ res (lily magicked (language-server-parser *path))
353+ ?: ?=(%| -.res)
354+ ~? > debug [%parsing-error p.res]
355+ [%| p.res]
356+ :- %&
357+ ~? > debug %parsed-good
358+ ((cury tab-list-hoon sut) hoon:`pile:clay`p.res)
359+::
360+:: Generators
361+++ tab-generators
362+ |= [pfix=path app=(unit term) gens=(list term)]
363+ ^- (list (option tank))
364+ %+ turn gens
365+ |= gen=term
366+ ^- (option tank)
367+ =/ pax=path
368+ (weld pfix ~[gen %hoon])
369+ =/ file
370+ .^(@t %cx pax)
371+ :_ (render-help file)
372+ ?~ app
373+ (cat 3 '+' gen)
374+ ?: =(%hood u.app)
375+ (cat 3 '|' gen)
376+ :((cury cat 3) ':' u.app '|' gen)
377+:: Stolen from +help
378+++ render-help
379+ |= a=@t
380+ ^- tank
381+ :- %leaf
382+ =/ c (to-wain:format a)
383+ ?~ c "~"
384+ ?. =(':: ' (end [3 4] i.c))
385+ "<undocumented>"
386+ (trip i.c)
387+--
base-desk/lib/language-server/easy-print.hoonnew file+484
@@ -0,0 +1,484 @@
1+:: Fast type printing that's easy on the eyes or your money back
2+::
3+=> |%
4+ +$ cape [p=(map @ud wine) q=wine]
5+ +$ wine
6+ $@ $? %noun
7+ %path
8+ %type
9+ %void
10+ %wall
11+ %wool
12+ %yarn
13+ ==
14+ $% [%mato p=term]
15+ [%gate p=hoon q=type r=wine]
16+ [%core p=(list @ta) q=wine]
17+ [%face p=term q=wine]
18+ [%list p=term q=wine]
19+ [%pear p=term q=@]
20+ [%bcwt p=(list wine)]
21+ [%plot p=(list wine)]
22+ [%stop p=@ud]
23+ [%tree p=term q=wine]
24+ [%unit p=term q=wine]
25+ ==
26+ --
27+|_ sut=type
28+++ dash
29+ |= [mil=tape lim=char lam=tape]
30+ ^- tape
31+ =/ esc (~(gas in *(set @tD)) lam)
32+ :- lim
33+ |- ^- tape
34+ ?~ mil [lim ~]
35+ ?: ?| =(lim i.mil)
36+ =('\\' i.mil)
37+ (~(has in esc) i.mil)
38+ ==
39+ ['\\' i.mil $(mil t.mil)]
40+ ?: (lte ' ' i.mil)
41+ [i.mil $(mil t.mil)]
42+ ['\\' ~(x ne (rsh 2 i.mil)) ~(x ne (end 2 i.mil)) $(mil t.mil)]
43+::
44+++ deal |=(lum=* (dish dole lum))
45+++ dial
46+ |= ham=cape
47+ =+ gid=*(set @ud)
48+ =| top-level=? :: don't need circumfix punctuation
49+ =< `tank`-:$
50+ |%
51+ ++ many
52+ |= haz=(list wine)
53+ ^- [(list tank) (set @ud)]
54+ ?~ haz [~ gid]
55+ =^ mor gid $(haz t.haz)
56+ =^ dis gid ^$(q.ham i.haz)
57+ [[dis mor] gid]
58+ ::
59+ ++ $
60+ ^- [tank (set @ud)]
61+ ?- q.ham
62+ %noun :_(gid [%leaf '*' ~])
63+ %path :_(gid [%leaf '/' ~])
64+ %type :_(gid [%leaf '#' 't' ~])
65+ %void :_(gid [%leaf '#' '!' ~])
66+ %wool :_(gid [%leaf '*' '"' '"' ~])
67+ %wall :_(gid [%leaf '*' '\'' '\'' ~])
68+ %yarn :_(gid [%leaf '"' '"' ~])
69+ [%mato *] :_(gid [%leaf '@' (trip p.q.ham)])
70+ [%gate *]
71+ =^ sam gid
72+ ?. ?=([%plot * * *] r.q.ham)
73+ ?: ?=(%plot -.r.q.ham)
74+ %- (slog -:$(q.ham r.q.ham) ~)
75+ `gid
76+ `gid
77+ [`u=- +]:$(q.ham i.p.r.q.ham, top-level |)
78+ :_ gid
79+ :+ %rose
80+ :- ?> ?=(%core -.q.q.ham)
81+ ?: ?=(%dry q.p.q.q.q.ham)
82+ " -> "
83+ " ~> "
84+ ?: top-level
85+ ["" ""]
86+ ["(" ")"]
87+ :+ ?~(sam leaf+"_" u.sam)
88+ =/ res (mule |.((~(play ut q.q.ham) p.q.ham)))
89+ ?- -.res
90+ %& duck(sut p.res)
91+ %| leaf+"###"
92+ ==
93+ ~
94+ ::
95+ [%core *]
96+ =^ sam gid
97+ ?. ?=([%plot * * ~] q.q.ham)
98+ `gid
99+ [`u=- +]:$(q.ham i.p.q.q.ham)
100+ :_ gid
101+ ?~ sam
102+ :+ %rose
103+ [[' ' ~] ['<' ~] ['>' ~]]
104+ |- ^- (list tank)
105+ ?~ p.q.ham ~
106+ [[%leaf (rip 3 i.p.q.ham)] $(p.q.ham t.p.q.ham)]
107+ :+ %rose
108+ [" -> " "" ""]
109+ :+ u.sam
110+ :+ %rose
111+ [[' ' ~] ['<' ~] ['>' ~]]
112+ |- ^- (list tank)
113+ ?~ p.q.ham ~
114+ [[%leaf (rip 3 i.p.q.ham)] $(p.q.ham t.p.q.ham)]
115+ ~
116+ ::
117+ [%face *]
118+ =^ cox gid $(q.ham q.q.ham)
119+ :_(gid [%palm [['=' ~] ~ ~ ~] [%leaf (trip p.q.ham)] cox ~])
120+ ::
121+ [%list *]
122+ =^ cox gid $(q.ham q.q.ham)
123+ :_(gid [%rose [" " (weld (trip p.q.ham) "(") ")"] cox ~])
124+ ::
125+ [%bcwt *]
126+ =^ coz gid (many p.q.ham)
127+ :_(gid [%rose [[' ' ~] ['?' '(' ~] [')' ~]] coz])
128+ ::
129+ [%plot *]
130+ =^ coz gid (many p.q.ham)
131+ :_(gid [%rose [[' ' ~] ['[' ~] [']' ~]] coz])
132+ ::
133+ [%pear *]
134+ :_(gid [%leaf '$' ~(rend co [%$ p.q.ham q.q.ham])])
135+ ::
136+ [%stop *]
137+ =+ num=~(rend co [%$ %ud p.q.ham])
138+ ?: (~(has in gid) p.q.ham)
139+ :_(gid [%leaf '#' num])
140+ =^ cox gid
141+ %= $
142+ gid (~(put in gid) p.q.ham)
143+ q.ham (~(got by p.ham) p.q.ham)
144+ ==
145+ :_(gid [%palm [['.' ~] ~ ~ ~] [%leaf ['^' '#' num]] cox ~])
146+ ::
147+ [%tree *]
148+ =^ cox gid $(q.ham q.q.ham)
149+ :_(gid [%rose [" " (weld (trip p.q.ham) "(") ")"] cox ~])
150+ ::
151+ [%unit *]
152+ =^ cox gid $(q.ham q.q.ham)
153+ :_(gid [%rose [" " (weld (trip p.q.ham) "(") ")"] cox ~])
154+ ==
155+ --
156+::
157+++ dish !:
158+ |= [ham=cape lum=*] ^- tank
159+ ~| [%dish-h ?@(q.ham q.ham -.q.ham)]
160+ ~| [%lump lum]
161+ ~| [%ham ham]
162+ %- need
163+ =| gil=(set [@ud *])
164+ |- ^- (unit tank)
165+ ?- q.ham
166+ %noun
167+ %= $
168+ q.ham
169+ ?: ?=(@ lum)
170+ [%mato %$]
171+ :- %plot
172+ |- ^- (list wine)
173+ [%noun ?:(?=(@ +.lum) [[%mato %$] ~] $(lum +.lum))]
174+ ==
175+ ::
176+ %path
177+ :- ~
178+ :+ %rose
179+ [['/' ~] ['/' ~] ~]
180+ |- ^- (list tank)
181+ ?~ lum ~
182+ ?@ lum !!
183+ ?> ?=(@ -.lum)
184+ [[%leaf (rip 3 -.lum)] $(lum +.lum)]
185+ ::
186+ %type
187+ =+ tyr=|.((dial dole))
188+ =+ vol=tyr(sut lum)
189+ =+ cis=;;(tank .*(vol [%9 2 %0 1]))
190+ :^ ~ %palm
191+ [~ ~ ~ ~]
192+ [[%leaf '#' 't' '/' ~] cis ~]
193+ ::
194+ %wall
195+ :- ~
196+ :+ %rose
197+ [[' ' ~] ['<' '|' ~] ['|' '>' ~]]
198+ |- ^- (list tank)
199+ ?~ lum ~
200+ ?@ lum !!
201+ [[%leaf (trip ;;(@ -.lum))] $(lum +.lum)]
202+ ::
203+ %wool
204+ :- ~
205+ :+ %rose
206+ [[' ' ~] ['<' '<' ~] ['>' '>' ~]]
207+ |- ^- (list tank)
208+ ?~ lum ~
209+ ?@ lum !!
210+ [(need ^$(q.ham %yarn, lum -.lum)) $(lum +.lum)]
211+ ::
212+ %yarn
213+ [~ %leaf (dash (tape lum) '"' "\{")]
214+ ::
215+ %void
216+ ~
217+ ::
218+ [%mato *]
219+ ?. ?=(@ lum)
220+ ~
221+ :+ ~
222+ %leaf
223+ ?+ (rash p.q.ham ;~(sfix (cook crip (star low)) (star hig)))
224+ ~(rend co [%$ p.q.ham lum])
225+ %$ ~(rend co [%$ %ud lum])
226+ %t (dash (rip 3 lum) '\'' ~)
227+ %tas ['%' ?.(=(0 lum) (rip 3 lum) ['$' ~])]
228+ ==
229+ ::
230+ [%gate *]
231+ !!
232+ ::
233+ [%core *]
234+ :: XX needs rethinking for core metal
235+ :: ?. ?=(^ lum) ~
236+ :: => .(lum `*`lum)
237+ :: =- ?~(tok ~ [~ %rose [[' ' ~] ['<' ~] ['>' ~]] u.tok])
238+ :: ^= tok
239+ :: |- ^- (unit (list tank))
240+ :: ?~ p.q.ham
241+ :: =+ den=^$(q.ham q.q.ham)
242+ :: ?~(den ~ [~ u.den ~])
243+ :: =+ mur=$(p.q.ham t.p.q.ham, lum +.lum)
244+ :: ?~(mur ~ [~ [[%leaf (rip 3 i.p.q.ham)] u.mur]])
245+ [~ (dial ham)]
246+ ::
247+ [%face *]
248+ =+ wal=$(q.ham q.q.ham)
249+ ?~ wal
250+ ~
251+ [~ %palm [['=' ~] ~ ~ ~] [%leaf (trip p.q.ham)] u.wal ~]
252+ ::
253+ [%list *]
254+ ?: =(~ lum)
255+ [~ %leaf '~' ~]
256+ =- ?~ tok
257+ ~
258+ [~ %rose [[' ' ~] ['~' '[' ~] [']' ~]] u.tok]
259+ ^= tok
260+ |- ^- (unit (list tank))
261+ ?: ?=(@ lum)
262+ ?.(=(~ lum) ~ [~ ~])
263+ =+ [for=^$(q.ham q.q.ham, lum -.lum) aft=$(lum +.lum)]
264+ ?. &(?=(^ for) ?=(^ aft))
265+ ~
266+ [~ u.for u.aft]
267+ ::
268+ [%bcwt *]
269+ |- ^- (unit tank)
270+ ?~ p.q.ham
271+ ~
272+ =+ wal=^$(q.ham i.p.q.ham)
273+ ?~ wal
274+ $(p.q.ham t.p.q.ham)
275+ wal
276+ ::
277+ [%plot *]
278+ =- ?~ tok
279+ ~
280+ [~ %rose [[' ' ~] ['[' ~] [']' ~]] u.tok]
281+ ^= tok
282+ |- ^- (unit (list tank))
283+ ?~ p.q.ham
284+ ~
285+ ?: ?=([* ~] p.q.ham)
286+ =+ wal=^$(q.ham i.p.q.ham)
287+ ?~(wal ~ [~ [u.wal ~]])
288+ ?@ lum
289+ ~
290+ =+ gim=^$(q.ham i.p.q.ham, lum -.lum)
291+ ?~ gim
292+ ~
293+ =+ myd=$(p.q.ham t.p.q.ham, lum +.lum)
294+ ?~ myd
295+ ~
296+ [~ u.gim u.myd]
297+ ::
298+ [%pear *]
299+ ?. =(lum q.q.ham)
300+ ~
301+ =. p.q.ham
302+ (rash p.q.ham ;~(sfix (cook crip (star low)) (star hig)))
303+ =+ fox=$(q.ham [%mato p.q.ham])
304+ ?> ?=([~ %leaf ^] fox)
305+ ?: ?=(?(%n %tas) p.q.ham)
306+ fox
307+ [~ %leaf '%' p.u.fox]
308+ ::
309+ [%stop *]
310+ ?: (~(has in gil) [p.q.ham lum]) ~
311+ =+ kep=(~(get by p.ham) p.q.ham)
312+ ?~ kep
313+ ~|([%stop-loss p.q.ham] !!)
314+ $(gil (~(put in gil) [p.q.ham lum]), q.ham u.kep)
315+ ::
316+ [%tree *]
317+ =- ?~ tok
318+ ~
319+ [~ %rose [[' ' ~] ['{' ~] ['}' ~]] u.tok]
320+ ^= tok
321+ =+ tuk=*(list tank)
322+ |- ^- (unit (list tank))
323+ ?: =(~ lum)
324+ [~ tuk]
325+ ?. ?=([n=* l=* r=*] lum)
326+ ~
327+ =+ rol=$(lum r.lum)
328+ ?~ rol
329+ ~
330+ =+ tim=^$(q.ham q.q.ham, lum n.lum)
331+ ?~ tim
332+ ~
333+ $(lum l.lum, tuk [u.tim u.rol])
334+ ::
335+ [%unit *]
336+ ?@ lum
337+ ?.(=(~ lum) ~ [~ %leaf '~' ~])
338+ ?. =(~ -.lum)
339+ ~
340+ =+ wal=$(q.ham q.q.ham, lum +.lum)
341+ ?~ wal
342+ ~
343+ [~ %rose [[' ' ~] ['[' ~] [']' ~]] [%leaf '~' ~] u.wal ~]
344+ ==
345+::
346+++ doge
347+ |= ham=cape
348+ =- ?+ woz woz
349+ [%list * [%mato %'ta']] %path
350+ [%list * [%mato %'t']] %wall
351+ [%list * [%mato %'tD']] %yarn
352+ [%list * %yarn] %wool
353+ ==
354+ ^= woz
355+ ^- wine
356+ ?. ?=([%stop *] q.ham)
357+ ?: ?& ?= [%bcwt [%pear %n %0] [%plot [%pear %n %0] [%face *] ~] ~]
358+ q.ham
359+ =(1 (met 3 p.i.t.p.i.t.p.q.ham))
360+ ==
361+ [%unit =<([p q] i.t.p.i.t.p.q.ham)]
362+ q.ham
363+ =+ may=(~(get by p.ham) p.q.ham)
364+ ?~ may
365+ q.ham
366+ =+ nul=[%pear %n 0]
367+ ?. ?& ?=([%bcwt *] u.may)
368+ ?=([* * ~] p.u.may)
369+ |(=(nul i.p.u.may) =(nul i.t.p.u.may))
370+ ==
371+ q.ham
372+ =+ din=?:(=(nul i.p.u.may) i.t.p.u.may i.p.u.may)
373+ ?: ?& ?=([%plot [%face *] [%face * %stop *] ~] din)
374+ =(p.q.ham p.q.i.t.p.din)
375+ =(1 (met 3 p.i.p.din))
376+ =(1 (met 3 p.i.t.p.din))
377+ ==
378+ :+ %list
379+ (cat 3 p.i.p.din p.i.t.p.din)
380+ q.i.p.din
381+ ?: ?& ?= $: %plot
382+ [%face *]
383+ [%face * %stop *]
384+ [[%face * %stop *] ~]
385+ ==
386+ din
387+ =(p.q.ham p.q.i.t.p.din)
388+ =(p.q.ham p.q.i.t.t.p.din)
389+ =(1 (met 3 p.i.p.din))
390+ =(1 (met 3 p.i.t.p.din))
391+ =(1 (met 3 p.i.t.t.p.din))
392+ ==
393+ :+ %tree
394+ %^ cat
395+ 3
396+ p.i.p.din
397+ (cat 3 p.i.t.p.din p.i.t.t.p.din)
398+ q.i.p.din
399+ q.ham
400+::
401+++ dole
402+ ^- cape
403+ =+ gil=*(set type)
404+ =+ dex=[p=*(map type @) q=*(map @ wine)]
405+ =< [q.p q]
406+ |- ^- [p=[p=(map type @) q=(map @ wine)] q=wine]
407+ =- [p.tez (doge q.p.tez q.tez)]
408+ ^= tez
409+ ^- [p=[p=(map type @) q=(map @ wine)] q=wine]
410+ ?: (~(meet ut sut) -:!>(*type))
411+ [dex %type]
412+ ?- sut
413+ %noun [dex sut]
414+ %void [dex sut]
415+ [%atom *] [dex ?~(q.sut [%mato p.sut] [%pear p.sut u.q.sut])]
416+ [%cell *]
417+ =+ hin=$(sut p.sut)
418+ =+ yon=$(dex p.hin, sut q.sut)
419+ :- p.yon
420+ :- %plot
421+ ?:(?=([%plot *] q.yon) [q.hin p.q.yon] [q.hin q.yon ~])
422+ ::
423+ [%core *]
424+ ?: ?=([[%$ [[%$ @ *] ~ ~]] ~ ~] q.r.q.sut)
425+ =/ dad $(sut p.sut)
426+ :- p.dad
427+ ~! q.r.q.sut
428+ [%gate q.n.q.n.q.r.q.sut sut(r.p.q %gold) q.dad]
429+ =+ yad=$(sut p.sut)
430+ :- p.yad
431+ =+ ^= doy ^- [p=(list @ta) q=wine]
432+ ?: ?=([%core *] q.yad)
433+ [p.q.yad q.q.yad]
434+ [~ q.yad]
435+ :- %core
436+ :_ q.doy
437+ :_ p.doy
438+ %^ cat 3
439+ %~ rent co
440+ :+ %$ %ud
441+ %- ~(rep by (~(run by q.r.q.sut) |=(tome ~(wyt by +<))))
442+ |=([[@ a=@u] b=@u] (add a b))
443+ %^ cat 3
444+ ?-(r.p.q.sut %gold '.', %iron '|', %lead '?', %zinc '&')
445+ =+ gum=(mug q.r.q.sut)
446+ %+ can 3
447+ :~ [1 (add 'a' (mod gum 26))]
448+ [1 (add 'a' (mod (div gum 26) 26))]
449+ [1 (add 'a' (mod (div gum 676) 26))]
450+ ==
451+ ::
452+ [%hint *]
453+ $(sut q.sut)
454+ ::
455+ [%face *]
456+ =+ yad=$(sut q.sut)
457+ ?^(p.sut yad [p.yad [%face p.sut q.yad]])
458+ ::
459+ [%fork *]
460+ =+ yed=(sort ~(tap in p.sut) aor)
461+ =- [p [%bcwt q]]
462+ |- ^- [p=[p=(map type @) q=(map @ wine)] q=(list wine)]
463+ ?~ yed
464+ [dex ~]
465+ =+ mor=$(yed t.yed)
466+ =+ dis=^$(dex p.mor, sut i.yed)
467+ [p.dis q.dis q.mor]
468+ ::
469+ [%hold *]
470+ =+ hey=(~(get by p.dex) sut)
471+ ?^ hey
472+ [dex [%stop u.hey]]
473+ ?: (~(has in gil) sut)
474+ =+ dyr=+(~(wyt by p.dex))
475+ [[(~(put by p.dex) sut dyr) q.dex] [%stop dyr]]
476+ =+ rom=$(gil (~(put in gil) sut), sut ~(repo ut sut))
477+ =+ rey=(~(get by p.p.rom) sut)
478+ ?~ rey
479+ rom
480+ [[p.p.rom (~(put by q.p.rom) u.rey q.rom)] [%stop u.rey]]
481+ ==
482+::
483+++ duck (dial dole)
484+--
base-desk/lib/language-server/json.hoonnew file+301
@@ -0,0 +1,301 @@
1+/- lsp=language-server
2+|%
3+::
4+++ util
5+ |%
6+ ++ get-json-string
7+ |= [jon=(map @t json) key=@t]
8+ ^- (unit cord)
9+ =/ cord-jon=(unit json)
10+ (~(get by jon) key)
11+ ?~ cord-jon
12+ ~
13+ ?> ?=([%s *] u.cord-jon)
14+ `p.u.cord-jon
15+ --
16+::
17+::
18+++ dejs
19+ =, dejs:format
20+ |%
21+ ++ request
22+ |= jon=json
23+ ?> ?=([%o *] jon)
24+ =/ method=cord
25+ %- method
26+ (trip (need (get-json-string:util p.jon 'method')))
27+ =/ id=cord
28+ (need (get-json-string:util p.jon 'id'))
29+ =/ params=json
30+ (~(got by p.jon) 'params')
31+ ^- all:request:lsp
32+ |^
33+ ?+ method [%unknown jon]
34+ %text-document--hover (text-document--hover params id)
35+ %text-document--completion (text-document--completion params id)
36+ ==
37+ ::
38+ ++ text-document--hover
39+ |= [params=json id=cord]
40+ ^- text-document--hover:request:lsp
41+ :+ %text-document--hover
42+ id
43+ %. params
44+ %: ot
45+ position+position
46+ 'textDocument'^text-document-id
47+ ~
48+ ==
49+ ::
50+ ++ text-document--completion
51+ |= [params=json id=cord]
52+ :+ %text-document--completion id
53+ %. params
54+ %: ot
55+ position+position
56+ 'textDocument'^text-document-id
57+ ~
58+ ==
59+ --
60+ ::
61+ ++ notification
62+ |= jon=json
63+ ?> ?=([%o *] jon)
64+ =/ method=cord
65+ %- method
66+ (trip (need (get-json-string:util p.jon 'method')))
67+ =/ params=json
68+ (~(got by p.jon) 'params')
69+ ^- all:notification:lsp
70+ |^
71+ ?+ method [%unknown jon]
72+ %text-document--did-change
73+ (text-document--did-change params)
74+ %text-document--did-open
75+ (text-document--did-open params)
76+ %text-document--did-save
77+ (text-document--did-save params)
78+ %text-document--did-close
79+ (text-document--did-close params)
80+ ==
81+ ::
82+ ++ text-document--did-save
83+ |= jon=json
84+ ^- text-document--did-save:notification:lsp
85+ ?> ?=([%o *] jon)
86+ =/ doc-id
87+ (~(got by p.jon) 'textDocument')
88+ :- %text-document--did-save
89+ (text-document-id doc-id)
90+ ::
91+ ++ text-document--did-close
92+ |= jon=json
93+ ^- text-document--did-close:notification:lsp
94+ ?> ?=([%o *] jon)
95+ =/ doc-id
96+ (~(got by p.jon) 'textDocument')
97+ :- %text-document--did-close
98+ (text-document-id doc-id)
99+ ::
100+ ++ text-document--did-change
101+ |= jon=json
102+ ^- text-document--did-change:notification:lsp
103+ :- %text-document--did-change
104+ %. jon
105+ %: ot
106+ 'textDocument'^text-document-id
107+ 'contentChanges'^text-document-changes
108+ ~
109+ ==
110+ ::
111+ ++ text-document--did-open
112+ |= jon=json
113+ ^- text-document--did-open:notification:lsp
114+ ?> ?=([%o *] jon)
115+ :- %text-document--did-open
116+ (text-document-item (~(got by p.jon) 'textDocument'))
117+ --
118+ :: Utilities
119+ ::
120+ ++ text-document-item
121+ |= jon=json
122+ ^- text-document-item:lsp
123+ %. jon
124+ %: ot
125+ uri+so
126+ version+(mu ni)
127+ text+so
128+ ~
129+ ==
130+ ::
131+ ++ text-document-id
132+ %: ou
133+ uri+(un so)
134+ version+(uf ~ (pe ~ ni))
135+ ~
136+ ==
137+ ::
138+ ++ text-document-changes
139+ %- ar
140+ %: ou
141+ range+(uf ~ (pe ~ range))
142+ 'rangeLength'^(uf ~ (pe ~ ni))
143+ text+(un so)
144+ ~
145+ ==
146+ ::
147+ ++ method
148+ |= =tape
149+ ^- cord
150+ %- crip %- zing
151+ %+ join "--"
152+ ^- (list ^tape)
153+ %+ turn
154+ ^- (list (list ^tape))
155+ %+ scan
156+ tape
157+ %+ more
158+ fas
159+ ;~ plug
160+ (star low)
161+ (star ;~(plug (cook |=(a=@ (add a 32)) hig) (star low)))
162+ ==
163+ |= words=(list ^tape)
164+ ^- ^tape
165+ (zing (join "-" words))
166+ ::
167+ ++ range
168+ %: ot
169+ start+position
170+ end+position
171+ ~
172+ ==
173+ ::
174+ ++ position
175+ %: ot
176+ line+ni
177+ character+ni
178+ ~
179+ ==
180+ --
181+::
182+++ enjs
183+ =, enjs:format
184+ |%
185+ ++ text-document--publish-diagnostics
186+ |= pub=text-document--publish-diagnostics:notification:lsp
187+ ^- json
188+ %: pairs
189+ uri+s+uri.pub
190+ diagnostics+a+(turn diagnostics.pub diagnostic)
191+ ~
192+ ==
193+ ++ notification
194+ |= notification=all:notification:lsp
195+ ^- json
196+ =/ params=json
197+ ?+ -.notification !!
198+ %text-document--publish-diagnostics
199+ (text-document--publish-diagnostics notification)
200+ ==
201+ ~! -.notification
202+ =/ method=cord (crip (unparse-method -.notification))
203+ %: pairs
204+ method+s+method
205+ params+params
206+ ~
207+ ==
208+ ::
209+ ++ response
210+ |= res=all:response:lsp
211+ ^- json
212+ |^
213+ ?- -.res
214+ %text-document--hover (text-document--hover res)
215+ %text-document--completion (text-document--completion res)
216+ ==
217+ ::
218+ ++ wrap-in-id
219+ |= [id=cord res=json]
220+ %: pairs
221+ id+s+id
222+ result+res
223+ ~
224+ ==
225+ ++ text-document--hover
226+ |= hov=text-document--hover:response:lsp
227+ %+ wrap-in-id id.hov
228+ %+ frond 'contents'
229+ ?~ contents.hov
230+ ~
231+ s+u.contents.hov
232+ ::
233+ ++ text-document--completion
234+ |= com=text-document--completion:response:lsp
235+ %+ wrap-in-id id.com
236+ [%a (turn completion.com completion-item)]
237+ --
238+ ++ unparse-method
239+ |= =cord
240+ ^- ^tape
241+ %+ rash cord
242+ %+ cook |=(l=(list ^tape) (zing (join "/" l)))
243+ %+ more (jest '--')
244+ %+ cook
245+ |= tapes=(list ^tape)
246+ ^- ^tape
247+ ?~ tapes ~
248+ %- zing
249+ :- i.tapes
250+ %+ turn t.tapes
251+ |= t=^tape
252+ ^- ^tape
253+ ?~ t ~
254+ [`@tD`(sub i.t 32) t.t]
255+ %+ more
256+ ;~(less (jest '--') hep)
257+ (star alf)
258+ ::
259+ ++ completion-item
260+ |= com=completion-item:lsp
261+ ^- json
262+ %: pairs
263+ label+s+label.com
264+ detail+s+detail.com
265+ kind+(numb kind.com)
266+ 'documentation'^s+doc.com
267+ 'insertText'^s+insert-text.com
268+ 'insertTextFormat'^(numb insert-text-format.com)
269+ ~
270+ ==
271+ ::
272+ ++ position
273+ |= =position:lsp
274+ ^- json
275+ %: pairs
276+ line+(numb row.position)
277+ character+(numb col.position)
278+ ~
279+ ==
280+ ::
281+ ++ range
282+ |= =range:lsp
283+ ^- json
284+ %: pairs
285+ start+(position start.range)
286+ end+(position end.range)
287+ ~
288+ ==
289+ ::
290+ ++ diagnostic
291+ |= diag=diagnostic:lsp
292+ ^- json
293+ %: pairs
294+ range+(range range.diag)
295+ severity+(numb severity.diag)
296+ message+s+message.diag
297+ ~
298+ ==
299+ ::
300+ --
301+--
base-desk/lib/language-server/parser.hoonnew file+72
@@ -0,0 +1,72 @@
1+:: lifted directly from ford, should probably be in zuse
2+=, clay
3+=< pile-rule
4+|%
5+++ pile-rule
6+ |= pax=path
7+ %- full
8+ %+ ifix
9+ :_ gay
10+ :: parse optional /? and ignore
11+ ::
12+ ;~(plug gay (punt ;~(plug fas wut gap dem gap)))
13+ |^
14+ ;~ plug
15+ %+ cook (bake zing (list (list taut)))
16+ %+ rune hep
17+ (most ;~(plug com gaw) taut-rule)
18+ ::
19+ %+ cook (bake zing (list (list taut)))
20+ %+ rune lus
21+ (most ;~(plug com gaw) taut-rule)
22+ ::
23+ %+ rune tis
24+ ;~(plug sym ;~(pfix gap stap))
25+ ::
26+ %+ rune sig
27+ ;~((glue gap) sym wyde:vast stap)
28+ ::
29+ %+ rune cen
30+ ;~(plug sym ;~(pfix gap ;~(pfix cen sym)))
31+ ::
32+ %+ rune buc
33+ ;~ (glue gap)
34+ sym
35+ ;~(pfix cen sym)
36+ ;~(pfix cen sym)
37+ ==
38+ ::
39+ %+ rune tar
40+ ;~ (glue gap)
41+ sym
42+ ;~(pfix cen sym)
43+ stap
44+ ==
45+ ::
46+ %+ stag %tssg
47+ (most gap tall:(vang & pax))
48+ ==
49+ ::
50+ ++ pant
51+ |* fel=^rule
52+ ;~(pose fel (easy ~))
53+ ::
54+ ++ mast
55+ |* [bus=^rule fel=^rule]
56+ ;~(sfix (more bus fel) bus)
57+ ::
58+ ++ rune
59+ |* [bus=^rule fel=^rule]
60+ %- pant
61+ %+ mast gap
62+ ;~(pfix fas bus gap fel)
63+ --
64+::
65+++ taut-rule
66+ %+ cook |=(taut +<)
67+ ;~ pose
68+ (stag ~ ;~(pfix tar sym))
69+ ;~(plug (stag ~ sym) ;~(pfix tis sym))
70+ (cook |=(a=term [`a a]) sym)
71+ ==
72+--
base-desk/lib/language-server/rune-snippet.hoonnew file+532
@@ -0,0 +1,532 @@
1+/- lsp-sur=language-server
2+/+ auto=language-server-complete
3+=>
4+|%
5+++ snippet
6+ |= [rune=tape text=tape]
7+ ^- json
8+ =, enjs:format
9+ %- pairs
10+ :~ 'label'^(tape rune)
11+ 'insertTextFormat'^(numb 2)
12+ 'insertText'^(tape text)
13+ ==
14+::
15+++ runes
16+ ^- (list (option:auto tape))
17+ :~ :- '|$'
18+ """
19+ $\{1:sample}
20+ $\{2:body}
21+ """
22+ :- '|_'
23+ """
24+ $\{1:sample}
25+ ++ $\{2:arm}
26+ $\{3:body}
27+ --
28+ """
29+ :- '|:'
30+ """
31+ $\{1:sample}
32+ $\{2:body}
33+ """
34+ :- '|%'
35+ """
36+
37+ ++ $\{1:arm}
38+ $\{2:body}
39+ --
40+ """
41+ :- '|.'
42+ """
43+ $\{1:body}
44+ """
45+ :- '|^'
46+ """
47+
48+ $\{1:body}
49+ ::
50+ ++ $\{2:arm}
51+ $\{3:body}
52+ --
53+ """
54+ :- '|-'
55+ """
56+ $\{1:body}
57+ """
58+ :- '|~'
59+ """
60+ $\{1:sample}
61+ $\{2:body}
62+ """
63+ :- '|*'
64+ """
65+ $\{1:sample}
66+ $\{2:body}
67+ """
68+ :- '|='
69+ """
70+ $\{1:sample}
71+ $\{2:body}
72+ """
73+ :- '|@'
74+ """
75+ ++ $\{1:arm}
76+ $\{2:body}
77+ --
78+ """
79+ :- '|?'
80+ """
81+ $\{1:sample}
82+ """
83+ ::
84+ :- ':_'
85+ """
86+ $\{1:tail}
87+ $\{2:head}
88+ """
89+ :- ':^'
90+ """
91+ $\{1:car}
92+ $\{2:cadr}
93+ $\{3:caddr}
94+ $\{4:cddr}
95+ """
96+ :- ':-'
97+ """
98+ $\{1:tail}
99+ $\{2:head}
100+ """
101+ :- ':+'
102+ """
103+ $\{1:car}
104+ $\{2:cadr}
105+ $\{3:cddr}
106+ """
107+ :- ':~'
108+ """
109+ $\{1:item}
110+ ==
111+ """
112+ :- ':*'
113+ """
114+ $\{1:item}
115+ ==
116+ """
117+ ::
118+ :- '%_'
119+ """
120+ $\{1:target}
121+ $\{2:wing} $\{3:new-value}
122+ ==
123+ """
124+ :- '%.'
125+ """
126+ $\{1:arg}
127+ $\{2:gate}
128+ """
129+ :- '%-'
130+ """
131+ $\{1:gate}
132+ $\{2:arg}
133+ """
134+ :- '%:'
135+ """
136+ $\{1:gate}
137+ $\{2:args}
138+ ==
139+ """
140+ :- '%*'
141+ """
142+ $\{1:target-wing} $\{2:from}
143+ $\{3:wing} $\{4:new-value}
144+ ==
145+ """
146+ :- '%^'
147+ """
148+ $\{1:gate}
149+ $\{2:arg1}
150+ $\{3:arg2}
151+ $\{4:arg3}
152+ """
153+ :- '%+'
154+ """
155+ $\{1:gate}
156+ $\{2:arg1}
157+ $\{3:arg2}
158+ """
159+ :- '%~'
160+ """
161+ $\{1:arm}
162+ $\{2:core}
163+ $\{3:arg}
164+ """
165+ :- '%='
166+ """
167+ $\{1:target}
168+ $\{2:wing} $\{3:new-value}
169+ ==
170+ """
171+ ::
172+ :- '.^'
173+ """
174+ $\{1:mold}
175+ $\{2:path}
176+ """
177+ :- '.+'
178+ """
179+ $\{1:atom}
180+ """
181+ :- '.*'
182+ """
183+ $\{1:subject}
184+ $\{2:formula}
185+ """
186+ :- '.='
187+ """
188+ $\{1:a}
189+ $\{2:b}
190+ """
191+ :- '.?'
192+ """
193+ $\{1:noun}
194+ """
195+ ::
196+ :- '^|'
197+ """
198+ $\{1:iron-core}
199+ """
200+ :- '^.'
201+ """
202+ $\{1:a}
203+ $\{2:b}
204+ """
205+ :- '^+'
206+ """
207+ $\{1:like}
208+ $\{2:body}
209+ """
210+ :- '^-'
211+ """
212+ $\{1:type}
213+ $\{2:body}
214+ """
215+ :- '^&'
216+ """
217+ $\{1:zinc-core}
218+ """
219+ :- '^~'
220+ """
221+ $\{1:constant}
222+ """
223+ :- '^='
224+ """
225+ $\{1:face}
226+ $\{2:body}
227+ """
228+ :- '^?'
229+ """
230+ $\{1:lead-core}
231+ """
232+ :- '^*'
233+ """
234+ $\{1:type}
235+ """
236+ :- '^:'
237+ """
238+ $\{1:type}
239+ """
240+ ::
241+ :- '~|'
242+ """
243+ $\{1:trace}
244+ $\{2:body}
245+ """
246+ :- '~_'
247+ """
248+ $\{1:tank}
249+ $\{2:body}
250+ """
251+ :- '~%'
252+ """
253+ $\{1:name}
254+ $\{2:parent}
255+ ~
256+ $\{3:body}
257+ """
258+ :- '~/'
259+ """
260+ $\{1:name}
261+ $\{2:body}
262+ """
263+ :- '~<'
264+ """
265+ $\{1:hint}
266+ $\{2:body}
267+ """
268+ :- '~>'
269+ """
270+ $\{1:hint}
271+ $\{2:body}
272+ """
273+ :- '~$'
274+ """
275+ $\{1:name}
276+ $\{2:body}
277+ """
278+ :- '~+'
279+ """
280+
281+ $\{1:body}
282+ """
283+ :- '~&'
284+ """
285+ $\{1:printf}
286+ $\{2:body}
287+ """
288+ :- '~='
289+ """
290+ $\{1:a}
291+ $\{2:b}
292+ """
293+ :- '~?'
294+ """
295+ $\{1:condition}
296+ $\{2:printf}
297+ $\{3:body}
298+ """
299+ :- '~!'
300+ """
301+ $\{1:type}
302+ $\{2:body}
303+ """
304+ ::
305+ :- ';='
306+ """
307+ $\{1:manx}
308+ ==
309+ """
310+ :- ';:'
311+ """
312+ $\{1:gate}
313+ $\{2:args}
314+ ==
315+ """
316+ :- ';/'
317+ """
318+ $\{1:tape}
319+ """
320+ :- ';<'
321+ """
322+ $\{1:type} bind:m $\{2:body1}
323+ $\{3:body2}
324+ """
325+ :- ';~'
326+ """
327+ $\{1:gate}
328+ $\{2:args}
329+ ==
330+ """
331+ :- ';;'
332+ """
333+ $\{1:type}
334+ $\{2:body}
335+ """
336+ ::
337+ :- '=|'
338+ """
339+ $\{1:type}
340+ $\{2:body}
341+ """
342+ :- '=:'
343+ """
344+ $\{1:wing} $\{2:value}
345+ ==
346+ $\{3:body}
347+ """
348+ :- '=/'
349+ """
350+ $\{1:face}
351+ $\{2:value}
352+ $\{3:body}
353+ """
354+ :- '=;'
355+ """
356+ $\{1:face}
357+ $\{2:body}
358+ $\{3:value}
359+ """
360+ :- '=.'
361+ """
362+ $\{1:wing}
363+ $\{2:value}
364+ $\{3:body}
365+ """
366+ :- '=?'
367+ """
368+ $\{1:wing} $\{2:condition}
369+ $\{3:value}
370+ $\{4:body}
371+ """
372+ :- '=<'
373+ """
374+ $\{1:formula}
375+ $\{2:subject}
376+ """
377+ :- '=-'
378+ """
379+ $\{1:body}
380+ $\{2:value}
381+ """
382+ :- '=>'
383+ """
384+ $\{1:subject}
385+ $\{2:formula}
386+ """
387+ :- '=^'
388+ """
389+ $\{1:face} $\{2:wing}
390+ $\{3:computation}
391+ $\{4:body}
392+ """
393+ :- '=+'
394+ """
395+ $\{1:value}
396+ $\{2:body}
397+ """
398+ :- '=~'
399+ """
400+
401+ $\{1:body}
402+ """
403+ :- '=*'
404+ """
405+ $\{1:alias} $\{2:value}
406+ $\{3:body}
407+ """
408+ :- '=,'
409+ """
410+ $\{1:alias}
411+ $\{3:body}
412+ """
413+ ::
414+ :- '?|'
415+ """
416+ $\{1:condition}
417+ ==
418+ """
419+ :- '?-'
420+ """
421+ $\{1:case}
422+ $\{2:type} $\{3:value}
423+ ==
424+ """
425+ :- '?:'
426+ """
427+ $\{1:if}
428+ $\{2:then}
429+ $\{3:else}
430+ """
431+ :- '?.'
432+ """
433+ $\{1:if}
434+ $\{2:else}
435+ $\{3:then}
436+ """
437+ :- '?^'
438+ """
439+ $\{1:value}
440+ $\{2:if-cell}
441+ $\{3:if-atom}
442+ """
443+ :- '?<'
444+ """
445+ $\{1:assertion}
446+ $\{2:body}
447+ """
448+ :- '?>'
449+ """
450+ $\{1:assertion}
451+ $\{2:body}
452+ """
453+ :- '?+'
454+ """
455+ $\{1:case} $\{2:else}
456+ $\{3:type} $\{4:value}
457+ ==
458+ """
459+ :- '?&'
460+ """
461+ $\{1:condition}
462+ ==
463+ """
464+ :- '?@'
465+ """
466+ $\{1:value}
467+ $\{2:if-atom}
468+ $\{3:if-cell}
469+ """
470+ :- '?~'
471+ """
472+ $\{1:value}
473+ $\{2:if-null}
474+ $\{3:if-nonnull}
475+ """
476+ :- '?#'
477+ """
478+ $\{1:skin}
479+ $\{2:wing}
480+ """
481+ :- '?='
482+ """
483+ $\{1:type}
484+ $\{2:wing}
485+ """
486+ :- '?!'
487+ """
488+ $\{1:loobean}
489+ """
490+ ::
491+ :- '!,'
492+ """
493+ *hoon
494+ $\{1:ast}
495+ """
496+ :- '!>'
497+ """
498+ $\{1:value}
499+ """
500+ :- '!;'
501+ """
502+ $\{1:type}
503+ $\{2:body}
504+ """
505+ :- '!='
506+ """
507+ $\{1:body}
508+ """
509+ :- '!@'
510+ """
511+ $\{1:wing}
512+ $\{2:if-not-exists}
513+ $\{3:if-exists}
514+ """
515+ :- '!?'
516+ """
517+ $\{1:version}
518+ $\{2:body}
519+ """
520+ :- '!!'
521+ ""
522+ ==
523+--
524+|= rune=tape
525+^- (list completion-item:lsp-sur)
526+=? rune =(' ' (snag 0 rune))
527+ (slag 1 rune)
528+~& rune
529+%+ turn (search-prefix:auto (crip rune) runes)
530+|= [name=cord snippet=tape]
531+^- completion-item:lsp-sur
532+[name 1 '' '' (crip snippet) 2]
base-desk/lib/mip.hoonnew file+55
@@ -0,0 +1,55 @@
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+--
base-desk/lib/naive.hoonnew file+926
@@ -0,0 +1,926 @@
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)
base-desk/lib/noun-diff.hoonnew file+213
@@ -0,0 +1,213 @@
1+=<
2+|%
3+++ diff
4+ |= [old=* new=*]
5+ ^- patch
6+ =/ del (extract-del (oracle old new) old)
7+ =/ ins (extract-ins (oracle old new) new)
8+ =/ allowed-holes (~(int in (find-del-holes del)) (find-ins-holes ins))
9+ =. del (filter-del-holes allowed-holes del)
10+ =/ ins (filter-ins-holes allowed-holes ins)
11+ =/ closed-patch (closure (gcp [del ins]))
12+ ?> =(& +.closed-patch)
13+ -.closed-patch
14+++ apply
15+ |= [patch=_id noun=*]
16+ ?- -.patch
17+ %diff
18+ =/ var-map (del del.patch noun)
19+ (ins ins.patch var-map)
20+ ::
21+ %cell
22+ ?> ?=(^ noun)
23+ [$(patch lhs.patch, noun -.noun) $(patch rhs.patch, noun +.noun)]
24+ ==
25+++ id
26+ ^- patch
27+ [%diff [%hole ~] [%hole ~]]
28++$ patch
29+ $% [%cell lhs=patch rhs=patch]
30+ [%diff ^diff]
31+ ==
32+--
33+::
34+|%
35++$ del-diff
36+ $% [%hole @]
37+ [%cell lhs=del-diff rhs=del-diff]
38+ [%ignore ~]
39+ ==
40++$ ins-diff
41+ $% [%hole @ original=*]
42+ [%cell lhs=ins-diff rhs=ins-diff]
43+ [%atom @]
44+ ==
45++$ final-ins-diff
46+ $% [%hole @]
47+ [%cell lhs=final-ins-diff rhs=final-ins-diff]
48+ [%atom @]
49+ ==
50++$ diff [del=del-diff ins=final-ins-diff]
51++$ patch
52+ $% [%cell lhs=patch rhs=patch]
53+ [%diff diff]
54+ ==
55+++ insify-noun
56+ |= noun=*
57+ ^- final-ins-diff
58+ ?- noun
59+ ^ [%cell $(noun -.noun) $(noun +.noun)]
60+ @ [%atom noun]
61+ ==
62+++ empty-set (silt `(list @)`~)
63+++ find-del-holes
64+ |= diff=del-diff
65+ ~+
66+ ^- (set @)
67+ ?- -.diff
68+ %hole (silt ~[+.diff])
69+ %cell (~(uni in $(diff lhs.diff)) $(diff rhs.diff))
70+ %ignore empty-set
71+ ==
72+++ find-final-ins-holes
73+ |= diff=final-ins-diff
74+ ~+
75+ ^- (set @)
76+ ?- -.diff
77+ %hole (silt ~[+.diff])
78+ %cell (~(uni in $(diff lhs.diff)) $(diff rhs.diff))
79+ %atom empty-set
80+ ==
81+++ find-ins-holes
82+ |= diff=ins-diff
83+ ~+
84+ ^- (set @)
85+ ?- -.diff
86+ %hole (silt ~[+<.diff])
87+ %cell (~(uni in $(diff lhs.diff)) $(diff rhs.diff))
88+ %atom empty-set
89+ ==
90+++ filter-del-holes
91+ |= [allowed-holes=(set @) diff=del-diff]
92+ ^- del-diff
93+ ?: ?=(%ignore -.diff) diff
94+ ?- -.diff
95+ %hole ?:((~(has in allowed-holes) +.diff) diff [%ignore ~])
96+ %cell [%cell $(diff +<.diff) $(diff +>.diff)]
97+ ==
98+++ filter-ins-holes
99+ |= [allowed-holes=(set @) diff=ins-diff]
100+ ^- final-ins-diff
101+ ?- -.diff
102+ %cell [%cell $(diff +<.diff) $(diff +>.diff)]
103+ %atom diff
104+ %hole
105+ ?: (~(has in allowed-holes) +<.diff) [%hole +<.diff]
106+ (insify-noun original:diff)
107+ ==
108+++ gcp
109+ |= diff=diff
110+ ^- patch
111+ ?- -.ins.diff
112+ %atom [%diff diff]
113+ %hole [%diff diff]
114+ %cell
115+ ?. ?=(%cell -.del.diff)
116+ [%diff diff]
117+ [%cell $(diff [+<.del.diff +<.ins.diff]) $(diff [+>.del.diff +>.ins.diff])]
118+ ==
119+++ closure
120+ |= =patch
121+ ^- [^patch ?]
122+ ?- -.patch
123+ %diff
124+ =/ del-holes (find-del-holes del:patch)
125+ =/ ins-holes (find-final-ins-holes ins:patch)
126+ =/ difference (~(dif in ins-holes) del-holes)
127+ [patch =(difference empty-set)]
128+ ::
129+ %cell
130+ =/ lhs $(patch lhs:patch)
131+ =/ rhs $(patch rhs:patch)
132+ ?: ?&(+.lhs +.rhs) [[%cell -.lhs -.rhs] &]
133+ $(patch (pull-diff [%cell -.lhs -.rhs]))
134+ ==
135+++ pull-diff
136+ |= =patch
137+ ^- [%diff del=del-diff ins=final-ins-diff]
138+ ?- -.patch
139+ %diff patch
140+ %cell
141+ =/ pulled-lhs $(patch lhs:patch)
142+ =/ pulled-rhs $(patch rhs:patch)
143+ :+ %diff
144+ [%cell del:pulled-lhs del:pulled-rhs]
145+ [%cell ins:pulled-lhs ins:pulled-rhs]
146+ ==
147+++ is-subtree
148+ |= [tree=* subtree=*]
149+ ~+
150+ ^- ?
151+ ?: =(tree subtree) &
152+ ?@ tree |
153+ ?| (is-subtree -.tree subtree)
154+ (is-subtree +.tree subtree)
155+ ==
156+++ oracle
157+ |= [a=* b=*]
158+ |= subtree=*
159+ ^- (unit @)
160+ ?: ?& (is-subtree a subtree)
161+ (is-subtree b subtree)
162+ ==
163+ `(mug subtree)
164+ ~
165+++ extract-del
166+ |= [oracle=$-(* (unit @)) subtree=*]
167+ ~+
168+ ^- del-diff
169+ =/ hash (oracle subtree)
170+ ?^ hash [%hole +.hash]
171+ ?@ subtree [%ignore ~]
172+ [%cell (extract-del oracle -.subtree) (extract-del oracle +.subtree)]
173+++ extract-ins
174+ |= [oracle=$-(* (unit @)) subtree=*]
175+ ~+
176+ ^- ins-diff
177+ =/ hash (oracle subtree)
178+ ?^ hash [%hole +.hash subtree]
179+ ?@ subtree [%atom subtree]
180+ [%cell (extract-ins oracle -.subtree) (extract-ins oracle +.subtree)]
181+++ ins
182+ |= [diff=final-ins-diff var-map=(map @ *)]
183+ ^- *
184+ ?- -.diff
185+ %atom +.diff
186+ %cell [$(diff +<.diff) $(diff +>.diff)]
187+ %hole (~(got by var-map) +.diff)
188+ ==
189+++ del
190+ |= [diff=del-diff noun=*]
191+ ^- (map @ *)
192+ |^ (go diff noun ((map @ *) ~))
193+ ++ go
194+ |= [diff=del-diff noun=* var-map=(map @ *)]
195+ ^- (map @ *)
196+ ?- -.diff
197+ %ignore
198+ var-map
199+ ::
200+ %hole
201+ =/ subtree (~(get by var-map) +.diff)
202+ ?~ subtree (~(put by var-map) +.diff noun)
203+ ?> =(+.subtree noun)
204+ var-map
205+ ::
206+ %cell
207+ ?> ?=(^ noun)
208+ =/ lhs-var-map $(diff +<.diff, noun -.noun)
209+ =/ rhs-var-map $(diff +>.diff, noun +.noun, var-map lhs-var-map)
210+ rhs-var-map
211+ ==
212+ --
213+--
base-desk/lib/ph/io.hoonnew file+531
@@ -0,0 +1,531 @@
1+/- *aquarium, spider
2+/+ libstrand=strand, *strandio, util=ph-util, aqua-azimuth, vere
3+=, strand=strand:libstrand
4+|%
5+++ send-events
6+ |= events=(list aqua-event)
7+ =/ m (strand ,~)
8+ ^- form:m
9+ (poke-our %aqua %aqua-events !>(events))
10+::
11+++ send-azimuth-action
12+ |= =azimuth-action
13+ =/ m (strand ,~)
14+ ^- form:m
15+ (poke-our %aqua %azimuth-action !>(azimuth-action))
16+::
17+++ take-unix-effect
18+ =/ m (strand ,[ship unix-effect])
19+ ^- form:m
20+ ;< [=path =cage] bind:m (take-fact-prefix /effect)
21+ ?> ?=(%aqua-effect p.cage)
22+ (pure:m !<([aqua-effect] q.cage))
23+::
24+++ start-simple
25+ (start-test %aqua-ames %aqua-behn %aqua-dill %aqua-eyre ~)
26+::
27+++ start-azimuth
28+ =/ m (strand ,~)
29+ ^- form:m
30+ ;<(~ bind:m start-simple init)
31+::
32+++ end
33+ (end-test %aqua-ames %aqua-behn %aqua-dill %aqua-eyre ~)
34+::
35+++ start-test
36+ |= vane-threads=(list term)
37+ =/ m (strand ,~)
38+ ^- form:m
39+ ~& > "starting"
40+ ;< tids=(map term tid:spider) bind:m (start-threads vane-threads)
41+ ;< ~ bind:m (watch-our /effect %aqua /effect)
42+ :: Get our very own event with no mistakes in it... yet.
43+ ::
44+ :: We want to wait for the vane threads to actually start and get
45+ :: their subscriptions started. Other ways to do this are delaying
46+ :: the ack from spider until the build is finished (does that
47+ :: guarantee the subscriptions have started?) or subscribe to the
48+ :: threads themselves for a notification when they're done. This is
49+ :: probably the best option because the thread can delay until it
50+ :: gets a positive ack on the subscription.
51+ ::
52+ :: Threads might not get built until a %writ is dripped back to
53+ :: spider. Drips are at +(now), so we sleep until two clicks in the
54+ :: future.
55+ ::
56+ ;< ~ bind:m (sleep `@dr`2)
57+ (pure:m ~)
58+::
59+++ end-test
60+ |= vane-threads=(list term)
61+ =/ m (strand ,~)
62+ ^- form:m
63+ ~& > "done"
64+ ;< ~ bind:m (stop-threads vane-threads)
65+ ;< ~ bind:m (leave-our /effect %aqua)
66+ (pure:m ~)
67+::
68+++ start-threads
69+ |= threads=(list term)
70+ =/ m (strand ,(map term tid:spider))
71+ ^- form:m
72+ ;< =bowl:spider bind:m get-bowl
73+ =| tids=(map term tid:spider)
74+ |- ^- form:m
75+ =* loop $
76+ ?~ threads
77+ (pure:m tids)
78+ =/ tid
79+ %+ scot %ta
80+ (cat 3 (cat 3 'strand_' i.threads) (scot %uv (sham i.threads eny.bowl)))
81+ =/ poke-vase !>([`tid.bowl ~ byk.bowl i.threads *vase])
82+ ;< ~ bind:m (poke-our %spider %spider-start poke-vase)
83+ loop(threads t.threads, tids (~(put by tids) i.threads tid))
84+::
85+++ stop-threads
86+ |= threads=(list term)
87+ =/ m (strand ,~)
88+ ^- form:m
89+ (pure:m ~)
90+::
91+++ init
92+ =/ m (strand ,~)
93+ ^- form:m
94+ (send-azimuth-action %init-azimuth ~)
95+::
96+++ spawn
97+ |= =ship
98+ ~& > "spawning {<ship>}"
99+ =/ m (strand ,~)
100+ ^- form:m
101+ (send-azimuth-action %spawn ship)
102+::
103+++ breach
104+ |= =ship
105+ ~& > "breaching {<ship>}"
106+ =/ m (strand ,~)
107+ ^- form:m
108+ (send-azimuth-action %breach ship)
109+::
110+:: who: breachee
111+:: her: wait until hears about breach
112+::
113+++ breach-and-hear
114+ |= [who=ship her=ship]
115+ ~& > "breaching {<who>} for {<her>}"
116+ =/ m (strand ,~)
117+ ;< =bowl:spider bind:m get-bowl
118+ =/ aqua-pax
119+ :- %i
120+ /(scot %p her)/j/(scot %p her)/rift/(scot %da now.bowl)/(scot %p who)/noun
121+ =/ old-rut ;;((unit @) (scry-aqua:util noun our.bowl now.bowl aqua-pax))
122+ =/ new-rut
123+ ?~ old-rut
124+ 1
125+ +(+.old-rut)
126+ ;< ~ bind:m (send-azimuth-action %breach who)
127+ ;< ~ bind:m ?~ old-rut (sleep ~s20) :: XX don't wait if possible
128+ (wait-for-sunk her who) :: wait only if previously talked
129+ |- ^- form:m
130+ =* loop $
131+ ;< ~ bind:m (sleep ~s10)
132+ ;< =bowl:spider bind:m get-bowl
133+ =/ aqua-pax
134+ :- %i
135+ /(scot %p her)/j/(scot %p her)/rift/(scot %da now.bowl)/(scot %p who)/noun
136+ =/ rut (scry-aqua:util noun our.bowl now.bowl aqua-pax)
137+ ?: =([~ new-rut] rut)
138+ (pure:m ~)
139+ loop
140+::
141+++ init-moon ::NOTE real moon always have the same keys
142+ |= [moon=ship fake=?]
143+ ?> ?=(%earl (clan:title moon))
144+ ?: fake (init-ship moon &)
145+ =/ m (strand ,~)
146+ ;< ~ bind:m
147+ %+ dojo (^sein:title moon)
148+ =/ =pass pub:ex:(get-keys:aqua-azimuth moon 1)
149+ "|moon {(scow %p moon)}, =public-key {(scow %uw pass)}"
150+ (init-ship moon |)
151+::
152+++ init-ship
153+ =| core=?(%mesa %ames) :: XX make %mesa the default core
154+ |= [=ship fake=?]
155+ =/ m (strand ,~)
156+ ^- form:m
157+ ~& > "starting {<ship>}"
158+ ;< ~ bind:m (send-events (init:util ship fake ~ core))
159+ (check-ship-booted ship)
160+::
161+++ init-comet
162+ =| core=?(%mesa %ames) :: XX make %mesa the default core
163+ |= comet=ship
164+ =/ m (strand ,~)
165+ ^- form:m
166+ :: hardcoded for:
167+ :: ~londeg-tirlys-somlyd-poltus--pintyn-tarbyl-bicnux-marbud
168+ ::
169+ =/ =feed:jael
170+ :* [%2 ~]
171+ who=comet
172+ ryf=0
173+ :_ ~
174+ :- lyf=1
175+ key=0wfm.lBEWM.08gfy.AxYjy.8-tBQ.uq-aa.LZt9c.CVQqd.XBJIs.
176+ CoG90.BNNGV.1ZmVi.ZbAhY.LuhwC.idNnU.lCVkt.Z4qug.7iY92
177+ ==
178+ ::
179+ ?> ?=(^ (veri:dawn:vere comet feed *point:azimuth-types ~))
180+ ~& > "mining comet under {<(^sein:title comet)>}"
181+ ;< ~ bind:m (send-events (init:util comet fake=%.n `feed core))
182+ (check-ship-booted comet)
183+::
184+:: Load network core protocol
185+::
186+++ load
187+ |= [who=ship ore=?(%mesa %ames)]
188+ =/ m (strand ,~)
189+ ^- form:m
190+ ;< ~ bind:m (send-events [%event who [/a/aqua/load %load ore]]~)
191+ (pure:m ~)
192+::
193+++ check-ship-booted
194+ |= =ship
195+ =/ m (strand ,~)
196+ ^- form:m
197+ =* loop $
198+ ;< [her=^ship =unix-effect] bind:m take-unix-effect
199+ =/ f |=(=tape (is-dojo-output:util ship her unix-effect tape))
200+ :: This is a pretty bad heuristic, but in general galaxies will
201+ :: hit the first of these cases, and other ships will hit the
202+ :: second.
203+ ::
204+ ?: ?| (f ":dojo>")
205+ (f "is your neighbor")
206+ ==
207+ (pure:m ~)
208+ loop
209+::
210+++ dojo
211+ |= [=ship =tape]
212+ =/ m (strand ,~)
213+ ^- form:m
214+ ~& > "dojo: {tape}"
215+ (send-events (dojo:util ship tape))
216+::
217+++ wait-for-output
218+ |= [=ship =tape]
219+ =/ m (strand ,~)
220+ ^- form:m
221+ ~& > "waiting for output: {tape}"
222+ |- ^- form:m
223+ =* loop $
224+ ;< [her=^ship =unix-effect] bind:m take-unix-effect
225+ ?: (is-dojo-output:util ship her unix-effect tape)
226+ (pure:m ~)
227+ loop
228+::
229+++ wait-for-flub
230+ |= [our=ship her=ship dap=term]
231+ =/ m (strand ,~)
232+ ^- form:m
233+ ;< =bowl:spider bind:m get-bowl
234+ |- ^- form:m
235+ =* loop $
236+ ;< [from=^ship =unix-effect] bind:m take-unix-effect
237+ ;< now=@da bind:m get-time
238+ ?. =(from our)
239+ :: our sends the $boon with the halted flow number, at this point
240+ :: gall has updated its state adding the app to gall's .halts map
241+ :: XX search deeper in the .unix-effect?
242+ ::
243+ loop
244+ =/ aqua-pax
245+ :- %i
246+ /(scot %p our)/gg/(scot %p our)//(scot %da now)/[%$]/noun
247+ =+ ;; flubs=(unit (jug ship term))
248+ (scry-aqua:util noun our.bowl now aqua-pax)
249+ ?~ flubs loop
250+ ?. (~(has ju u.flubs) her dap)
251+ loop
252+ (pure:m ~)
253+::
254+++ wait-for-spur
255+ |= [our=ship her=ship dap=term]
256+ =/ m (strand ,~)
257+ ^- form:m
258+ ;< =bowl:spider bind:m get-bowl
259+ |- ^- form:m
260+ =* loop $
261+ ;< [from=ship =unix-effect] bind:m take-unix-effect
262+ ;< now=@da bind:m get-time
263+ ?. =(from our)
264+ :: our ack to the %spur $boon is sent, at this point
265+ :: gall has updated its state adding the app to gall's .flubs map
266+ :: XX search deeper in the .unix-effect?
267+ ::
268+ loop
269+ =/ aqua-pax
270+ :- %i
271+ /(scot %p our)/gg/(scot %p our)//(scot %da now)/[%$]/noun
272+ =+ ;; flubs=(unit (jug ship term))
273+ (scry-aqua:util noun our.bowl now aqua-pax)
274+ ?~ flubs loop
275+ ?: (~(has ju u.flubs) her dap)
276+ loop
277+ (pure:m ~)
278+::
279+++ wait-for-has-halt
280+ |= [our=ship her=ship dap=term]
281+ =/ m (strand ,~)
282+ ^- form:m
283+ ;< =bowl:spider bind:m get-bowl
284+ |- ^- form:m
285+ =* loop $
286+ ;< [from=ship =unix-effect] bind:m take-unix-effect
287+ ;< now=@da bind:m get-time
288+ :: only %send or %push effects
289+ ::
290+ ?. ?=(?(%send %push) -.q.unix-effect)
291+ loop
292+ ~& >> from^unix-effect
293+ ?. =(from our)
294+ :: wait until our ack for the %flub $boon is sent, at this point
295+ :: gall has updated its state adding the app to gall's .flubs map
296+ :: XX search deeper in the .unix-effect?
297+ ::
298+ loop
299+ =/ aqua-pax
300+ :- %i
301+ /(scot %p our)/gh/(scot %p our)//(scot %da now)/[%$]/noun
302+ =+ ;; halts=(unit (jug app=term [ship =duct]))
303+ (scry-aqua:util noun our.bowl now aqua-pax)
304+ ?~ halts loop
305+ ?. (~(has by u.halts) dap) :: XX check .her as well
306+ loop
307+ (pure:m ~)
308+::
309+++ wait-for-del-halt
310+ |= [our=ship her=ship dap=term]
311+ =/ m (strand ,~)
312+ ^- form:m
313+ ;< =bowl:spider bind:m get-bowl
314+ |- ^- form:m
315+ =* loop $
316+ ;< [from=ship =unix-effect] bind:m take-unix-effect
317+ ;< now=@da bind:m get-time
318+ ?. =(from our)
319+ :: when the %spur $boon has been sent, gall has updated its state deleting
320+ :: the app from gall's .flubs map
321+ :: XX search deeper in the .unix-effect?
322+ ::
323+ loop
324+ =/ aqua-pax
325+ :- %i
326+ /(scot %p our)/gh/(scot %p our)//(scot %da now)/[%$]/noun
327+ =+ ;; halts=(unit (jug app=term [ship =duct]))
328+ (scry-aqua:util noun our.bowl now aqua-pax)
329+ ?~ halts loop
330+ ?: (~(has by u.halts) dap) :: XX check .her as well
331+ loop
332+ (pure:m ~)
333+::
334+++ wait-for-pac
335+ |= [our=ship to=ship]
336+ =/ m (strand ,~)
337+ ^- form:m
338+ ~& > "waiting for ack: {<[from=our to=to]>}"
339+ |- ^- form:m
340+ =* loop $
341+ ;< [from=ship =unix-effect] bind:m take-unix-effect
342+ ?. =(our from)
343+ loop
344+ :: only %send or %push effects
345+ ::
346+ ?. ?=(?(%send %push) -.q.unix-effect)
347+ loop
348+ :: XX check that this is an %ack?
349+ :: XX check that this is for .to?
350+ ::
351+ (pure:m ~)
352+:: Send "|hi" from one ship to another
353+::
354+++ send-hi
355+ |= [from=@p to=@p]
356+ =/ m (strand ,~)
357+ ^- form:m
358+ ;< ~ bind:m (dojo from "|hi {(scow %p to)}")
359+ (wait-for-output from "hi {(scow %p to)} successful")
360+::
361+:: Send "|hi" and wait for "not responding" message
362+::
363+++ wait-for-sunk
364+ |= [from=@p to=@p]
365+ =/ m (strand ,~)
366+ (wait-for-output from "{(scow %p to)} has sunk")
367+::
368+++ wait-for-fact
369+ |= [=ship =mark =wire gate=$-([mark noun] ?)]
370+ =/ m (strand ,noun)
371+ ^- form:m
372+ ~& > "waiting for fact: {<mark>}"
373+ |- ^- form:m
374+ =* loop $
375+ ;< [her=^ship =unix-effect] bind:m take-unix-effect
376+ ?. =(her ship)
377+ loop
378+ ?. ?& =(wire p.unix-effect)
379+ ?=([%unto %raw-fact *] q.unix-effect)
380+ =(mark mark.unto.q.unix-effect)
381+ (gate mark noun.unto.q.unix-effect)
382+ ==
383+ loop
384+ (pure:m noun.unto.q.unix-effect)
385+::
386+++ wait-for-cork
387+ |= [our=ship her=ship flow=(each bone:ames side:ames)]
388+ =/ m (strand ,~)
389+ ^- form:m
390+ ;< =bowl:spider bind:m get-bowl
391+ |- ^- form:m
392+ =* loop $
393+ ;< [from=ship =unix-effect] bind:m take-unix-effect
394+ ;< now=@da bind:m get-time
395+ :: only %send or %push effects
396+ ::
397+ ?. ?=(?(%send %push) -.q.unix-effect)
398+ loop
399+ :: XX check that this is an %ack?
400+ ::
401+ ?. =(from our)
402+ :: wait until the ack for the %cork $plea is sent, at this point
403+ :: the publisher has already corked the flow
404+ ::
405+ loop
406+ =/ aqua-pax
407+ %+ weld /i/(scot %p our)/ax/(scot %p our)//(scot %da now)
408+ ?: ?=(%& -.flow)
409+ /corked/(scot %p her)/(scot %ud +.flow)/noun
410+ =/ [=bone:ames =dire:ames] +.flow
411+ /corked/(scot %p her)/[dire]/(scot %ud bone)/noun
412+ =+ ;; corked=(unit ?) (scry-aqua:util noun our.bowl now aqua-pax)
413+ ?~ corked loop
414+ ?. u.corked :: XX check .her as well
415+ loop
416+ ~& >> flow-is-corked/flow
417+ (pure:m ~)
418+::
419+:: Send "|hi" and wait for "not responding" message
420+::
421+++ send-hi-not-responding
422+ |= [from=@p to=@p]
423+ ~& > 'sending hi not responding'
424+ =/ m (strand ,~)
425+ ;< ~ bind:m (dojo from "|hi {(scow %p to)}")
426+ (wait-for-output from "{(scow %p to)} not responding still trying")
427+::
428+:: Mount a desk.
429+::
430+++ mount
431+ |= [=ship =desk]
432+ =/ m (strand ,~)
433+ ^- form:m
434+ ;< ~ bind:m (dojo ship "|mount /={(trip desk)}=")
435+ |- ^- form:m
436+ =* loop $
437+ ;< [her=^ship =unix-effect] bind:m take-unix-effect
438+ ?: (is-ergo:util ship her unix-effect)
439+ (pure:m ~)
440+ loop
441+::
442+:: Modify /sur/aquarium/hoon on the given ship
443+::
444+++ touch-file
445+ |= [her=ship =desk extra=@t]
446+ =/ m (strand ,@t)
447+ ^- form:m
448+ (touch her desk /sur/aquarium/hoon extra)
449+::
450+:: Modify path on the given ship
451+::
452+++ touch
453+ |= [her=ship =desk pax=path extra=@t]
454+ =/ m (strand ,@t)
455+ ^- form:m
456+ ~& > "touching file on {<her>}/{<desk>}"
457+ ;< ~ bind:m (mount her desk)
458+ ;< our=@p bind:m get-our
459+ ;< now=@da bind:m get-time
460+ =/ aqua-pax
461+ ;: weld
462+ /i/(scot %p her)/cx/(scot %p her)/[desk]/(scot %da now)
463+ pax
464+ /noun
465+ ==
466+ =/ warped
467+ %^ cat 3 '=> . '
468+ %^ cat 3 extra
469+ (need (scry-aqua:util (unit @) our now aqua-pax))
470+ ;< ~ bind:m (send-events (insert-files:util her desk [pax warped] ~))
471+ (pure:m warped)
472+::
473+++ copy-file
474+ =/ m (strand ,~)
475+ |= [her=ship pax=path file=@t]
476+ ^- form:m
477+ ;< ~ bind:m
478+ (send-events (insert-files:util her %base [pax file] ~))
479+ (sleep ~s1)
480+::
481+:: Check /sur/aquarium/hoon on the given has the given contents.
482+::
483+++ check-file-touched
484+ |= [=ship =desk warped=@t]
485+ =/ m (strand ,~)
486+ (check-touched ship desk /sur/aquarium/hoon warped)
487+::
488+:: Check path on the given desk has the given contents.
489+::
490+++ check-touched
491+ |= [=ship =desk pax=path warped=@t]
492+ =/ m (strand ,~)
493+ ~& > "checking file touched on {<ship>}/{<desk>}"
494+ ;< ~ bind:m (mount ship desk)
495+ ^- form:m
496+ |- ^- form:m
497+ =* loop $
498+ ;< [her=^ship =unix-effect] bind:m take-unix-effect
499+ ;< our=@p bind:m get-our
500+ ;< now=@da bind:m get-time
501+ :: %ergo is no longer sufficient because .^ is pinned to beginning of
502+ :: the event. So we hope somebody sets a timer for something.
503+ ::
504+ ?. &(=(ship her) ?=(?(%init %ergo %doze) -.q.unix-effect))
505+ loop
506+ =/ aqua-pax
507+ ;: weld
508+ /i/(scot %p ship)/cx/(scot %p ship)/[desk]/(scot %da now)
509+ pax
510+ /noun
511+ ==
512+ ?: =(warped (need (scry-aqua:util (unit @) our now aqua-pax)))
513+ (pure:m ~)
514+ loop
515+::
516+:: Turns poke into a dojo command
517+::
518+++ poke-app
519+ |= [=ship app=term =mark data=*]
520+ =/ m (strand ,~)
521+ ^- form:m
522+ =/ command=tape ":{(trip app)} &{(trip mark)} {<data>}"
523+ (send-events (dojo:util ship command))
524+::
525+++ dojo-thread
526+ |= [=ship ted=term =mark data=*]
527+ =/ m (strand ,~)
528+ ^- form:m
529+ =/ command=tape "-{(trip ted)} &{(trip mark)} {<data>}"
530+ (send-events (dojo:util ship command))
531+--
base-desk/lib/ph/util.hoonnew file+125
@@ -0,0 +1,125 @@
1+:: Utility functions for constructing tests
2+::
3+/- aquarium
4+=, aquarium
5+|%
6+::
7+:: Turn [ship (list unix-event)] into (list ph-event)
8+::
9+++ send-events-to
10+ |= [who=ship what=(list unix-event)]
11+ ^- (list aqua-event)
12+ %+ turn what
13+ |= ue=unix-event
14+ [%event who ue]
15+::
16+:: Start a ship (low-level; prefer +raw-ship)
17+::
18+++ init
19+ |= [who=ship ake=? eed=(unit feed:jael) ore=?(%mesa %ames)]
20+ ^- (list aqua-event)
21+ :~ [%init-ship who ake eed]
22+ [%event who [/a/aqua/load %load ore]]
23+ ==
24+::
25+:: Send dojo command
26+::
27+++ dojo
28+ |= [who=ship what=tape]
29+ ^- (list aqua-event)
30+ %+ send-events-to who
31+ ^- (list unix-event)
32+ :~
33+ [/d/term/1 %belt %mod %ctl `@c`%e]
34+ [/d/term/1 %belt %mod %ctl `@c`%u]
35+ [/d/term/1 %belt %txt ((list @c) what)]
36+ [/d/term/1 %belt %ret ~]
37+ ==
38+::
39+:: Control character
40+::
41+++ ctrl
42+ |= [who=ship what=term]
43+ ^- (list ph-event)
44+ %+ send-events-to who
45+ :~ [/d/term/1 %belt %mod %ctl (,@c what)]
46+ ==
47+::
48+:: Inject a file into a ship
49+::
50+++ insert-files
51+ |= [who=ship des=desk files=(list [=path txt=@t])]
52+ ^- (list aqua-event)
53+ =/ input
54+ %+ turn files
55+ |= [=path txt=@t]
56+ [path ~ /text/plain (as-octs:mimes:html txt)]
57+ %+ send-events-to who
58+ :~
59+ [/c/sync/0v1n.2m9vh %into des | input]
60+ ==
61+::
62+:: Checks whether the given event is a dojo output blit containing the
63+:: given tape
64+::TODO should be rename -dill-output
65+++ is-dojo-output
66+ |= [who=ship her=ship uf=unix-effect what=tape]
67+ |^
68+ ?& =(who her)
69+ ?=(%blit -.q.uf)
70+ (lien p.q.uf handle-blit)
71+ ==
72+ ::
73+ ++ handle-blit
74+ |= =blit:dill
75+ ^- ?
76+ ?: ?=(%mor -.blit)
77+ (lien p.blit handle-blit)
78+ ?+ -.blit |
79+ %put !=(~ (find what p.blit))
80+ ::
81+ %klr
82+ %+ lien p.blit
83+ |= [* q=(list @c)]
84+ !=(~ (find what q))
85+ ==
86+ --
87+::
88+:: Test is successful if +is-dojo-output
89+::
90+++ expect-dojo-output
91+ |= [who=ship her=ship uf=unix-effect what=tape]
92+ ^- (list ph-event)
93+ ?. (is-dojo-output who her uf what)
94+ ~
95+ [%test-done &]~
96+::
97+:: Check whether the given event is an ergo
98+::
99+++ is-ergo
100+ |= [who=ship her=ship uf=unix-effect]
101+ ?& =(who her)
102+ ?=(%ergo -.q.uf)
103+ ==
104+::
105+:: Check if given effect is an http request; extract
106+::
107+++ extract-request
108+ |= [uf=unix-effect dest=@t]
109+ ^- (unit [num=@ud =request:http])
110+ ?. ?=(%request -.q.uf) ~
111+ ?. =(dest url.request.q.uf) ~
112+ `[id.q.uf request.q.uf]
113+::
114+:: Scry into a running aqua ship
115+::
116+++ scry-aqua
117+ |* [a=mold our=@p now=@da pax=path]
118+ .^ a
119+ %gx
120+ (scot %p our)
121+ %aqua
122+ (scot %da now)
123+ pax
124+ ==
125+--
base-desk/lib/pill.hoonnew file+620
@@ -0,0 +1,620 @@
1+:: |pill: helper functions for making pills
2+::
3+/- dice
4+^?
5+=<
6+|%
7+::
8++$ pill
9+ $% [%ivory p=(list)]
10+ $: %pill
11+ nam=term
12+ boot-ova=(list)
13+ kernel-ova=(list unix-event)
14+ userspace-ova=(list unix-event)
15+ ==
16+ $: %cash
17+ $: nam=term
18+ boot-ova=(list)
19+ kernel-ova=(list unix-event)
20+ userspace-ova=(list unix-event)
21+ ==
22+ cache=(list)
23+ == ==
24+::
25++$ unix-event
26+ %+ pair wire
27+ $% [%wack p=@]
28+ [%what p=(list (pair path (cask)))]
29+ [%whom p=ship]
30+ [%boot ? $%($>(%fake task:jael) $>(%dawn task:jael))]
31+ [%wyrd p=vere]
32+ [%verb p=(unit ?)]
33+ unix-task
34+ ==
35+:: +boot-ovum: boostrap kernel filesystem load
36+::
37+++ boot-ovum
38+ |= [hoon=cord arvo=cord]
39+ :~ //arvo
40+ %what
41+ [/sys/hoon hoon/hoon]
42+ [/sys/arvo hoon/arvo]
43+ ==
44+:: +dirs: filter for userspace directories to include
45+::
46+++ dirs
47+ |= [bas=path exc=(list spur)]
48+ ^- (list spur)
49+ ?~ exc ~(tap in dir:.^(arch %cy bas))
50+ %+ skim
51+ ~(tap in dir:.^(arch %cy bas))
52+ |=(=spur =(~ (find ~[spur] exc)))
53+:: +file-ovum: userspace filesystem load
54+::
55+:: bas: full path to / directory
56+::
57+++ file-ovum
58+ |= [des=desk bas=path exc=(list spur)]
59+ ^- unix-event
60+ %. (dirs bas exc)
61+ |= :: sal: all spurs to load from
62+ ::
63+ sal=(list spur)
64+ ^- unix-event
65+ ::
66+ :: hav: all user files
67+ ::
68+ =; hav ~& user-files+(lent hav)
69+ =/ =yuki:clay
70+ :- *(list tako:clay)
71+ %- ~(gas by *(map path (each page lobe:clay)))
72+ (turn hav |=([=path =page] [path &+page]))
73+ [/c/sync [%park des &+yuki *rang:clay]]
74+ (file-pages bas sal)
75+::
76+++ file-pages
77+ |= [bas=path sal=(list spur)]
78+ =| hav=(list [path page:clay])
79+ |- ^+ hav
80+ ?~ sal ~
81+ =. hav $(sal t.sal)
82+ ::
83+ :: tyl: spur
84+ ::
85+ =/ tyl i.sal
86+ |- ^+ hav
87+ ::
88+ :: pax: full path at `tyl`
89+ :: lon: directory at `tyl`
90+ ::
91+ =/ lyt (flop tyl)
92+ =/ pax (weld bas lyt)
93+ =/ lon .^(arch %cy pax)
94+ =? hav ?=(^ fil.lon)
95+ :_ hav
96+ :- lyt
97+ ?. ?=([%azimuth-snapshot *] tyl)
98+ [mark=;;(@tas (head tyl)) noun=.^(* %cx pax)]
99+ =; convert
100+ mime/(convert .^(snap-state:dice %cx pax))
101+ .^($-(snap-state:dice mime) %cf (weld bas /azimuth-snapshot/mime))
102+ =/ all ~(tap by dir.lon)
103+ |- ^+ hav
104+ ?~ all hav
105+ $(all t.all, hav ^$(tyl [p.i.all tyl]))
106+::
107+:: +file-ovum2: electric boogaloo
108+::
109+++ file-ovum2 |=(z=[path (list spur)] `unix-event`[//arvo what/(user-files z)])
110+::
111+++ get-wynn
112+ |= [sys=path new-wynn=?]
113+ ^- wynn
114+ ?. new-wynn
115+ :~ zuse+zuse
116+ lull+lull
117+ arvo+arvo
118+ hoon+hoon-version
119+ ==
120+ ~> %bout.[0 %get-wynn]
121+ =+ .^(zus=vase %ca (welp sys /zuse/hoon))
122+ =+ .^(lul=vase %ca (welp sys /lull/hoon))
123+ =+ .^(arv=vase %ca (welp sys /arvo/hoon))
124+ =+ .^(hun=vase %ca (welp sys /hoon/hoon))
125+ :~ [%zuse ;;(@ud q:(slap zus limb+%zuse))]
126+ [%lull ;;(@ud q:(slap lul limb+%lull))]
127+ [%arvo ;;(@ud q:(slap arv limb+%arvo))]
128+ [%hoon ;;(@ud q:(slap hun limb+%hoon-version))]
129+ ==
130+::
131+++ prep-ovum
132+ |= dez=(list path)
133+ ^- unix-event
134+ =- ~& clay-blobs+~(wyt by -)
135+ [/c/inflate [%prep -]]
136+ %+ roll dez
137+ |= [bas=path out=(map lobe:clay page:clay)]
138+ %- ~(uni by out)
139+ .^(_out %cs (snoc bas %bloc))
140+::
141+:: +user-files: all userspace hoon files
142+::
143+++ user-files
144+ |= [bas=path exc=(list spur)]
145+ %. (dirs bas exc)
146+ |= sal=(list spur)
147+ ^- (list (pair path (cask)))
148+ ::
149+ :: hav: all user files
150+ ::
151+ =| hav=(list (pair path (cask)))
152+ |- ^+ hav
153+ ?~ sal ~
154+ =. hav $(sal t.sal)
155+ ::
156+ :: tyl: spur
157+ ::
158+ =/ tyl i.sal
159+ |- ^+ hav
160+ ::
161+ :: pax: full path at `tyl`
162+ :: lon: directory at `tyl`
163+ ::
164+ =/ pax (weld bas (flop tyl))
165+ =/ lon .^(arch %cy pax)
166+ =? hav ?=(^ fil.lon)
167+ ::
168+ :: install only hoon files for now
169+ ::
170+ ?. ?=([%hoon *] tyl)
171+ hav
172+ :_ hav
173+ [(flop `path`t.tyl) hoon/.^(@t %cx pax)]
174+ ::
175+ =/ all ~(tap by dir.lon)
176+ |- ^+ hav
177+ ?~ all hav
178+ $(all t.all, hav ^$(tyl [p.i.all tyl]))
179+::
180+::TODO include %prep task in solid and brass?
181+++ solid
182+ :: sys: root path to boot system, `/~me/[desk]/now/sys`
183+ :: dez: secondary desks and their root paths
184+ :: exc: list of desk folders to exclude
185+ ::
186+ |= [sys=path dez=(list [desk path]) dub=? now=@da prime=? exc=(list spur)]
187+ ^- pill
188+ =/ bas=path (scag 3 sys)
189+ =/ compiler-path (weld sys /hoon)
190+ =/ arvo-path (weld sys /arvo)
191+ ~& %solid-start
192+ =/ compiler-src .^(@t %cx (weld compiler-path /hoon))
193+ =/ arvo-src .^(@t %cx (weld arvo-path /hoon))
194+ =/ arvo-formula
195+ ~& %solid-loaded
196+ =/ compiler-hoon (rain compiler-path compiler-src)
197+ ?. dub
198+ :: compile arvo against hoon, with our current compiler
199+ ::
200+ =/ whole-hoon=hoon
201+ [%tsgr compiler-hoon [%tsgr [%$ 7] (rain arvo-path arvo-src)]]
202+ ~& %solid-parsed
203+ =/ whole-formula q:(~(mint ut %noun) %noun whole-hoon)
204+ ~& %solid-arvo
205+ whole-formula
206+ :: compile arvo against hoon, with a freshly compiled hoon (via +ride)
207+ ::
208+ ~& %solid-parsed
209+ =/ compiler-formula q:(~(mint ut %noun) %noun compiler-hoon)
210+ ~& %solid-compiled
211+ =/ whole-src
212+ (rap 3 ['=> ' compiler-src '=> +7 ' arvo-src ~])
213+ ~& %solid-double-loaded
214+ =/ whole-formula
215+ =< +
216+ .* [%noun whole-src]
217+ [%8 compiler-formula [%9 2 %10 [6 %0 3] [%0 2]]]
218+ ~& %solid-double-compiled
219+ whole-formula
220+ ::
221+ ~& [%solid-kernel `@ux`(mug arvo-formula)]
222+ ::
223+ :: installed: Arvo gate (formal interface) with %zuse and vanes installed
224+ ::
225+ =/ installed
226+ =< q
227+ %^ spin
228+ ^- (list ovum)
229+ :- (boot-ovum:pill compiler-src arvo-src)
230+ %+ turn
231+ (snoc (turn dez tail) bas)
232+ |= =path
233+ (file-ovum2 [path exc])
234+ .*(0 arvo-formula)
235+ |= [ovo=ovum ken=*]
236+ [~ (slum ken [now ovo])]
237+ ::
238+ :: kernel-formula
239+ ::
240+ :: We evaluate :arvo-formula (for jet registration),
241+ :: then ignore the result and produce .installed
242+ ::
243+ =/ kernel-formula
244+ [%7 arvo-formula %1 installed]
245+ ::
246+ :: boot-two: startup formula
247+ ::
248+ =/ boot-two
249+ => *[kernel-formula=^ tale=*]
250+ != [.*(0 kernel-formula) tale]
251+ ::
252+ :: boot-ova
253+ ::
254+ =/ boot-ova=(list)
255+ [aeon:eden:part boot-two kernel-formula ~]
256+ ::
257+ :: a pill is a 3-tuple of event-lists: [boot kernel userspace]
258+ ::
259+ :: Our kernel event-list is ~, as we've already installed them.
260+ :: Our userspace event-list is a list containing a full %clay
261+ :: filesystem sync event.
262+ ::
263+ :+ %pill %solid
264+ :+ boot-ova ~
265+ =. dez (snoc dez [%base bas])
266+ ;: weld
267+ %+ turn dez
268+ |= [dek=desk bas=path]
269+ (file-ovum [dek bas exc])
270+ ::
271+ ?. prime ~
272+ [(prep-ovum (turn dez tail))]~
273+ ::
274+ %+ turn dez
275+ |= [dek=desk *]
276+ ^- unix-event
277+ [/c/essential/[dek] %esse dek %.y]
278+ ==
279+::
280+++ brass
281+ :: sys: root path to boot system, `/~me/[desk]/now/sys`
282+ :: dez: secondary desks and their root paths
283+ :: exc: list of desk folders to exclude
284+ ::
285+ |= [sys=path dez=(list [desk path]) cache=? prime=? new-wynn=? exc=(list spur)]
286+ ^- pill
287+ =/ bas=path (scag 3 sys)
288+ :: compiler-source: hoon source file producing compiler, `sys/hoon`
289+ ::
290+ =+ compiler-source=.^(@t %cx (welp sys /hoon/hoon))
291+ ::
292+ :: compiler-twig: compiler as hoon expression
293+ ::
294+ ~& %brass-parsing
295+ =+ compiler-twig=(rain /sys/hoon/hoon compiler-source)
296+ ~& %brass-parsed
297+ ::
298+ :: compiler-formula: compiler as nock formula
299+ ::
300+ ~& %brass-compiling
301+ =+ compiler-formula=q:(~(mint ut %noun) %noun compiler-twig)
302+ ~& %brass-compiled
303+ ::
304+ :: arvo-source: hoon source file producing arvo kernel, `sys/arvo`
305+ ::
306+ =+ arvo-source=.^(@t %cx (welp sys /arvo/hoon))
307+ ::
308+ :: boot-ova: startup events
309+ ::
310+ =/ boot-ova=(list)
311+ :~ aeon:eden:part
312+ boot:eden:part
313+ compiler-formula
314+ compiler-source
315+ arvo-source
316+ ==
317+ ::
318+ =/ kernel-ova=(list unix-event)
319+ :~ (boot-ovum compiler-source arvo-source)
320+ (file-ovum2 [bas exc])
321+ ==
322+ ::
323+ =/ userspace-ova
324+ =. dez (snoc dez [%base bas])
325+ ;: weld
326+ %+ turn dez
327+ |= [dek=desk bas=path]
328+ (file-ovum [dek bas exc])
329+ ::
330+ ?. prime ~
331+ [(prep-ovum (turn dez tail))]~
332+ ::
333+ %+ turn dez
334+ |= [dek=desk *]
335+ ^- unix-event
336+ [/c/essential/[dek] %esse dek %.y]
337+ ==
338+ ::
339+ =/ =wynn (get-wynn sys new-wynn)
340+ ::
341+ =/ cache=(list)
342+ ?. cache ~
343+ %~ tap by
344+ =< +
345+ %- mice
346+ :_ [%2 [%0 3] %0 2]
347+ ;: weld
348+ boot-ova
349+ ^- (list)
350+ :~ [*@da //arvo %wack *@uvJ]
351+ [*@da //arvo %whom *@p]
352+ [*@da //arvo %wyrd [~.nonce /] wynn]
353+ ==
354+ `(list)`(turn kernel-ova (lead *@da))
355+ `(list)`[*@da [/d/term/1 %boot & %fake *@p]]^~
356+ `(list)`(turn userspace-ova (lead *@da))
357+ `(list)`[*@da [/c/init-zest %zeal (turn dez |=([d=desk *] [d %live]))]]^~
358+ ==
359+ ::
360+ ~> %slog.[0 leaf+"brass: cache entries: {<(lent cache)>}"]
361+ ::
362+ :- %cash
363+ :_ cache
364+ [%brass boot-ova kernel-ova userspace-ova]
365+::
366+++ ivory
367+ |= sys=path
368+ ^- pill
369+ =/ lib (snoc (scag 3 sys) %lib)
370+ |^ =/ ver
371+ =/ sub *(trap vase)
372+ =. sub (build-sys sub %hoon)
373+ =. sub (build-sys sub %arvo)
374+ =. sub (build-sys sub %lull)
375+ =. sub (build-sys sub %zuse)
376+ =. sub (build-lib sub & %ethereum)
377+ =. sub (build-lib sub & %azimuth)
378+ (build-lib sub | %vere)
379+ =/ nok !.
380+ => *[ver=(trap vase) ~]
381+ != q:$:ver
382+ ivory/[nok ver ~]
383+ ::
384+ ++ build-sys
385+ |= [sub=(trap vase) nam=term] ^- (trap vase)
386+ ~> %slog.[0 leaf+"ivory: building /sys/{(trip nam)}"]
387+ (swat sub (rain /sys/[nam]/hoon .^(@t cx+(welp sys /[nam]/hoon))))
388+ ::
389+ ++ build-lib
390+ |= [sub=(trap vase) imp=? nam=term] ^- (trap vase)
391+ ~> %slog.[0 leaf+"ivory: building /lib/{(trip nam)}"]
392+ =/ hun=hoon
393+ %+ mist /lib/[nam]/hoon
394+ .^(@t cx+(welp lib /[nam]/hoon))
395+ ?. imp (swat sub hun)
396+ (swel sub [%ktts nam hun])
397+ :: +mist: +rain but skipping past ford runes
398+ ::
399+ ++ mist
400+ |= [bon=path txt=@]
401+ ^- hoon
402+ =+ vas=vast
403+ ~| bon
404+ %+ scan (trip txt)
405+ %- full
406+ =; fud
407+ (ifix [;~(plug gay fud) gay] tall:vas(wer bon))
408+ %- star
409+ ;~ pose vul
410+ %+ ifix [fas (just `@`10)]
411+ (star ;~(less (just `@`10) next))
412+ ==
413+ :: +swel: +swat but with +slop
414+ ::
415+ ++ swel
416+ |= [tap=(trap vase) gen=hoon]
417+ ^- (trap vase)
418+ =/ gun (~(mint ut p:$:tap) %noun gen)
419+ => [tap=tap gun=gun]
420+ |. ~+
421+ =/ pro q:$:tap
422+ [[%cell p.gun p:$:tap] [.*(pro q.gun) pro]]
423+ --
424+::
425+++ events
426+ |%
427+ +$ prop [%prop meta tier (list ovum)]
428+ +$ meta term
429+ +$ tier ?(%fore %hind) :: before or after userspace
430+ ::
431+ ++ install
432+ |= [as=desk =beak pri=?]
433+ ^- prop
434+ :^ %prop (rap 3 %install '-' as ~) %hind
435+ ::TODO will exclude non-:directories files, such as /changelog/txt
436+ =- (murn - same)
437+ ^- (list (unit ovum))
438+ :~ `(file-ovum as (en-beam beak /) ~)
439+ ::
440+ ?. pri ~
441+ `(prep-ovum (en-beam beak /) ~)
442+ ::
443+ `[/d/install/[as] [%seat as]]
444+ ==
445+ --
446+--
447+::
448+~% %non ..part ~
449+:: +mice: %memo hint caching version of mink
450+::
451+|%
452+++ mice !.
453+ ~/ %mice
454+ |= [subject=* formula=*]
455+ =| trace=(list [@ta *])
456+ =| memo=(map)
457+ =; [ton=tone mem=_memo]
458+ ?. ?=(%0 -.ton)
459+ [ton ~]
460+ [ton mem]
461+ |^ ^- [tone _memo]
462+ ?+ formula [[%2 trace] memo]
463+ [^ *]
464+ =^ head memo $(formula -.formula)
465+ ?. ?=(%0 -.head) [head memo]
466+ =^ tail memo $(formula +.formula)
467+ :_ memo
468+ ?. ?=(%0 -.tail) tail
469+ [%0 product.head product.tail]
470+ ::
471+ [%0 axis=@]
472+ :_ memo
473+ =/ part (frag axis.formula subject)
474+ ?~ part [%2 trace]
475+ [%0 u.part]
476+ ::
477+ [%1 constant=*]
478+ [[%0 constant.formula] memo]
479+ ::
480+ [%2 subject=* formula=*]
481+ =^ subject memo $(formula subject.formula)
482+ ?. ?=(%0 -.subject) [subject memo]
483+ =^ formula memo $(formula formula.formula)
484+ ?. ?=(%0 -.formula) [formula memo]
485+ %= $
486+ subject product.subject
487+ formula product.formula
488+ ==
489+ ::
490+ [%3 argument=*]
491+ =^ argument memo $(formula argument.formula)
492+ :_ memo
493+ ?. ?=(%0 -.argument) argument
494+ [%0 .?(product.argument)]
495+ ::
496+ [%4 argument=*]
497+ =^ argument memo $(formula argument.formula)
498+ :_ memo
499+ ?. ?=(%0 -.argument) argument
500+ ?^ product.argument [%2 trace]
501+ [%0 .+(product.argument)]
502+ ::
503+ [%5 a=* b=*]
504+ =^ a memo $(formula a.formula)
505+ ?. ?=(%0 -.a) [a memo]
506+ =^ b memo $(formula b.formula)
507+ :_ memo
508+ ?. ?=(%0 -.b) b
509+ [%0 =(product.a product.b)]
510+ ::
511+ [%6 test=* yes=* no=*]
512+ =^ result memo $(formula test.formula)
513+ ?. ?=(%0 -.result) [result memo]
514+ ?+ product.result [[%2 trace] memo]
515+ %& $(formula yes.formula)
516+ %| $(formula no.formula)
517+ ==
518+ ::
519+ [%7 subject=* next=*]
520+ =^ subject memo $(formula subject.formula)
521+ ?. ?=(%0 -.subject) [subject memo]
522+ %= $
523+ subject product.subject
524+ formula next.formula
525+ ==
526+ ::
527+ [%8 head=* next=*]
528+ =^ head memo $(formula head.formula)
529+ ?. ?=(%0 -.head) [head memo]
530+ %= $
531+ subject [product.head subject]
532+ formula next.formula
533+ ==
534+ ::
535+ [%9 axis=@ core=*]
536+ =^ core memo
537+ $(formula core.formula)
538+ ?. ?=(%0 -.core) [core memo]
539+ =/ arm (frag axis.formula product.core)
540+ ?~ arm [[%2 trace] memo]
541+ %= $
542+ subject product.core
543+ formula u.arm
544+ ==
545+ ::
546+ [%10 [axis=@ value=*] target=*]
547+ ?: =(0 axis.formula) [[%2 trace] memo]
548+ =^ target memo $(formula target.formula)
549+ ?. ?=(%0 -.target) [target memo]
550+ =^ value memo $(formula value.formula)
551+ :_ memo
552+ ?. ?=(%0 -.value) value
553+ =/ mutant=(unit *)
554+ (edit axis.formula product.target product.value)
555+ ?~ mutant [%2 trace]
556+ [%0 u.mutant]
557+ ::
558+ [%11 tag=@ next=*]
559+ =^ next memo $(formula next.formula)
560+ :_ memo
561+ ?. ?=(%0 -.next) next
562+ :- %0
563+ .* subject
564+ [11 tag.formula 1 product.next]
565+ ::
566+ [%11 [tag=@ clue=*] next=*]
567+ =^ clue memo $(formula clue.formula)
568+ ?. ?=(%0 -.clue) [clue memo]
569+ ?: ?=(%memo tag.formula)
570+ ?^ hit=(~(get by memo) subject next.formula)
571+ [[%0 u.hit] memo]
572+ =^ ton memo $(formula next.formula)
573+ ?. ?=(%0 -.ton)
574+ [ton memo]
575+ ?: ?=(?(@ [%clay %ford *]) product.clue)
576+ [ton memo]
577+ [ton (~(put by memo) [subject next.formula] product.ton)]
578+ =^ next memo
579+ =? trace
580+ ?=(?(%hunk %hand %lose %mean %spot) tag.formula)
581+ [[tag.formula product.clue] trace]
582+ $(formula next.formula)
583+ :_ memo
584+ ?. ?=(%0 -.next) next
585+ :- %0
586+ .* subject
587+ [11 [tag.formula 1 product.clue] 1 product.next]
588+ ==
589+ ::
590+ ++ frag
591+ |= [axis=@ noun=*]
592+ ^- (unit)
593+ ?: =(0 axis) ~
594+ |- ^- (unit)
595+ ?: =(1 axis) `noun
596+ ?@ noun ~
597+ =/ pick (cap axis)
598+ %= $
599+ axis (mas axis)
600+ noun ?-(pick %2 -.noun, %3 +.noun)
601+ ==
602+ ::
603+ ++ edit
604+ |= [axis=@ target=* value=*]
605+ ^- (unit)
606+ ?: =(1 axis) `value
607+ ?@ target ~
608+ =/ pick (cap axis)
609+ =/ mutant
610+ %= $
611+ axis (mas axis)
612+ target ?-(pick %2 -.target, %3 +.target)
613+ ==
614+ ?~ mutant ~
615+ ?- pick
616+ %2 `[u.mutant +.target]
617+ %3 `[-.target u.mutant]
618+ ==
619+ --
620+--
base-desk/lib/pkcs.hoonnew file+378
@@ -0,0 +1,378 @@
1+/- asn1
2+/+ primitive-rsa, der
3+=* rsa primitive-rsa
4+:::: %/lib/pkcs
5+|%
6+:: +rs256: RSA signatures over a sha-256 digest
7+::
8+++ rs256
9+ |_ k=key:rsa
10+ :: +emsa:rs256: message digest
11+ ::
12+ :: Padded, DER encoded sha-256 hash (EMSA-PKCS1-v1_5).
13+ ::
14+ ++ emsa
15+ |= m=byts
16+ =/ emlen (met 3 n.pub.k)
17+ =/ pec=spec:asn1
18+ :~ %seq
19+ [%seq [%obj sha-256:obj:asn1] [%nul ~] ~]
20+ [%oct 32 (shay wid.m dat.m)]
21+ ==
22+ :: note: this asn.1 digest is rendered raw here, as we require
23+ :: big-endian bytes, and the product of +en:der is little-endian
24+ ::
25+ =/ t=(list @D) ~(ren raw:en:der pec)
26+ =/ tlen=@ud (lent t)
27+ ?: (lth emlen (add 11 tlen))
28+ ~|(%emsa-too-short !!)
29+ =/ ps=(list @D)
30+ (reap (sub emlen (add 3 tlen)) 0xff)
31+ (rep 3 (flop (weld [0x0 0x1 ps] [0x0 t])))
32+ :: +sign:rs256: sign message
33+ ::
34+ :: An RSA signature is the primitive decryption of the message hash.
35+ ::
36+ ++ sign
37+ |=(m=byts (de:rsa (emsa m) k))
38+ :: +verify:rs256: verify signature
39+ ::
40+ :: RSA signature verification confirms that the primitive encryption
41+ :: of the signature matches the message hash.
42+ ::
43+ ++ verify
44+ |= [s=@ m=byts]
45+ =((emsa m) (en:rsa s k))
46+ --
47+:: |pem: generic PEM implementation (rfc7468)
48+::
49+:: PEM is the base64 encoding of DER encoded data, with BEGIN and
50+:: END labels indicating some type.
51+::
52+++ pem
53+ |%
54+ :: +en:pem: PEM encode
55+ ::
56+ ++ en
57+ |= [lab=@t len=@ud der=@ux]
58+ ^- wain
59+ :: XX validate label?
60+ :- (rap 3 ['-----BEGIN ' lab '-----' ~])
61+ =/ a (en:base64:mimes:html len `@`der)
62+ |- ^- wain
63+ ?~ a
64+ [(rap 3 ['-----END ' lab '-----' ~]) ~]
65+ [(end [3 64] a) $(a (rsh [3 64] a))]
66+ :: +de:pem: PEM decode
67+ ::
68+ ++ de
69+ |= [lab=@t mep=wain]
70+ ^- (unit [len=@ud der=@ux])
71+ =/ a (sub (lent mep) 2)
72+ ?~ mep ~
73+ :: XX validate label?
74+ ?. =((rap 3 ['-----BEGIN ' lab '-----' ~]) i.mep) ~
75+ ?. =((rap 3 ['-----END ' lab '-----' ~]) (snag a t.mep)) ~
76+ ^- (unit [@ @])
77+ (de:base64:mimes:html (rap 3 (scag a t.mep)))
78+ --
79+:: |pkcs1: RSA asymmetric cryptography (rfc3447)
80+::
81+++ pkcs1
82+ |%
83+ :: |spec:pkcs1: ASN.1 specs for RSA keys
84+ ::
85+ ++ spec
86+ |%
87+ :: |en:spec:pkcs1: ASN.1 encoding for RSA keys
88+ ::
89+ ++ en
90+ |%
91+ :: +pass:en:spec:pkcs1: encode public key to ASN.1
92+ ::
93+ ++ pass
94+ |= k=key:rsa
95+ ^- spec:asn1
96+ [%seq [%int n.pub.k] [%int e.pub.k] ~]
97+ :: +ring:en:spec:pkcs1: encode private key to ASN.1
98+ ::
99+ ++ ring
100+ |= k=key:rsa
101+ ^- spec:asn1
102+ ~| %rsa-need-ring
103+ ?> ?=(^ sek.k)
104+ :~ %seq
105+ [%int 0]
106+ [%int n.pub.k]
107+ [%int e.pub.k]
108+ [%int d.u.sek.k]
109+ [%int p.u.sek.k]
110+ [%int q.u.sek.k]
111+ [%int (mod d.u.sek.k (dec p.u.sek.k))]
112+ [%int (mod d.u.sek.k (dec q.u.sek.k))]
113+ [%int (~(inv fo p.u.sek.k) q.u.sek.k)]
114+ ==
115+ --
116+ :: |de:spec:pkcs1: ASN.1 decoding for RSA keys
117+ ::
118+ ++ de
119+ |%
120+ :: +pass:de:spec:pkcs1: decode ASN.1 public key
121+ ::
122+ ++ pass
123+ |= a=spec:asn1
124+ ^- (unit key:rsa)
125+ ?. ?=([%seq [%int *] [%int *] ~] a)
126+ ~
127+ =* n int.i.seq.a
128+ =* e int.i.t.seq.a
129+ `[[n e] ~]
130+ :: +ring:de:spec:pkcs1: decode ASN.1 private key
131+ ::
132+ ++ ring
133+ |= a=spec:asn1
134+ ^- (unit key:rsa)
135+ ?. ?=([%seq *] a) ~
136+ ?. ?= $: [%int %0]
137+ [%int *]
138+ [%int *]
139+ [%int *]
140+ [%int *]
141+ [%int *]
142+ *
143+ ==
144+ seq.a
145+ ~
146+ =* n int.i.t.seq.a
147+ =* e int.i.t.t.seq.a
148+ =* d int.i.t.t.t.seq.a
149+ =* p int.i.t.t.t.t.seq.a
150+ =* q int.i.t.t.t.t.t.seq.a
151+ `[[n e] `[d p q]]
152+ --
153+ --
154+ :: |der:pkcs1: DER encoding for RSA keys
155+ ::
156+ :: En(coding) and de(coding) for public (pass) and private (ring) keys.
157+ ::
158+ ++ der
159+ |%
160+ ++ en
161+ |%
162+ ++ pass |=(k=key:rsa (en:^der (pass:en:spec k)))
163+ ++ ring |=(k=key:rsa (en:^der (ring:en:spec k)))
164+ --
165+ ++ de
166+ |%
167+ ++ pass |=([len=@ud dat=@ux] `(unit key:rsa)`(biff (de:^der len dat) pass:de:spec))
168+ ++ ring |=([len=@ud dat=@ux] `(unit key:rsa)`(biff (de:^der len dat) ring:de:spec))
169+ --
170+ --
171+ :: |pem:pkcs1: PEM encoding for RSA keys
172+ ::
173+ :: En(coding) and de(coding) for public (pass) and private (ring) keys.
174+ ::
175+ ++ pem
176+ |%
177+ ++ en
178+ |%
179+ ++ pass |=(k=key:rsa (en:^pem 'RSA PUBLIC KEY' (pass:en:der k)))
180+ ++ ring |=(k=key:rsa (en:^pem 'RSA PRIVATE KEY' (ring:en:der k)))
181+ --
182+ ++ de
183+ |%
184+ ++ pass |=(mep=wain (biff (de:^pem 'RSA PUBLIC KEY' mep) pass:de:der))
185+ ++ ring |=(mep=wain (biff (de:^pem 'RSA PRIVATE KEY' mep) ring:de:der))
186+ --
187+ --
188+ --
189+:: |pkcs8: asymmetric cryptography (rfc5208, rfc5958)
190+::
191+:: RSA-only for now.
192+::
193+++ pkcs8
194+ |%
195+ :: |spec:pkcs8: ASN.1 specs for asymmetric keys
196+ ::
197+ ++ spec
198+ |%
199+ ++ en
200+ |%
201+ :: +pass:spec:pkcs8: public key ASN.1
202+ ::
203+ :: Technically not part of pkcs8, but standardized later in
204+ :: the superseding RFC. Included here for symmetry.
205+ ::
206+ ++ pass
207+ |= k=key:rsa
208+ ^- spec:asn1
209+ :~ %seq
210+ [%seq [[%obj rsa:obj:asn1] [%nul ~] ~]]
211+ =/ a=[len=@ud dat=@ux]
212+ (pass:en:der:pkcs1 k)
213+ [%bit (mul 8 len.a) dat.a]
214+ ==
215+ :: +ring:spec:pkcs8: private key ASN.1
216+ ::
217+ ++ ring
218+ |= k=key:rsa
219+ ^- spec:asn1
220+ :~ %seq
221+ [%int 0]
222+ [%seq [[%obj rsa:obj:asn1] [%nul ~] ~]]
223+ [%oct (ring:en:der:pkcs1 k)]
224+ ==
225+ --
226+ :: |de:spec:pkcs8: ASN.1 decoding for asymmetric keys
227+ ::
228+ ++ de
229+ |%
230+ :: +pass:de:spec:pkcs8: decode public key ASN.1
231+ ::
232+ ++ pass
233+ |= a=spec:asn1
234+ ^- (unit key:rsa)
235+ ?. ?=([%seq [%seq *] [%bit *] ~] a)
236+ ~
237+ ?. ?& ?=([[%obj *] [%nul ~] ~] seq.i.seq.a)
238+ =(rsa:obj:asn1 obj.i.seq.i.seq.a)
239+ ==
240+ ~
241+ (pass:de:der:pkcs1 (div len.i.t.seq.a 8) bit.i.t.seq.a)
242+ :: +ring:de:spec:pkcs8: decode private key ASN.1
243+ ::
244+ ++ ring
245+ |= a=spec:asn1
246+ ^- (unit key:rsa)
247+ ?. ?=([%seq [%int %0] [%seq *] [%oct *] ~] a)
248+ ~
249+ ?. ?& ?=([[%obj *] [%nul ~] ~] seq.i.t.seq.a)
250+ =(rsa:obj:asn1 obj.i.seq.i.t.seq.a)
251+ ==
252+ ~
253+ (ring:de:der:pkcs1 [len oct]:i.t.t.seq.a)
254+ --
255+ --
256+ :: |der:pkcs8: DER encoding for asymmetric keys
257+ ::
258+ :: En(coding) and de(coding) for public (pass) and private (ring) keys.
259+ :: RSA-only for now.
260+ ::
261+ ++ der
262+ |%
263+ ++ en
264+ |%
265+ ++ pass |=(k=key:rsa `[len=@ud dat=@ux]`(en:^der (pass:en:spec k)))
266+ ++ ring |=(k=key:rsa `[len=@ud dat=@ux]`(en:^der (ring:en:spec k)))
267+ --
268+ ++ de
269+ |%
270+ ++ pass |=([len=@ud dat=@ux] `(unit key:rsa)`(biff (de:^der len dat) pass:de:spec))
271+ ++ ring |=([len=@ud dat=@ux] `(unit key:rsa)`(biff (de:^der len dat) ring:de:spec))
272+ --
273+ --
274+ :: |pem:pkcs8: PEM encoding for asymmetric keys
275+ ::
276+ :: En(coding) and de(coding) for public (pass) and private (ring) keys.
277+ :: RSA-only for now.
278+ ::
279+ ++ pem
280+ |%
281+ ++ en
282+ |%
283+ ++ pass |=(k=key:rsa (en:^pem 'PUBLIC KEY' (pass:en:der k)))
284+ ++ ring |=(k=key:rsa (en:^pem 'PRIVATE KEY' (ring:en:der k)))
285+ --
286+ ++ de
287+ |%
288+ ++ pass |=(mep=wain (biff (de:^pem 'PUBLIC KEY' mep) pass:de:der))
289+ ++ ring |=(mep=wain (biff (de:^pem 'PRIVATE KEY' mep) ring:de:der))
290+ --
291+ --
292+ --
293+:: |pkcs10: certificate signing requests (rfc2986)
294+::
295+:: Only implemented for RSA keys with subject-alternate names.
296+::
297+++ pkcs10
298+ => |%
299+ :: +csr:pkcs10: certificate request
300+ ::
301+ +$ csr [key=key:rsa hot=(list turf)]
302+ --
303+ |%
304+ :: |spec:pkcs10: ASN.1 specs for certificate signing requests
305+ ::
306+ ++ spec
307+ |%
308+ :: +en:spec:pkcs10: ASN.1 encoding for certificate signing requests
309+ ::
310+ ++ en
311+ |= csr
312+ ^- spec:asn1
313+ |^ =/ dat=spec:asn1 (info key hot)
314+ :~ %seq
315+ dat
316+ [%seq [[%obj rsa-sha-256:obj:asn1] [%nul ~] ~]]
317+ :: big-endian signature bits
318+ ::
319+ :: the signature bitwidth is definitionally the key length
320+ ::
321+ :+ %bit
322+ (met 0 n.pub.key)
323+ (swp 3 (~(sign rs256 key) (en:^der dat)))
324+ ==
325+ :: +info:en:spec:pkcs10: certificate request info
326+ ::
327+ ++ info
328+ |= csr
329+ ^- spec:asn1
330+ :~ %seq
331+ [%int 0]
332+ [%seq ~]
333+ (pass:en:spec:pkcs8 key)
334+ :: explicit, context-specific tag #0 (extensions)
335+ ::
336+ :+ %con
337+ `bespoke:asn1`[| 0]
338+ %~ ren
339+ raw:en:^der
340+ :~ %seq
341+ [%obj csr-ext:obj:asn1]
342+ :~ %set
343+ :~ %seq
344+ :~ %seq
345+ [%obj sub-alt:obj:asn1]
346+ [%oct (en:^der (san hot))]
347+ == == == == ==
348+ :: +san:en:spec:pkcs10: subject-alternate-names
349+ ::
350+ ++ san
351+ |= hot=(list turf)
352+ ^- spec:asn1
353+ :- %seq
354+ %+ turn hot
355+ :: implicit, context-specific tag #2 (IA5String)
356+ :: XX sanitize string?
357+ |=(=turf [%con `bespoke:asn1`[& 2] (trip (en-turf:html turf))])
358+ --
359+ :: |de:spec:pkcs10: ASN.1 decoding for certificate signing requests
360+ ++ de !!
361+ --
362+ :: |der:pkcs10: DER encoding for certificate signing requests
363+ ::
364+ ++ der
365+ |%
366+ ++ en |=(a=csr `[len=@ud der=@ux]`(en:^der (en:spec a)))
367+ ++ de !! ::|=(a=@ `(unit csr)`(biff (de:^der a) de:spec))
368+ --
369+ :: |pem:pkcs10: PEM encoding for certificate signing requests
370+ ::
371+ ++ pem
372+ |%
373+ ++ en |=(a=csr (en:^pem 'CERTIFICATE REQUEST' (en:der a)))
374+ ++ de !! ::|=(mep=wain (biff (de:^pem 'CERTIFICATE REQUEST' mep) de:der))
375+ --
376+ --
377+--
378+
base-desk/lib/primitive-rsa.hoonnew file+84
@@ -0,0 +1,84 @@
1+:: |rsa: primitive, textbook RSA
2+::
3+:: Unpadded, unsafe, unsuitable for encryption!
4+::
5+|%
6+:: +key:rsa: rsa public or private key
7+::
8++$ key
9+ $: :: pub: public parameters (n=modulus, e=pub-exponent)
10+ ::
11+ pub=[n=@ux e=@ux]
12+ :: sek: secret parameters (d=private-exponent, p/q=primes)
13+ ::
14+ sek=(unit [d=@ux p=@ux q=@ux])
15+ ==
16+:: +ramp: make rabin-miller probabilistic prime
17+::
18+:: XX replace +ramp:number?
19+:: a: bitwidth
20+:: b: snags (XX small primes to check divisibility?)
21+:: c: entropy
22+::
23+++ ramp
24+ |= [a=@ b=(list @) c=@]
25+ =. c (shas %ramp c)
26+ :: XX what is this value?
27+ ::
28+ =| d=@
29+ |- ^- @ux
30+ :: XX what is this condition?
31+ ::
32+ ?: =((mul 100 a) d)
33+ ~|(%ar-ramp !!)
34+ :: e: prime candidate
35+ ::
36+ :: Sets low bit, as prime must be odd.
37+ :: Sets high bit, as +raw:og only gives up to :a bits.
38+ ::
39+ =/ e :(con 1 (lsh [0 (dec a)] 1) (~(raw og c) a))
40+ :: XX what algorithm is this modular remainder check?
41+ ::
42+ ?: ?& (levy b |=(f=@ !=(1 (mod e f))))
43+ (pram:number e)
44+ ==
45+ e
46+ $(c +(c), d (shax d))
47+:: +elcm:rsa: carmichael totient
48+::
49+++ elcm
50+ |= [a=@ b=@]
51+ (div (mul a b) d:(egcd a b))
52+:: +new-key:rsa: write somethingXXX
53+::
54+++ new-key
55+ =/ e `@ux`65.537
56+ |= [wid=@ eny=@]
57+ ^- key
58+ =/ diw (rsh 0 wid)
59+ =/ p=@ux (ramp diw [3 5 ~] eny)
60+ =/ q=@ux (ramp diw [3 5 ~] +(eny))
61+ =/ n=@ux (mul p q)
62+ =/ d=@ux (~(inv fo (elcm (dec p) (dec q))) e)
63+ [[n e] `[d p q]]
64+:: +en:rsa: primitive RSA encryption
65+::
66+:: ciphertext = message^e (mod n)
67+::
68+++ en
69+ |= [m=@ k=key]
70+ ~| %rsa-len
71+ ?> (lte (met 0 m) (met 0 n.pub.k))
72+ (~(exp fo n.pub.k) e.pub.k m)
73+:: +de:rsa: primitive RSA decryption
74+::
75+:: message = ciphertext^d (mod e)
76+::
77+++ de
78+ |= [m=@ k=key]
79+ :: XX assert rsa-len here too?
80+ ~| %rsa-need-ring
81+ ?> ?=(^ sek.k)
82+ =/ fu (fu:number p.u.sek.k q.u.sek.k)
83+ (out.fu (exp.fu d.u.sek.k (sit.fu m)))
84+--
base-desk/lib/ring.hoonnew file+478
@@ -0,0 +1,478 @@
1+/- *ring
2+:: ring signatures over the edwards curve
3+::
4+|%
5+:: +raw is the raw internal ring signature implementation. +raw does not deal
6+:: with urbit ship identities or urbit nouns and is low level. It only deals
7+:: with ed25519 keys and message digests.
8+::
9+:: This raw interface is vaguely modeled on the haskell aos-signature package,
10+:: but is written in terms of ed25519 primitives instead of general ECC and
11+:: changes how linkage tags are computed so that how linkage occurs is a
12+:: client decision instead of hard coding the set of public keys as the
13+:: linkage scope.
14+::
15+++ raw
16+ |%
17+ :: +generate-public-linkage: generate public linkage information
18+ ::
19+ ++ generate-public-linkage
20+ |= link-scope=@
21+ ^- [data=@ h=@uxpoint]
22+ ::
23+ =/ data=@ (mod link-scope l:ed:crypto)
24+ =/ h=@uxpoint (scalarmult-base:ed:crypto data)
25+ [data h]
26+ :: +generate-linkage: linkage information from scope and private key
27+ ::
28+ :: data: deterministically picked data point based off scope
29+ :: h: h = [data] * g
30+ :: y: y = [x] * h
31+ ++ generate-linkage
32+ |= [link-scope=(unit @) my-private-key=@]
33+ ^- (unit [data=@ h=@uxpoint y=@uxpoint])
34+ ::
35+ ?~ link-scope
36+ ~
37+ ::
38+ =+ [data=@ h=@uxpoint]=(generate-public-linkage u.link-scope)
39+ =/ y=@uxpoint (scalarmult:ed:crypto my-private-key h)
40+ [~ data h y]
41+ :: +generate-challenge: generate challenge from a given message
42+ ::
43+ :: When :link-scope is ~ (ie, we're not building a linked ring signature),
44+ :: calculates just the hash of `[message g]`. Otherwise, weaves the
45+ :: linkage state into the challenge.
46+ ::
47+ ++ generate-challenge
48+ |= $: :: common to both linked and unlinked
49+ message=@
50+ g=@uxpoint
51+ :: high level universal state
52+ ::
53+ link-state=(unit [data=@ h=@uxpoint y=@uxpoint])
54+ :: point to include in challenge when link-state isn't ~
55+ ::
56+ h=(unit @uxpoint)
57+ ==
58+ ^- @
59+ :: concatenate and reduce our message down to a 512-bit hash
60+ =/ concatenated
61+ ?~ link-state
62+ (shal 96 (can 3 ~[[64 message] [32 g]]))
63+ ::
64+ %+ shal 192
65+ %+ can 3
66+ :~ [64 message]
67+ [32 g]
68+ [32 data.u.link-state]
69+ [32 y.u.link-state]
70+ [32 (need h)]
71+ ==
72+ ::
73+ (mod concatenated l:ed:crypto)
74+ :: +generate-challenges: generates the full list of challenges
75+ ::
76+ ++ generate-challenges
77+ |= $: link-state=(unit [data=@ h=@uxpoint y=@uxpoint])
78+ message=@
79+ public-keys=(list @uxpoint)
80+ ss=(list @)
81+ ::
82+ prev-k=@u
83+ prev-s=@
84+ prev-ch=@
85+ challenges=(list @)
86+ ==
87+ ^- (list @)
88+ ::
89+ =/ gs=@uxpoint
90+ %- add-scalarmult-scalarmult-base:ed:crypto :*
91+ prev-ch
92+ (snag prev-k public-keys)
93+ prev-s
94+ ==
95+ ::
96+ =/ hs=(unit @uxpoint)
97+ ?~ link-state
98+ ~
99+ ::
100+ :- ~
101+ %- add-double-scalarmult:ed:crypto :*
102+ prev-s
103+ h.u.link-state
104+ prev-ch
105+ y.u.link-state
106+ ==
107+ ::
108+ =/ ch=@
109+ (generate-challenge message gs link-state hs)
110+ ::
111+ ?~ ss
112+ [ch challenges]
113+ ::
114+ %_ $
115+ prev-k (mod (add prev-k 1) (lent public-keys))
116+ prev-s i.ss
117+ prev-ch ch
118+ ss t.ss
119+ challenges [ch challenges]
120+ ==
121+ :: +scalarmult-h: maybe multiply u by h in linkage
122+ ::
123+ :: Since linkage tags are optional, we need to be able to just do the math
124+ :: in case :linkage is set and fall through otherwise. +scalarmult-h is
125+ :: used to generate the (unit point) consumed by +generate-challenge.
126+ ::
127+ ++ scalarmult-h
128+ |= [u=@ linkage=(unit [data=@ h=@uxpoint y=@uxpoint])]
129+ ^- (unit @uxpoint)
130+ ?~ linkage
131+ ~
132+ [~ (scalarmult:ed:crypto u h.u.linkage)]
133+ :: +reorder: reorders a list so the ith element is first
134+ ::
135+ ++ reorder
136+ |* [i=@ l=(list)]
137+ %+ weld
138+ (slag i l)
139+ (scag i l)
140+ :: +sign: creates a ring signature on an ed25519 curve
141+ ::
142+ ++ sign
143+ |= $: message=@
144+ link-scope=(unit @)
145+ ::
146+ anonymity-set=(set @uxpoint)
147+ my-public-key=@uxpoint
148+ my-private-key=@uxscalar
149+ ::
150+ eny=@uvJ
151+ ==
152+ ^- raw-ring-signature
153+ |^ :: k: our public-key's position in :anonymity-list
154+ ::
155+ =/ k=@u
156+ ~| [%couldnt-find my-public-key in=anonymity-list]
157+ (need (find [my-public-key ~] anonymity-list))
158+ :: Generate linkage information if given
159+ ::
160+ =/ linkage=(unit [data=@ h=@uxpoint y=@uxpoint])
161+ (generate-linkage link-scope my-private-key)
162+ :: initialize our random number generator from entropy
163+ ::
164+ =+ rand=~(. og eny)
165+ :: generate the random s values used in the ring
166+ ::
167+ =^ random-s-values=(list @) rand
168+ =| count=@
169+ =| random-s-values=(list @)
170+ |-
171+ ?: =(count (sub participants 1))
172+ [random-s-values rand]
173+ ::
174+ =^ v=@ rand (rads:rand l:ed:crypto)
175+ $(count (add 1 count), random-s-values [v random-s-values])
176+ ::
177+ ?> ?=(^ random-s-values)
178+ =/ sk1=@ i.random-s-values
179+ =/ sk2-to-prev-sk=(list @) t.random-s-values
180+ :: Pick a random :u
181+ ::
182+ =^ u=@ rand
183+ (rads:rand l:ed:crypto)
184+ :: Compute challenge at k + 1
185+ ::
186+ =/ chk1=@
187+ %- generate-challenge :*
188+ message
189+ (scalarmult-base:ed:crypto u)
190+ linkage
191+ (scalarmult-h u linkage)
192+ ==
193+ :: Generate challenges for [ck, ..., c1, c0, ... ck + 2, ck + 1]
194+ ::
195+ =/ reversed-chk-to-chk1=(list @)
196+ %- generate-challenges :*
197+ linkage
198+ message
199+ anonymity-list
200+ sk2-to-prev-sk
201+ ::
202+ (mod (add k 1) participants)
203+ sk1
204+ chk1
205+ [chk1 ~]
206+ ==
207+ =/ chk=@ (head reversed-chk-to-chk1)
208+ :: Compute s = u - x * c mod n
209+ ::
210+ =/ sk=@ (~(dif fo l:ed:crypto) u (mul my-private-key chk))
211+ ::
212+ =/ ordered-challenges=(list @)
213+ (order-challenges k (flop reversed-chk-to-chk1))
214+ ::
215+ =/ ordered-ss=(list @) (order-ss k [sk sk1 sk2-to-prev-sk])
216+ =/ ch0 (head ordered-challenges)
217+ ::
218+ [ch0 ordered-ss ?~(linkage ~ `y.u.linkage)]
219+ ::
220+ ++ anonymity-list
221+ ~(tap in anonymity-set)
222+ ::
223+ ++ participants
224+ (lent anonymity-list)
225+ ::
226+ ++ order-challenges
227+ |= [k=@ ch=(list @)]
228+ (reorder (sub participants (add k 1)) ch)
229+ ::
230+ ++ order-ss
231+ |= [k=@ sk-to-prev-sk=(list @)]
232+ (reorder (sub participants k) sk-to-prev-sk)
233+ --
234+ :: +verify: verify signature
235+ ::
236+ ++ verify
237+ |= $: message=@
238+ link-scope=(unit @)
239+ ::
240+ anonymity-set=(set @uxpoint)
241+ signature=raw-ring-signature
242+ ==
243+ ^- ?
244+ :: if there's a linkage scope but no tag, fail
245+ ::
246+ ?: &(?=(^ link-scope) ?=(~ y.signature))
247+ %.n
248+ :: if there's no linkage scope but a tag, fail
249+ ::
250+ ?: &(?=(~ link-scope) ?=(^ y.signature))
251+ %.n
252+ :: vice versa.
253+ ::
254+ :: decompose the signature into [s0 s1 s2....]
255+ ::
256+ ?> ?=([@ @ *] s.signature)
257+ =/ s0=@ i.s.signature
258+ =/ s1=@ i.t.s.signature
259+ =/ s2-to-end=(list @) t.t.s.signature
260+ :: anonymity-list: set of public keys listified in ring order
261+ ::
262+ =/ anonymity-list=(list @uxpoint)
263+ ~(tap in anonymity-set)
264+ :: participants: length of :anonymity-list
265+ ::
266+ =/ participants=@u
267+ (lent anonymity-list)
268+ ::
269+ =/ z0p=@uxpoint
270+ %- add-scalarmult-scalarmult-base:ed:crypto :*
271+ ch0.signature
272+ (head anonymity-list)
273+ s0
274+ ==
275+ :: generate the linkage using public data, and the y point from the
276+ :: signature
277+ ::
278+ =/ linkage=(unit [data=@ h=@uxpoint y=@uxpoint])
279+ ?~ link-scope
280+ ~
281+ =+ [data=@ h=@uxpoint]=(generate-public-linkage u.link-scope)
282+ :- ~
283+ [data h (need y.signature)]
284+ ::
285+ =/ z0pp=(unit @uxpoint)
286+ ?~ linkage
287+ ~
288+ :- ~
289+ %- add-double-scalarmult:ed:crypto :*
290+ s0
291+ h.u.linkage
292+ ch0.signature
293+ y.u.linkage
294+ ==
295+ :: initial challenge
296+ ::
297+ =/ ch1=@
298+ (generate-challenge message z0p linkage z0pp)
299+ ::
300+ =/ challenges
301+ %- generate-challenges :*
302+ linkage
303+ message
304+ anonymity-list
305+ s2-to-end
306+ ::
307+ (mod 1 participants)
308+ s1
309+ ch1
310+ [ch1 ~]
311+ ==
312+ ::
313+ =(ch0.signature (head challenges))
314+ --
315+:: +detail: details about getting keys from Azimuth
316+::
317+++ detail
318+ |%
319+ :: +seed-to-private-key-scalar: keyfile form to scalar we can multiply with
320+ ::
321+ ++ seed-to-private-key-scalar
322+ |= sk=@I ^- @uxscalar
323+ ?: (gth (met 3 sk) 32) !!
324+ =+ h=(shal (rsh [0 3] b:ed:crypto) sk)
325+ %+ add
326+ (bex (sub b:ed:crypto 2))
327+ (lsh [0 3] (cut 0 [3 (sub b:ed:crypto 5)] h))
328+ :: +get-public-key-from-pass: decode the raw @ public key structure
329+ ::
330+ ++ get-public-key-from-pass
331+ |= a=pass
332+ ^- [@ @]
333+ =+ [mag=(end 3 a) bod=(rsh 3 a)]
334+ ~| %not-crub-pubkey ?> =('b' mag)
335+ [cry=(rsh 8 bod) sgn=(end 8 bod)]
336+ ::
337+ ::
338+ ++ get-private-key-from-ring
339+ |= a=ring
340+ ^- [@ @]
341+ =+ [mag=(end 3 a) bod=(rsh 3 a)]
342+ ~| %not-crub-seckey ?> =('B' mag)
343+ =+ [c=(rsh 8 bod) s=(end 8 bod)]
344+ :: todo: do we puck here?
345+ [c s]
346+ :: +ship-life-to-pubid: fetches public key information from jael
347+ ::
348+ ++ ship-life-to-pubid
349+ |= [our=@p now=@da ship=@p =life]
350+ ^- @uxpoint
351+ ::
352+ =/ d=[=^life =pass *]
353+ =/ scry-path=path
354+ :~ %j
355+ (scot %p our)
356+ %deed
357+ (scot %da now)
358+ (scot %p ship)
359+ (scot %ud life)
360+ ==
361+ .^([^life pass *] scry-path)
362+ :: we have the deed which has pass, which is several numbers +cat-ed
363+ :: together; pull out the keys
364+ ::
365+ =/ x=[crypt=@ auth=@] (get-public-key-from-pass pass.d)
366+ ::
367+ `@uxpoint`auth.x
368+ ::
369+ ++ build-signing-participants
370+ |= [our=@p now=@da invited=(list @p)]
371+ ^- [(set [@p life]) (set @uxpoint)]
372+ ::
373+ =| participants=(set [@p life])
374+ =| keys=(set @uxpoint)
375+ ::
376+ |-
377+ ?~ invited
378+ [participants keys]
379+ ::
380+ =/ lyfe=(unit @ud)
381+ .^((unit @ud) j+/(scot %p our)/lyfe/(scot %da now)/(scot %p i.invited))
382+ ::
383+ ?~ lyfe
384+ $(invited t.invited)
385+ ::
386+ =/ pubkey=@uxpoint (ship-life-to-pubid our now i.invited u.lyfe)
387+ ::
388+ =. participants (~(put in participants) [i.invited u.lyfe])
389+ =. keys (~(put in keys) pubkey)
390+ ::
391+ $(invited t.invited)
392+ ::
393+ ::
394+ ++ build-verifying-participants
395+ |= [our=@p now=@da invited=(list [ship=@p =life])]
396+ ^- (set @uxpoint)
397+ ::
398+ =| keys=(set @uxpoint)
399+ ::
400+ |-
401+ ?~ invited
402+ keys
403+ ::
404+ =/ pubkey=@uxpoint
405+ (ship-life-to-pubid our now ship.i.invited life.i.invited)
406+ =. keys
407+ (~(put in keys) pubkey)
408+ ::
409+ $(invited t.invited)
410+ --
411+--
412+:: public interface
413+::
414+|%
415+:: +sign: ring-signs a message using the current ship
416+::
417+++ sign
418+ |= $: our=@p
419+ now=@da
420+ eny=@uvJ
421+ ::
422+ message=*
423+ link-scope=(unit *)
424+ anonymity-set=(set @p)
425+ ==
426+ ^- ring-signature
427+ :: if our is not in @p, we must be in @p.
428+ ::
429+ =. anonymity-set (~(put in anonymity-set) our)
430+ ::
431+ =/ msg-hash=@ (shaz (jam message))
432+ =/ link-hash=(unit @) (bind link-scope |=(a=* (shaz (jam a))))
433+ :: get everyone's public keys
434+ ::
435+ =/ p=[participants=(set [ship=@p =life]) keys=(set @uxpoint)]
436+ (build-signing-participants:detail our now ~(tap in anonymity-set))
437+ :: get our ships' current life
438+ ::
439+ =/ our-life=life
440+ .^(life %j /(scot %p our)/life/(scot %da now)/(scot %p our))
441+ :: get our ships' secret keyfile ring
442+ ::
443+ =/ secret-ring=ring
444+ .^(ring %j /(scot %p our)/vein/(scot %da now)/(scot %ud our-life))
445+ :: fetch the encoded auth seed from the ring
446+ ::
447+ =/ secret-auth-seed=@
448+ +:(get-private-key-from-ring:detail secret-ring)
449+ :: get our ships' public key
450+ ::
451+ =/ public-key=@uxpoint
452+ (ship-life-to-pubid:detail our now our our-life)
453+ ::
454+ :- participants.p
455+ :- link-scope
456+ %- sign:raw :*
457+ msg-hash
458+ link-hash
459+ keys.p
460+ public-key
461+ (seed-to-private-key-scalar:detail secret-auth-seed)
462+ eny
463+ ==
464+:: +verify: verifies a message against a ring signature
465+::
466+++ verify
467+ |= [our=@p now=@da message=* =ring-signature]
468+ ^- ?
469+ ::
470+ =/ keys=(set @uxpoint)
471+ %^ build-verifying-participants:detail our now
472+ ~(tap in participants.ring-signature)
473+ ::
474+ =/ msg-hash=@ (shaz (jam message))
475+ =/ link-hash=(unit @) (bind link-scope.ring-signature |=(a=* (shaz (jam a))))
476+ ::
477+ (verify:raw msg-hash link-hash keys raw.ring-signature)
478+--
base-desk/lib/server.hoonnew file+159
@@ -0,0 +1,159 @@
1+=, eyre
2+|%
3++$ request-line
4+ $: [ext=(unit @ta) site=(list @t)]
5+ args=(list [key=@t value=@t])
6+ ==
7+:: +parse-request-line: take a cord and parse out a url
8+::
9+++ parse-request-line
10+ |= url=@t
11+ ^- request-line
12+ (fall (rush url ;~(plug apat:de-purl:html yque:de-purl:html)) [[~ ~] ~])
13+::
14+++ manx-to-octs
15+ |= man=manx
16+ ^- octs
17+ (as-octt:mimes:html (en-xml:html man))
18+::
19+++ json-to-octs
20+ |= jon=json
21+ ^- octs
22+ (as-octs:mimes:html (en:json:html jon))
23+::
24+++ app
25+ |%
26+ ::
27+ :: +require-authorization:
28+ :: redirect to the login page when unauthenticated
29+ :: otherwise call handler on inbound request
30+ ::
31+ ++ require-authorization
32+ |= $: =inbound-request:eyre
33+ handler=$-(inbound-request:eyre simple-payload:http)
34+ ==
35+ ^- simple-payload:http
36+ ::
37+ ?: authenticated.inbound-request
38+ ~! this
39+ ~! +:*handler
40+ (handler inbound-request)
41+ ::
42+ =- [[307 ['location' -]~] ~]
43+ %^ cat 3
44+ '/~/login?redirect='
45+ url.request.inbound-request
46+ ::
47+ :: +require-authorization-simple:
48+ :: redirect to the login page when unauthenticated
49+ :: otherwise pass through simple-paylod
50+ ::
51+ ++ require-authorization-simple
52+ |= [=inbound-request:eyre =simple-payload:http]
53+ ^- simple-payload:http
54+ ::
55+ ?: authenticated.inbound-request
56+ ~! this
57+ simple-payload
58+ ::
59+ =- [[307 ['location' -]~] ~]
60+ %^ cat 3
61+ '/~/login?redirect='
62+ url.request.inbound-request
63+ ::
64+ ++ give-simple-payload
65+ |= [eyre-id=@ta =simple-payload:http]
66+ ^- (list card:agent:gall)
67+ =/ header-cage
68+ [%http-response-header !>(response-header.simple-payload)]
69+ =/ data-cage
70+ [%http-response-data !>(data.simple-payload)]
71+ :~ [%give %fact ~[/http-response/[eyre-id]] header-cage]
72+ [%give %fact ~[/http-response/[eyre-id]] data-cage]
73+ [%give %kick ~[/http-response/[eyre-id]] ~]
74+ ==
75+ --
76+++ gen
77+ |%
78+ ::
79+ ++ max-1-da ['cache-control' 'max-age=86400']
80+ ++ max-1-wk ['cache-control' 'max-age=604800']
81+ ::
82+ ++ html-response
83+ =| cache=?
84+ |= =octs
85+ ^- simple-payload:http
86+ :_ `octs
87+ [200 [['content-type' 'text/html'] ?:(cache [max-1-wk ~] ~)]]
88+ ::
89+ ++ css-response
90+ =| cache=?
91+ |= =octs
92+ ^- simple-payload:http
93+ :_ `octs
94+ [200 [['content-type' 'text/css'] ?:(cache [max-1-wk ~] ~)]]
95+ ::
96+ ++ js-response
97+ =| cache=?
98+ |= =octs
99+ ^- simple-payload:http
100+ :_ `octs
101+ [200 [['content-type' 'text/javascript'] ?:(cache [max-1-wk ~] ~)]]
102+ ::
103+ ++ png-response
104+ =| cache=?
105+ |= =octs
106+ ^- simple-payload:http
107+ :_ `octs
108+ [200 [['content-type' 'image/png'] ?:(cache [max-1-wk ~] ~)]]
109+ ::
110+ ++ svg-response
111+ =| cache=?
112+ |= =octs
113+ ^- simple-payload:http
114+ :_ `octs
115+ [200 [['content-type' 'image/svg+xml'] ?:(cache [max-1-wk ~] ~)]]
116+ ::
117+ ++ ico-response
118+ |= =octs
119+ ^- simple-payload:http
120+ [[200 [['content-type' 'image/x-icon'] max-1-wk ~]] `octs]
121+ ::
122+ ++ woff2-response
123+ =| cache=?
124+ |= =octs
125+ ^- simple-payload:http
126+ [[200 [['content-type' 'font/woff2'] max-1-wk ~]] `octs]
127+ ::
128+ ++ json-response
129+ =| cache=_|
130+ |= =json
131+ ^- simple-payload:http
132+ :_ `(json-to-octs json)
133+ [200 [['content-type' 'application/json'] ?:(cache [max-1-da ~] ~)]]
134+ ::
135+ ++ manx-response
136+ =| cache=_|
137+ |= man=manx
138+ ^- simple-payload:http
139+ :_ `(manx-to-octs man)
140+ [200 [['content-type' 'text/html'] ?:(cache [max-1-da ~] ~)]]
141+ ::
142+ ++ not-found
143+ ^- simple-payload:http
144+ [[404 ~] ~]
145+ ::
146+ ++ login-redirect
147+ |= =request:http
148+ ^- simple-payload:http
149+ =- [[307 ['location' -]~] ~]
150+ %^ cat 3
151+ '/~/login?redirect='
152+ url.request
153+ ::
154+ ++ redirect
155+ |= redirect=cord
156+ ^- simple-payload:http
157+ [[307 ['location' redirect]~] ~]
158+ --
159+--
base-desk/lib/shoe.hoonnew file+568
@@ -0,0 +1,568 @@
1+:: shoe: console application library
2+::
3+:: /lib/sole: draw some characters
4+:: /lib/shoe: draw the rest of the fscking app
5+::
6+:: call +agent with a type, then call the resulting function with a core
7+:: of the shape described in +shoe.
8+:: you may produce classic gall cards and "shoe-effects", shorthands for
9+:: sending cli events to connected clients.
10+:: default implementations for the shoe-specific arms are in +default.
11+:: for a simple usage example, see /app/shoe.
12+::
13+/- *sole
14+/+ sole, auto=language-server-complete
15+|%
16++$ state-2
17+ $: %2
18+ soles=(map sole-id sole-share)
19+ ==
20+:: $card: standard gall cards plus shoe effects
21+::
22++$ card
23+ $% card:agent:gall
24+ [%shoe sole-ids=(list sole-id) effect=shoe-effect] :: ~ sends to all
25+ ==
26+:: $shoe-effect: easier sole-effects
27+::
28++$ shoe-effect
29+ $% :: %sole: raw sole-effect
30+ ::
31+ [%sole effect=sole-effect]
32+ :: %table: sortable, filterable data, with suggested column char widths
33+ ::
34+ [%table head=(list dime) wide=(list @ud) rows=(list (list dime))]
35+ :: %row: line sections with suggested char widths
36+ ::
37+ [%row wide=(list @ud) cols=(list dime)]
38+ ==
39+:: +shoe: gall agent core with extra arms
40+::
41+++ shoe
42+ |* command-type=mold
43+ $_ ^|
44+ |_ bowl:gall
45+ :: +command-parser: input parser for a specific session
46+ ::
47+ :: if the head of the result is true, instantly run the command
48+ ::
49+ ++ command-parser
50+ |~ =sole-id
51+ |~(nail *(like [? command-type]))
52+ :: +tab-list: autocomplete options for the session (to match +command-parser)
53+ ::
54+ ++ tab-list
55+ |~ =sole-id
56+ :: (list [@t tank])
57+ *(list (option:auto tank))
58+ :: +on-command: called when a valid command is run
59+ ::
60+ ++ on-command
61+ |~ [=sole-id command=command-type]
62+ *(quip card _^|(..on-init))
63+ ::
64+ ++ can-connect
65+ |~ =sole-id
66+ *?
67+ ::
68+ ++ on-connect
69+ |~ =sole-id
70+ *(quip card _^|(..on-init))
71+ ::
72+ ++ on-disconnect
73+ |~ =sole-id
74+ *(quip card _^|(..on-init))
75+ ::
76+ ::NOTE standard gall agent arms below, though they may produce %shoe cards
77+ ::
78+ ++ on-init
79+ *(quip card _^|(..on-init))
80+ ::
81+ ++ on-save
82+ *vase
83+ ::
84+ ++ on-load
85+ |~ vase
86+ *(quip card _^|(..on-init))
87+ ::
88+ ++ on-poke
89+ |~ [mark vase]
90+ *(quip card _^|(..on-init))
91+ ::
92+ ++ on-watch
93+ |~ path
94+ *(quip card _^|(..on-init))
95+ ::
96+ ++ on-leave
97+ |~ path
98+ *(quip card _^|(..on-init))
99+ ::
100+ ++ on-peek
101+ |~ path
102+ *(unit (unit cage))
103+ ::
104+ ++ on-agent
105+ |~ [wire sign:agent:gall]
106+ *(quip card _^|(..on-init))
107+ ::
108+ ++ on-arvo
109+ |~ [wire sign-arvo]
110+ *(quip card _^|(..on-init))
111+ ::
112+ ++ on-fail
113+ |~ [term tang]
114+ *(quip card _^|(..on-init))
115+ --
116+:: +default: bare-minimum implementations of shoe arms
117+::
118+++ default
119+ |* [shoe=* command-type=mold]
120+ |_ =bowl:gall
121+ ++ command-parser
122+ |= =sole-id
123+ (easy *[? command-type])
124+ ::
125+ ++ tab-list
126+ |= =sole-id
127+ ~
128+ ::
129+ ++ on-command
130+ |= [=sole-id command=command-type]
131+ [~ shoe]
132+ ::
133+ ++ can-connect
134+ |= =sole-id
135+ (team:title [our src]:bowl)
136+ ::
137+ ++ on-connect
138+ |= =sole-id
139+ [~ shoe]
140+ ::
141+ ++ on-disconnect
142+ |= =sole-id
143+ [~ shoe]
144+ --
145+:: +agent: creates wrapper core that handles sole events and calls shoe arms
146+::
147+++ agent
148+ |* command-type=mold
149+ |= =(shoe command-type)
150+ =| state-2
151+ =* state -
152+ ^- agent:gall
153+ =>
154+ |%
155+ ++ deal
156+ |= cards=(list card)
157+ %+ turn cards
158+ |= =card
159+ ^- card:agent:gall
160+ ?. ?=(%shoe -.card) card
161+ ?- -.effect.card
162+ %sole
163+ =- [%give %fact - %sole-effect !>(effect.effect.card)]
164+ %+ turn
165+ ?^ sole-ids.card sole-ids.card
166+ ~(tap in ~(key by soles))
167+ id-to-path:sole
168+ ::
169+ %table
170+ =; fez=(list sole-effect)
171+ $(effect.card [%sole %mor fez])
172+ =, +.effect.card
173+ :- (row:draw & wide head)
174+ %+ turn rows
175+ (cury (cury row:draw |) wide)
176+ ::
177+ %row
178+ $(effect.card [%sole (row:draw | +.effect.card)])
179+ ==
180+ --
181+ ::
182+ |_ =bowl:gall
183+ +* this .
184+ og ~(. shoe bowl)
185+ ::
186+ ++ on-init
187+ ^- (quip card:agent:gall agent:gall)
188+ =^ cards shoe on-init:og
189+ [(deal cards) this]
190+ ::
191+ ++ on-save :(slop !>(%shoe-app) on-save:og !>(state))
192+ ::
193+ ++ on-load
194+ |= old-state=vase
195+ ^- (quip card:agent:gall agent:gall)
196+ :: we could be upgrading from a shoe-less app, in which case the vase
197+ :: contains inner application state instead of our +on-save.
198+ :: to distinguish between the two, we check for the presence of our own
199+ :: +on-save tag in the vase.
200+ ::
201+ ?. ?=([%shoe-app ^] q.old-state)
202+ =^ cards shoe (on-load:og old-state)
203+ [(deal cards) this]
204+ |^ :: versions %0 and %1 stored the inner state double-vased.
205+ :: fixing this coincided with the 408 type-of-type migration.
206+ ::
207+ ?: ?=([%shoe-app * ?(%0 %1) *] q.old-state)
208+ =| old-outer=state-any
209+ =^ old-inner old-outer
210+ +:!<([%shoe-app vase:h136 state-any] old-state)
211+ =^ caz shoe (on-load:og (next-vase:h136 old-inner))
212+ =^ cuz old-outer
213+ ?. ?=(%0 -.old-outer) [~ old-outer]
214+ (state-0-to-1 old-outer)
215+ =? old-outer ?=(%1 -.old-outer) (state-1-to-2 old-outer)
216+ ?> ?=(%2 -.old-outer)
217+ [(weld cuz (deal caz)) this(state old-outer)]
218+ ::
219+ =+ !<(old=state-any (slot 7 old-state))
220+ ?> ?=(%2 -.old)
221+ =. state old
222+ ::
223+ =^ caz shoe (on-load:og (slot 6 old-state))
224+ [(deal caz) this]
225+ ::
226+ +$ state-any $%(state-2 state-1 state-0)
227+ +$ state-1 _%*(. *state-2 - %1)
228+ +$ state-0 [%0 soles=(map @ta sole-share)]
229+ ++ state-1-to-2 |=(old=state-1 old(- %2))
230+ ++ state-0-to-1
231+ |= old=state-0
232+ ^- (quip card:agent:gall state-1)
233+ :- %+ turn ~(tap in ~(key by soles.old))
234+ |= id=@ta
235+ ^- card:agent:gall
236+ [%give %kick ~[/sole/[id]] ~]
237+ :- %1
238+ %- ~(gas by *(map sole-id sole-share))
239+ %+ murn ~(tap by soles.old)
240+ |= [id=@ta s=sole-share]
241+ (bind (upgrade-id:sole id) (late s))
242+ --
243+ ::
244+ ++ on-poke
245+ |= [=mark =vase]
246+ ^- (quip card:agent:gall agent:gall)
247+ ?. ?=(%sole-action mark)
248+ =^ cards shoe (on-poke:og mark vase)
249+ [(deal cards) this]
250+ ::
251+ =/ act !<(sole-action vase)
252+ =* sole-id id.act
253+ =/ cli-state=sole-share
254+ (~(gut by soles) sole-id *sole-share)
255+ |^ =^ [cards=(list card) =_cli-state] shoe
256+ ?- -.dat.act
257+ %det (apply-edit +.dat.act)
258+ %clr [[~ cli-state] shoe]
259+ %ret try-command
260+ %tab [(tab +.dat.act) shoe]
261+ ==
262+ :- (deal cards)
263+ this(soles (~(put by soles) sole-id cli-state))
264+ ::
265+ ++ effect
266+ |= =sole-effect
267+ ^- card
268+ [%shoe [sole-id]~ %sole sole-effect]
269+ ::
270+ ++ apply-edit
271+ |= =sole-change
272+ ^+ [[*(list card) cli-state] shoe]
273+ =^ inverse cli-state
274+ (~(transceive sole cli-state) sole-change)
275+ :: res: & for fully parsed, | for parsing failure at location
276+ ::
277+ =/ res=(each (unit [run=? cmd=command-type]) @ud)
278+ %+ rose (tufa buf.cli-state)
279+ (command-parser:og sole-id)
280+ ?: ?=(%& -.res)
281+ :: only auto-run eligible commands if they were typed out
282+ :: (that is, not retrieved from command history)
283+ ::
284+ ?. &(?=(^ p.res) run.u.p.res !?=(%set -.ted.sole-change))
285+ [[~ cli-state] shoe]
286+ (run-command cmd.u.p.res)
287+ :_ shoe
288+ :: parsing failed
289+ ::
290+ ?. &(?=(%del -.inverse) =(+(p.inverse) (lent buf.cli-state)))
291+ :: if edit was somewhere in the middle, let it happen anyway
292+ ::
293+ [~ cli-state]
294+ :: if edit was insertion at buffer tail, revert it
295+ ::
296+ =^ undo cli-state
297+ (~(transmit sole cli-state) inverse)
298+ :_ cli-state
299+ :_ ~
300+ %+ effect %mor
301+ :~ [%det undo] :: undo edit
302+ [%err p.res] :: cursor to error location
303+ ==
304+ ::
305+ ++ try-command
306+ ^+ [[*(list card) cli-state] shoe]
307+ =/ res=(unit [? cmd=command-type])
308+ %+ rust (tufa buf.cli-state)
309+ (command-parser:og sole-id)
310+ ?^ res (run-command cmd.u.res)
311+ [[[(effect %bel ~)]~ cli-state] shoe]
312+ ::
313+ ++ run-command
314+ |= cmd=command-type
315+ ^+ [[*(list card) cli-state] shoe]
316+ =^ cards shoe (on-command:og sole-id cmd)
317+ :: clear buffer
318+ ::
319+ =^ clear cli-state (~(transmit sole cli-state) [%set ~])
320+ =- [[[- cards] cli-state] shoe]
321+ %+ effect %mor
322+ :~ [%nex ~]
323+ [%det clear]
324+ ==
325+ ::
326+ ++ tab
327+ |= pos=@ud
328+ ^- (quip card _cli-state)
329+ =+ (get-id-cord:auto pos (tufa buf.cli-state))
330+ =/ needle=term
331+ (fall id %$)
332+ :: autocomplete empty command iff user at start of command
333+ ::
334+ =/ options=(list (option:auto tank))
335+ (search-prefix:auto needle (tab-list:og sole-id))
336+ =/ advance=term
337+ (longest-match:auto options)
338+ =/ to-send=tape
339+ %- trip
340+ (rsh [3 (met 3 needle)] advance)
341+ =/ send-pos=@ud
342+ %+ add pos
343+ (met 3 (fall forward ''))
344+ =| cards=(list card)
345+ :: only render the option list if we couldn't complete anything
346+ ::
347+ =? cards &(?=(~ to-send) ?=(^ options))
348+ [(effect %tab options) cards]
349+ |- ^- (quip card _cli-state)
350+ ?~ to-send
351+ [(flop cards) cli-state]
352+ =^ char cli-state
353+ (~(transmit sole cli-state) [%ins send-pos `@c`i.to-send])
354+ %_ $
355+ cards [(effect %det char) cards]
356+ send-pos +(send-pos)
357+ to-send t.to-send
358+ ==
359+ --
360+ ::
361+ ++ on-watch
362+ |= =path
363+ ^- (quip card:agent:gall agent:gall)
364+ ?~ sole-id=(path-to-id:sole path)
365+ =^ cards shoe
366+ (on-watch:og path)
367+ [(deal cards) this]
368+ ?> (can-connect:og u.sole-id)
369+ =. soles (~(put by soles) u.sole-id *sole-share)
370+ =^ cards shoe
371+ (on-connect:og u.sole-id)
372+ :_ this
373+ %- deal
374+ :_ cards
375+ [%shoe [u.sole-id]~ %sole %pro & dap.bowl "> "]
376+ ::
377+ ++ on-leave
378+ |= =path
379+ ^- (quip card:agent:gall agent:gall)
380+ =^ cards shoe (on-leave:og path)
381+ [(deal cards) this]
382+ ::
383+ ++ on-peek
384+ |= =path
385+ ^- (unit (unit cage))
386+ ?. =(/x/dbug/state path) (on-peek:og path)
387+ ``noun+(slop on-save:og !>(shoe=state))
388+ ::
389+ ++ on-agent
390+ |= [=wire =sign:agent:gall]
391+ ^- (quip card:agent:gall agent:gall)
392+ =^ cards shoe (on-agent:og wire sign)
393+ [(deal cards) this]
394+ ::
395+ ++ on-arvo
396+ |= [=wire =sign-arvo]
397+ ^- (quip card:agent:gall agent:gall)
398+ =^ cards shoe (on-arvo:og wire sign-arvo)
399+ [(deal cards) this]
400+ ::
401+ ++ on-fail
402+ |= [=term =tang]
403+ ^- (quip card:agent:gall agent:gall)
404+ =^ cards shoe (on-fail:og term tang)
405+ [(deal cards) this]
406+ --
407+::
408+++ draw
409+ |%
410+ ++ row
411+ |= [bold=? wide=(list @ud) cols=(list dime)]
412+ ^- sole-effect
413+ :- %mor
414+ ^- (list sole-effect)
415+ =/ cows=(list [wid=@ud col=dime])
416+ %- head
417+ %^ spin cols wide
418+ |= [col=dime wiz=(list @ud)]
419+ ~| [%too-few-wide col]
420+ ?> ?=(^ wiz)
421+ [[i.wiz col] t.wiz]
422+ =/ cobs=(list [wid=@ud (list tape)])
423+ (turn cows col-as-lines)
424+ =+ [lin=0 any=|]
425+ =+ len=(lent cobs)
426+ =| fez=(list sole-effect)
427+ |- ^+ fez
428+ =; [line=(list tape) end=@ud]
429+ :: done when we're past the end of all columns
430+ ::
431+ ?: =(len end)
432+ (flop fez)
433+ =; fec=sole-effect
434+ $(lin +(lin), fez [fec fez])
435+ =/ out=tape
436+ (zing (join " " line))
437+ ?. bold txt+out
438+ klr+[[`%br ~ ~]^[(crip out)]~]~
439+ %^ spin cobs 0
440+ |= [[wid=@ud lines=(list tape)] empty=@ud]
441+ =+ l=(swag [lin 1] lines)
442+ ?^ l [i.l empty]
443+ [(reap wid ' ') +(empty)]
444+ ::
445+ ++ col-as-lines
446+ |= [wid=@ud col=dime]
447+ ^- [@ud (list tape)]
448+ :- wid
449+ %+ turn
450+ (break wid (col-as-text col) (break-sets -.col))
451+ (cury (cury pad wid) (alignment -.col))
452+ ::
453+ ++ col-as-text
454+ |= col=dime
455+ ^- tape
456+ ?+ p.col (scow col)
457+ %t (trip q.col)
458+ %tas ['%' (scow col)]
459+ ==
460+ ::
461+ ++ alignment
462+ |= wut=@ta
463+ ^- ?(%left %right)
464+ ?: ?=(?(%t %ta %tas %da) wut)
465+ %left
466+ %right
467+ ::
468+ ++ break-sets
469+ |= wut=@ta
470+ :: for: may break directly before these characters
471+ :: aft: may break directly after these characters
472+ :: new: always break on these characters, consuming them
473+ ::
474+ ^- [for=(set @t) aft=(set @t) new=(set @t)]
475+ ?+ wut [(sy " ") (sy ".:-/") (sy "\0a")]
476+ ?(%p %q) [(sy "-") (sy "-") ~]
477+ %ux [(sy ".") ~ ~]
478+ ==
479+ ::
480+ ++ break
481+ |= [wid=@ud cot=tape brs=_*break-sets]
482+ ^- (list tape)
483+ ~| [wid cot]
484+ ?: =("" cot) ~
485+ =; [lin=tape rem=tape]
486+ [lin $(cot rem)]
487+ :: take snip of max width+1, search for breakpoint on that.
488+ :: we grab one char extra, to look-ahead for for.brs.
489+ :: later on, we always transfer _at least_ the extra char.
490+ ::
491+ =^ lin=tape cot
492+ [(scag +(wid) cot) (slag +(wid) cot)]
493+ =+ len=(lent lin)
494+ :: find the first newline character
495+ ::
496+ =/ new=(unit @ud)
497+ =+ new=~(tap in new.brs)
498+ =| las=(unit @ud)
499+ |-
500+ ?~ new las
501+ $(new t.new, las (hunt lth las (find [i.new]~ lin)))
502+ :: if we found a newline, break on it
503+ ::
504+ ?^ new
505+ :- (scag u.new lin)
506+ (weld (slag +(u.new) lin) cot)
507+ :: if it fits, we're done
508+ ::
509+ ?: (lte len wid)
510+ [lin cot]
511+ =+ nil=(flop lin)
512+ :: search for latest aft match
513+ ::
514+ =/ aft=(unit @ud)
515+ :: exclude the look-ahead character from search
516+ ::
517+ =. len (dec len)
518+ =. nil (slag 1 nil)
519+ =- ?~(- ~ `+(u.-))
520+ ^- (unit @ud)
521+ =+ aft=~(tap in aft.brs)
522+ =| las=(unit @ud)
523+ |-
524+ ?~ aft (bind las (cury sub (dec len)))
525+ $(aft t.aft, las (hunt lth las (find [i.aft]~ nil)))
526+ :: search for latest for match
527+ ::
528+ =/ for=(unit @ud)
529+ =+ for=~(tap in for.brs)
530+ =| las=(unit @ud)
531+ |-
532+ ?~ for (bind las (cury sub (dec len)))
533+ =- $(for t.for, las (hunt lth las -))
534+ =+ (find [i.for]~ nil)
535+ :: don't break before the first character
536+ ::
537+ ?:(=(`(dec len) -) ~ -)
538+ :: if any result, break as late as possible
539+ ::
540+ =+ brk=(hunt gth aft for)
541+ ?~ brk
542+ :: lin can't break, produce it in its entirety
543+ :: (after moving the look-ahead character back)
544+ ::
545+ :- (scag wid lin)
546+ (weld (slag wid lin) cot)
547+ :- (scag u.brk lin)
548+ =. cot (weld (slag u.brk lin) cot)
549+ :: eat any leading whitespace the next line might have, "clean break"
550+ ::
551+ |- ^+ cot
552+ ?~ cot ~
553+ ?. ?=(?(%' ' %'\09') i.cot)
554+ cot
555+ $(cot t.cot)
556+ ::
557+ ++ pad
558+ |= [wid=@ud lyn=?(%left %right) lin=tape]
559+ ^+ lin
560+ =+ l=(lent lin)
561+ ?: (gte l wid) lin
562+ =+ p=(reap (sub wid l) ' ')
563+ ?- lyn
564+ %left (weld lin p)
565+ %right (weld p lin)
566+ ==
567+ --
568+--
base-desk/lib/sink.hoonnew file+26
@@ -0,0 +1,26 @@
1+/+ noun-diff
2+|%
3+++ clog
4+ |$ [stut]
5+ $%
6+ [%flush stut]
7+ [%drain patch:noun-diff]
8+ ==
9+++ sink
10+ |* pats=(list path)
11+ |* stat=*
12+ |@
13+ ++ sync
14+ |= [stat=_stat]
15+ ^- [card:agent:gall _..sync]
16+ =/ dif
17+ %+ diff:noun-diff ^stat stat
18+ :-
19+ [%give %fact pats %noun !>(^-((clog) [%drain dif]))]
20+ ..sync(stat stat)
21+ ++ paths pats
22+ ++ flush
23+ ^- card:agent:gall
24+ [%give %fact pats %noun !>(^-((clog) [%flush stat]))]
25+ --
26+--
base-desk/lib/skeleton.hoonnew file+51
@@ -0,0 +1,51 @@
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+--
base-desk/lib/sole.hoonnew file+163
@@ -0,0 +1,163 @@
1+::
2+:::: /hoon/sole/lib
3+ ::
4+/? 310
5+/- *sole
6+::::
7+ ::
8+|_ sole-share :: shared-state engine
9+++ abet +<
10+++ apply
11+ |= ted=sole-edit
12+ ^+ +>
13+ ?- -.ted
14+ %del +>.$(buf (weld (scag p.ted buf) (slag +(p.ted) buf)))
15+ %ins +>.$(buf (weld (scag p.ted buf) `_buf`[q.ted (slag p.ted buf)]))
16+ %mor |- ^+ +>.^$
17+ ?~ p.ted
18+ +>.^$
19+ $(p.ted t.p.ted, +>.^$ ^$(ted i.p.ted))
20+ %nop +>.$
21+ %set +>.$(buf p.ted)
22+ ==
23+::
24+::::
25+:: ++transmute: symmetric operational transformation.
26+::
27+:: for any sole state +>, obeys
28+::
29+:: =+ [x=(transmute a b) y=(transmute b a)]
30+:: .= (apply:(apply a) x)
31+:: (apply:(apply b) y)
32+::
33+++ transmute :: dex as after sin
34+ |= [sin=sole-edit dex=sole-edit]
35+ ~| [%transmute sin dex]
36+ ^- sole-edit
37+ ?: ?=(%mor -.sin)
38+ |- ^- sole-edit
39+ ?~ p.sin dex
40+ $(p.sin t.p.sin, dex ^$(sin i.p.sin))
41+ ::
42+ ?: ?=(%mor -.dex)
43+ :- %mor
44+ |- ^- (list sole-edit)
45+ ?~ p.dex ~
46+ [^$(dex i.p.dex) $(p.dex t.p.dex)]
47+ ::
48+ ?: |(?=(%nop -.sin) ?=(%nop -.dex)) dex
49+ ?: ?=(%set -.sin) [%nop ~]
50+ ?: ?=(%set -.dex) dex
51+ ::
52+ ?- -.sin
53+ %del
54+ ?- -.dex
55+ %del ?: =(p.sin p.dex) [%nop ~]
56+ ?:((lth p.sin p.dex) dex(p (dec p.dex)) dex)
57+ %ins ?:((lth p.sin p.dex) dex(p (dec p.dex)) dex)
58+ ==
59+ ::
60+ %ins
61+ ?- -.dex
62+ %del ?:((lte p.sin p.dex) dex(p +(p.dex)) dex)
63+ %ins ?: =(p.sin p.dex)
64+ ?:((lth q.sin q.dex) dex dex(p +(p.dex)))
65+ ?:((lte p.sin p.dex) dex(p +(p.dex)) dex)
66+ ==
67+ ==
68+::
69+++ commit :: local change
70+ |= ted=sole-edit
71+ ^- sole-share
72+ abet:(apply(own.ven +(own.ven), leg [ted leg]) ted)
73+::
74+::::
75+:: ++inverse: inverse of change in context.
76+::
77+:: for any sole state +>, obeys
78+::
79+:: =(+> (apply:(apply a) (inverse a)))
80+::
81+++ inverse :: relative inverse
82+ |= ted=sole-edit
83+ ^- sole-edit
84+ =. ted ?.(?=([%mor * ~] ted) ted i.p.ted)
85+ ?- -.ted
86+ %del [%ins p.ted (snag p.ted buf)]
87+ %ins [%del p.ted]
88+ %mor :- %mor
89+ %- flop
90+ |- ^- (list sole-edit)
91+ ?~ p.ted ~
92+ :- ^$(ted i.p.ted)
93+ $(p.ted t.p.ted, +>.^$ (apply i.p.ted))
94+ %nop [%nop ~]
95+ %set [%set buf]
96+ ==
97+::
98+++ receive :: naturalize event
99+ |= sole-change
100+ ^- [sole-edit sole-share]
101+ ?. &(=(his.ler his.ven) (lte own.ler own.ven))
102+ ~| [%receive-sync his+[his.ler his.ven] own+[own.ler own.ven]]
103+ !!
104+ ?> &(=(his.ler his.ven) (lte own.ler own.ven))
105+ ?> |(!=(own.ler own.ven) =(`@`0 haw) =(haw (sham buf)))
106+ =. leg (scag (sub own.ven own.ler) leg)
107+ :: ~? !=(own.ler own.ven) [%miss-leg leg]
108+ =+ dat=(transmute [%mor leg] ted)
109+ :: ~? !=(~ leg) [%transmute from+ted to+dat ~]
110+ [dat abet:(apply(his.ven +(his.ven)) dat)]
111+::
112+++ remit :: conditional accept
113+ |= [cal=sole-change ask=$-((list @c) ?)]
114+ ^- [(unit sole-change) sole-share]
115+ =+ old=buf
116+ =^ dat +>+<.$ (receive cal)
117+ ?: (ask buf)
118+ [~ +>+<.$]
119+ =^ lic +>+<.$ (transmit (inverse(buf old) dat))
120+ [`lic +>+<.$]
121+::
122+++ transmit :: outgoing change
123+ |= ted=sole-edit
124+ ^- [sole-change sole-share]
125+ [[[his.ven own.ven] (sham buf) ted] (commit ted)]
126+::
127+++ transceive :: receive and invert
128+ |= sole-change
129+ ^- [sole-edit sole-share]
130+ =+ old=buf
131+ =^ dat +>+<.$ (receive +<.$)
132+ [(inverse(buf old) dat) +>+<.$]
133+::
134+++ transpose :: adjust position
135+ |= pos=@ud
136+ =+ dat=(transmute [%mor leg] [%ins pos `@c`0])
137+ ?> ?=(%ins -.dat)
138+ p.dat
139+::
140+::
141+++ path-to-id
142+ |= =path
143+ ^- (unit sole-id)
144+ ?. ?=([%sole @ ?(~ [@ ~])] path) ~
145+ ?~ who=(slaw %p i.t.path) ~
146+ `[u.who ?~(t.t.path %$ i.t.t.path)]
147+::
148+++ id-to-path
149+ |= sole-id
150+ ^- path
151+ ::TODO this whole "no empty path ending" business feels icky.
152+ :: do we want default session to be ~.~ ?
153+ :: concern here is that outsiders cannot subscribe to the default
154+ :: session, because /sole/~zod/ isn't a valid path...
155+ [%sole (scot %p who) ?~(ses ~ /[ses])]
156+::
157+++ upgrade-id
158+ |= old=@ta
159+ ^- (unit sole-id)
160+ %+ rush old
161+ %+ cook (late %$)
162+ ;~(pfix (jest 'drum_~') fed:ag)
163+--
base-desk/lib/sss.hoonnew file+445
@@ -0,0 +1,445 @@
1+/- *sss
2+/+ *mip
3+::
4+|%
5+++ mk-subs :: Create sub-map.
6+ |* [=(lake) paths=mold]
7+ -:+6:(da lake paths)
8+::
9+++ mk-pubs :: Create pub-map.
10+ |* [=(lake) paths=mold]
11+ -:+6:(du lake paths)
12+::
13+++ mk-mar :: Create mar.
14+ |* =(lake)
15+ |_ =(response:poke lake *)
16+ ++ grow
17+ |%
18+ ++ noun response
19+ --
20+ ++ grab
21+ |%
22+ ++ noun (response:poke lake *)
23+ --
24+ ++ grad %noun
25+ --
26+++ fled :: Like +sped but head is a path.
27+ |= vax=vase
28+ ^- vase
29+ :_ q.vax
30+ %- ~(play ut p.vax)
31+ =- [%wtgr [%wtts - [%& 2]~] [%$ 1]]
32+ =/ pax ~| %path-none ;;(path -.q.vax)
33+ |- ^- spec
34+ ?~ pax [%base %null]
35+ [%bccl ~[[%leaf %ta -.pax] $(pax +.pax)]]
36+::
37+++ zoom |= =noun ~| %need-path $/sss/;;(path noun)
38+::
39+++ da :: Manage subscriptions.
40+ |* [=(lake) paths=mold]
41+ =>
42+ |%
43+ +$ from (on-rock:poke lake paths)
44+ +$ into (response:poke lake paths)
45+ +$ result (request:poke paths)
46+ +$ fail [paths ship dude]
47+ +$ flow [=aeon stale=_| fail=_| =rock:lake]
48+ +$ subs [%0 (map [ship dude paths] (unit flow))]
49+ --
50+ |= $: sub=subs
51+ =bowl:gall
52+ result-type=type
53+ on-rock-type=type
54+ fail-type=type
55+ ==
56+ => .(sub +.sub)
57+ |%
58+ ++ surf :: Subscribe to [ship dude path].
59+ |= which=[ship dude paths]
60+ ^- (quip card:agent:gall subs)
61+ ?+ flow=(~(get by sub) which) `0/sub
62+ ~ [~[(pine which)] 0/(~(put by sub) which ~)]
63+ [~ ~] [~[(pine which)] 0/sub]
64+ [~ ~ [* %& * *]] [~[(pine which)] 0/sub]
65+ ==
66+ ++ quit (corl (lead %0) ~(del by sub)) :: Unsub from [ship dude path].
67+ ++ read :: See current subscribed states.
68+ ^- (map [ship dude paths] [stale=? fail=? =rock:lake])
69+ %- malt %+ murn ~(tap by sub)
70+ |= [key=[ship dude paths] val=(unit flow)]
71+ ?~ val ~
72+ `[key +.u.val]
73+ :: :: Check poke-ack for errors.
74+ :: :: If an %sss-on-rock poke nacks,
75+ ++ chit :: that state is flagged as failed.
76+ |= [[aeon=term ship=term dude=term path=paths] =sign:agent:gall]
77+ ^- subs
78+ :- %0
79+ ?> ?=(%poke-ack -.sign)
80+ ?~ p.sign sub
81+ %+ ~(jab by sub) [(slav %p ship) dude path]
82+ |= (unit flow)
83+ =/ =flow (need +<)
84+ ?> =(aeon.flow (slav %ud aeon))
85+ `flow(fail &)
86+ :: :: Check poke-ack for errors.
87+ :: :: If a scry request nacks,
88+ ++ tell :: that state is flagged as stale.
89+ |= [[ship=term =dude aeon=term path=paths] =sign:agent:gall]
90+ ^- (quip card:agent:gall subs)
91+ ?> ?=(%poke-ack -.sign)
92+ ?~ p.sign `0/sub
93+ =/ current [ship=(slav %p ship) dude=dude path=path]
94+ ?+ flow=(~(get by sub) current) `0/sub
95+ [~ ~ *]
96+ =. stale.u.u.flow &
97+ :_ 0/(~(put by sub) current u.flow)
98+ ~[(on-rock-poke fake=& current u.u.flow ~)]
99+ ::
100+ [~ ~]
101+ :_ 0/(~(del by sub) current) :_ ~
102+ :* %pass (zoom surf-fail/aeon/ship/dude/path)
103+ %agent [our dap]:bowl
104+ %poke %sss-surf-fail fail-type ^- fail
105+ [path ship dude]:current
106+ ==
107+ ==
108+ ++ apply :: Handle response from publisher.
109+ |= res=(response:poke lake paths)
110+ ^- (quip card:agent:gall subs)
111+ =* current [src.bowl dude.res path.res]
112+ =/ old=flow (fall (~(got by sub) current) *flow)
113+ ?: ?=(%tomb what.res)
114+ =/ =flow old(stale &)
115+ :_ 0/(~(put by sub) current `flow) :_ ~
116+ (on-rock-poke fake=& current flow ~)
117+ ::
118+ =/ [wave=(unit wave:lake) new=(unit flow)]
119+ ?- what.res
120+ %rock ?: (lte aeon.res aeon.old) [~ ~]
121+ [~ `[aeon.res | | rock.res]]
122+ %wave ?: (lte aeon.res aeon.old) [~ ~]
123+ ?> =(aeon.res +(aeon.old))
124+ [`wave.res `[aeon.res | | (wash:lake rock.old wave.res)]]
125+ ==
126+ ?~ new `0/sub
127+ :_ 0/(~(put by sub) current new) :_ ~
128+ (on-rock-poke fake=& current u.new wave)
129+ ::
130+ ++ handle-fake-on-rock
131+ |= =(on-rock:poke lake paths)
132+ ^- (list card:agent:gall)
133+ ?~ flow=(~(get by sub) [src from path]:on-rock) ~
134+ ?~ u.flow ~
135+ ?. =([stale fail rock]:u.u.flow [stale fail rock]:on-rock) ~
136+ ~[(on-rock-poke fake=| [src from path]:on-rock u.u.flow wave.on-rock)]
137+ ::
138+ :: Non-public facing arms below
139+ ::
140+ ++ pine
141+ |= [who=ship which=dude where=paths]
142+ ^- card:agent:gall
143+ :* %pass (zoom scry-request/(scot %p who)^which^where)
144+ %agent [who which]
145+ %poke sss-to-pub/[result-type `result`[where dap.bowl]]
146+ ==
147+ ++ on-rock-poke
148+ |= [fake=? [=ship =dude path=paths] flow wave=(unit wave:lake)]
149+ ^- card:agent:gall
150+ :* %pass %+ zoom ?:(fake %fake %on-rock)
151+ (scot %ud aeon)^(scot %p ship)^dude^path
152+ %agent [our dap]:bowl
153+ %poke ?:(fake %sss-fake-on-rock %sss-on-rock)
154+ on-rock-type `from`[path ship dude stale fail rock wave]
155+ ==
156+ --
157+++ du :: Manage publications.
158+ |* [=(lake) paths=mold]
159+ =>
160+ |%
161+ +$ into (request:poke paths)
162+ +$ result (response:poke lake paths)
163+ +$ rule $~ [`5 5]
164+ [horizon=(unit @ud) frequency=@ud] :: Retention policy
165+ +$ tide
166+ $: rok=((mop aeon rock:lake) gte)
167+ wav=((mop aeon wave:lake) lte)
168+ rul=rule
169+ mem=(jug ship dude)
170+ ==
171+ +$ buoy
172+ $: tid=$~(*tide $@(aeon tide))
173+ alo=(unit (set ship))
174+ ==
175+ ++ pubs
176+ =< $>(%1 versioned)
177+ |%
178+ ++ update
179+ |= =versioned
180+ ^- pubs
181+ ?- -.versioned
182+ %1 versioned
183+ %0
184+ :- %1
185+ %- ~(run by +.versioned)
186+ |= =buoy-0:^versioned
187+ ^- buoy
188+ %= buoy-0
189+ tid
190+ ?@ tid.buoy-0 tid.buoy-0
191+ ^- tide
192+ %= tid.buoy-0
193+ rocks.rul
194+ ?: =(waves.rul.tid.buoy-0 0) ~
195+ `(mul [+(rocks) waves]:rul.tid.buoy-0)
196+ ::
197+ mem
198+ ^- (jug ship dude)
199+ %- ~(run by mem.tid.buoy-0)
200+ |= =(map dude @da)
201+ ^- (set dude)
202+ ~(key by map)
203+ ==
204+ ==
205+ ==
206+ ++ versioned
207+ =< $% [%0 (map paths buoy-0)]
208+ [%1 (map paths buoy)]
209+ ==
210+ |%
211+ +$ buoy-0
212+ $: tid=$~(*tide-0 $@(aeon tide-0))
213+ alo=(unit (set ship))
214+ ==
215+ +$ tide-0
216+ $: rok=((mop aeon rock:lake) gte)
217+ wav=((mop aeon wave:lake) lte)
218+ rul=[rocks=@ud waves=@ud]
219+ mem=(mip ship dude @da)
220+ ==
221+ --
222+ --
223+ --
224+ |= [pub=versioned:pubs =bowl:gall result-type=type]
225+ => .(pub +:(update:pubs pub))
226+ =* rok ((on aeon rock:lake) gte)
227+ =* wav ((on aeon wave:lake) lte)
228+ |%
229+ ++ rule :: Set new retention policy.
230+ |= [path=paths =^rule]
231+ ^- pubs
232+ :- %1
233+ %- fall :_ (~(put by pub) path %*(. *$<(aeon buoy) rul.tid rule))
234+ %- mole |.
235+ %+ ~(jab by pub) path
236+ |= =buoy
237+ ?@ tid.buoy buoy
238+ buoy(tid (form tid.buoy(rul rule)))
239+ ::
240+ ++ wipe :: Create new rock and wipe rest.
241+ |= path=paths
242+ ^- pubs
243+ :- %1
244+ %+ ~(jab by pub) path
245+ |= =buoy
246+ ?@ tid.buoy buoy
247+ %* . buoy(tid (form tid.buoy(rul [`0 1])))
248+ rul.tid rul.tid.buoy
249+ wav.tid ~
250+ ==
251+ ++ give :: Give a wave on a path.
252+ |= [path=paths =wave:lake]
253+ ^- (quip card:agent:gall pubs)
254+ ?~ ((soft ^path) path) ~| %need-path !!
255+ =/ buoy (~(gut by pub) path *buoy)
256+ =? buoy ?=(@ tid.buoy)
257+ %*(. buoy(tid *tide) rok.tid (put:rok ~ +(tid.buoy) *rock:lake))
258+ ?> ?=(^ tid.buoy)
259+ =* tide tid.buoy
260+ =/ next=aeon +((latest tide))
261+ :- %- zing
262+ %+ turn ~(tap by mem.tide)
263+ |= [=ship =(set dude)]
264+ %+ turn ~(tap in set)
265+ |= =dude
266+ (send wave/[next wave] ship dude path)
267+ :- %1
268+ %+ ~(put by pub) path
269+ =/ last=[=aeon =rock:lake] (fall (pry:rok rok.tide) *[key val]:rok)
270+ =. wav.tide (put:wav wav.tide next wave)
271+ =. mem.tide ~
272+ ?. =(next (add aeon.last frequency.rul.tide)) buoy
273+ buoy(tid (form tide))
274+ ::
275+ ++ fork :: Fork a pub into an empty path.
276+ |= [from=paths to=paths]
277+ ^- pubs
278+ :- %1
279+ ?< (~(has by pub) to)
280+ (~(put by pub) to (~(got by pub) from))
281+ ::
282+ ++ copy :: Fork a sub into an empty path.
283+ |= [sub=_(mk-subs lake *) from=[ship dude *] to=paths]
284+ ^- pubs
285+ :- %1
286+ ?< (~(has by pub) to)
287+ %+ ~(put by pub) to
288+ %* . *$<(aeon buoy)
289+ rok.tid (put:rok ~ [aeon rock]:(need (~(got by +:sub) from)))
290+ ==
291+ ::
292+ ++ perm :: Change permissions with gate.
293+ |= [where=(list paths) diff=$-((unit (set ship)) (unit (set ship)))]
294+ ^- (quip card:agent:gall pubs)
295+ %+ edit where
296+ |= =buoy
297+ =/ new=_alo.buoy (diff alo.buoy)
298+ ?@ tid.buoy buoy(alo new)
299+ %= buoy
300+ alo new
301+ mem.tid ?~ new mem.tid.buoy
302+ %. mem.tid.buoy
303+ ~(int by (malt (turn ~(tap in u.new) (late *(set @)))))
304+ ==
305+ ++ public (curr perm _~) :: Make list of paths public.
306+ ++ secret (curr perm _`~) :: Make list of paths secret.
307+ :: :: Block ships from paths.
308+ ++ block :: No-ops on public paths.
309+ |= [who=(list ship) whence=(list paths)]
310+ ^- (quip card:agent:gall pubs)
311+ %+ perm whence
312+ |= old=(unit (set ship))
313+ ?~ old ~ `(~(dif in u.old) (sy who))
314+ :: :: Allow ships to paths.
315+ ++ allow :: Any public paths will no-op.
316+ |= [who=(list ship) where=(list paths)]
317+ ^- (quip card:agent:gall pubs)
318+ %+ perm where
319+ |= old=(unit (set ship))
320+ ?~ old ~ `(~(gas in u.old) who)
321+ :: :: Kill a list of paths, i.e. tell
322+ ++ kill :: subs to not expect updates.
323+ (curr edit |=(=buoy buoy(tid (latest tid.buoy))))
324+ :: :: Reopen list of killed paths.
325+ ++ read :: See current published states.
326+ ^- (map paths [allowed=(unit (set ship)) =rock:lake])
327+ %- malt %+ murn ~(tap by pub)
328+ |= [path=paths =buoy]
329+ ^- (unit [paths (unit (set ship)) rock:lake])
330+ ?@ tide=tid.buoy ~
331+ :^ ~ path alo.buoy =< rock
332+ =/ snap=[=aeon =rock:lake] (fall (pry:rok rok.tide) *[key val]:rok)
333+ %+ roll (tap:wav (lot:wav wav.tide `aeon.snap ~))
334+ |= [[=aeon =wave:lake] =_snap]
335+ ?. =(aeon +(aeon.snap)) snap
336+ [aeon (wash:lake rock.snap wave)]
337+ ::
338+ ++ apply :: Handle request from subscriber.
339+ |= req=(request:poke paths)
340+ ^- (quip card:agent:gall pubs)
341+ =/ =buoy (~(gut by pub) path.req *buoy)
342+ ?< &(?=(^ alo.buoy) !(~(has in u.alo.buoy) src.bowl))
343+ ?@ tid.buoy
344+ :_ 1/pub :_ ~
345+ (send tomb/~ src.bowl dude.req path.req)
346+ :_ 1/pub :_ ~
347+ =/ last (fall (pry:rok rok.tid.buoy) *[=key =val]:rok)
348+ (send rock/last src.bowl dude.req path.req)
349+ ::
350+ ++ tell
351+ |= [[ship=term =dude aeon=term path=paths] =sign:agent:gall]
352+ ^- (quip card:agent:gall pubs)
353+ ?> ?=(%poke-ack -.sign)
354+ ?^ p.sign `1/pub
355+ =/ =buoy (~(gut by pub) path *buoy)
356+ ?< &(?=(^ alo.buoy) !(~(has in u.alo.buoy) src.bowl))
357+ ?@ tid.buoy
358+ :_ 1/pub :_ ~
359+ (send tomb/~ src.bowl dude path)
360+ ::
361+ => .(aeon +((slav %ud aeon)))
362+ ?^ dat=(get:wav wav.tid.buoy aeon)
363+ :_ 1/pub :_ ~
364+ (send wave/[aeon u.dat] src.bowl dude path)
365+ =/ last (fall (pry:rok rok.tid.buoy) [=key =val]:rok)
366+ ?: (lte aeon key.last)
367+ :_ 1/pub :_ ~
368+ (send rock/last src.bowl dude path)
369+ :- ~
370+ :- %1
371+ %+ ~(put by pub) path
372+ %= buoy
373+ mem.tid (~(put ju mem.tid.buoy) src.bowl dude)
374+ ==
375+ ::
376+ :: Non-public facing arms below
377+ ::
378+ ++ send
379+ |= [payload=_|2:*(response:poke lake paths) =ship =dude path=paths]
380+ ^- card:agent:gall
381+ =* mark (cat 3 %sss- name:lake)
382+ =/ callback=^path
383+ ?: ?=(%tomb what.payload) (zoom tomb-response/(scot %p ship)^dude^path)
384+ (zoom scry-response/(scot %p ship)^dude^(scot %ud aeon.payload)^path)
385+ :* %pass callback
386+ %agent [ship dude]
387+ %poke mark result-type ^- (response:poke lake paths)
388+ [path dap.bowl payload]
389+ ==
390+ ++ latest
391+ |= =$@(aeon tide)
392+ ^- aeon
393+ ?@ tide tide
394+ %+ max (fall (bind (pry:rok rok.tide) head) 0)
395+ (fall (bind (ram:wav wav.tide) head) 0)
396+ ::
397+ ++ edit
398+ |= [ps=(list paths) edit=$-(buoy buoy)]
399+ ^- (quip card:agent:gall pubs)
400+ %- ~(rep in (sy ps))
401+ |= [path=paths caz=(list card:agent:gall) %1 =_pub]
402+ ?~ old=(~(get by pub) path) [caz 1/pub]
403+ =/ new=buoy (edit u.old)
404+ :_ 1/(~(put by pub) path new)
405+ %- weld :_ caz
406+ ^- (list card:agent:gall)
407+ ?@ tid.u.old ~
408+ ?@ tid.new
409+ %- zing
410+ %+ turn ~(tap by mem.tid.u.old)
411+ |= [=ship =(set dude)]
412+ (turn ~(tap in set) |=(=dude (send tomb/~ ship dude path)))
413+ ?~ alo.new ~
414+ =/ new-alo=(jug ship dude)
415+ (malt (turn ~(tap in u.alo.new) (late *(set @))))
416+ %- zing
417+ %+ turn ~(tap by (~(dif by mem.tid.u.old) new-alo))
418+ |= [=ship =(set dude)]
419+ (turn ~(tap in set) |=(=dude (send tomb/~ ship dude path)))
420+ ::
421+ ++ form
422+ |= =tide
423+ ^+ tide
424+ =/ max-rock=[=aeon =rock:lake] (fall (pry:rok rok.tide) *[key val]:rok)
425+ =/ max-wave (fall (bind (ram:wav wav.tide) head) 0)
426+ =? rok.tide :: Create new rock.
427+ ?& !=(frequency.rul.tide 0)
428+ (gte max-wave (add aeon.max-rock frequency.rul.tide))
429+ ==
430+ %+ put:rok rok.tide
431+ %+ roll (tab:wav wav.tide `aeon.max-rock max-wave)
432+ |: [*[now=aeon =wave:lake] `[prev=aeon =rock:lake]`max-rock]
433+ ~| %aeon-awry
434+ ?> =(now +(prev))
435+ [now (wash:lake rock wave)]
436+ =. rok.tide
437+ ?~ horizon.rul.tide :: Only keep genesis and latest.
438+ (gas:rok ~ (murn ~[(ram:rok rok.tide) (pry:rok rok.tide)] same))
439+ %^ lot:rok rok.tide :: Delete beyond horizon.
440+ ~
441+ (mole |.((sub max-wave (max [u.horizon frequency]:rul.tide))))
442+ ~| %rock-zero
443+ tide(wav (lot:wav wav.tide (bind (ram:rok rok.tide) |=([r=@ *] (dec r))) ~))
444+ --
445+--
base-desk/lib/story.hoonnew file+88
@@ -0,0 +1,88 @@
1+/- *story
2+!:
3+^?
4+|%
5+:: XX generalize move to hoon.hoon
6+++ dif-ju
7+ |= [a=story b=story]
8+ ^- story
9+ :: if 0 is the empty set,
10+ :: a \ 0 = a
11+ :: 0 \ b = 0 :: anything in 0 but not in b is by definition 0
12+ ::
13+ ?: =(~ a) ~
14+ :: uno := (a-b) + (merged items in both a and b) + (b-a)
15+ :: ret := (a-b) + (merged items in both a and b)
16+ :: ret = (~(int by a) uno) :: preserve only the entries whose keys are in a
17+ =/ uno=story
18+ %- (~(uno by a) b)
19+ |= [k=tako:clay proses-a=proses proses-b=proses]
20+ ^- proses
21+ (~(dif in proses-a) proses-b)
22+ ::
23+ =/ ret=story (~(int by a) uno)
24+ :: normalizing step, remove any keys with null sets,
25+ :: which can occur if proses-a == proses-b above
26+ %- ~(gas by *story)
27+ (skip ~(tap by ret) |=([k=* v=proses] ?=(~ v)))
28+::
29+++ uni-ju
30+ |= [a=story b=story]
31+ ^- story
32+ :: 0 + b = b
33+ ?: =(~ a) b
34+ %- (~(uno by a) b)
35+ |= [k=tako:clay proses-a=proses proses-b=proses]
36+ ^- proses
37+ (~(uni in proses-a) proses-b)
38+::
39+:: Canonical textual representation
40+::
41+++ chapter-to-text
42+ |= [=tako:clay =proses]
43+ ^- wain
44+ :- (crip "commit: {<`@uv`tako>}")
45+ %- zing
46+ %+ join `wain`~['|||']
47+ %+ turn ~(tap in proses)
48+ |= prose
49+ ^- wain
50+ %- to-wain:format
51+ (rap 3 title '\0a\0a' body ~)
52+::
53+:: Parsers
54+::
55+++ parse-commit-hash
56+ ;~ sfix
57+ ;~ pfix (jest 'commit: ')
58+ (cook @uv ;~(pfix (jest '0v') viz:ag))
59+ ==
60+ ::
61+ (just '\0a')
62+ ==
63+::
64+++ parse-title
65+ ;~ sfix
66+ (cook crip (star prn))
67+ (jest '\0a\0a')
68+ ==
69+::
70+++ parse-body
71+ %+ cook of-wain:format
72+ %- star
73+ ;~ less
74+ ;~(pose (jest '|||\0a') (jest '---\0a'))
75+ (cook crip ;~(sfix (star prn) (just '\0a')))
76+ ==
77+::
78+++ parse-prose ;~(plug parse-title parse-body)
79+++ parse-rest-proses (star ;~(pfix (jest '|||\0a') parse-prose))
80+++ parse-proses (cook silt ;~(plug parse-prose parse-rest-proses))
81+++ parse-chapter ;~(plug parse-commit-hash parse-proses)
82+++ parse-story
83+ (cook ~(gas by *story) (star ;~(sfix parse-chapter (jest '---\0a'))))
84+::
85+:: N.B: If conflicting messages are written individually,
86+:: instead of under the same commit, we will overwrite previous entries
87+:: with later ones due to the nature of gas:by.
88+--
base-desk/lib/strand.hoonnew file+1
@@ -0,0 +1 @@
1+rand
base-desk/lib/strandio.hoonnew file+918
@@ -0,0 +1,918 @@
1+/- spider
2+/+ libstrand=strand
3+=, strand=strand:libstrand
4+=, strand-fail=strand-fail:libstrand
5+|%
6+++ send-raw-cards
7+ |= cards=(list =card:agent:gall)
8+ =/ m (strand ,~)
9+ ^- form:m
10+ |= strand-input:strand
11+ [cards %done ~]
12+::
13+++ send-raw-card
14+ |= =card:agent:gall
15+ =/ m (strand ,~)
16+ ^- form:m
17+ (send-raw-cards card ~)
18+::
19+++ ignore
20+ |= tin=strand-input:strand
21+ `[%fail %ignore ~]
22+::
23+++ get-bowl
24+ =/ m (strand ,bowl:strand)
25+ ^- form:m
26+ |= tin=strand-input:strand
27+ `[%done bowl.tin]
28+::
29+++ get-beak
30+ =/ m (strand ,beak)
31+ ^- form:m
32+ |= tin=strand-input:strand
33+ `[%done [our q.byk da+now]:bowl.tin]
34+::
35+++ get-time
36+ =/ m (strand ,@da)
37+ ^- form:m
38+ |= tin=strand-input:strand
39+ `[%done now.bowl.tin]
40+::
41+++ get-our
42+ =/ m (strand ,ship)
43+ ^- form:m
44+ |= tin=strand-input:strand
45+ `[%done our.bowl.tin]
46+::
47+++ get-entropy
48+ =/ m (strand ,@uvJ)
49+ ^- form:m
50+ |= tin=strand-input:strand
51+ `[%done eny.bowl.tin]
52+::
53+:: Convert skips to %ignore failures.
54+::
55+:: This tells the main loop to try the next handler.
56+::
57+++ handle
58+ |* a=mold
59+ =/ m (strand ,a)
60+ |= =form:m
61+ ^- form:m
62+ |= tin=strand-input:strand
63+ =/ res (form tin)
64+ =? next.res ?=(%skip -.next.res)
65+ [%fail %ignore ~]
66+ res
67+::
68+:: Wait for a poke with a particular mark
69+::
70+++ take-poke
71+ |= =mark
72+ =/ m (strand ,vase)
73+ ^- form:m
74+ |= tin=strand-input:strand
75+ ?+ in.tin `[%skip ~]
76+ ~
77+ `[%wait ~]
78+ ::
79+ [~ %poke @ *]
80+ ?. =(mark p.cage.u.in.tin)
81+ `[%skip ~]
82+ `[%done q.cage.u.in.tin]
83+ ==
84+::
85+++ take-sign-arvo
86+ =/ m (strand ,[wire sign-arvo])
87+ ^- form:m
88+ |= tin=strand-input:strand
89+ ?+ in.tin `[%skip ~]
90+ ~
91+ `[%wait ~]
92+ ::
93+ [~ %sign *]
94+ `[%done [wire sign-arvo]:u.in.tin]
95+ ==
96+::
97+:: Wait for a subscription update on a wire
98+::
99+++ take-fact-prefix
100+ |= =wire
101+ =/ m (strand ,[path cage])
102+ ^- form:m
103+ |= tin=strand-input:strand
104+ ?+ in.tin `[%skip ~]
105+ ~ `[%wait ~]
106+ [~ %agent * %fact *]
107+ ?. =(watch+wire (scag +((lent wire)) wire.u.in.tin))
108+ `[%skip ~]
109+ `[%done (slag (lent wire) wire.u.in.tin) cage.sign.u.in.tin]
110+ ==
111+::
112+:: Wait for a subscription update on a wire
113+::
114+++ take-fact
115+ |= =wire
116+ =/ m (strand ,cage)
117+ ^- form:m
118+ |= tin=strand-input:strand
119+ ?+ in.tin `[%skip ~]
120+ ~ `[%wait ~]
121+ [~ %agent * %fact *]
122+ ?. =(watch+wire wire.u.in.tin)
123+ `[%skip ~]
124+ `[%done cage.sign.u.in.tin]
125+ ==
126+::
127+:: Wait for a subscription close
128+::
129+++ take-kick
130+ |= =wire
131+ =/ m (strand ,~)
132+ ^- form:m
133+ |= tin=strand-input:strand
134+ ?+ in.tin `[%skip ~]
135+ ~ `[%wait ~]
136+ [~ %agent * %kick *]
137+ ?. =(watch+wire wire.u.in.tin)
138+ `[%skip ~]
139+ `[%done ~]
140+ ==
141+::
142+++ echo
143+ =/ m (strand ,~)
144+ ^- form:m
145+ %- (main-loop ,~)
146+ :~ |= ~
147+ ^- form:m
148+ ;< =vase bind:m ((handle ,vase) (take-poke %echo))
149+ =/ message=tape !<(tape vase)
150+ %- (slog leaf+"{message}..." ~)
151+ ;< ~ bind:m (sleep ~s2)
152+ %- (slog leaf+"{message}.." ~)
153+ (pure:m ~)
154+ ::
155+ |= ~
156+ ^- form:m
157+ ;< =vase bind:m ((handle ,vase) (take-poke %over))
158+ %- (slog leaf+"over..." ~)
159+ (pure:m ~)
160+ ==
161+::
162+++ take-watch
163+ =/ m (strand ,path)
164+ |= tin=strand-input:strand
165+ ?+ in.tin `[%skip ~]
166+ ~ `[%wait ~]
167+ [~ %watch *]
168+ `[%done path.u.in.tin]
169+ ==
170+::
171+++ take-wake
172+ |= until=(unit @da)
173+ =/ m (strand ,~)
174+ ^- form:m
175+ |= tin=strand-input:strand
176+ ?+ in.tin `[%skip ~]
177+ ~ `[%wait ~]
178+ [~ %sign [%wait @ ~] %behn %wake *]
179+ ?. |(?=(~ until) =(`u.until (slaw %da i.t.wire.u.in.tin)))
180+ `[%skip ~]
181+ ?~ error.sign-arvo.u.in.tin
182+ `[%done ~]
183+ `[%fail %timer-error u.error.sign-arvo.u.in.tin]
184+ ==
185+++ take-whey
186+ |= =wire
187+ =/ m (strand ,[spar:ames fragment-size=@ud num-fragments=@ud])
188+ ^- form:m
189+ |= tin=strand-input:strand
190+ ?+ in.tin `[%skip ~]
191+ ~ `[%wait ~]
192+ ::
193+ [~ %sign * %ames %sage sage=*]
194+ ?. =(wire wire.u.in.tin)
195+ `[%skip ~]
196+ =/ =sage:mess:ames sage.sign-arvo.u.in.tin
197+ :^ ~ %done spar=p.sage
198+ ?~ q.sage
199+ [boq=13 tot=0]
200+ =< [boq tot]
201+ ;;([%whey boq=@ud tot=@ud] q.sage)
202+ ==
203+::
204+++ take-sage
205+ |= =wire
206+ =/ m (strand ,sage:mess:ames)
207+ ^- form:m
208+ |= tin=strand-input:strand
209+ ?+ in.tin `[%skip ~]
210+ ~ `[%wait ~]
211+ ::
212+ [~ %sign * %ames %sage sage=*]
213+ ?. =(wire wire.u.in.tin)
214+ `[%skip ~]
215+ `[%done sage.sign-arvo.u.in.tin]
216+ ==
217+:: XX deprecate in 409k
218+::
219+++ take-near
220+ |= =wire
221+ =/ m (strand ,[spar:ames (unit (unit page))])
222+ ^- form:m
223+ |= tin=strand-input:strand
224+ ?+ in.tin `[%skip ~]
225+ ~ `[%wait ~]
226+ ::
227+ [~ %sign * %ames %near ^ *]
228+ ?. =(wire wire.u.in.tin)
229+ `[%skip ~]
230+ `[%done +>.sign-arvo.u.in.tin]
231+ ==
232+::
233+++ take-poke-ack
234+ |= =wire
235+ =/ m (strand ,~)
236+ ^- form:m
237+ |= tin=strand-input:strand
238+ ?+ in.tin `[%skip ~]
239+ ~ `[%wait ~]
240+ [~ %agent * %poke-ack *]
241+ ?. =(wire wire.u.in.tin)
242+ `[%skip ~]
243+ ?~ p.sign.u.in.tin
244+ `[%done ~]
245+ `[%fail %poke-fail u.p.sign.u.in.tin]
246+ ==
247+::
248+++ take-watch-ack
249+ |= =wire
250+ =/ m (strand ,~)
251+ ^- form:m
252+ |= tin=strand-input:strand
253+ ?+ in.tin `[%skip ~]
254+ ~ `[%wait ~]
255+ [~ %agent * %watch-ack *]
256+ ?. =(watch+wire wire.u.in.tin)
257+ `[%skip ~]
258+ ?~ p.sign.u.in.tin
259+ `[%done ~]
260+ `[%fail %watch-ack-fail u.p.sign.u.in.tin]
261+ ==
262+::
263+++ poke
264+ |= [=dock =cage]
265+ =/ m (strand ,~)
266+ ^- form:m
267+ =/ =card:agent:gall [%pass /poke %agent dock %poke cage]
268+ ;< ~ bind:m (send-raw-card card)
269+ (take-poke-ack /poke)
270+::
271+++ raw-poke
272+ |= [=dock =cage]
273+ =/ m (strand ,~)
274+ ^- form:m
275+ =/ =card:agent:gall [%pass /poke %agent dock %poke cage]
276+ ;< ~ bind:m (send-raw-card card)
277+ =/ m (strand ,~)
278+ ^- form:m
279+ |= tin=strand-input:strand
280+ ?+ in.tin `[%skip ~]
281+ ~
282+ `[%wait ~]
283+ ::
284+ [~ %agent * %poke-ack *]
285+ ?. =(/poke wire.u.in.tin)
286+ `[%skip ~]
287+ `[%done ~]
288+ ==
289+::
290+++ raw-poke-our
291+ |= [app=term =cage]
292+ =/ m (strand ,~)
293+ ^- form:m
294+ ;< =bowl:spider bind:m get-bowl
295+ (raw-poke [our.bowl app] cage)
296+::
297+++ poke-our
298+ |= [=term =cage]
299+ =/ m (strand ,~)
300+ ^- form:m
301+ ;< our=@p bind:m get-our
302+ (poke [our term] cage)
303+::
304+++ watch
305+ |= [=wire =dock =path]
306+ =/ m (strand ,~)
307+ ^- form:m
308+ =/ =card:agent:gall [%pass watch+wire %agent dock %watch path]
309+ ;< ~ bind:m (send-raw-card card)
310+ (take-watch-ack wire)
311+::
312+++ watch-one
313+ |= [=wire =dock =path]
314+ =/ m (strand ,cage)
315+ ^- form:m
316+ ;< ~ bind:m (watch wire dock path)
317+ ;< =cage bind:m (take-fact wire)
318+ ;< ~ bind:m (take-kick wire)
319+ (pure:m cage)
320+::
321+++ watch-our
322+ |= [=wire =term =path]
323+ =/ m (strand ,~)
324+ ^- form:m
325+ ;< our=@p bind:m get-our
326+ (watch wire [our term] path)
327+::
328+++ scry
329+ |* [=mold =path]
330+ =/ m (strand ,mold)
331+ ^- form:m
332+ ?> ?=(^ path)
333+ ?> ?=(^ t.path)
334+ ;< =bowl:spider bind:m get-bowl
335+ %- pure:m
336+ .^(mold i.path (scot %p our.bowl) i.t.path (scot %da now.bowl) t.t.path)
337+::
338+++ leave
339+ |= [=wire =dock]
340+ =/ m (strand ,~)
341+ ^- form:m
342+ =/ =card:agent:gall [%pass watch+wire %agent dock %leave ~]
343+ (send-raw-card card)
344+::
345+++ leave-our
346+ |= [=wire =term]
347+ =/ m (strand ,~)
348+ ^- form:m
349+ ;< our=@p bind:m get-our
350+ (leave wire [our term])
351+::
352+++ rewatch
353+ |= [=wire =dock =path]
354+ =/ m (strand ,~)
355+ ;< ~ bind:m ((handle ,~) (take-kick wire))
356+ ;< ~ bind:m (flog-text "rewatching {<dock>} {<path>}")
357+ ;< ~ bind:m (watch wire dock path)
358+ (pure:m ~)
359+::
360+++ wait
361+ |= until=@da
362+ =/ m (strand ,~)
363+ ^- form:m
364+ ;< ~ bind:m (send-wait until)
365+ (take-wake `until)
366+::
367+++ mass
368+ =/ m (strand ,(list quac:dill))
369+ ^- form:m
370+ =/ =card:agent:gall [%pass /mass %arvo %d %mass ~]
371+ ;< ~ bind:m (send-raw-card card)
372+ ;< quz=(list quac:dill) bind:m take-meme
373+ (pure:m quz)
374+::
375+++ take-meme
376+ =/ m (strand ,(list quac:dill))
377+ ^- form:m
378+ |= tin=strand-input:strand
379+ ?+ in.tin `[%skip ~]
380+ ~ `[%wait ~]
381+ [~ %sign [%mass ~] %dill %meme *]
382+ `[%done p.sign-arvo.u.in.tin]
383+ ==
384+::
385+++ keen
386+ |= [=wire =spar:ames sec=(unit [@ @])]
387+ =/ m (strand ,~)
388+ ^- form:m
389+ (send-raw-card %pass wire %arvo %a %keen sec spar)
390+::
391+++ chum
392+ |= [=wire =spar:ames]
393+ =/ m (strand ,~)
394+ ^- form:m
395+ (send-raw-card %pass wire %arvo %a %chum spar)
396+::
397+++ keen-shut
398+ |= [=wire =spar:ames]
399+ =/ m (strand ,~)
400+ ^- form:m
401+ (send-raw-card %pass wire %keen & spar)
402+::
403+++ yawn
404+ |= [=wire =spar:ames]
405+ =/ m (strand ,~)
406+ ^- form:m
407+ (send-raw-card %pass wire %arvo %a %yawn spar)
408+::
409+++ whey
410+ |= [=wire boq=@ud =spar:ames]
411+ =/ m (strand ,~)
412+ ^- form:m
413+ :: encrypted using %chum namespace
414+ ::
415+ ;< our=@p bind:m get-our
416+ =. path.spar
417+ [%a %x '1' %$ %whey (scot %ud boq) (scot %p our) path.spar]
418+ (chum wire spar)
419+::
420+++ meta
421+ |= [=wire =spar:ames]
422+ =/ m (strand ,~)
423+ ^- form:m
424+ ?+ path.spar !!
425+ $% [%ames bone=@ %cork ~]
426+ [%ames bone=@ %sent seq=@ ~]
427+ [%flow bone=@ =dire:ames %cork ~]
428+ [?(%ames %flow) bone=@ =dire:ames ?(%sent %loads %naxp %acked) seq=@ ~]
429+ ==
430+ :: encrypted using %chum namespace
431+ ::
432+ ;< our=@p bind:m get-our
433+ %- send-raw-card
434+ :* %pass wire %arvo %a %chum
435+ spar(path [%a %x '1' %$ %meta (scot %p our) path.spar])
436+ ==
437+ ==
438+::
439+++ sleep
440+ |= for=@dr
441+ =/ m (strand ,~)
442+ ^- form:m
443+ ;< now=@da bind:m get-time
444+ (wait (add now for))
445+::
446+++ send-wait
447+ |= until=@da
448+ =/ m (strand ,~)
449+ ^- form:m
450+ =/ =card:agent:gall
451+ [%pass /wait/(scot %da until) %arvo %b %wait until]
452+ (send-raw-card card)
453+::
454+++ map-err
455+ |* computation-result=mold
456+ =/ m (strand ,computation-result)
457+ |= [f=$-([term tang] [term tang]) computation=form:m]
458+ ^- form:m
459+ |= tin=strand-input:strand
460+ =* loop $
461+ =/ c-res (computation tin)
462+ ?: ?=(%cont -.next.c-res)
463+ c-res(self.next ..loop(computation self.next.c-res))
464+ ?. ?=(%fail -.next.c-res)
465+ c-res
466+ c-res(err.next (f err.next.c-res))
467+::
468+++ set-timeout
469+ |* computation-result=mold
470+ =/ m (strand ,computation-result)
471+ |= [time=@dr computation=form:m]
472+ ^- form:m
473+ ;< now=@da bind:m get-time
474+ =/ when (add now time)
475+ =/ =card:agent:gall
476+ [%pass /timeout/(scot %da when) %arvo %b %wait when]
477+ ;< ~ bind:m (send-raw-card card)
478+ |= tin=strand-input:strand
479+ =* loop $
480+ ?: ?& ?=([~ %sign [%timeout @ ~] %behn %wake *] in.tin)
481+ =((scot %da when) i.t.wire.u.in.tin)
482+ ==
483+ `[%fail %timeout ~]
484+ =/ c-res (computation tin)
485+ ?: ?=(%cont -.next.c-res)
486+ c-res(self.next ..loop(computation self.next.c-res))
487+ ?: ?=(%done -.next.c-res)
488+ =/ =card:agent:gall
489+ [%pass /timeout/(scot %da when) %arvo %b %rest when]
490+ c-res(cards [card cards.c-res])
491+ c-res
492+::
493+++ send-request
494+ |= =request:http
495+ =/ m (strand ,~)
496+ ^- form:m
497+ (send-raw-card %pass /request %arvo %i %request request *outbound-config:iris)
498+::
499+++ send-cancel-request
500+ =/ m (strand ,~)
501+ ^- form:m
502+ (send-raw-card %pass /request %arvo %i %cancel-request ~)
503+::
504+++ take-client-response
505+ =/ m (strand ,client-response:iris)
506+ ^- form:m
507+ |= tin=strand-input:strand
508+ ?+ in.tin `[%skip ~]
509+ ~ `[%wait ~]
510+ ::
511+ [~ %sign [%request ~] %iris %http-response %cancel *]
512+ ::NOTE iris does not (yet?) retry after cancel, so it means failure
513+ :- ~
514+ :+ %fail
515+ %http-request-cancelled
516+ ['http request was cancelled by the runtime']~
517+ ::
518+ [~ %sign [%request ~] %iris %http-response %finished *]
519+ `[%done client-response.sign-arvo.u.in.tin]
520+ ==
521+::
522+:: Wait until we get an HTTP response or cancelation and unset contract
523+::
524+++ take-maybe-sigh
525+ =/ m (strand ,(unit httr:eyre))
526+ ^- form:m
527+ ;< rep=(unit client-response:iris) bind:m
528+ take-maybe-response
529+ ?~ rep
530+ (pure:m ~)
531+ :: XX s/b impossible
532+ ::
533+ ?. ?=(%finished -.u.rep)
534+ (pure:m ~)
535+ (pure:m (some (to-httr:iris +.u.rep)))
536+::
537+++ take-maybe-response
538+ =/ m (strand ,(unit client-response:iris))
539+ ^- form:m
540+ |= tin=strand-input:strand
541+ ?+ in.tin `[%skip ~]
542+ ~ `[%wait ~]
543+ [~ %sign [%request ~] %iris %http-response %cancel *]
544+ `[%done ~]
545+ [~ %sign [%request ~] %iris %http-response %finished *]
546+ `[%done `client-response.sign-arvo.u.in.tin]
547+ ==
548+::
549+++ extract-body
550+ |= =client-response:iris
551+ =/ m (strand ,cord)
552+ ^- form:m
553+ ?> ?=(%finished -.client-response)
554+ %- pure:m
555+ ?~ full-file.client-response ''
556+ q.data.u.full-file.client-response
557+::
558+++ fetch-cord
559+ |= url=tape
560+ =/ m (strand ,cord)
561+ ^- form:m
562+ =/ =request:http [%'GET' (crip url) ~ ~]
563+ ;< ~ bind:m (send-request request)
564+ ;< =client-response:iris bind:m take-client-response
565+ (extract-body client-response)
566+::
567+++ fetch-json
568+ |= url=tape
569+ =/ m (strand ,json)
570+ ^- form:m
571+ ;< =cord bind:m (fetch-cord url)
572+ =/ json=(unit json) (de:json:html cord)
573+ ?~ json
574+ (strand-fail %json-parse-error ~)
575+ (pure:m u.json)
576+::
577+++ hiss-request
578+ |= =hiss:eyre
579+ =/ m (strand ,(unit httr:eyre))
580+ ^- form:m
581+ ;< ~ bind:m (send-request (hiss-to-request:html hiss))
582+ take-maybe-sigh
583+::
584+:: +build-file: build the source file at the specified $beam
585+::
586+++ build-file
587+ |= [[=ship =desk =case] =spur]
588+ =* arg +<
589+ =/ m (strand ,(unit vase))
590+ ^- form:m
591+ ;< =riot:clay bind:m
592+ (warp ship desk ~ %sing %a case spur)
593+ ?~ riot
594+ (pure:m ~)
595+ ?> =(%vase p.r.u.riot)
596+ (pure:m (some !<(vase q.r.u.riot)))
597+::
598+++ build-file-hard
599+ |= [[=ship =desk =case] =spur]
600+ =* arg +<
601+ =/ m (strand ,vase)
602+ ^- form:m
603+ ;< =riot:clay
604+ bind:m
605+ (warp ship desk ~ %sing %a case spur)
606+ ?> ?=(^ riot)
607+ ?> ?=(%vase p.r.u.riot)
608+ (pure:m !<(vase q.r.u.riot))
609+:: +build-mark: build a mark definition to a $dais
610+::
611+++ build-mark
612+ |= [[=ship =desk =case] mak=mark]
613+ =* arg +<
614+ =/ m (strand ,dais:clay)
615+ ^- form:m
616+ ;< =riot:clay bind:m
617+ (warp ship desk ~ %sing %b case /[mak])
618+ ?~ riot
619+ (strand-fail %build-mark >arg< ~)
620+ ?> =(%dais p.r.u.riot)
621+ (pure:m !<(dais:clay q.r.u.riot))
622+:: +build-tube: build a mark conversion gate ($tube)
623+::
624+++ build-tube
625+ |= [[=ship =desk =case] =mars:clay]
626+ =* arg +<
627+ =/ m (strand ,tube:clay)
628+ ^- form:m
629+ ;< =riot:clay bind:m
630+ (warp ship desk ~ %sing %c case /[a.mars]/[b.mars])
631+ ?~ riot
632+ (strand-fail %build-tube >arg< ~)
633+ ?> =(%tube p.r.u.riot)
634+ (pure:m !<(tube:clay q.r.u.riot))
635+::
636+:: +build-nave: build a mark definition to a $nave
637+::
638+++ build-nave
639+ |= [[=ship =desk =case] mak=mark]
640+ =* arg +<
641+ =/ m (strand ,vase)
642+ ^- form:m
643+ ;< =riot:clay bind:m
644+ (warp ship desk ~ %sing %e case /[mak])
645+ ?~ riot
646+ (strand-fail %build-nave >arg< ~)
647+ ?> =(%nave p.r.u.riot)
648+ (pure:m q.r.u.riot)
649+:: +build-cast: build a mark conversion gate (static)
650+::
651+++ build-cast
652+ |= [[=ship =desk =case] =mars:clay]
653+ =* arg +<
654+ =/ m (strand ,vase)
655+ ^- form:m
656+ ;< =riot:clay bind:m
657+ (warp ship desk ~ %sing %f case /[a.mars]/[b.mars])
658+ ?~ riot
659+ (strand-fail %build-cast >arg< ~)
660+ ?> =(%cast p.r.u.riot)
661+ (pure:m q.r.u.riot)
662+::
663+:: Read from Clay
664+::
665+++ warp
666+ |= [=ship =riff:clay]
667+ =/ m (strand ,riot:clay)
668+ ;< ~ bind:m (send-raw-card %pass /warp %arvo %c %warp ship riff)
669+ (take-writ /warp)
670+::
671+++ read-file
672+ |= [[=ship =desk =case] =spur]
673+ =* arg +<
674+ =/ m (strand ,cage)
675+ ;< =riot:clay bind:m (warp ship desk ~ %sing %x case spur)
676+ ?~ riot
677+ (strand-fail %read-file >arg< ~)
678+ (pure:m r.u.riot)
679+::
680+++ check-for-file
681+ |= [[=ship =desk =case] =spur]
682+ =/ m (strand ,?)
683+ ;< =riot:clay bind:m (warp ship desk ~ %sing %u case spur)
684+ ?> ?=(^ riot)
685+ (pure:m !<(? q.r.u.riot))
686+::
687+++ list-tree
688+ |= [[=ship =desk =case] =spur]
689+ =* arg +<
690+ =/ m (strand ,(list path))
691+ ;< =riot:clay bind:m (warp ship desk ~ %sing %t case spur)
692+ ?~ riot
693+ (strand-fail %list-tree >arg< ~)
694+ (pure:m !<((list path) q.r.u.riot))
695+::
696+++ list-desk
697+ |= [[=ship =desk =case] =spur]
698+ =* arg +<
699+ =/ m (strand arch)
700+ ;< =riot:clay bind:m (warp ship desk ~ %sing %y case spur)
701+ ?~ riot
702+ (strand-fail %list-desk >arg< ~)
703+ (pure:m !<(arch q.r.u.riot))
704+:: Take Clay read result
705+::
706+++ take-writ
707+ |= =wire
708+ =/ m (strand ,riot:clay)
709+ ^- form:m
710+ |= tin=strand-input:strand
711+ ?+ in.tin `[%skip ~]
712+ ~ `[%wait ~]
713+ [~ %sign * ?(%behn %clay) %writ *]
714+ ?. =(wire wire.u.in.tin)
715+ `[%skip ~]
716+ `[%done +>.sign-arvo.u.in.tin]
717+ ==
718+:: +check-online: require that peer respond before timeout
719+::
720+++ check-online
721+ |= [who=ship lag=@dr]
722+ =/ m (strand ,~)
723+ ^- form:m
724+ %+ (map-err ,~) |=(* [%offline *tang])
725+ %+ (set-timeout ,~) lag
726+ ;< ~ bind:m
727+ (poke [who %hood] %helm-hi !>(~))
728+ (pure:m ~)
729+::
730+++ eval-hoon
731+ |= [gen=hoon bez=(list beam)]
732+ =/ m (strand ,vase)
733+ ^- form:m
734+ =/ sut=vase !>(..zuse)
735+ |-
736+ ?~ bez
737+ (pure:m (slap sut gen))
738+ ;< vax=vase bind:m (build-file-hard i.bez)
739+ $(bez t.bez, sut (slop vax sut))
740+::
741+++ send-thread
742+ |= [=bear:khan =shed:khan =wire]
743+ =/ m (strand ,~)
744+ ^- form:m
745+ (send-raw-card %pass wire %arvo %k %lard bear shed)
746+::
747+:: Queue on skip, try next on fail %ignore
748+::
749+++ main-loop
750+ |* a=mold
751+ =/ m (strand ,~)
752+ =/ m-a (strand ,a)
753+ =| queue=(qeu (unit input:strand))
754+ =| active=(unit [in=(unit input:strand) =form:m-a forms=(list $-(a form:m-a))])
755+ =| state=a
756+ |= forms=(lest $-(a form:m-a))
757+ ^- form:m
758+ |= tin=strand-input:strand
759+ =* top `form:m`..$
760+ =. queue (~(put to queue) in.tin)
761+ |^ (continue bowl.tin)
762+ ::
763+ ++ continue
764+ |= =bowl:strand
765+ ^- output:m
766+ ?> =(~ active)
767+ ?: =(~ queue)
768+ `[%cont top]
769+ =^ in=(unit input:strand) queue ~(get to queue)
770+ ^- output:m
771+ =. active `[in (i.forms state) t.forms]
772+ ^- output:m
773+ (run bowl in)
774+ ::
775+ ++ run
776+ ^- form:m
777+ |= tin=strand-input:strand
778+ ^- output:m
779+ ?> ?=(^ active)
780+ =/ res (form.u.active tin)
781+ =/ =output:m
782+ ?- -.next.res
783+ %wait `[%wait ~]
784+ %skip `[%cont ..$(queue (~(put to queue) in.tin))]
785+ %cont `[%cont ..$(active `[in.u.active self.next.res forms.u.active])]
786+ %done (continue(active ~, state value.next.res) bowl.tin)
787+ %fail
788+ ?: &(?=(^ forms.u.active) ?=(%ignore p.err.next.res))
789+ %= $
790+ active `[in.u.active (i.forms.u.active state) t.forms.u.active]
791+ in.tin in.u.active
792+ ==
793+ `[%fail err.next.res]
794+ ==
795+ [(weld cards.res cards.output) next.output]
796+ --
797+::
798+++ retry
799+ |* result=mold
800+ |= [crash-after=(unit @ud) computation=_*form:(strand (unit result))]
801+ =/ m (strand ,result)
802+ =| try=@ud
803+ |- ^- form:m
804+ =* loop $
805+ ?: =(crash-after `try)
806+ (strand-fail %retry-too-many ~)
807+ ;< ~ bind:m (backoff try ~m1)
808+ ;< res=(unit result) bind:m computation
809+ ?^ res
810+ (pure:m u.res)
811+ loop(try +(try))
812+::
813+++ backoff
814+ |= [try=@ud limit=@dr]
815+ =/ m (strand ,~)
816+ ^- form:m
817+ ;< eny=@uvJ bind:m get-entropy
818+ %- sleep
819+ %+ min limit
820+ ?: =(0 try) ~s0
821+ %+ add
822+ (mul ~s1 (bex (dec try)))
823+ (mul ~s0..0001 (~(rad og eny) 1.000))
824+::
825+:: ----
826+::
827+:: Output
828+::
829+++ flog
830+ |= =flog:dill
831+ =/ m (strand ,~)
832+ ^- form:m
833+ (send-raw-card %pass / %arvo %d %flog flog)
834+::
835+++ flog-text
836+ |= =tape
837+ =/ m (strand ,~)
838+ ^- form:m
839+ (flog %text tape)
840+::
841+++ flog-tang
842+ |= =tang
843+ =/ m (strand ,~)
844+ ^- form:m
845+ =/ =wall
846+ (zing (turn (flop tang) (cury wash [0 80])))
847+ |- ^- form:m
848+ =* loop $
849+ ?~ wall
850+ (pure:m ~)
851+ ;< ~ bind:m (flog-text i.wall)
852+ loop(wall t.wall)
853+::
854+++ trace
855+ |= =tang
856+ =/ m (strand ,~)
857+ ^- form:m
858+ (pure:m ((slog tang) ~))
859+::
860+++ app-message
861+ |= [app=term =cord =tang]
862+ =/ m (strand ,~)
863+ ^- form:m
864+ =/ msg=tape :(weld (trip app) ": " (trip cord))
865+ ;< ~ bind:m (flog-text msg)
866+ (flog-tang tang)
867+::
868+:: ----
869+::
870+:: Handle domains
871+::
872+++ install-domain
873+ |= =turf
874+ =/ m (strand ,~)
875+ ^- form:m
876+ (send-raw-card %pass / %arvo %e %rule %turf %put turf)
877+::
878+:: ----
879+::
880+:: Threads
881+::
882+++ start-thread
883+ |= file=term
884+ =/ m (strand ,tid:spider)
885+ ;< =bowl:spider bind:m get-bowl
886+ (start-thread-with-args byk.bowl file *vase)
887+::
888+++ start-thread-with-args
889+ |= [=beak file=term args=vase]
890+ =/ m (strand ,tid:spider)
891+ ^- form:m
892+ ;< =bowl:spider bind:m get-bowl
893+ =/ tid
894+ (scot %ta (cat 3 (cat 3 'strand_' file) (scot %uv (sham file eny.bowl))))
895+ =/ poke-vase !>(`start-args:spider`[`tid.bowl `tid beak file args])
896+ ;< ~ bind:m (poke-our %spider %spider-start poke-vase)
897+ ;< ~ bind:m (sleep ~s0) :: wait for thread to start
898+ (pure:m tid)
899+::
900++$ thread-result
901+ (each vase [term tang])
902+::
903+++ await-thread
904+ |= [file=term args=vase]
905+ =/ m (strand ,thread-result)
906+ ^- form:m
907+ ;< =bowl:spider bind:m get-bowl
908+ =/ tid (scot %ta (cat 3 'strand_' (scot %uv (sham file eny.bowl))))
909+ =/ poke-vase !>(`start-args:spider`[`tid.bowl `tid byk.bowl file args])
910+ ;< ~ bind:m (watch-our /awaiting/[tid] %spider /thread-result/[tid])
911+ ;< ~ bind:m (poke-our %spider %spider-start poke-vase)
912+ ;< =cage bind:m (take-fact /awaiting/[tid])
913+ ;< ~ bind:m (take-kick /awaiting/[tid])
914+ ?+ p.cage ~|([%strange-thread-result p.cage file tid] !!)
915+ %thread-done (pure:m %& q.cage)
916+ %thread-fail (pure:m %| !<([term tang] q.cage))
917+ ==
918+--
base-desk/lib/test.hoonnew file+103
@@ -0,0 +1,103 @@
1+:: testing utilities meant to be directly used from files in %/tests
2+::
3+|%
4+:: +expect-eq: compares :expected and :actual and pretty-prints the result
5+::
6+++ expect-eq
7+ |= [expected=vase actual=vase]
8+ ^- tang
9+ ::
10+ =| result=tang
11+ ::
12+ =? result !=(q.expected q.actual)
13+ %+ weld result
14+ ^- tang
15+ :~ [%palm [": " ~ ~ ~] [leaf+"expected" (sell expected) ~]]
16+ [%palm [": " ~ ~ ~] [leaf+"actual " (sell actual) ~]]
17+ ==
18+ ::
19+ =? result !(~(nest ut p.actual) | p.expected)
20+ %+ weld result
21+ ^- tang
22+ :~ :+ %palm [": " ~ ~ ~]
23+ :~ [%leaf "failed to nest"]
24+ (~(dunk ut p.actual) %actual)
25+ (~(dunk ut p.expected) %expected)
26+ == ==
27+ result
28+:: +expect: compares :actual to %.y and pretty-prints anything else
29+::
30+++ expect
31+ |= actual=vase
32+ (expect-eq !>(%.y) actual)
33+:: +expect-fail: kicks a trap, expecting crash. pretty-prints if succeeds
34+::
35+++ expect-fail
36+ |= a=(trap)
37+ ^- tang
38+ =/ b (mule a)
39+ ?- -.b
40+ %| ~
41+ %& ['expected failure - succeeded' ~]
42+ ==
43+:: +expect-success: kicks a trap, expecting success; returns trace on failure
44+::
45+++ expect-success
46+ |= a=(trap)
47+ ^- tang
48+ =/ b (mule a)
49+ ?- -.b
50+ %& ~
51+ %| ['expected success - failed' p.b]
52+ ==
53+::
54+:: +expect-fail-message: kicks a trap, expecting crash, compares the resulting error message
55+++ expect-fail-message
56+ |= [msg=@t a=(trap)]
57+ ^- tang
58+ =/ b (mule a)
59+ ?- -.b
60+ %| |^
61+ =/ =tang (flatten +.b)
62+ ?: ?=(^ (find (trip msg) tang))
63+ ~
64+ ['expected error message - not found' ~]
65+ ++ flatten
66+ |= tang=(list tank)
67+ =| res=tape
68+ |- ^- tape
69+ ?~ tang res
70+ $(tang t.tang, res (weld ~(ram re i.tang) res))
71+ --
72+ %& ['expected failure - succeeded' ~]
73+ ==
74+:: $a-test-chain: a sequence of tests to be run
75+::
76+:: NB: arms shouldn't start with `test-` so that `-test % ~` runs
77+::
78++$ a-test-chain
79+ $_
80+ |?
81+ ?: =(0 0)
82+ [%& p=*tang]
83+ [%| p=[tang=*tang next=^?(..$)]]
84+:: +run-chain: run a sequence of tests, stopping at first failure
85+::
86+++ run-chain
87+ |= seq=a-test-chain
88+ ^- tang
89+ =/ res $:seq
90+ ?- -.res
91+ %& p.res
92+ %| ?. =(~ tang.p.res)
93+ tang.p.res
94+ $(seq next.p.res)
95+ ==
96+:: +category: prepends a name to an error result; passes successes unchanged
97+::
98+++ category
99+ |= [a=tape b=tang] ^- tang
100+ ?: =(~ b) ~ :: test OK
101+ :- leaf+"in: '{a}'"
102+ (turn b |=(c=tank rose+[~ " " ~]^~[c]))
103+--
base-desk/lib/tiny.hoonnew file+670
@@ -0,0 +1,670 @@
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+--
base-desk/lib/verb.hoonnew file+182
@@ -0,0 +1,182 @@
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 |.("{<dap.bowl>}: on-init"))
16+ =^ cards agent on-init:ag
17+ :_ this
18+ :_ :_ cards
19+ (emit-event %on-init ~)
20+ (emit-event-plus bowl [%on-init ~] cards)
21+::
22+++ on-save
23+ ^- vase
24+ %- (print bowl |.("{<dap.bowl>}: on-save"))
25+ on-save:ag
26+::
27+++ on-load
28+ |= old-state=vase
29+ ^- (quip card:agent:gall agent:gall)
30+ %- (print bowl |.("{<dap.bowl>}: on-load"))
31+ =^ cards agent (on-load:ag old-state)
32+ :_ this
33+ :_ :_ cards
34+ (emit-event %on-load ~)
35+ (emit-event-plus bowl [%on-load ~] cards)
36+::
37+++ on-poke
38+ |= [=mark =vase]
39+ ^- (quip card:agent:gall agent:gall)
40+ %- (print bowl |.("{<dap.bowl>}: on-poke with mark {<mark>}"))
41+ ?: ?=(%verb mark)
42+ ?- !<(?(%loud %bowl) vase)
43+ %loud `this(loud !loud)
44+ %bowl `this(bowl-print !bowl-print)
45+ ==
46+ =^ cards agent (on-poke:ag mark vase)
47+ :_ this
48+ :_ :_ cards
49+ (emit-event %on-poke mark)
50+ (emit-event-plus bowl [%on-poke mark (mug q.vase)] cards)
51+::
52+++ on-watch
53+ |= =path
54+ ^- (quip card:agent:gall agent:gall)
55+ %- (print bowl |.("{<dap.bowl>}: on-watch on path {<path>}"))
56+ =^ cards agent
57+ ?: ?=([%verb ?(%events %events-plus) ~] path)
58+ [~ agent]
59+ (on-watch:ag path)
60+ :_ this
61+ :_ :_ cards
62+ (emit-event %on-watch path)
63+ (emit-event-plus bowl [%on-watch path] cards)
64+::
65+++ on-leave
66+ |= =path
67+ ^- (quip card:agent:gall agent:gall)
68+ %- (print bowl |.("{<dap.bowl>}: on-leave on path {<path>}"))
69+ ?: ?=([%verb %event ~] path)
70+ [~ this]
71+ =^ cards agent (on-leave:ag path)
72+ :_ this
73+ :_ :_ cards
74+ (emit-event %on-leave path)
75+ (emit-event-plus bowl [%on-leave path] cards)
76+::
77+++ on-peek
78+ |= =path
79+ ^- (unit (unit cage))
80+ %- (print bowl |.("{<dap.bowl>}: on-peek on path {<path>}"))
81+ (on-peek:ag path)
82+::
83+++ on-agent
84+ |= [=wire =sign:agent:gall]
85+ ^- (quip card:agent:gall agent:gall)
86+ %- (print bowl |.("{<dap.bowl>}: on-agent on wire {<wire>}, {<-.sign>}"))
87+ =^ cards agent (on-agent:ag wire sign)
88+ :_ this
89+ :_ :_ cards
90+ (emit-event %on-agent wire -.sign)
91+ =; =^sign
92+ (emit-event-plus bowl [%on-agent wire sign] cards)
93+ ?- -.sign
94+ %poke-ack [%poke-ack ?=(~ p.sign)]
95+ %watch-ack [%watch-ack ?=(~ p.sign)]
96+ %kick [%kick ~]
97+ %fact [%fact p.cage.sign (mug q.q.cage.sign)]
98+ ==
99+::
100+++ on-arvo
101+ |= [=wire =sign-arvo]
102+ ^- (quip card:agent:gall agent:gall)
103+ %- %+ print bowl |.
104+ "{<dap.bowl>}: on-arvo on wire {<wire>}, {<[- +<]:sign-arvo>}"
105+ =^ cards agent (on-arvo:ag wire sign-arvo)
106+ :_ this
107+ :_ :_ cards
108+ (emit-event %on-arvo wire [- +<]:sign-arvo)
109+ (emit-event-plus bowl [%on-arvo wire [- +<]:sign-arvo] cards)
110+::
111+++ on-fail
112+ |= [=term =tang]
113+ ^- (quip card:agent:gall agent:gall)
114+ %- (print bowl |.("{<dap.bowl>}: on-fail with term {<term>}"))
115+ =^ cards agent (on-fail:ag term tang)
116+ :_ this
117+ :_ :_ cards
118+ (emit-event %on-fail term)
119+ (emit-event-plus bowl [%on-fail term] cards)
120+--
121+::
122+++ print
123+ |= [=bowl:gall render=(trap tape)]
124+ ^+ same
125+ =? . bowl-print
126+ %- (slog >bowl< ~)
127+ .
128+ ?. loud same
129+ %- (slog [%leaf $:render] ~)
130+ same
131+::
132+++ emit-event
133+ |= =event
134+ ^- card:agent:gall
135+ [%give %fact ~[/verb/events] %verb-event !>(event)]
136+::
137+++ emit-event-plus
138+ |= [=bowl:gall =cause cards=(list card:agent:gall)]
139+ ^- card:agent:gall
140+ =; event=event-plus
141+ [%give %fact ~[/verb/events-plus] %verb-event-plus !>(event)]
142+ =- [act.bowl now.bowl src.bowl sap.bowl cause -]
143+ %+ turn cards
144+ |= =card:agent:gall
145+ ^- effect
146+ ::TODO for %fact, %kick, could calculate how many ships affected
147+ ?- card
148+ [%pass * %agent * ?(%poke %poke-as) *]
149+ =, q.card
150+ =/ =cage ?-(-.task.q.card %poke cage.task, %poke-as [mark.task q.cage.task])
151+ [%poke p.card [ship name] p.cage `@`(mug q.q.cage)]
152+ ::
153+ [%pass * %agent * ?(%watch %watch-as) *]
154+ =, q.card
155+ =/ =path ?-(-.task.q.card %watch path.task, %watch-as path.task)
156+ [%watch p.card [ship name] path]
157+ ::
158+ [%pass * %agent * %leave *]
159+ =, q.card
160+ [%leave p.card [ship name]]
161+ ::
162+ [%give %fact *]
163+ =, p.card
164+ [%fact paths p.cage (mug q.q.cage)]
165+ ::
166+ [%give %kick *]
167+ [%kick paths.p.card]
168+ ::
169+ [%give ?(%poke-ack %watch-ack) *]
170+ ~| %explicit-ack
171+ !! :: shouldn't be given explicitly
172+ ::
173+ [%pass * %arvo *]
174+ [%arvo p.card -.q.card +<.q.card]
175+ ::
176+ [%pass *]
177+ [%arvo p.card %$ -.q.card]
178+ ::
179+ [%slip *]
180+ $(card [%pass //slip p.card])
181+ ==
182+--
base-desk/mar/atom.hoonnew file+18
@@ -0,0 +1,18 @@
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+--
base-desk/mar/belt.hoonnew file+20
@@ -0,0 +1,20 @@
1+:: belt: runtime belt structure
2+::
3+/+ dill
4+::
5+|_ =belt:dill
6+++ grad %noun
7+:: +grab: convert from
8+::
9+++ grab
10+ |%
11+ ++ noun belt:dill
12+ ++ json belt:dejs:dill
13+ --
14+:: +grow: convert to
15+::
16+++ grow
17+ |%
18+ ++ noun belt
19+ --
20+--
base-desk/mar/bill.hoonnew file+34
@@ -0,0 +1,34 @@
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+--
base-desk/mar/blit.hoonnew file+20
@@ -0,0 +1,20 @@
1+:: blit: runtime blit structure
2+::
3+/+ dill
4+::
5+|_ =blit:dill
6+++ grad %noun
7+:: +grab: convert from
8+::
9+++ grab
10+ |%
11+ ++ noun blit:dill
12+ --
13+:: +grow: convert to
14+::
15+++ grow
16+ |%
17+ ++ noun blit
18+ ++ json (blit:enjs:dill blit)
19+ --
20+--
base-desk/mar/css.hoonnew file+25
@@ -0,0 +1,25 @@
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+--
base-desk/mar/docket-0.hoonnew file+25
@@ -0,0 +1,25 @@
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+--
base-desk/mar/hoon.hoonnew file+303
@@ -0,0 +1,303 @@
1+|_ own=@t
2+::
3+++ grow :: convert to
4+ |%
5+ ++ mime `^mime`[/text/x-hoon (as-octs:mimes:html own)] :: convert to %mime
6+ ++ hymn
7+ ^- manx
8+ =/ to-wall
9+ |= =tape
10+ ^- wall
11+ %+ roll (flop tape)
12+ |= [char=@tD =wall]
13+ ?~ wall
14+ [[char ~] ~]
15+ ?: =('\0a' char)
16+ [~ wall]
17+ [[char i.wall] t.wall]
18+ ::
19+ =/ src=tape (trip own)
20+ =/ count=@ud (lent (to-wall src))
21+ =; [style=tape script=tape]
22+ ;html
23+ ;head
24+ ;title: source
25+ ;meta(charset "utf-8");
26+ ;meta(name "viewport", content "width=device-width, initial-scale=1");
27+ ;style: {style}
28+ ==
29+ ;body
30+ ;div.viewer
31+ :: ;div.viewer-bar
32+ :: ;span.viewer-name: {(scow %ud count)} lines
33+ :: ;button.copy-link(id "copy-link", hidden ""): copy link
34+ :: ==
35+ ;div.code
36+ ;pre.gutter(id "gutter");
37+ ;div.code-body
38+ ;div(id "hl");
39+ ;pre.code-pre(id "code"): {src}
40+ ==
41+ ==
42+ ==
43+ ;script: {script}
44+ ==
45+ ==
46+ ::
47+ :-
48+ ^~ ^= style
49+ ^- tape
50+ %- trip
51+ '''
52+ :root {
53+ --bg: #fbfbf9;
54+ --panel: #ffffff;
55+ --gutter-bg: #f3f3ef;
56+ --line: #e4e4dd;
57+ --fg: #2b2b2b;
58+ --fg-dim: #9a9a90;
59+ --sel: #fff7d6;
60+ --sel-edge: #f1e4a8;
61+ --accent: #4a6da7;
62+ --lh: 20px;
63+ --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
64+ "Liberation Mono", "Courier New", monospace;
65+ }
66+ * { box-sizing: border-box; }
67+ html, body {
68+ margin: 0;
69+ height: 100%;
70+ background: var(--bg);
71+ color: var(--fg);
72+ font-family: var(--mono);
73+ -webkit-font-smoothing: antialiased;
74+ }
75+ .viewer {
76+ height: 100vh;
77+ display: flex;
78+ flex-direction: column;
79+ padding: 16px;
80+ gap: 12px;
81+ }
82+ .viewer-bar {
83+ flex: 0 0 auto;
84+ display: flex;
85+ align-items: center;
86+ gap: 12px;
87+ font-size: 13px;
88+ color: var(--fg-dim);
89+ }
90+ .viewer-name {
91+ flex: 1 1 auto;
92+ min-width: 0;
93+ overflow: hidden;
94+ text-overflow: ellipsis;
95+ white-space: nowrap;
96+ color: var(--fg);
97+ }
98+ .copy-link {
99+ flex: 0 0 auto;
100+ padding: 4px 12px;
101+ border: 1px solid var(--line);
102+ border-radius: 6px;
103+ background: var(--panel);
104+ color: var(--fg-dim);
105+ font: inherit;
106+ font-size: 12px;
107+ cursor: pointer;
108+ transition: color .12s, border-color .12s;
109+ }
110+ .copy-link:hover { color: var(--accent); border-color: var(--accent); }
111+ .copy-link[hidden] { display: none; }
112+ .code {
113+ flex: 1 1 auto;
114+ min-height: 0;
115+ display: flex;
116+ align-items: flex-start;
117+ overflow: auto;
118+ background: var(--panel);
119+ border: 1px solid var(--line);
120+ border-radius: 8px;
121+ }
122+ .code-body {
123+ position: relative;
124+ flex: 1 1 auto;
125+ min-width: 0;
126+ width: max-content;
127+ }
128+ #gutter, #code {
129+ margin: 0;
130+ padding: 14px 0;
131+ font-family: var(--mono);
132+ font-size: 13px;
133+ line-height: var(--lh);
134+ white-space: pre;
135+ tab-size: 2;
136+ }
137+ #gutter {
138+ position: sticky;
139+ left: 0;
140+ z-index: 2;
141+ flex: 0 0 auto;
142+ padding-left: 16px;
143+ padding-right: 12px;
144+ text-align: right;
145+ color: var(--fg-dim);
146+ background: var(--gutter-bg);
147+ border-right: 1px solid var(--line);
148+ user-select: none;
149+ -webkit-user-select: none;
150+ cursor: pointer;
151+ }
152+ #code {
153+ display: block;
154+ padding-left: 14px;
155+ padding-right: 18px;
156+ color: var(--fg);
157+ }
158+ #hl {
159+ position: absolute;
160+ left: 0;
161+ right: 0;
162+ z-index: 0; /* under the text */
163+ display: none;
164+ background: var(--sel);
165+ box-shadow: inset 2px 0 0 var(--sel-edge);
166+ pointer-events: none;
167+ }
168+ #code { position: relative; z-index: 1; } /* text above the bar */
169+ :focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
170+ '''
171+ ^~ ^= code
172+ ^- tape
173+ %- trip
174+ '''
175+ (function () {
176+ "use strict";
177+ const panel = document.querySelector(".code"); // the scroll container
178+ const code = document.getElementById("code");
179+ const gutter = document.getElementById("gutter");
180+ const hl = document.getElementById("hl");
181+ if (!panel || !code || !gutter || !hl) return;
182+ const text = code.textContent;
183+ let lineCount = text.length ? text.split("\n").length : 1;
184+ if (text.endsWith("\n")) lineCount -= 1;
185+ if (lineCount < 1) lineCount = 1;
186+ (function fillGutter() {
187+ let s = "";
188+ for (let i = 1; i <= lineCount; i++) s += i + "\n";
189+ gutter.textContent = s;
190+ })();
191+ let lineH = 0;
192+ let codeTop = 0; // code's content-box top padding, the y-origin of line 1
193+ function measure() {
194+ const cs = getComputedStyle(code);
195+ const lh = parseFloat(cs.lineHeight);
196+ lineH = isNaN(lh) ? parseFloat(cs.fontSize) * 1.55 : lh;
197+ codeTop = parseFloat(cs.paddingTop) || 0;
198+ positionHighlight(); // keep the bar correct after a re-measure
199+ }
200+ let anchor = null;
201+ let selLo = 0;
202+ let selHi = 0;
203+ function positionHighlight() {
204+ if (!selLo) { hl.style.display = "none"; return; }
205+ hl.style.display = "block";
206+ hl.style.top = (codeTop + (selLo - 1) * lineH) + "px";
207+ hl.style.height = ((selHi - selLo + 1) * lineH) + "px";
208+ }
209+ function applySel(lo, hi) {
210+ selLo = lo;
211+ selHi = hi;
212+ positionHighlight();
213+ }
214+ function deselect() {
215+ selLo = selHi = 0;
216+ anchor = null;
217+ positionHighlight();
218+ history.replaceState(null, "", location.pathname + location.search);
219+ }
220+ function parseHash(hash) {
221+ const m = /^#L(\d+)(?:-L(\d+))?$/.exec(hash || "");
222+ if (!m) return null;
223+ let lo = parseInt(m[1], 10);
224+ let hi = m[2] ? parseInt(m[2], 10) : lo;
225+ if (hi < lo) { const t = lo; lo = hi; hi = t; }
226+ lo = Math.max(1, Math.min(lo, lineCount));
227+ hi = Math.max(1, Math.min(hi, lineCount));
228+ return [lo, hi];
229+ }
230+ function setHash(lo, hi) {
231+ const frag = lo === hi ? "L" + lo : "L" + lo + "-L" + hi;
232+ history.replaceState(null, "", "#" + frag);
233+ }
234+ function scrollToLine(n) {
235+ const y = codeTop + (n - 1) * lineH;
236+ if (y < panel.scrollTop || y > panel.scrollTop + panel.clientHeight) {
237+ panel.scrollTop = Math.max(0, y - panel.clientHeight / 2);
238+ }
239+ }
240+ function selectFromHash(scroll) {
241+ const r = parseHash(location.hash);
242+ if (!r) return false;
243+ anchor = r[0];
244+ applySel(r[0], r[1]);
245+ if (scroll) scrollToLine(r[0]);
246+ return true;
247+ }
248+ function lineFromEvent(e) {
249+ // y within the code content: pointer relative to the code pre's rendered
250+ // top, which already accounts for scroll since getBoundingClientRect is
251+ // viewport-relative and the pre moves as the panel scrolls.
252+ const rect = code.getBoundingClientRect();
253+ const y = e.clientY - rect.top - codeTop;
254+ let n = Math.floor(y / lineH) + 1;
255+ if (n < 1) n = 1;
256+ if (n > lineCount) n = lineCount;
257+ return n;
258+ }
259+ function onClick(e) {
260+ const inGutter = e.target === gutter;
261+ if (!inGutter && !e.shiftKey) return; // normal text interaction in code
262+ const n = lineFromEvent(e);
263+ if (!e.shiftKey && selLo === n && selHi === n) {
264+ deselect();
265+ return;
266+ }
267+ if (e.shiftKey && anchor !== null) {
268+ applySel(Math.min(anchor, n), Math.max(anchor, n));
269+ setHash(selLo, selHi);
270+ } else {
271+ anchor = n;
272+ applySel(n, n);
273+ setHash(n, n);
274+ }
275+ }
276+ gutter.addEventListener("click", onClick);
277+ code.addEventListener("click", onClick);
278+ document.addEventListener("keydown", function (e) {
279+ if (e.key === "Escape") deselect();
280+ });
281+ window.addEventListener("hashchange", function () {
282+ if (!selectFromHash(true)) deselect();
283+ });
284+ let rz = null;
285+ window.addEventListener("resize", function () {
286+ clearTimeout(rz);
287+ rz = setTimeout(measure, 100);
288+ });
289+ measure();
290+ selectFromHash(true);
291+ })();
292+ '''
293+ ++ txt
294+ (to-wain:format own)
295+ --
296+++ grab
297+ |% :: convert from
298+ ++ mime |=([p=mite q=octs] q.q)
299+ ++ noun @t :: clam from %noun
300+ ++ txt of-wain:format
301+ --
302+++ grad %txt
303+--
base-desk/mar/htm.hoonnew file+6
@@ -0,0 +1,6 @@
1+::
2+:::: /hoon/htm/mar
3+ ::
4+/? 310
5+/= htm /mar/html
6+htm
base-desk/mar/html.hoonnew file+22
@@ -0,0 +1,22 @@
1+::
2+:::: /hoon/html/mar
3+ ::
4+/? 310
5+ ::
6+:::: compute
7+ ::
8+=, html
9+|_ htm=@t
10+++ grow :: convert to
11+ ^?
12+ |% ::
13+ ++ mime [/text/html (met 3 htm) htm] :: to %mime
14+ ++ hymn (need (de-xml htm)) :: to %hymn
15+ -- ::
16+++ grab ^?
17+ |% :: convert from
18+ ++ noun @t :: clam from %noun
19+ ++ mime |=([p=mite q=octs] q.q) :: retrieve form %mime
20+ --
21+++ grad %mime
22+--
base-desk/mar/httr.hoonnew file+24
@@ -0,0 +1,24 @@
1+::
2+:::: /hoon/httr/mar
3+ ::
4+/? 310
5+::
6+=, eyre
7+=, format
8+|_ hit=httr
9+++ grad %noun
10+++ grow |% ++ wall (turn wain trip)
11+ ++ wain (to-wain cord)
12+ ++ json (need (de:json:html cord))
13+ ++ cord q:octs
14+ ++ noun hit
15+ ++ octs
16+ ~| hit
17+ ?> =(2 (div p.hit 100))
18+ (need r.hit)
19+ --
20+++ grab :: convert from
21+ |%
22+ ++ noun httr :: clam from %noun
23+ --
24+--
base-desk/mar/hymn.hoonnew file+17
@@ -0,0 +1,17 @@
1+::
2+:::: /hoon/hymn/mar
3+ ::
4+/? 310
5+=, mimes:html
6+=, html
7+|_ own=manx
8+::
9+++ grad %noun
10+++ grow :: convert to
11+ |%
12+ ++ html (crip (en-xml own)) :: convert to %html
13+ ++ mime [/text/html (as-octs html)] :: convert to %mime
14+ --
15+++ grab |% :: convert from
16+ ++ noun manx :: clam from %noun
17+-- --
base-desk/mar/js.hoonnew file+25
@@ -0,0 +1,25 @@
1+::
2+:::: /hoon/js/mar
3+ ::
4+/? 310
5+::
6+=, eyre
7+|_ mud=@
8+++ grow
9+ |%
10+ ++ mime [/application/javascript (as-octs:mimes:html (@t mud))]
11+ ++ hymn :: convert to %hymn
12+ |^ html
13+ ++ script ;script
14+ ;- (trip (@t mud))
15+ ==
16+ ++ html ;html:(head:"{script}" body)
17+ --
18+ --
19+++ grab
20+ |% :: convert from
21+ ++ mime |=([p=mite q=octs] (@t q.q))
22+ ++ noun cord :: clam from %noun
23+ --
24+++ grad %mime
25+--
base-desk/mar/json.hoonnew file+26
@@ -0,0 +1,26 @@
1+::
2+:::: /hoon/json/mar
3+ ::
4+/? 310
5+ ::
6+:::: compute
7+ ::
8+=, eyre
9+=, format
10+=, html
11+|_ jon=^json
12+::
13+++ grow :: convert to
14+ |%
15+ ++ mime [/application/json (as-octs:mimes -:txt)] :: convert to %mime
16+ ++ txt [(en:json jon)]~
17+ --
18+++ grab
19+ |% :: convert from
20+ ++ mime |=([p=mite q=octs] (fall (de:json (@t q.q)) *^json))
21+ ++ noun ^json :: clam from %noun
22+ ++ numb numb:enjs
23+ ++ time time:enjs
24+ --
25+++ grad %mime
26+--
base-desk/mar/json/rpc/response.hoonnew file+42
@@ -0,0 +1,42 @@
1+::
2+/- *json-rpc
3+::
4+|_ res=response
5+::
6+++ grad %noun
7+++ grow
8+ |%
9+ ++ noun res
10+ --
11+++ grab :: convert from
12+ |%
13+ ++ noun response :: from noun
14+ ++ httr :: from httr
15+ |= hit=httr:eyre
16+ ^- response
17+ ~| hit
18+ ?: ?=(%2 (div p.hit 100))
19+ %- json
20+ ?~ r.hit
21+ a+~
22+ (need (de:json:html q:u.r.hit))
23+ fail+hit
24+ ++ json :: from json
25+ =, dejs-soft:format
26+ |= a=json
27+ ^- response
28+ =; dere
29+ =+ res=((ar dere) a)
30+ ?~ res (need (dere a))
31+ [%batch u.res]
32+ |= a=json
33+ ^- (unit response)
34+ =/ res=(unit [@t json])
35+ ::TODO breaks when no id present
36+ ((ot id+so result+some ~) a)
37+ ?^ res `[%result u.res]
38+ ~| a
39+ :+ ~ %error %- need
40+ ((ot id+so error+(ot code+no message+so ~) ~) a)
41+ --
42+--
base-desk/mar/kelvin.hoonnew file+28
@@ -0,0 +1,28 @@
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+--
base-desk/mar/language-server/rpc/notification.hoonnew file+18
@@ -0,0 +1,18 @@
1+/- *language-server
2+/+ lsp-json=language-server-json
3+|_ not=all:notification
4+++ grad %noun
5+++ grab
6+ |%
7+ ++ noun all:notification
8+ ++ json
9+ |= jon=^json
10+ (notification:dejs:lsp-json jon)
11+ --
12+++ grow
13+ |%
14+ ++ noun not
15+ ++ json
16+ (notification:enjs:lsp-json not)
17+ --
18+--
base-desk/mar/language-server/rpc/request.hoonnew file+16
@@ -0,0 +1,16 @@
1+/- *language-server
2+/+ lsp-json=language-server-json
3+|_ req=all:request
4+++ grad %noun
5+++ grow
6+ |%
7+ ++ noun req
8+ --
9+++ grab
10+ |%
11+ ++ noun all:request
12+ ++ json
13+ |= jon=^json
14+ (request:dejs:lsp-json jon)
15+ --
16+--
base-desk/mar/language-server/rpc/response.hoonnew file+17
@@ -0,0 +1,17 @@
1+/- *language-server
2+/+ lsp=language-server-json
3+|_ res=all:response
4+::
5+++ grad %noun
6+++ grow
7+ |%
8+ ++ noun res
9+ ++ json (response:enjs:lsp res)
10+ --
11+::
12+++ grab
13+ |%
14+ ++ noun all:response
15+ --
16+::
17+--
base-desk/mar/mime.hoonnew file+32
@@ -0,0 +1,32 @@
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+--
base-desk/mar/noun.hoonnew file+22
@@ -0,0 +1,22 @@
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+--
base-desk/mar/path.hoonnew file+11
@@ -0,0 +1,11 @@
1+|_ pax=path
2+++ grad %noun
3+++ grow
4+ |%
5+ ++ noun pax
6+ --
7+++ grab
8+ |%
9+ ++ noun path
10+ --
11+--
base-desk/mar/png.hoonnew file+12
@@ -0,0 +1,12 @@
1+|_ dat=@
2+++ grow
3+ |%
4+ ++ mime [/image/png (as-octs:mimes:html dat)]
5+ --
6+++ grab
7+ |%
8+ ++ mime |=([p=mite q=octs] q.q)
9+ ++ noun @
10+ --
11+++ grad %mime
12+--
base-desk/mar/purl.hoonnew file+18
@@ -0,0 +1,18 @@
1+::
2+:::: /hoon/purl/mar
3+ ::
4+/? 310
5+=, eyre
6+|_ url=purl
7+++ grad %noun
8+::
9+++ grow
10+ |%
11+ ++ noun url
12+ ++ hiss [url %get ~ ~]
13+ --
14+++ grab :: convert from
15+ |%
16+ ++ noun purl :: clam from %noun
17+ --
18+--
base-desk/mar/ship.hoonnew file+20
@@ -0,0 +1,20 @@
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+--
base-desk/mar/sole/action.hoonnew file+52
@@ -0,0 +1,52 @@
1+::
2+:::: /hoon/action/sole/mar
3+ ::
4+/? 310
5+/- sole
6+::
7+::::
8+ ::
9+=, sole
10+|_ sole-action
11+::
12+++ grad %noun
13+++ grow
14+ |%
15+ ++ noun +<.grad
16+ --
17+++ grab :: convert from
18+ |%
19+ ++ json
20+ |= jon=^json ^- sole-action
21+ %- need %. jon
22+ => [dejs-soft:format ..sole-action]
23+ |^ (ot id+id dat+(fo %ret (of det+change tab+ni ~)) ~)
24+ ++ id
25+ (ot who+(su ;~(pfix sig fed:ag)) ses+so ~)
26+ ++ fo
27+ |* [a=term b=fist]
28+ |=(c=json ?.(=([%s a] c) (b c) (some [a ~])))
29+ ::
30+ ++ ra
31+ |* [a=[term fist] b=fist]
32+ |= c=json %. c
33+ ?.(=(%a -.c) b (pe -.a (ar +.a)))
34+ ::
35+ ++ ke :: callbacks
36+ |* [gar=* sef=(trap fist)]
37+ |= jon=json ^- (unit _gar)
38+ =- ~! gar ~! (need -) -
39+ ((sef) jon)
40+ ::
41+ ++ change (ot ler+(at ni ni ~) ted+(pe 0v0 edit) ~)
42+ ++ char (cu taft so)
43+ ++ edit
44+ %+ ke *sole-edit |. ~+
45+ %+ fo %nop
46+ %+ ra mor+edit
47+ (of del+ni set+(cu tuba sa) ins+(ot at+ni cha+char ~) ~)
48+ --
49+ ::
50+ ++ noun sole-action :: clam from %noun
51+ --
52+--
base-desk/mar/sole/effect.hoonnew file+82
@@ -0,0 +1,82 @@
1+::
2+:::: /hoon/effect/sole/mar
3+ ::
4+/? 310
5+/- sole
6+!:
7+::
8+::::
9+ ::
10+=, sole
11+=, format
12+|%
13+++ mar-sole-change :: XX dependency
14+ |_ cha=sole-change
15+ ++ grow
16+ |% ++ json
17+ ^- ^json
18+ =, enjs
19+ =; edi
20+ =,(cha (pairs ted+(edi ted) ler+a+~[(numb own.ler) (numb his.ler)] ~))
21+ |= det=sole-edit
22+ ?- -.det
23+ %nop [%s 'nop']
24+ %mor [%a (turn p.det ..$)]
25+ %del (frond %del (numb p.det))
26+ %set (frond %set (tape (tufa p.det)))
27+ %ins (frond %ins (pairs at+(numb p.det) cha+s+(tuft q.det) ~))
28+ ==
29+ --
30+ --
31+++ wush
32+ |= [wid=@u tan=tang]
33+ ^- tape
34+ (of-wall (turn (flop tan) |=(a=tank (of-wall (wash 0^wid a)))))
35+::
36+++ purge :: discard ++styx style
37+ |= a=styx ^- tape
38+ %- zing %+ turn a
39+ |= a=_?>(?=(^ a) i.a)
40+ ?@(a (trip a) ^$(a q.a))
41+--
42+::
43+|_ sef=sole-effect
44+::
45+++ grad %noun
46+++ grab :: convert from
47+ |%
48+ ++ noun sole-effect :: clam from %noun
49+ --
50+++ grow
51+ =, enjs
52+ |%
53+ ++ noun sef
54+ ++ json
55+ ^- ^json
56+ ?+ -.sef
57+ ~|(unsupported-effect+-.sef !!)
58+ %mor [%a (turn p.sef |=(a=sole-effect json(sef a)))]
59+ %err (frond %hop (numb p.sef))
60+ %txt (frond %txt (tape p.sef))
61+ %tan (frond %tan (tape (wush 160 p.sef)))
62+ %det (frond %det json:~(grow mar-sole-change +.sef))
63+ ::
64+ %pro
65+ %+ frond %pro
66+ (pairs vis+b+vis.sef tag+s+tag.sef cad+(tape (purge cad.sef)) ~)
67+ ::
68+ %tab
69+ :- %a
70+ %+ turn p.sef
71+ |= [=cord =^tank]
72+ %+ frond %tab
73+ %- pairs
74+ :~ match+s+cord
75+ info+(tape ~(ram re tank))
76+ ==
77+ ::
78+ ?(%bel %clr %nex %bye)
79+ (frond %act %s -.sef)
80+ ==
81+ --
82+--
base-desk/mar/story-diff.hoonnew file+16
@@ -0,0 +1,16 @@
1+::
2+::::
3+ ::
4+/- *story
5+|_ =story-diff
6+::
7+++ grad %noun
8+++ grow
9+ |%
10+ ++ noun story-diff
11+ --
12+++ grab :: convert from
13+ |%
14+ ++ noun ^story-diff :: make from %noun
15+ --
16+--
base-desk/mar/story.hoonnew file+65
@@ -0,0 +1,65 @@
1+/- *story
2+/+ *story
3+|_ tale=story
4+++ grad
5+ |%
6+ ++ form %story-diff
7+ ++ diff
8+ |= tory=story
9+ ^- story-diff
10+ :: Given new story (tory), old story (tale), compute the diff
11+ :: additions = new - old
12+ :: deletions = old - new
13+ [(dif-ju tory tale) (dif-ju tale tory)]
14+ ++ pact
15+ |= dif=story-diff
16+ :: Compute the new story after applying dif to tale.
17+ ::
18+ ^- story
19+ =. tale (uni-ju tale additions.dif)
20+ =. tale (dif-ju tale deletions.dif)
21+ tale
22+ ++ join
23+ |= [ali=story-diff bob=story-diff]
24+ ^- (unit story-diff)
25+ =/ joined-additions (uni-ju additions.ali additions.bob)
26+ =/ joined-deletions (uni-ju deletions.ali deletions.bob)
27+ ::
28+ :: In a true join, we'd do a set intersection on the keys.
29+ :: If they're not equal, we have a conflict.
30+ :: In this case, we'd produce null and kick the flow to +mash
31+ ::
32+ %- some
33+ [joined-additions joined-deletions]
34+ ++ mash
35+ :: called by meld, force merge, annotating conflicts
36+ |= $: [als=ship ald=desk ali=story-diff]
37+ [bos=ship bod=desk bob=story-diff]
38+ ==
39+ ^- story-diff
40+ (need (join ali bob)) :: XX temporary, only because join doesn't fail
41+ --
42+::
43+++ grow :: convert to
44+ |% ::
45+ ++ mime :: to %mime
46+ [/text/x-urb-story (as-octs:mimes:html (of-wain:format txt))]
47+ ++ txt
48+ ^- wain
49+ %- zing
50+ %+ join `wain`~['---']
51+ %+ murn ~(tap by tale)
52+ |= [=tako:clay =proses]
53+ ^- (unit wain)
54+ ?~ proses ~
55+ (some (chapter-to-text tako proses))
56+ --
57+++ grab
58+ |% :: convert from
59+ ++ noun story :: clam from %noun
60+ ++ mime :: retrieve from %mime
61+ |= [p=mite q=octs]
62+ =/ story-text `@t`q.q
63+ `story`(rash story-text parse-story)
64+ --
65+--
base-desk/mar/svg.hoonnew file+12
@@ -0,0 +1,12 @@
1+|_ dat=@
2+++ grow
3+ |%
4+ ++ mime [/image/'svg+xml' (as-octs:mimes:html dat)]
5+ --
6+++ grab
7+ |%
8+ ++ mime |=([p=mite q=octs] q.q)
9+ ++ noun @
10+ --
11+++ grad %mime
12+--
base-desk/mar/tang.hoonnew file+30
@@ -0,0 +1,30 @@
1+::
2+:::: /hoon/tang/mar
3+ ::
4+/? 310
5+::
6+=, format
7+|_ tan=(list tank)
8+++ grad %noun
9+++ grow
10+ |%
11+ ++ noun tan
12+ ++ json
13+ =/ result=(each (list ^json) tang)
14+ (mule |.((turn tan tank:enjs:format)))
15+ ?- -.result
16+ %& a+p.result
17+ %| a+[a+[%s '[[output rendering error]]']~]~
18+ ==
19+ ++ txt
20+ ^- wain
21+ %+ turn (flop tan)
22+ |=(=tank (crip ~(ram re tank)))
23+ --
24+++ grab :: convert from
25+ |%
26+ ++ noun (list ^tank) :: clam from %noun
27+ ++ tank |=(a=^tank [a]~)
28+ ++ txt |=(=wain (flop (turn wain tank)))
29+ --
30+--
base-desk/mar/tape.hoonnew file+12
@@ -0,0 +1,12 @@
1+|_ tap=tape
2+++ grad %noun
3+++ grow
4+ |%
5+ ++ noun tap
6+ ++ json s+(crip tap)
7+ --
8+++ grab
9+ |%
10+ ++ noun tape
11+ --
12+--
base-desk/mar/thread-done.hoonnew file+11
@@ -0,0 +1,11 @@
1+|_ res=*
2+++ grab
3+ |%
4+ ++ noun *
5+ --
6+++ grow
7+ |%
8+ ++ noun res
9+ --
10+++ grad %noun
11+--
base-desk/mar/thread-fail.hoonnew file+11
@@ -0,0 +1,11 @@
1+|_ err=[term tang]
2+++ grab
3+ |%
4+ ++ noun (pair term tang)
5+ --
6+++ grow
7+ |%
8+ ++ noun err
9+ --
10+++ grad %noun
11+--
base-desk/mar/txt-diff.hoonnew file+16
@@ -0,0 +1,16 @@
1+::
2+:::: /hoon/txt-diff/mar
3+ ::
4+/? 310
5+|_ txt-diff=(urge:clay cord)
6+::
7+++ grad %noun
8+++ grow
9+ |%
10+ ++ noun txt-diff
11+ --
12+++ grab :: convert from
13+ |%
14+ ++ noun (urge:clay cord) :: make from %noun
15+ --
16+--
base-desk/mar/txt.hoonnew file+274
@@ -0,0 +1,274 @@
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+ --
22+++ grad
23+ |%
24+ ++ form %txt-diff
25+ ++ diff
26+ |= tyt=wain
27+ ^- (urge cord)
28+ (lusk txt tyt (loss txt tyt))
29+ ::
30+ ++ pact
31+ |= dif=(urge cord)
32+ ~| [%pacting dif]
33+ ^- wain
34+ (lurk txt dif)
35+ ::
36+ ++ join
37+ |= [ali=(urge cord) bob=(urge cord)]
38+ ^- (unit (urge cord))
39+ |^
40+ =. ali (clean ali)
41+ =. bob (clean bob)
42+ |- ^- (unit (urge cord))
43+ ?~ ali `bob
44+ ?~ bob `ali
45+ ?- -.i.ali
46+ %&
47+ ?- -.i.bob
48+ %&
49+ ?: =(p.i.ali p.i.bob)
50+ %+ bind $(ali t.ali, bob t.bob)
51+ |=(cud=(urge cord) [i.ali cud])
52+ ?: (gth p.i.ali p.i.bob)
53+ %+ bind $(p.i.ali (sub p.i.ali p.i.bob), bob t.bob)
54+ |=(cud=(urge cord) [i.bob cud])
55+ %+ bind $(ali t.ali, p.i.bob (sub p.i.bob p.i.ali))
56+ |=(cud=(urge cord) [i.ali cud])
57+ ::
58+ %|
59+ ?: =(p.i.ali (lent p.i.bob))
60+ %+ bind $(ali t.ali, bob t.bob)
61+ |=(cud=(urge cord) [i.bob cud])
62+ ?: (gth p.i.ali (lent p.i.bob))
63+ %+ bind $(p.i.ali (sub p.i.ali (lent p.i.bob)), bob t.bob)
64+ |=(cud=(urge cord) [i.bob cud])
65+ ~
66+ ==
67+ ::
68+ %|
69+ ?- -.i.bob
70+ %|
71+ ?. =(i.ali i.bob)
72+ ~
73+ %+ bind $(ali t.ali, bob t.bob)
74+ |=(cud=(urge cord) [i.ali cud])
75+ ::
76+ %&
77+ ?: =(p.i.bob (lent p.i.ali))
78+ %+ bind $(ali t.ali, bob t.bob)
79+ |=(cud=(urge cord) [i.ali cud])
80+ ?: (gth p.i.bob (lent p.i.ali))
81+ %+ bind $(ali t.ali, p.i.bob (sub p.i.bob (lent p.i.ali)))
82+ |=(cud=(urge cord) [i.ali cud])
83+ ~
84+ ==
85+ ==
86+ ++ clean :: clean
87+ |= wig=(urge cord)
88+ ^- (urge cord)
89+ ?~ wig ~
90+ ?~ t.wig wig
91+ ?: ?=(%& -.i.wig)
92+ ?: ?=(%& -.i.t.wig)
93+ $(wig [[%& (add p.i.wig p.i.t.wig)] t.t.wig])
94+ [i.wig $(wig t.wig)]
95+ ?: ?=(%| -.i.t.wig)
96+ $(wig [[%| (welp p.i.wig p.i.t.wig) (welp q.i.wig q.i.t.wig)] t.t.wig])
97+ [i.wig $(wig t.wig)]
98+ --
99+ ::
100+ ++ mash
101+ |= $: [als=ship ald=desk ali=(urge cord)]
102+ [bos=ship bod=desk bob=(urge cord)]
103+ ==
104+ ^- (urge cord)
105+ |^
106+ =. ali (clean ali)
107+ =. bob (clean bob)
108+ |- ^- (urge cord)
109+ ?~ ali bob
110+ ?~ bob ali
111+ ?- -.i.ali
112+ %&
113+ ?- -.i.bob
114+ %&
115+ ?: =(p.i.ali p.i.bob)
116+ [i.ali $(ali t.ali, bob t.bob)]
117+ ?: (gth p.i.ali p.i.bob)
118+ [i.bob $(p.i.ali (sub p.i.ali p.i.bob), bob t.bob)]
119+ [i.ali $(ali t.ali, p.i.bob (sub p.i.bob p.i.ali))]
120+ ::
121+ %|
122+ ?: =(p.i.ali (lent p.i.bob))
123+ [i.bob $(ali t.ali, bob t.bob)]
124+ ?: (gth p.i.ali (lent p.i.bob))
125+ [i.bob $(p.i.ali (sub p.i.ali (lent p.i.bob)), bob t.bob)]
126+ =/ [fic=(unce cord) ali=(urge cord) bob=(urge cord)]
127+ (resolve ali bob)
128+ [fic $(ali ali, bob bob)]
129+ :: ~ :: here, alice is good for a while, but not for the whole
130+ == :: length of bob's changes
131+ ::
132+ %|
133+ ?- -.i.bob
134+ %|
135+ =/ [fic=(unce cord) ali=(urge cord) bob=(urge cord)]
136+ (resolve ali bob)
137+ [fic $(ali ali, bob bob)]
138+ ::
139+ %&
140+ ?: =(p.i.bob (lent p.i.ali))
141+ [i.ali $(ali t.ali, bob t.bob)]
142+ ?: (gth p.i.bob (lent p.i.ali))
143+ [i.ali $(ali t.ali, p.i.bob (sub p.i.bob (lent p.i.ali)))]
144+ =/ [fic=(unce cord) ali=(urge cord) bob=(urge cord)]
145+ (resolve ali bob)
146+ [fic $(ali ali, bob bob)]
147+ ==
148+ ==
149+ ::
150+ ++ annotate :: annotate conflict
151+ |= $: ali=(list @t)
152+ bob=(list @t)
153+ bas=(list @t)
154+ ==
155+ ^- (list @t)
156+ %- zing
157+ ^- (list (list @t))
158+ %- flop
159+ ^- (list (list @t))
160+ :- :_ ~
161+ %^ cat 3 '<<<<<<<<<<<<'
162+ %^ cat 3 ' '
163+ %^ cat 3 `@t`(scot %p bos)
164+ %^ cat 3 '/'
165+ bod
166+
167+ :- bob
168+ :- ~['------------']
169+ :- bas
170+ :- ~['++++++++++++']
171+ :- ali
172+ :- :_ ~
173+ %^ cat 3 '>>>>>>>>>>>>'
174+ %^ cat 3 ' '
175+ %^ cat 3 `@t`(scot %p als)
176+ %^ cat 3 '/'
177+ ald
178+ ~
179+ ::
180+ ++ clean :: clean
181+ |= wig=(urge cord)
182+ ^- (urge cord)
183+ ?~ wig ~
184+ ?~ t.wig wig
185+ ?: ?=(%& -.i.wig)
186+ ?: ?=(%& -.i.t.wig)
187+ $(wig [[%& (add p.i.wig p.i.t.wig)] t.t.wig])
188+ [i.wig $(wig t.wig)]
189+ ?: ?=(%| -.i.t.wig)
190+ $(wig [[%| (welp p.i.wig p.i.t.wig) (welp q.i.wig q.i.t.wig)] t.t.wig])
191+ [i.wig $(wig t.wig)]
192+ ::
193+ ++ resolve
194+ |= [ali=(urge cord) bob=(urge cord)]
195+ ^- [fic=[%| p=(list cord) q=(list cord)] ali=(urge cord) bob=(urge cord)]
196+ =- [[%| bac (annotate alc boc bac)] ali bob]
197+ |- ^- $: $: bac=(list cord)
198+ alc=(list cord)
199+ boc=(list cord)
200+ ==
201+ ali=(urge cord)
202+ bob=(urge cord)
203+ ==
204+ ?~ ali [[~ ~ ~] ali bob]
205+ ?~ bob [[~ ~ ~] ali bob]
206+ ?- -.i.ali
207+ %&
208+ ?- -.i.bob
209+ %& [[~ ~ ~] ali bob] :: no conflict
210+ %|
211+ =+ lob=(lent p.i.bob)
212+ ?: =(lob p.i.ali)
213+ [[p.i.bob p.i.bob q.i.bob] t.ali t.bob]
214+ ?: (lth lob p.i.ali)
215+ [[p.i.bob p.i.bob q.i.bob] [[%& (sub p.i.ali lob)] t.ali] t.bob]
216+ =+ wat=(scag (sub lob p.i.ali) p.i.bob)
217+ =+ ^= res
218+ %= $
219+ ali t.ali
220+ bob [[%| (scag (sub lob p.i.ali) p.i.bob) ~] t.bob]
221+ ==
222+ :* :* (welp bac.res wat)
223+ (welp alc.res wat)
224+ (welp boc.res q.i.bob)
225+ ==
226+ ali.res
227+ bob.res
228+ ==
229+ ==
230+ ::
231+ %|
232+ ?- -.i.bob
233+ %&
234+ =+ loa=(lent p.i.ali)
235+ ?: =(loa p.i.bob)
236+ [[p.i.ali q.i.ali p.i.ali] t.ali t.bob]
237+ ?: (lth loa p.i.bob)
238+ [[p.i.ali q.i.ali p.i.ali] t.ali [[%& (sub p.i.bob loa)] t.bob]]
239+ =+ wat=(slag (sub loa p.i.bob) p.i.ali)
240+ =+ ^= res
241+ %= $
242+ ali [[%| (scag (sub loa p.i.bob) p.i.ali) ~] t.ali]
243+ bob t.bob
244+ ==
245+ :* :* (welp bac.res wat)
246+ (welp alc.res q.i.ali)
247+ (welp boc.res wat)
248+ ==
249+ ali.res
250+ bob.res
251+ ==
252+ ::
253+ %|
254+ =+ loa=(lent p.i.ali)
255+ =+ lob=(lent p.i.bob)
256+ ?: =(loa lob)
257+ [[p.i.ali q.i.ali q.i.bob] t.ali t.bob]
258+ =+ ^= res
259+ ?: (gth loa lob)
260+ $(ali [[%| (scag (sub loa lob) p.i.ali) ~] t.ali], bob t.bob)
261+ ~& [%scagging loa=loa pibob=p.i.bob slag=(scag loa p.i.bob)]
262+ $(ali t.ali, bob [[%| (scag (sub lob loa) p.i.bob) ~] t.bob])
263+ :* :* (welp bac.res ?:((gth loa lob) p.i.bob p.i.ali))
264+ (welp alc.res q.i.ali)
265+ (welp boc.res q.i.bob)
266+ ==
267+ ali.res
268+ bob.res
269+ ==
270+ ==
271+ ==
272+ --
273+ --
274+--
base-desk/mar/udon.hoonnew file+27
@@ -0,0 +1,27 @@
1+::
2+:::: /hoon/udon/mar
3+ ::
4+/+ cram
5+::
6+|_ mud=@t
7+++ grow
8+ |%
9+ ++ mime [/text/x-unmark (as-octs:mimes:html mud)]
10+ ++ txt
11+ (to-wain:format mud)
12+ ++ front :: XX performance, types
13+ ^- (map term knot)
14+ %- ~(run by inf:(static:cram (ream mud)))
15+ |= a=dime ^- cord
16+ ?+ (end 3 p.a) (scot a)
17+ %t q.a
18+ ==
19+ --
20+++ grab
21+ |%
22+ ++ mime |=((pair mite octs) q.q)
23+ ++ noun @t
24+ ++ txt of-wain:format
25+ --
26+++ grad %txt
27+--
base-desk/mar/umd.hoonnew file+28
@@ -0,0 +1,28 @@
1+::
2+:::: /hoon/umd/mar
3+ ::
4+/+ cram
5+::
6+|_ mud=@t
7+++ grow
8+ |%
9+ ++ mime [/text/x-unmark (as-octs:mimes:html mud)]
10+ ++ txt
11+ (to-wain:format mud)
12+ ++ front :: XX performance, types
13+ ^- (map term knot)
14+ %- ~(run by inf:(static:cram (ream mud)))
15+ |= a=dime ^- cord
16+ ?+ (end 3 p.a) (scot a)
17+ %t q.a
18+ ==
19+ --
20+++ grab
21+ |%
22+ ++ mime |=((pair mite octs) q.q)
23+ ++ noun @t
24+ ++ txt of-wain:format
25+ --
26+++ grad %txt
27+++ garb /down
28+--
base-desk/mar/urb.hoonnew file+18
@@ -0,0 +1,18 @@
1+::
2+:::: /hoon/urb/mar
3+ ::
4+/? 310
5+=, mimes:html
6+=, html
7+|_ own=manx
8+::
9+++ grad %noun
10+++ grow :: convert to
11+ |%
12+ ++ hymn ;html:(head body:"+{own}") :: convert to %hymn
13+ ++ html (crip (en-xml hymn)) :: convert to %html
14+ ++ mime [/text/html (as-octs html)] :: convert to %mime
15+ --
16+++ grab |% :: convert from
17+ ++ noun manx :: clam from %noun
18+-- --
base-desk/mar/urbit.hoonnew file+17
@@ -0,0 +1,17 @@
1+::
2+:::: /hoon/urbit/mar
3+ ::
4+/? 310
5+:::: A minimal urbit mark
6+::
7+|_ her=@p
8+++ grab
9+ |%
10+ ++ noun @p
11+ --
12+++ grow
13+ |%
14+ ++ noun her
15+ --
16+++ grad %noun
17+--
base-desk/mar/woff2.hoonnew file+12
@@ -0,0 +1,12 @@
1+|_ dat=octs
2+++ grow
3+ |%
4+ ++ mime [/font/woff2 dat]
5+ --
6+++ grab
7+ |%
8+ ++ mime |=([=mite =octs] octs)
9+ ++ noun octs
10+ --
11+++ grad %mime
12+--
base-desk/mar/xml.hoonnew file+21
@@ -0,0 +1,21 @@
1+::
2+:::: /hoon/xml/mar
3+ ::
4+/? 310
5+ ::
6+:::: compute
7+ ::
8+=, mimes:html
9+=, html
10+|_ xml=@t
11+::
12+++ grad %mime
13+++ grow :: convert to
14+ |% ::
15+ ++ mime [/application/xml (as-octs xml)] :: to %mime
16+ ++ hymn (need (de-xml xml)) :: to %hymn
17+ -- ::
18+++ grab |% :: convert from
19+ ++ noun @t :: clam from %noun
20+ ++ mime |=([p=mite q=octs] q.q) :: retrieve form %mime
21+-- --
base-desk/sources.txtnew file+3
@@ -0,0 +1,3 @@
1+urbit-src/pkg/base-dev
2+urbit-src/pkg/landscape
3+urbit-src/pkg/arvo
base-desk/sur/aquarium.hoonnew file+89
@@ -0,0 +1,89 @@
1+:: Traditionally, ovo refers to an ovum -- (pair wire card) -- and ova
2+:: refers to a list of them. We have several versions of each of these
3+:: depending on context, so we do away with that naming scheme and use
4+:: the following naming scheme.
5+::
6+:: Every card is either an `event` or an `effect`. Prepended to this
7+:: is `unix` if it has no ship associated with it, or `aqua` if it
8+:: does. `timed` is added if it includes the time of the event.
9+::
10+:: Short names are simply the first letter of each word plus `s` if
11+:: it's a list.
12+::
13+|%
14++$ az-log [topics=(lest @) data=@t]
15++$ az-state
16+ $: logs=(list az-log)
17+ lives=(map ship [lyfe=life rut=rift])
18+ tym=@da
19+ ==
20+++ ph-event
21+ $% [%test-done p=?]
22+ aqua-event
23+ ==
24+::
25++$ unix-event ::NOTE like unix-event:pill-lib but for all tasks
26+ %+ pair wire
27+ $% [%wack p=@]
28+ [%what p=(list (pair path (cask)))]
29+ [%whom p=ship]
30+ [%boot ? $%($>(%fake task:jael) $>(%dawn task:jael))]
31+ [%wyrd p=vere]
32+ [%verb p=(unit ?)]
33+ task-arvo
34+ ==
35+::
36++$ aqua-event
37+ $% [%init-ship who=ship fake=? feed=(unit feed:jael)]
38+ [%pause-events who=ship]
39+ [%snap-ships lab=term hers=(list ship)]
40+ [%restore-snap lab=term]
41+ [%read [from=[=ship life=@ubC] =path] for=[=lane:ames life=@ubC] num=@ud]
42+ [%event who=ship ue=unix-event]
43+ ==
44+::
45++$ azimuth-action
46+ $% [%init-azimuth ~]
47+ [%spawn who=ship]
48+ [%breach who=ship]
49+ ==
50+::
51++$ aqua-effects
52+ [who=ship ufs=(list unix-effect)]
53+::
54++$ aqua-effect
55+ [who=ship ufs=unix-effect]
56+::
57++$ aqua-events
58+ [who=ship utes=(list unix-timed-event)]
59+::
60++$ aqua-boths
61+ [who=ship ub=(list unix-both)]
62+::
63++$ unix-both
64+ $% [%event unix-timed-event]
65+ [%effect unix-effect]
66+ ==
67+::
68++$ unix-timed-event [tym=@da ue=unix-event]
69+::
70++$ unix-effect
71+ %+ pair wire
72+ $% [%blit p=(list blit:dill)]
73+ [%send p=lane:ames q=@]
74+ [%push p=(list lane:pact:ames) q=@]
75+ [%saxo sponsors=(list ship)]
76+ [%nail =ship lanes=(list lane:ames)]
77+ [%doze p=(unit @da)]
78+ [%thus p=@ud q=(unit hiss:eyre)]
79+ [%ergo p=@tas q=mode:clay]
80+ [%sleep ~]
81+ [%restore ~]
82+ [%kill ~]
83+ [%init ~]
84+ [%request id=@ud request=request:http]
85+ [%turf p=(list turf)]
86+ [%unto =unto:gall] :: internal gifts to host ships
87+ :: (%facts are transformed to %raw-facts)
88+ ==
89+--
base-desk/sur/asn1.hoonnew file+80
@@ -0,0 +1,80 @@
1+:: |asn1: small selection of types and constants for ASN.1
2+::
3+:: A minimal representation of some basic ASN.1 types,
4+:: created to support PKCS keys, digests, and cert requests.
5+::
6+^?
7+|%
8+:: +bespoke:asn1: context-specific, generic ASN.1 tag type
9+::
10+:: Note that *explicit* implies *constructed* (ie, bit 5 is set in DER).
11+::
12++$ bespoke
13+ :: imp: & is implicit, | is explicit
14+ :: tag: 5 bits for the custom tag number
15+ ::
16+ [imp=? tag=@ud]
17+:: +spec:asn1: minimal representations of basic ASN.1 types
18+::
19++$ spec
20+ $% :: %int: arbitrary-sized, unsigned integers
21+ ::
22+ :: Unsigned integers, represented as having a positive sign.
23+ :: Negative integers would be two's complement in DER,
24+ :: but we don't need them.
25+ ::
26+ [%int int=@u]
27+ :: %bit: very minimal support for bit strings
28+ ::
29+ :: Specifically, values must already be padded and byte-aligned.
30+ :: len: bitwidth
31+ :: bit: data
32+ ::
33+ [%bit len=@ud bit=@ux]
34+ :: %oct: octets in little-endian byte order
35+ ::
36+ :: len: bytewidth
37+ :: bit: data
38+ ::
39+ [%oct len=@ud oct=@ux]
40+ :: %nul: fully supported!
41+ ::
42+ [%nul ~]
43+ :: %obj: object identifiers, pre-packed
44+ ::
45+ :: Object identifiers are technically a sequence of integers,
46+ :: represented here in their already-encoded form.
47+ ::
48+ [%obj obj=@ux]
49+ :: %seq: a list of specs
50+ ::
51+ [%seq seq=(list spec)]
52+ :: %set: a logical set of specs
53+ ::
54+ :: Implemented here as a list for the sake of simplicity.
55+ :: must be already deduplicated and sorted!
56+ ::
57+ [%set set=(list spec)]
58+ :: %con: context-specific
59+ ::
60+ :: General support for context-specific tags.
61+ :: bes: custom tag number, implicit or explicit
62+ :: con: already-encoded bytes
63+ ::
64+ [%con bes=bespoke con=(list @D)]
65+ ==
66+:: |obj:asn1: constant object ids, pre-encoded
67+::
68+++ obj
69+ ^?
70+ |% :: rfc4055
71+ ++ sha-256 0x1.0204.0365.0148.8660 :: 2.16.840.1.101.3.4.2.1
72+ ++ rsa 0x1.0101.0df7.8648.862a :: 1.2.840.113549.1.1.1
73+ ++ rsa-sha-256 0xb.0101.0df7.8648.862a :: 1.2.840.113549.1.1.11
74+ :: rfc2985
75+ ++ csr-ext 0xe.0901.0df7.8648.862a :: 1.2.840.113549.1.9.14
76+ :: rfc3280
77+ ++ sub-alt 0x11.1d55 :: 2.5.29.17
78+ --
79+--
80+
base-desk/sur/bitcoin.hoonnew file+84
@@ -0,0 +1,84 @@
1+:: sur/btc.hoon
2+:: Utilities for working with BTC data types and transactions
3+::
4+:: chyg: whether account is (non-)change. 0 or 1
5+:: bytc: "btc-byts" with dat cast to @ux
6+|%
7++$ network ?(%main %testnet %regtest)
8++$ hexb [wid=@ dat=@ux] :: hex byts
9++$ bits [wid=@ dat=@ub]
10++$ xpub @ta
11++$ address
12+ $% [%base58 @uc]
13+ [%bech32 cord]
14+ ==
15++$ fprint hexb
16++$ bipt $?(%44 %49 %84)
17++$ chyg $?(%0 %1)
18++$ idx @ud
19++$ hdkey [=fprint pubkey=hexb =network =bipt =chyg =idx]
20++$ sats @ud
21++$ vbytes @ud
22++$ txid hexb
23++$ utxo [pos=@ =txid height=@ value=sats recvd=(unit @da)]
24+++ address-info
25+ $: =address
26+ confirmed-value=sats
27+ unconfirmed-value=sats
28+ utxos=(set utxo)
29+ ==
30+++ tx
31+ |%
32+ +$ data
33+ $: is=(list input)
34+ os=(list output)
35+ locktime=@ud
36+ nversion=@ud
37+ segwit=(unit @ud)
38+ ==
39+ +$ val
40+ $: =txid
41+ pos=@ud
42+ =address
43+ value=sats
44+ ==
45+ :: included: whether tx is in the mempool or blockchain
46+ ::
47+ +$ info
48+ $: included=?
49+ =txid
50+ confs=@ud
51+ recvd=(unit @da)
52+ inputs=(list val)
53+ outputs=(list val)
54+ ==
55+ +$ input
56+ $: =txid
57+ pos=@ud
58+ sequence=hexb
59+ script-sig=(unit hexb)
60+ pubkey=(unit hexb)
61+ value=sats
62+ ==
63+ +$ output
64+ $: script-pubkey=hexb
65+ value=sats
66+ ==
67+ --
68+++ psbt
69+ |%
70+ +$ base64 cord
71+ +$ in [=utxo rawtx=hexb =hdkey]
72+ +$ out [=address hk=(unit hdkey)]
73+ +$ target $?(%input %output)
74+ +$ keyval [key=hexb val=hexb]
75+ +$ map (list keyval)
76+ --
77+++ ops
78+ |%
79+ ++ op-dup 118
80+ ++ op-equalverify 136
81+ ++ op-hash160 169
82+ ++ op-checksig 172
83+ --
84+--
base-desk/sur/docket.hoonnew file+82
@@ -0,0 +1,82 @@
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+--
base-desk/sur/hark-store.hoonnew file+159
@@ -0,0 +1,159 @@
1+^?
2+::
3+:: %hark-store: Notification, unreads store
4+::
5+:: Timeboxing & binning:
6+::
7+:: Unread notifications accumulate in $unreads. They are grouped by
8+:: their $bin. A notification may become read by either:
9+:: a) being read by a %read-count or %read-each or %read-note
10+:: b) being read by a %seen
11+::
12+:: If a) then we insert the corresponding bin into $reads at the
13+:: current timestamp
14+:: If b) then we empty $unreads and move all bins to $reads at the
15+:: current timestamp
16+::
17+:: Unread tracking:
18+:: Unread tracking has two 'modes' which may be used concurrently,
19+:: if necessary.
20+::
21+:: count:
22+:: This stores the unreads as a simple atom, describing the number
23+:: of unread items. May be increased with %unread-count and
24+:: set to zero with %read-count. Ideal for high-frequency linear
25+:: datastructures, e.g. chat
26+:: each:
27+:: This stores the unreads as a set of paths, describing the set of
28+:: unread items. Unreads may be added to the set with %unread-each
29+:: and removed with %read-each. Ideal for non-linear, low-frequency
30+:: datastructures, e.g. blogs
31+::
32+|%
33+:: $place: A location, under which landscape stores stats
34+::
35+:: .desk must match q.byk.bowl
36+:: Examples:
37+:: A chat:
38+:: [%landscape /~dopzod/urbit-help]
39+:: A note in a notebook:
40+:: [%landscape /~darrux-landes/feature-requests/12374893234232]
41+:: A group:
42+:: [%hark-group-hook /~bitbet-bolbel/urbit-community]
43+:: Comments on a link
44+:: [%landscape /~dabben-larbet/urbit-in-the-news/17014118450499614194868/2]
45+::
46++$ place [=desk =path]
47+::
48+:: $bin: Identifier for grouping notifications
49+::
50+:: Examples
51+:: A mention in a chat:
52+:: [/mention %landscape /~dopzod/urbit-help]
53+:: New messages in a chat
54+:: [/message %landscape /~dopzod/urbit-help]
55+:: A new comment in a notebook:
56+:: [/comment %landscape /~darrux-landes/feature-requests/12374893234232/2]
57+::
58++$ bin [=path =place]
59+::
60+:: $lid: Reference to a timebox
61+::
62++$ lid
63+ $% [%archive =time]
64+ [%seen ~]
65+ [%unseen ~]
66+ ==
67+:: $content: Notification content
68++$ content
69+ $% [%ship =ship]
70+ [%text =cord]
71+ ==
72+::
73+:: $body: A notification body
74+::
75++$ body
76+ $: title=(list content)
77+ content=(list content)
78+ =time
79+ binned=path
80+ link=path
81+ ==
82+::
83++$ notification
84+ [date=@da =bin body=(list body)]
85+:: $timebox: Group of notificatons
86++$ timebox
87+ (map bin notification)
88+:: $archive: Archived notifications, ordered by time
89++$ archive
90+ ((mop @da timebox) gth)
91+::
92++$ action
93+ $% :: hook actions
94+ ::
95+ :: %add-note: add a notification
96+ [%add-note =bin =body]
97+ ::
98+ :: %del-place: Underlying resource disappeared, remove all
99+ :: associated notifications
100+ [%del-place =place]
101+ :: %unread-count: Change unread count by .count
102+ [%unread-count =place inc=? count=@ud]
103+ :: %unread-each: Add .path to list of unreads for .place
104+ [%unread-each =place =path]
105+ :: %saw-place: Update last-updated for .place to now.bowl
106+ [%saw-place =place time=(unit time)]
107+ :: store actions
108+ ::
109+ :: %archive: archive single notification
110+ :: if .time is ~, then archiving unread notification
111+ :: else, archiving read notification
112+ [%archive =lid =bin]
113+ :: %read-count: set unread count to zero
114+ [%read-count =place]
115+ :: %read-each: remove path from unreads for .place
116+ [%read-each =place =path]
117+ :: %read-note: Read note at .bin
118+ [%read-note =bin]
119+ :: %archive-all: Archive all notifications
120+ [%archive-all ~]
121+ :: %opened: User opened notifications, reset timeboxing logic.
122+ ::
123+ [%opened ~]
124+ ::
125+ :: XX: previously in hark-store, now deprecated
126+ :: the hooks responsible for creating notifications may offer pokes
127+ :: similar to this
128+ :: [%read-graph =resource]
129+ :: [%read-group =resource]
130+ :: [%remove-graph =resource]
131+ ::
132+ ==
133+:: .stats: Statistics for a .place
134+::
135++$ stats
136+ $: count=@ud
137+ each=(set path)
138+ last=@da
139+ timebox=(unit @da)
140+ ==
141+::
142++$ update
143+ $% action
144+ :: %more: more updates
145+ [%archived =time =lid =notification]
146+ [%more more=(list update)]
147+ :: %note-read: note has been read with timestamp
148+ [%note-read =time =bin]
149+ [%added =notification]
150+ :: %timebox: description of timebox.
151+ ::
152+ [%timebox =lid =(list notification)]
153+ :: %place-stats: description of .stats for a .place
154+ [%place-stats =place =stats]
155+ :: %place-stats: stats for all .places
156+ [%all-stats places=(map place stats)]
157+ ==
158+--
159+
base-desk/sur/hood.hoonnew file+401
@@ -0,0 +1,401 @@
1+/% kelvin %kelvin
2+=, clay
3+=* dude dude:gall
4+|%
5++$ pike
6+ $: sync=(unit [=ship =desk])
7+ hash=@uv
8+ =zest
9+ wic=(set weft)
10+ ==
11+::
12++$ pikes (map desk pike)
13+:: $jump: changes to update source change requests
14+::
15++$ jump
16+ $% [%all all=(map dock dock)] :: pending requests
17+ [%add old=dock new=dock] :: new request
18+ [%yea old=dock new=dock] :: approved
19+ [%nay old=dock new=dock] :: denied
20+ ==
21+:: $rung: reference to upstream commit
22+::
23++$ rung [=aeon =weft]
24+:: #sync-record: source and destination of a kiln sync
25+::
26++$ sync-record ::
27+ $: syd=desk :: local desk
28+ her=ship :: foreign ship
29+ sud=desk :: foreign desk
30+ ==
31+::
32++$ sync-state ::
33+ $: nun=@ta :: nonce
34+ kid=(unit desk) :: has kids desk too?
35+ let=@ud :: next revision
36+ nit=(unit ?) :: automerge or default
37+ hav=(unit @ud) :: update available
38+ yea=? :: update approved
39+ ==
40+::
41++$ sync-update
42+ $% [%new for=sync-record rev=@ud]
43+ [%done for=sync-record rev=@ud]
44+ [%drop for=sync-record rev=@ud]
45+ [%pending pending=(set [for=sync-record rev=@ud])]
46+ ==
47+::
48++$ sink (unit [her=@p sud=desk kid=(unit desk) let=@ud])
49+:: +truncate-hash: get last 5 digits of hash and convert to tape
50+::
51+++ truncate-hash
52+ |= hash=@uv
53+ ^- tape
54+ (slag 2 <`@uv`(mod hash 0v1.00000)>)
55+:: +report-prep: get data required for reports
56+::
57+++ report-prep
58+ |= [our=@p now=@da]
59+ =/ ego (scot %p our)
60+ =/ wen (scot %da now)
61+ :* .^(rock:tire %cx /[ego]//[wen]/tire)
62+ .^(cone %cx /[ego]//[wen]/domes)
63+ .^((map desk [ship desk]) %gx /[ego]/hood/[wen]/kiln/sources/noun)
64+ .^ (map [desk ship desk] sync-state) %gx
65+ /[ego]/hood/[wen]/kiln/syncs/noun
66+ ==
67+ ==
68+:: +report-vats: report on all desk installations
69+::
70+++ report-vats
71+ |= [our=@p now=@da desks=(list desk) filt=@tas verb=?]
72+ ^- tang
73+ =/ ego (scot %p our)
74+ =/ wen (scot %da now)
75+ =+ prep=[tyr cone sor zyn]=(report-prep our now)
76+ ?: =(%$ filt)
77+ %- zing
78+ %+ turn
79+ ?^ desks
80+ (flop desks)
81+ %+ sort ~(tap in ~(key by tyr.prep))
82+ |= [a=desk b=desk]
83+ ?: |(=(a %kids) =(b %base)) &
84+ ?: |(=(a %base) =(b %kids)) |
85+ (aor b a)
86+ |=(syd=@tas (report-vat prep our now syd verb))
87+ =/ deks=(list [=desk =zest wic=(set weft)])
88+ ?~ desks
89+ %+ sort ~(tap by tyr.prep)
90+ |= [[a=desk *] [b=desk *]]
91+ ?: |(=(a %kids) =(b %base)) &
92+ ?: |(=(a %base) =(b %kids)) |
93+ (aor b a)
94+ %+ murn (flop desks)
95+ |= des=desk
96+ ^- (unit [=desk =zest wic=(set weft)])
97+ ?~ got=(~(get by tyr.prep) des)
98+ ~
99+ `[des u.got]
100+ ?: =(filt %blocking)
101+ =/ base-weft=(unit weft)
102+ %- ~(rep in wic:(~(got by tyr.prep) %base))
103+ |= [=weft out=(unit weft)]
104+ ?~ out
105+ `weft
106+ ?: (lth num.weft num.u.out)
107+ out
108+ `weft
109+ ?~ base-weft ~['%base already up-to-date']
110+ =/ blockers=(list desk)
111+ %+ sort
112+ ^- (list desk)
113+ %+ murn deks
114+ |= [=desk =zest wic=(set weft)]
115+ ^- (unit ^desk)
116+ ?. =(%live zest)
117+ ~
118+ ?: (~(has in wic) u.base-weft)
119+ ~
120+ `desk
121+ aor
122+ ?~ blockers ~['No desks blocking upgrade']
123+ %- zing
124+ ^- (list tang)
125+ :- :~ %+ rap 3
126+ :~ 'These desks are blocking upgrade to [%zuse '
127+ (scot %ud num.u.base-weft)
128+ ']:'
129+ == ==
130+ %+ turn blockers
131+ |=(syd=desk (report-vat prep our now syd verb))
132+ ::
133+ %- zing
134+ %+ turn
135+ ?+ filt !!
136+ %exists
137+ %+ skip deks
138+ |= [syd=desk *]
139+ ?~ got=(~(get by cone.prep) our syd)
140+ &
141+ =(0 let.u.got)
142+ ::
143+ %running
144+ %+ skim deks
145+ |=([* [zest=@tas *]] =(zest %live))
146+ ::
147+ %suspended
148+ %+ skip deks
149+ |= [syd=@tas [zest=@tas *]]
150+ ?| =(syd %kids)
151+ =(zest %live)
152+ ?~ got=(~(get by cone.prep) our syd)
153+ &
154+ =(0 let.u.got)
155+ ==
156+ ::
157+ %exists-not
158+ %+ skim deks
159+ |= [syd=desk *]
160+ ?~ got=(~(get by cone.prep) our syd)
161+ |
162+ =(0 let.u.got)
163+ ==
164+ |=([syd=desk *] (report-vat prep our now syd verb))
165+:: +report-vat: report on a single desk installation
166+::
167+++ report-vat
168+ |= $: $: tyr=rock:tire =cone sor=(map desk (pair ship desk))
169+ zyn=(map [desk ship desk] sync-state)
170+ ==
171+ our=ship now=@da syd=desk verb=?
172+ ==
173+ |^ ^- tang
174+ =/ ego (scot %p our)
175+ =/ wen (scot %da now)
176+ ?. ((sane %tas) syd)
177+ ~[(cat 3 'insane desk: %' syd)]
178+ ?. (~(has by cone) our syd)
179+ ~[(cat 3 'desk does not yet exist: %' syd)]
180+ =/ hash .^(@uv %cz /[ego]/[syd]/[wen])
181+ ?: =(%kids syd)
182+ ~[(cat 3 '%kids %cz hash: ' (scot %uv hash))]
183+ =/ kel-path /[ego]/[syd]/[wen]/sys/kelvin
184+ ?. .^(? %cu kel-path)
185+ ~[(cat 3 'bad desk: %' syd)]
186+ =+ .^(=waft %cx kel-path)
187+ ^- tang
188+ =/ =sink
189+ ?~ s=(~(get by sor) syd)
190+ ~
191+ ?~ z=(~(get by zyn) syd u.s)
192+ ~
193+ `[p.u.s q.u.s [kid let]:u.z]
194+ =/ meb=(list @uv)
195+ ?~ sink ~[hash]
196+ %+ turn
197+ .^ (list tako) %cs
198+ /[ego]/[syd]/[wen]/base/(scot %p her.u.sink)/[sud.u.sink]
199+ ==
200+ |=(=tako .^(@uv %cs /[ego]/[syd]/[wen]/hash/(scot %uv tako)))
201+ =/ dek (~(got by tyr) syd)
202+ =/ sat
203+ ?- zest.dek
204+ %live 'running'
205+ %dead 'suspended'
206+ %held 'suspended until next update'
207+ ==
208+ =/ kul=cord (print-wefts (waft-to-wefts waft))
209+ =/ ese=cord
210+ ?:(.^(? %cx /[ego]//[wen]/esse/[syd]) 'yes' 'no')
211+ =/ pax=path /(scot %p our)/[syd]/(scot %da now)
212+ ?. verb
213+ :~ '::'
214+ =+ .^(exist=? cu+(weld pax /desk/bill))
215+ ?. exist ' /desk/bill: missing'
216+ =+ .^(dudes=(list dude:gall) cx+(weld pax /desk/bill))
217+ (cat 3 ' /desk/bill: ' (crip "{<dudes>}"))
218+ (cat 3 ' pending updates: ' (print-wefts wic.dek))
219+ (cat 3 ' source ship: ' ?~(sink '~' (scot %p her.u.sink)))
220+ (cat 3 ' app status: ' sat)
221+ (cat 3 ' essential desk: ' ese)
222+ (cat 3 ' %cz hash ends in: ' (print-shorthash hash))
223+ (cat 3 ' /sys/kelvin: ' (print-wefts (waft-to-wefts waft)))
224+ (cat 3 '%' syd)
225+ ==
226+ ::
227+ =/ [on=(list @tas) of=(list @tas)]
228+ =/ [on=(list @tas) of=(list @tas)]
229+ %- ~(rep by ren:(~(got by cone) our syd))
230+ |= [[=dude:gall is-on=?] on=(list @tas) of=(list @tas)]
231+ ?: is-on
232+ [[dude on] of]
233+ [on [dude of]]
234+ [(sort on aor) (sort of aor)]
235+ :~ '::'
236+ (cat 3 ' pending updates: ' (print-wefts wic.dek))
237+ %^ cat 3 ' kids desk: ' ?~ sink '~'
238+ ?~ kid.u.sink '~'
239+ (cat 3 '%' u.kid.u.sink)
240+ (cat 3 ' source aeon: ' ?~(sink '~' (scot %ud let.u.sink)))
241+ (cat 3 ' source desk: ' ?~(sink '~' (cat 3 '%' sud.u.sink)))
242+ (cat 3 ' source ship: ' ?~(sink '~' (scot %p her.u.sink)))
243+ (cat 3 ' updates: ' ?~(sink 'local' 'remote'))
244+ %^ cat 3 ' publishing ship: ' ?~ got=(get-publisher our syd now)
245+ '~'
246+ (scot %p u.got)
247+ ::
248+ (cat 3 ' force off: ' (print-agents of))
249+ (cat 3 ' force on: ' (print-agents on))
250+ (cat 3 ' app status: ' sat)
251+ (cat 3 ' essential desk: ' ese)
252+ ::
253+ (cat 3 ' %cz hash: ' (scot %uv hash))
254+ (cat 3 ' base hash: ' (print-mergebases meb))
255+ (cat 3 ' /sys/kelvin: ' (print-wefts (waft-to-wefts waft)))
256+ (cat 3 '%' syd)
257+ ==
258+ ++ print-wefts
259+ |= wefts=(set weft)
260+ ^- @t
261+ ?: =(~ wefts)
262+ '~'
263+ %+ roll (sort ~(tap in wefts) aor)
264+ |= [=weft out=@t]
265+ ?: =('' out)
266+ (rap 3 '[%' lal.weft ' ' (scot %ud num.weft) ']' ~)
267+ (rap 3 out ' [%' lal.weft ' ' (scot %ud num.weft) ']' ~)
268+ ::
269+ ++ print-shorthash
270+ |= hash=@uv
271+ ^- @t
272+ (crip ((v-co:co 5) (end [0 25] hash)))
273+ ::
274+ ++ print-mergebases
275+ |= hashes=(list @uv)
276+ ^- @t
277+ ?~ hashes
278+ '~'
279+ ?~ t.hashes
280+ (scot %uv i.hashes)
281+ %+ roll `(list @uv)`hashes
282+ |= [hash=@uv out=@t]
283+ ?: =('' out)
284+ (print-shorthash hash)
285+ (rap 3 out ' ' (print-shorthash hash) ~)
286+ ::
287+ ++ print-agents
288+ |= agents=(list @tas)
289+ ^- @t
290+ ?~ agents
291+ '~'
292+ %+ roll `(list @tas)`agents
293+ |= [agent=@tas out=@tas]
294+ ?: =('' out)
295+ (cat 3 '%' agent)
296+ (rap 3 out ' %' agent ~)
297+ --
298+:: +report-kids: non-vat cz hash report for kids desk
299+::
300+++ report-kids
301+ |= [our=ship now=@da]
302+ ^- tank
303+ =/ syd %kids
304+ =/ ego (scot %p our)
305+ =/ wen (scot %da now)
306+ ?. (~(has in .^((set desk) %cd /[ego]//[wen])) syd)
307+ 'no %kids desk'
308+ =+ .^(hash=@uv %cz /[ego]/[syd]/[wen])
309+ (cat 3 '%kids %cz hash: ' (scot %uv hash))
310+:: +read-bill-foreign: read /desk/bill from a foreign desk
311+::
312+++ read-bill-foreign
313+ |= [=ship =desk =aeon]
314+ ^- (list dude)
315+ ~| +<
316+ =/ her (scot %p ship)
317+ =/ syd (scot %tas desk)
318+ =/ yon (scot %ud aeon)
319+ ::
320+ =/ dom .^(domo cv/~[her syd yon])
321+ =/ tak ~| aeons=~(key by hit.dom)
322+ (scot %uv (~(got by hit.dom) aeon))
323+ =/ yak .^(yaki cs/~[her syd yon %yaki tak])
324+ =/ fil (~(get by q.yak) /desk/bill)
325+ ?~ fil ~
326+ =/ lob (scot %uv u.fil)
327+ =/ peg .^(page cs/~[her syd yon %blob lob])
328+ ;;((list dude) q.peg)
329+:: +read-bill: read contents of /desk/bill manifest
330+::
331+++ read-bill
332+ |= [our=ship =desk now=@da]
333+ =/ pax (en-beam [our desk da+now] /desk/bill)
334+ ?. .^(? cu/pax)
335+ *(list dude)
336+ .^((list dude) cx/pax)
337+::
338+++ get-remote-diff
339+ |= [our=ship here=desk now=@da her=ship there=desk when=aeon]
340+ =+ .^(our-hash=@uv cz/[(scot %p our) here (scot %da now) ~])
341+ =+ .^(her-hash=@uv cz/[(scot %p her) there (scot %ud when) ~])
342+ !=(our-hash her-hash)
343+::
344+++ get-publisher
345+ |= [our=ship =desk now=@da]
346+ ^- (unit ship)
347+ =/ pax /(scot %p our)/[desk]/(scot %da now)/desk/ship
348+ ?. .^(? %cu pax) ~
349+ `.^(ship %cx pax)
350+::
351+++ get-apps-live
352+ |= [our=ship =desk now=@da]
353+ ^- (list dude)
354+ %+ murn (get-apps-have our desk now)
355+ |=([=dude live=?] ?.(live ~ `dude))
356+:: +get-apps-have: find which apps Gall is running on a desk
357+::
358+++ get-apps-have
359+ |= [our=ship =desk now=@da]
360+ ^- (list [=dude live=?])
361+ %~ tap in
362+ .^((set [=dude live=?]) ge+/(scot %p our)/[desk]/(scot %da now)/$)
363+::
364+++ mergebase-hashes
365+ |= [our=@p syd=desk now=@da her=ship sud=desk]
366+ =/ her (scot %p her)
367+ =/ ego (scot %p our)
368+ =/ wen (scot %da now)
369+ %+ turn .^((list tako) %cs /[ego]/[syd]/[wen]/base/[her]/[sud])
370+ |=(=tako .^(@uv %cs /[ego]/[syd]/[wen]/hash/(scot %uv tako)))
371+::
372+++ enjs
373+ =, enjs:format
374+ |%
375+ ++ tim
376+ |= t=@
377+ ^- json
378+ (numb (fall (mole |.((unm:chrono:userlib t))) 0))
379+ ::
380+ ++ cass
381+ |= c=^cass
382+ %- pairs
383+ :~ ud+(numb ud.c)
384+ da+(tim da.c)
385+ ==
386+ ::
387+ ++ weft
388+ |= w=^weft
389+ %- pairs
390+ :~ name+s+lal.w
391+ kelvin+(numb num.w)
392+ ==
393+ ::
394+ ++ rung
395+ |= r=^rung
396+ %- pairs
397+ :~ aeon+(numb aeon.r)
398+ weft+(weft weft.r)
399+ ==
400+ --
401+--
base-desk/sur/json/rpc.hoonnew file+28
@@ -0,0 +1,28 @@
1+:: json-rpc: protocol types
2+::
3+|%
4++$ batch-request
5+ $% [%a p=(list request)]
6+ [%o p=request]
7+ ==
8+::
9++$ request
10+ $: id=@t
11+ jsonrpc=@t
12+ method=@t
13+ params=request-params
14+ ==
15+::
16++$ request-params
17+ $% [%list (list json)]
18+ [%map (map @t json)]
19+ [%object (list (pair @t json))]
20+ ==
21++$ response
22+ $~ [%fail *httr:eyre]
23+ $% [%result id=@t res=json]
24+ [%error id=@t code=@t message=@t] ::TODO data?
25+ [%fail hit=httr:eyre]
26+ [%batch bas=(list response)]
27+ ==
28+--
base-desk/sur/keygen.hoonnew file+23
@@ -0,0 +1,23 @@
1+|%
2++$ revision @ud
3++$ nodetype tape
4++$ mnemonic tape
5+::
6++$ vault
7+ $: ownership=node
8+ voting=node
9+ management=node
10+ transfer=node
11+ spawn=node
12+ network=uode
13+ ==
14+::
15++$ node [type=nodetype seed=mnemonic keys=wallet]
16++$ uode [revi=revision seed=@ux keys=edkeys]
17+::
18++$ wallet [keys=[public=@ux private=@ux] addr=@ux chain=@ux]
19+::
20++$ edkeys [auth=keypair crypt=keypair]
21+::
22++$ keypair [public=@ux secret=@ux]
23+--
base-desk/sur/language-server.hoonnew file+114
@@ -0,0 +1,114 @@
1+|%
2+::
3++$ versioned-doc-id
4+ [uri=@t version=(unit @)]
5+::
6+++ request
7+ |%
8+ +$ all
9+ $%
10+ text-document--hover
11+ text-document--completion
12+ unknown
13+ ==
14+ +$ text-document--hover
15+ [%text-document--hover id=cord position versioned-doc-id]
16+ +$ text-document--completion
17+ [%text-document--completion id=cord position versioned-doc-id]
18+ +$ unknown
19+ [%unknown json]
20+ --
21+++ response
22+ |%
23+ +$ all
24+ $%
25+ text-document--hover
26+ text-document--completion
27+ ==
28+ +$ text-document--hover
29+ [%text-document--hover id=cord contents=(unit @t)]
30+ +$ text-document--completion
31+ [%text-document--completion id=cord completion=(list completion-item)]
32+ --
33+::
34++$ completion-item
35+ $:
36+ label=cord
37+ kind=@ud
38+ detail=cord
39+ doc=cord
40+ insert-text=cord
41+ insert-text-format=@ud
42+ ==
43+
44+
45+
46+::
47++$ diagnostic
48+ [=range severity=@ud message=@t]
49+::
50++$ position
51+ [row=@ud col=@ud]
52+::
53++$ text-document-item
54+ [uri=@t version=(unit @) text=@t]
55+::
56+++ notification
57+ |%
58+ ::
59+ +$ in
60+ $%
61+ text-document--did-change
62+ text-document--did-open
63+ text-document--did-save
64+ text-document--did-close
65+ exit
66+ unknown
67+ ==
68+ ::
69+ +$ out
70+ $%
71+ text-document--publish-diagnostics
72+ ==
73+ ::
74+ +$ all
75+ $%
76+ out
77+ in
78+ ==
79+ ::
80+ +$ text-document--did-change
81+ [%text-document--did-change versioned-doc-id changes=(list change)]
82+ ::
83+ +$ text-document--did-open
84+ [%text-document--did-open text-document-item]
85+ ::
86+ +$ text-document--did-save
87+ [%text-document--did-save versioned-doc-id]
88+ ::
89+ +$ text-document--did-close
90+ [%text-document--did-close versioned-doc-id]
91+ ::
92+ +$ exit
93+ [%exit ~]
94+ ::
95+ +$ unknown
96+ [%unknown =json]
97+ ::
98+ +$ text-document--publish-diagnostics
99+ [%text-document--publish-diagnostics uri=@t diagnostics=(list diagnostic)]
100+ ::
101+ --
102+::
103++$ change
104+ $: range=(unit range)
105+ range-length=(unit @ud)
106+ text=@t
107+ ==
108+::
109++$ range
110+ $: start=position
111+ end=position
112+ ==
113+::
114+--
base-desk/sur/ring.hoonnew file+47
@@ -0,0 +1,47 @@
1+|%
2+:: +raw-ring-signature: low level ring signature type
3+::
4+:: The :s field of a ring signature grows O(n) with the number of
5+:: participants in the ring.
6+::
7+++ raw-ring-signature
8+ $: ch0=@
9+ ::
10+ s=(list @)
11+ :: linked ring signature tag
12+ ::
13+ :: Two linked ring signatures with the same link scope can be shown to
14+ :: have been made by the same private key, leading to Sybil
15+ :: resistance...but if your private keys are compromised, your
16+ :: adversary can determine which signatures you made.
17+ ::
18+ y=(unit @uxpoint)
19+ ==
20+:: +ring-signature: higher level ring signature type
21+::
22+:: This contains all the identifying information to verify a ring signature
23+:: in an urbit context.
24+::
25+++ ring-signature
26+ $: :: a ring signature is computed over a set of public keys. the
27+ :: participants set is not those keys, but static references to them.
28+ ::
29+ participants=(set [ship=@p =life])
30+ :: the linkage scope this signature was made on
31+ ::
32+ link-scope=(unit *)
33+ :: the rest of the low level ring signature is appended
34+ ::
35+ raw=raw-ring-signature
36+ ==
37+::
38++$ ring-group
39+ $: :: a ring signature is computed over a set of public keys. the
40+ :: participants set is not those keys, but static references to them.
41+ ::
42+ participants=(set [ship=@p =life])
43+ :: the linkage scope this signature was made on
44+ ::
45+ link-scope=(unit *)
46+ ==
47+--
base-desk/sur/settings.hoonnew file+44
@@ -0,0 +1,44 @@
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+--
base-desk/sur/sole.hoonnew file+88
@@ -0,0 +1,88 @@
1+::
2+:::: /hoon/sole/sur
3+ ::
4+^?
5+|%
6++$ sole-id [who=@p ses=@ta]
7++$ sole-action :: sole to app
8+ $: id=sole-id :: session id
9+ $= dat
10+ $% :: [%abo ~] :: reset interaction
11+ [%det sole-change] :: command line edit
12+ [%ret ~] :: submit and clear
13+ [%clr ~] :: exit context
14+ [%tab pos=@ud] :: tab complete
15+ == ::
16+ ==
17++$ sole-buffer (list @c) :: command state
18++$ sole-change :: network change
19+ $: ler=sole-clock :: destination clock
20+ haw=@uvH :: source hash
21+ ted=sole-edit :: state change
22+ == ::
23++$ sole-clock [own=@ud his=@ud] :: vector clock
24++$ sole-edit :: shared state change
25+ $% [%del p=@ud] :: delete one at
26+ [%ins p=@ud q=@c] :: insert at
27+ [%mor p=(list sole-edit)] :: combination
28+ [%nop ~] :: no-op
29+ [%set p=sole-buffer] :: discontinuity
30+ == ::
31++$ sole-effect :: app to sole
32+ $% [%bel ~] :: beep
33+ [%blk p=@ud q=@c] :: blink+match char at
34+ [%bye ~] :: close session
35+ [%clr ~] :: clear screen
36+ [%det sole-change] :: edit command
37+ [%err p=@ud] :: error point
38+ [%klr p=styx] :: styled text line
39+ [%mor p=(list sole-effect)] :: multiple effects
40+ [%nex ~] :: save clear command
41+ [%pro sole-prompt] :: set prompt
42+ [%sag p=path q=*] :: save to jamfile
43+ [%sav p=path q=@] :: save to file
44+ [%tab p=(list [=cord =tank])] :: tab-complete list
45+ [%tan p=(list tank)] :: classic tank
46+ :: [%taq p=tanq] :: modern tank
47+ [%txt p=tape] :: text line
48+ [%url p=@t] :: activate url
49+ == ::
50++$ sole-command :: command state
51+ $: pos=@ud :: cursor position
52+ say=sole-share :: cursor
53+ == ::
54++$ sole-prompt :: prompt definition
55+ $: vis=? :: command visible
56+ tag=term :: history mode
57+ cad=styx :: caption
58+ == ::
59++$ sole-share :: symmetric state
60+ $: ven=sole-clock :: our vector clock
61+ leg=(list sole-edit) :: unmerged edits
62+ buf=sole-buffer :: sole state
63+ == ::
64+:: ::
65+:: ::
66+++ sole-dialog :: standard dialog
67+ |* out=$-(* *) :: output structure
68+ $-(sole-input (sole-result out)) :: output function
69+:: ::
70++$ sole-input tape :: prompt input
71+++ sole-result :: conditional result
72+ |* out=$-(* *) :: output structure
73+ $@(@ud (sole-product out)) :: error position
74+:: ::
75+++ sole-product :: success result
76+ |* out=$-(* *) ::
77+ %+ pair (list tank) ::
78+ %+ each (unit out) :: ~ is abort
79+ (pair sole-prompt (sole-dialog out)) :: ask and continue
80+:: ::
81++$ sole-gen :: XX virtual type
82+ $% [%say $-((sole-args) (cask))] :: direct noun
83+ [%ask $-((sole-args) (sole-product (cask)))] :: dialog
84+ == ::
85+++ sole-args :: generator arguments
86+ |* _[* *] ::
87+ ,[[now=@da eny=@uvJ bek=beak] [,+<- ,+<+]] ::
88+--
base-desk/sur/spider.hoonnew file+27
@@ -0,0 +1,27 @@
1+/+ libstrand=strand
2+=, strand=strand:libstrand
3+|%
4++$ thread $-(vase shed:khan)
5++$ input [=tid =cage]
6++$ tid tid:strand
7++$ bowl bowl:strand
8++$ http-error
9+ $? %bad-request :: 400
10+ %forbidden :: 403
11+ %nonexistent :: 404
12+ %offline :: 504
13+ ==
14++$ start-args
15+ $: parent=(unit tid)
16+ use=(unit tid)
17+ =beak
18+ file=term
19+ =vase
20+ ==
21++$ inline-args
22+ $: parent=(unit tid)
23+ use=(unit tid)
24+ =beak
25+ =shed:khan
26+ ==
27+--
base-desk/sur/sss.hoonnew file+39
@@ -0,0 +1,39 @@
1+|%
2+++ lake
3+ |$ [rock wave]
4+ $_ ^?
5+ |%
6+ ++ name *term
7+ +$ rock ^rock
8+ +$ wave ^wave
9+ ++ wash |~ [rock wave] *rock
10+ --
11++$ aeon @ud
12++$ dude dude:agent:gall
13+++ poke
14+ |%
15+ ++ request
16+ |* paths=mold
17+ $: path=paths
18+ =dude
19+ ==
20+ ++ response
21+ |* [=(lake) paths=mold]
22+ $: path=paths
23+ =dude
24+ $% [what=%tomb ~]
25+ [what=%rock =aeon =rock:lake]
26+ [what=%wave =aeon =wave:lake]
27+ == ==
28+ ++ on-rock
29+ |* [=(lake) paths=mold]
30+ $: path=paths
31+ src=ship
32+ from=dude
33+ stale=?
34+ fail=?
35+ =rock:lake
36+ wave=(unit wave:lake)
37+ ==
38+ --
39+--
base-desk/sur/story.hoonnew file+9
@@ -0,0 +1,9 @@
1+^?
2+|%
3++$ prose [title=@t body=@t]
4++$ proses (set prose)
5++$ story (jug tako:clay prose) :: set len > 1 means conflicting messages have been assigned
6++$ chapter [tako:clay proses] :: prose entry type
7++$ cash $%([%tako p=tako:clay] case) :: used in generators to accept a tako directly as well
8++$ story-diff [additions=story deletions=story]
9+--
base-desk/sur/verb.hoonnew file+48
@@ -0,0 +1,48 @@
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+::
13++$ event-plus
14+ $: act=@ud
15+ now=@da
16+ src=@p
17+ sap=path
18+ =cause
19+ effects=(list effect)
20+ ==
21+::
22++$ cause
23+ $% [%on-init ~]
24+ [%on-load ~]
25+ [%on-poke =mark mug=@ux]
26+ [%on-watch =path]
27+ [%on-leave =path]
28+ [%on-agent =wire =sign]
29+ [%on-arvo =wire vane=term sign=term]
30+ [%on-fail =term]
31+ ==
32+::
33++$ sign
34+ $% [%poke-ack ack=?]
35+ [%watch-ack ack=?]
36+ [%kick ~]
37+ [%fact =mark mug=@ux]
38+ ==
39+::
40++$ effect
41+ $% [%poke =wire =gill:gall =mark mug=@ux]
42+ [%watch =wire =gill:gall =path]
43+ [%leave =wire =gill:gall]
44+ [%fact paths=(list path) =mark mug=@ux]
45+ [%kick paths=(list path)]
46+ [%arvo =wire vane=term task=term]
47+ ==
48+--
bin/commit.shnew file+24
@@ -0,0 +1,24 @@
1+#!/bin/bash
2+
3+usage() { printf "Usage: $0 URBIT_DESK_DIRECTORY\n" 1>&2; exit 1; }
4+
5+cdir=$(dirname $0)
6+
7+if [ $# -eq 0 ]; then
8+ usage
9+ exit 2
10+fi
11+DESK_DIR=${@: -1}
12+DESK_DIR="${DESK_DIR/#\~/$HOME}"
13+PIER=$(dirname $DESK_DIR)
14+DESK=$(basename $DESK_DIR)
15+
16+port=$(cat $PIER/.http.ports | grep loopback | tr -s ' ' '\n' | head -n 1)
17+
18+lensa() {
19+ curl -s \
20+ --data "{\"source\":{\"dojo\":\"$2\"},\"sink\":{\"app\":\"$1\"}}" \
21+ "http://localhost:$port" | xargs printf %s | sed 's/\\n/\n/g'
22+}
23+
24+lensa 'hood' "+hood/commit %$DESK"
bin/get_glob.shnew file+19
@@ -0,0 +1,19 @@
1+#!/bin/bash
2+
3+usage() { printf "Usage: $0 URBIT_GLOBBER_DESK_DIRECTORY" 1>&2; exit 1; }
4+
5+cdir=$(dirname $0)
6+
7+if [ $# -eq 0 ]; then
8+ usage
9+ exit 2
10+fi
11+DESK="${1//\~/$HOME}"
12+GLOBS="$DESK/../.urb/put"
13+GLOB=$(ls -t $GLOBS | head -1)
14+TARGET_GLOBS="$cdir"/../globs/
15+mkdir -p $TARGET_GLOBS
16+cp "$GLOBS/$GLOB" $TARGET_GLOBS/
17+HASH="${GLOB//glob-/}"
18+HASH="${HASH//.glob/}"
19+echo $HASH
bin/install.shnew file+82
@@ -0,0 +1,82 @@
1+#!/bin/bash
2+#
3+# Taken from: https://github.com/timlucmiptev/btc-agents/blob/master/install.sh
4+# by ~timluc-miptev
5+#
6+# Modified HEAVILY
7+#
8+usage() { printf "Usage: $0 [-w] [-g] URBIT_DESK_DIRECTORY\n(-w: flag to watch and live copy code)\n(-g: install built ui to globber desk)\n" 1>&2; exit 1; }
9+
10+cdir=$(dirname $0)
11+
12+if [ $# -eq 0 ]; then
13+ usage
14+ exit 2
15+fi
16+DESK_DIR=${@: -1}
17+DESK_DIR="${DESK_DIR/#\~/$HOME}"
18+PIER=$(dirname $DESK_DIR)
19+DESK=$(basename $DESK_DIR)
20+EXCLUDE_FILE="${cdir}"/../config/ignore_files_on_install.txt
21+
22+port=$(cat $PIER/.http.ports | grep loopback | tr -s ' ' '\n' | head -n 1)
23+
24+lensd() {
25+ curl -s \
26+ --data "{\"source\":{\"dojo\":\"$1\"},\"sink\":{\"stdout\":null}}" \
27+ "http://localhost:$port" | xargs printf %s | sed 's/\\n/\n/g'
28+}
29+
30+lensa() {
31+ curl -s \
32+ --data "{\"source\":{\"dojo\":\"$2\"},\"sink\":{\"app\":\"$1\"}}" \
33+ "http://localhost:$port" | xargs printf %s | sed 's/\\n/\n/g'
34+}
35+
36+sync() {
37+ rsync -r --copy-links --exclude-from=$EXCLUDE_FILE "${cdir}"/../base-desk/* $DESK_DIR/
38+ rsync -r --copy-links --exclude-from=$EXCLUDE_FILE "${cdir}"/../docs-dev-desk/* $DESK_DIR/
39+ rsync -r --copy-links --exclude-from=$EXCLUDE_FILE "${cdir}"/../desk/* $DESK_DIR/
40+ if [ "$GLOBBER" ]; then
41+ rsync -r --copy-links "${cdir}"/../ui/dist/* $DESK_DIR/astrolabe
42+ fi
43+}
44+
45+
46+while getopts "wg" opt; do
47+ case ${opt} in
48+ w) WATCH_MODE="true"
49+ ;;
50+ g) GLOBBER="true"
51+ ;;
52+ *) usage
53+ ;;
54+ esac
55+done
56+
57+if [ -z "$WATCH_MODE" ]; then
58+ echo "Installed %astrolabe to ${DESK_DIR}"
59+ rm -r $DESK_DIR/*
60+ sync
61+ lensa 'hood' "+hood/commit %$DESK"
62+ if [ "$GLOBBER" ]; then
63+ lensd '-garden!make-glob %globber /astrolabe'
64+ GLOBS="$PIER/.urb/put"
65+ GLOB=$(ls -t $GLOBS | head -1)
66+ TARGET_GLOBS="$cdir"/../globs/
67+ mkdir -p $TARGET_GLOBS
68+ cp "$GLOBS/$GLOB" $TARGET_GLOBS/
69+ echo "copied from $GLOBS to $TARGET_GLOBS"
70+ HASH="${GLOB//glob-/}"
71+ HASH="${HASH//.glob/}"
72+ echo $HASH
73+ fi
74+else
75+ echo "Watching for changes to copy to ${DESK_DIR}..."
76+ rm -r $DESK_DIR/*
77+ while [ 0 ]
78+ do
79+ sleep 0.8
80+ sync
81+ done
82+fi
bin/make_glob.pynew file+208
@@ -0,0 +1,208 @@
1+#!/usr/bin/env python3
2+
3+import hashlib
4+import sys
5+from pathlib import Path
6+from urllib.parse import quote
7+
8+from noun import Cell, deep, intbytes, mug
9+
10+MIME_TYPES = {
11+ "css": "text/css",
12+ "gif": "image/gif",
13+ "html": "text/html",
14+ "ico": "image/x-icon",
15+ "jpeg": "image/jpeg",
16+ "jpg": "image/jpeg",
17+ "js": "application/javascript",
18+ "json": "application/json",
19+ "png": "image/png",
20+ "svg": "image/svg+xml",
21+ "ttf": "font/ttf",
22+ "webmanifest": "application/manifest+json",
23+ "woff": "font/woff",
24+ "woff2": "font/woff2",
25+}
26+BASE32 = "0123456789abcdefghijklmnopqrstuv"
27+
28+
29+class BitWriter:
30+ def __init__(self):
31+ self.output = bytearray()
32+ self.buffer = 0
33+ self.used = 0
34+ self.cursor = 0
35+
36+ def write(self, value, count):
37+ if count == 0:
38+ return
39+ self.buffer |= value << self.used
40+ self.used += count
41+ self.cursor += count
42+ byte_count = self.used // 8
43+ if byte_count:
44+ self.output.extend(self.buffer.to_bytes((self.used + 7) // 8, "little")[:byte_count])
45+ self.buffer >>= byte_count * 8
46+ self.used -= byte_count * 8
47+
48+ def finish(self):
49+ if self.used:
50+ self.output.append(self.buffer)
51+ self.buffer = 0
52+ self.used = 0
53+ return bytes(self.output)
54+
55+
56+def jam_bytes(value):
57+ writer = BitWriter()
58+ references = {}
59+
60+ def save(noun):
61+ references[noun] = writer.cursor
62+
63+ def mat(atom):
64+ if atom == 0:
65+ writer.write(1, 1)
66+ return
67+ atom_length = atom.bit_length()
68+ length_size = atom_length.bit_length()
69+ writer.write(1 << length_size, length_size + 1)
70+ writer.write(atom_length & ((1 << (length_size - 1)) - 1), length_size - 1)
71+ writer.write(atom, atom_length)
72+
73+ def back(reference):
74+ writer.write(3, 2)
75+ mat(reference)
76+
77+ def serialize(noun):
78+ duplicate = references.get(noun)
79+ if deep(noun):
80+ if duplicate is not None:
81+ back(duplicate)
82+ return
83+ save(noun)
84+ writer.write(1, 1)
85+ writer.write(0, 1)
86+ serialize(noun.head)
87+ serialize(noun.tail)
88+ return
89+ if duplicate is not None:
90+ atom_size = noun.bit_length()
91+ reference_size = duplicate.bit_length()
92+ if atom_size >= reference_size:
93+ back(duplicate)
94+ return
95+ save(noun)
96+ writer.write(0, 1)
97+ mat(noun)
98+
99+ serialize(value)
100+ return writer.finish()
101+
102+
103+def cord(value):
104+ return int.from_bytes(value.encode(), "little")
105+
106+
107+def path_noun(parts):
108+ result = 0
109+ for part in reversed(parts):
110+ result = Cell(cord(part), result)
111+ return result
112+
113+
114+def dor(a, b):
115+ if a == b:
116+ return True
117+ if deep(a):
118+ if not deep(b):
119+ return False
120+ if a.head == b.head:
121+ return dor(a.tail, b.tail)
122+ return dor(a.head, b.head)
123+ if deep(b):
124+ return True
125+ return a < b
126+
127+
128+def gor(a, b):
129+ a_mug = mug(a)
130+ b_mug = mug(b)
131+ return dor(a, b) if a_mug == b_mug else a_mug < b_mug
132+
133+
134+def map_put(tree, entry):
135+ if tree == 0:
136+ return Cell(entry, Cell(0, 0))
137+ node = tree.head
138+ if entry.head == node.head:
139+ return Cell(entry, tree.tail)
140+ left = tree.tail.head
141+ right = tree.tail.tail
142+ if gor(entry.head, node.head):
143+ return Cell(node, Cell(map_put(left, entry), right))
144+ return Cell(node, Cell(left, map_put(right, entry)))
145+
146+
147+def shas(salt, serialized):
148+ value_hash = int.from_bytes(hashlib.sha256(serialized).digest(), "little")
149+ length = max(32, len(intbytes(salt)))
150+ digest = hashlib.sha256((salt ^ value_hash).to_bytes(length, "little")).digest()
151+ return int.from_bytes(digest, "little")
152+
153+
154+def sham(serialized):
155+ hashed = shas(cord("sham"), serialized)
156+ mask = (1 << 128) - 1
157+ return (hashed & mask) ^ (hashed >> 128)
158+
159+
160+def scow_uv(value):
161+ if value == 0:
162+ return "0v0"
163+ digits = []
164+ while value:
165+ value, digit = divmod(value, 32)
166+ digits.append(BASE32[digit])
167+ digits = "".join(reversed(digits))
168+ first_length = (len(digits) - 1) % 5 + 1
169+ groups = [digits[:first_length]]
170+ groups.extend(digits[i:i + 5] for i in range(first_length, len(digits), 5))
171+ return "0v" + ".".join(groups)
172+
173+
174+def file_entry(root, file_path):
175+ relative = file_path.relative_to(root)
176+ parts = []
177+ for part in relative.parts:
178+ parts.extend(quote(segment, safe="-_~") for segment in part.split("."))
179+ extension = relative.suffix.removeprefix(".").lower()
180+ if extension not in MIME_TYPES:
181+ raise ValueError(f"no MIME type configured for {relative}")
182+ data = file_path.read_bytes()
183+ mime = Cell(path_noun(MIME_TYPES[extension].split("/")), Cell(len(data), int.from_bytes(data, "little")))
184+ return Cell(path_noun(parts), mime)
185+
186+
187+def make_glob(source, destination):
188+ root = Path(source)
189+ files = sorted((path for path in root.rglob("*") if path.is_file()), key=lambda path: path.as_posix())
190+ if not (root / "index.html").is_file():
191+ raise ValueError("glob source must contain index.html")
192+ glob = 0
193+ for file_path in files:
194+ glob = map_put(glob, file_entry(root, file_path))
195+ serialized = jam_bytes(glob)
196+ glob_hash = scow_uv(sham(serialized))
197+ output = Path(destination)
198+ output.mkdir(parents=True, exist_ok=True)
199+ filename = f"glob-{glob_hash}.glob"
200+ (output / filename).write_bytes(serialized)
201+ (output / "hash").write_text(glob_hash + "\n")
202+ print(filename)
203+
204+
205+if __name__ == "__main__":
206+ if len(sys.argv) != 3:
207+ raise SystemExit(f"usage: {sys.argv[0]} SOURCE_DIRECTORY OUTPUT_DIRECTORY")
208+ make_glob(sys.argv[1], sys.argv[2])
config/ignore_files_on_install.txtnew file+4
@@ -0,0 +1,4 @@
1+.*
2+*.sh
3+*.md
4+*.txt
desk/app/astrolabe.hoonnew file+345
@@ -0,0 +1,345 @@
1+/- *astrolabe
2+/+ *astrolabe, *search, slib=state
3+/+ *mip, naive, default-agent, dbug, agentio
4+/$ udon-to-docu %udon %docu
5+|%
6++$ card card:agent:gall
7+--
8+%- agent:dbug
9+=| state-latest
10+=* state -
11+^- agent:gall
12+=<
13+|_ =bowl:gall
14++* this .
15+ def ~(. (default-agent this %.n) bowl)
16+ hc ~(. +> bowl)
17+::
18+++ on-init
19+ ^- (quip card _this)
20+ :_ this
21+ :~ ug-handler-card:hc
22+ groups-link-patch-card:hc
23+ talk-link-patch-card:hc
24+ az-events-card:hc
25+ ==
26+::
27+++ on-save !>(state)
28+++ on-load
29+ |= old-state=vase
30+ ^- (quip card _this)
31+ =/ old !<(versioned-state old-state)
32+ =/ [cards-01=(list card) new=state-latest]
33+ ?. |(?=(?(%0 %1 %2 %3) -.old) (lth bump.old bump)) `old
34+ (on-naive-state:hc get-nas:hc)
35+ ?> ?=(%4 -.new)
36+ =/ cards=(list card)
37+ :~ ug-handler-card:hc
38+ groups-link-patch-card:hc
39+ talk-link-patch-card:hc
40+ ==
41+ =. cards (weld cards-01 cards)
42+ [cards this(state new)]
43+++ on-poke on-poke:def
44+++ on-watch on-watch:def
45+++ on-leave on-leave:def
46+::
47+++ on-peek
48+ |= =path
49+ ^- (unit (unit cage))
50+ ?+ path (on-peek:def path)
51+ [%x %nop ~]
52+ ``noun+!>(~)
53+ [%x %point @ ~]
54+ ``astrolabe-point+!>((get-point:hc &3.path))
55+ [%x %point @ %spawned ?(~ [spawned-filter ~])]
56+ =/ =ship `@p`(slav %p &3.path)
57+ =/ filter t.t.t.t.path
58+ =/ arg ?~(filter %all -.filter)
59+ ``astrolabe-point-set+!>((get-spawned-points:hc ship arg))
60+ [%x %search %patp @ ?(~ [%narrow ~])]
61+ =/ =search-text (trip &4.path)
62+ ?~ search-text ~|(%search-predicted-too-broad !!)
63+ =/ expand-search =(t.t.t.path ~)
64+ ``astrolabe-point-set+!>((search-opoints-patp:hc search-text expand-search))
65+ [%x %search %sigil @ ~]
66+ =/ =search-text (trip &4.path)
67+ ?~ search-text ~|(%search-predicted-too-broad !!)
68+ ``astrolabe-point-set+!>((search-opoints-sigil:hc search-text))
69+ [%x %peers ~]
70+ =/ peers .^((map ship ?(%alien %known)) %ax (scrio:hc %$ /peers))
71+ ``astrolabe-point-set+!>((turn ~(tap in peers) head))
72+ [%x %chart-data ~]
73+ ``json+!>(get-chart-data:hc)
74+ [%x %doc ^]
75+ =/ doc-path=^path t.t.path
76+ =/ doc (read-doc:hc doc-path)
77+ ?~ doc
78+ `~
79+ ``json+!>(s+u.doc)
80+ ==
81+++ on-agent
82+ |= [=wire =sign:agent:gall]
83+ ^- (quip card _this)
84+ |^
85+ ?+ wire (on-agent:def wire sign)
86+ [%azimuth-events ~] (azimuth-event sign)
87+ ==
88+ ::
89+ ++ azimuth-event
90+ |= =sign:agent:gall
91+ ^- (quip card _this)
92+ ?+ -.sign [~ this]
93+ %watch-ack
94+ ?~ p.sign [~ this]
95+ =/ =tank leaf+"{(trip dap.bowl)} couldn't start listen to %azimuth"
96+ %- (slog tank u.p.sign)
97+ [~ this]
98+ ::
99+ %fact
100+ ?+ p.cage.sign (on-agent:def wire sign)
101+ %naive-diffs
102+ =+ !<(=diff:naive q.cage.sign)
103+ =^ cards state
104+ (on-naive-diff:hc diff)
105+ [cards this]
106+ ::
107+ %naive-state
108+ :: ~& > %received-azimuth-state
109+ :: =+ !<([nas=^state:naive =indices:dice] q.cage.sign)
110+ =+ !<([nas=^state:naive indices=*] q.cage.sign)
111+ =^ cards state
112+ (on-naive-state:hc nas)
113+ [cards this]
114+ ==
115+ ==
116+ --
117+::
118+++ on-arvo on-arvo:def
119+++ on-fail on-fail:def
120+--
121+::
122+:: Helper Core
123+|_ =bowl:gall
124+++ scrio ~(scry agentio bowl)
125+++ az-events-card [%pass /azimuth-events %agent [our.bowl %azimuth] %watch /event]
126+++ get-nas .^(^state:naive %gx (scrio %azimuth /nas/noun))
127+++ put-in-fropoints
128+ |= =ship
129+ ^- _state
130+ =. fopoints
131+ (put:ors fopoints (to-q ship) ~)
132+ =. ropoints
133+ (put:ors ropoints (switch-words (to-q ship)) ~)
134+ state
135+::
136+++ put-in-spawn-mip
137+ |= [child=ship nas=^state:naive]
138+ ^- _state
139+ =/ =npoint (get-npoint-from-nas child nas)
140+ (put-in-spawn-mip:slib child npoint state)
141+::
142+++ on-naive-state
143+ |= nas=^state:naive
144+ ^- (quip card _state)
145+ =+ points=points.nas :: =points, eh?
146+ :- ~
147+ |-
148+ ^- _state
149+ ?~ points state
150+ =/ =ship -.n.points
151+ =. state (put-in-fropoints ship)
152+ =. state (put-in-spawn-mip ship nas)
153+ $(points l.points, state $(points r.points))
154+::
155+++ on-naive-diff
156+ |= =diff:naive
157+ ^- (quip card _state)
158+ :: ~& %+ weld "received diff:naive: {<-.diff>}"
159+ :: ?+ -.diff ""
160+ :: %nonce " ship: {<ship.diff>}"
161+ :: %tx " from: {<ship.from.tx.raw-tx.diff>} - {<+<.tx.raw-tx.diff>}"
162+ :: %point " ship: {<ship.diff>} - {<+>-.diff>}"
163+ :: ==
164+ =? state ?=([%tx [* * * %spawn ship *] *] diff)
165+ %- put-in-fropoints
166+ ship.tx.raw-tx.diff
167+ =? state ?=([%point @ %owner *] diff)
168+ %- put-in-fropoints
169+ ship.diff
170+ =? state ?=([%point @ *] diff)
171+ %+ put-in-spawn-mip
172+ ship.diff
173+ get-nas
174+ `state
175+::
176+++ is-spawn-tx
177+ |= =diff:naive
178+ ^- ?
179+ ?= [%tx [* * * %spawn ship *] *] diff
180+::
181+++ get-unpoint-term
182+ |= ship-name=term
183+ .^(unpoint %gx (scrio %azimuth /point/[ship-name]/noun))
184+::
185+++ get-unpoint
186+ |= =ship
187+ (get-unpoint-term (scot %p ship))
188+::
189+++ get-point
190+ |= ship-name=term
191+ ^- point
192+ =/ =ship `@p`(slav %p ship-name)
193+ =/ unpoint (get-unpoint-term ship-name)
194+ :* ship
195+ unpoint
196+ (spa-count ship)
197+ (sponsor-chain ship unpoint)
198+ (probable-dominion ship unpoint)
199+ ==
200+++ get-npoint-from-nas
201+ |= [=ship nas=^state:naive]
202+ ^- npoint
203+ (need (get:orm:naive points.nas ship))
204+::
205+++ run-spawned-points
206+ |* [agg=mold targ=ship nas=^state:naive filter=spawned-filter]
207+ |= f=$-([agg [ship npoint]] agg)
208+ ^- agg
209+ =| =agg
210+ ?. ?=(?(%czar %king) (clan:title targ))
211+ agg
212+ =+ points=points.nas
213+ |-
214+ ^- _agg
215+ ?~ points
216+ agg
217+ =* n -.n.points
218+ =/ gt=? (por:naive targ n)
219+ ?: |(=(targ n) !gt)
220+ $(points r.points)
221+ =? agg =(targ (end (add 2 (xeb (met 3 targ))) n))
222+ $(points r.points)
223+ =/ should-agg
224+ ?& =(targ (^sein:title n))
225+ ?| =(filter %all)
226+ .= =(filter %locked) (is-npoint-locked +.n.points)
227+ ==
228+ ==
229+ =? agg should-agg
230+ (f agg n.points)
231+ $(points l.points)
232+++ get-spawned-points
233+ |= [targ=ship filter=spawned-filter]
234+ =/ nas get-nas
235+ %- (run-spawned-points (list ship) targ nas filter)
236+ |= [agg=(list ship) [spawn=ship *]]
237+ [spawn agg]
238+::
239+++ spa-count
240+ |= targ=ship
241+ %- (run-spawned-points @ud targ get-nas %all)
242+ |= [agg=@ud [spawn=ship *]]
243+ +(agg)
244+::
245+++ search-opoints-patp
246+ |= [=search-text expand-search=?]
247+ ^- (list ship)
248+ =/ search-fulls
249+ ?: expand-search
250+ (search-text-to-fulls search-text)
251+ ~[(search-text-to-full search-text)]
252+ (search-opoints search-fulls)
253+::
254+++ search-opoints-sigil
255+ |= [=search-text]
256+ ^- (list ship)
257+ =/ search-fulls
258+ ~[(sigil-search-text-to-full search-text)]
259+ (search-opoints search-fulls)
260+::
261+++ search-opoints
262+ |= [search-fulls=(list search-full)]
263+ ^- (list ship)
264+ =/ mr-searches (maybe-reverse-searches search-fulls 1.000)
265+ :: ~& (turn mr-searches |=(=mr-search pain.mr-search))
266+ :: ~& mr-searches
267+ ?~ mr-searches ~|(%search-predicted-too-broad !!)
268+ =/ res
269+ %+ roll `(list mr-search)`mr-searches
270+ (run-mr-search fopoints ropoints)
271+ :: ~& "search for {<search-text>}".
272+ :: " returning {<~(wyt by agg.res)>}".
273+ :: " of {<count.res>} results"
274+ (turn ~(tap in agg.res) head)
275+::
276+++ sponsor-chain
277+ |= [=ship =unpoint]
278+ ^- (list ^ship)
279+ ?~ unpoint ~
280+ =/ sponsor sponsor.net.u.unpoint
281+ ?. has.sponsor ~
282+ =/ spon who.sponsor
283+ ?: =(spon ship) ~
284+ :- spon
285+ =/ spon-point (get-unpoint spon)
286+ $(ship spon, unpoint spon-point)
287+::
288+++ probable-dominion
289+ |= [=ship =unpoint]
290+ ^- dominion:naive
291+ ?^ unpoint
292+ dominion.u.unpoint
293+ =/ parent (^sein:title ship)
294+ ?: =(parent ship) %l1
295+ =/ parent-point (get-unpoint parent)
296+ $(ship parent, unpoint parent-point)
297+::
298+++ get-chart-data
299+ ^- json
300+ =/ nas get-nas
301+ =/ main-data
302+ ^- tape
303+ %- ~(rep by spam)
304+ |= [[=ship kids=(map ship tape)] agg=tape]
305+ ^- tape
306+ %+ weld agg
307+ %+ pdata:smel (ship:smel ship)
308+ (flop ~(val by kids))
309+ =/ gal-data
310+ %+ pdata:smel "base"
311+ %+ turn galaxies
312+ |= gal=ship
313+ =/ npoint (get-npoint-from-nas gal nas)
314+ (pdata:smel (pmeta:smel gal npoint) ~)
315+ s+(crip :(weld "[" gal-data main-data "]"))
316+::
317+::
318+++ ug-handler-card
319+ =/ ug-vase !>([/astrolabe '/apps/astrolabe/#'])
320+ [%pass /monkey-ug %agent [our.bowl %monkey] %poke [%bind-ug ug-vase]]
321+++ groups-link-patch-card
322+ =/ catch [%cord '/apps/groups/desk.js']
323+ =/ hatch [%before "."]
324+ =/ patch [/apps/groups catch hatch groups-link-thatch]
325+ =/ patch-kit-vase !>([/groups/astrolabe/link patch])
326+ [%pass /monkey/patch/groups/link %agent [our.bowl %monkey] %poke [%patch patch-kit-vase]]
327+++ talk-link-patch-card
328+ =/ catch [%cord '/apps/talk/desk.js']
329+ =/ hatch [%before "."]
330+ =/ patch [/apps/talk catch hatch groups-link-thatch]
331+ =/ patch-kit-vase !>([/talk/astrolabe/link patch])
332+ [%pass /monkey/patch/talk/link %agent [our.bowl %monkey] %poke [%patch patch-kit-vase]]
333+::
334+++ read-doc
335+ |= =path
336+ =/ doc-path=^path :(weld /doc/usr path /udon)
337+ ^- (unit @t)
338+ ?. .^(? %cu (scrio q.byk.bowl doc-path))
339+ ~
340+ =/ mme=(each manx tang) (mule |.((udon-to-docu .^(@t %cx (scrio q.byk.bowl doc-path)))))
341+ ?: ?=(%.n -.mme)
342+ %- (slog p.mme)
343+ ~
344+ `(crip (en-xml:html p.mme))
345+--
desk/desk.bill+2−1
@@ -1 +1,2 @@
1−~
1+:~ %astrolabe
2+==
desk/desk.docket-0+6−5
@@ -1,9 +1,10 @@
11:~ title+'Astrolabe'
2− info+'An Urbit app that does great things'
3− color+0x2e.4347
4− glob-http+['https://bootstrap.urbit.org/glob-0v5.hurm4.ejod5.ngg9h.iub9i.n1j7o.glob' 0v5.hurm4.ejod5.ngg9h.iub9i.n1j7o]
2+ info+'Your guide to the Urbit constellations. Search for ships, view their info, and explore the Star Chart.'
3+ color+0x1f.243c
4+ image+'https://raw.githubusercontent.com/johnhyde/astrolabe/main/ui/src/assets/astrolabe-tile.svg'
5+ glob-http+['https://s3.us-east-2.amazonaws.com/warkgnall.com/urbit/astrolabe/globs/glob-0v4.88rt1.guqn5.nnatp.lca68.ej9aj.glob' 0v4.88rt1.guqn5.nnatp.lca68.ej9aj]
56 base+'astrolabe'
6− version+[0 0 1]
7− website+'https://github.com'
7+ version+[1 0 7]
8+ website+'https://github.com/johnhyde/astrolabe'
89 license+'MIT'
910==
desk/desk.sealnew file+7
@@ -0,0 +1,7 @@
1+:- :~ [%watch & %azimuth /event]
2+ [%reads %gall `%x `%azimuth /]
3+ [%reads %clay `%u ~ /]
4+ [%reads %clay `%x ~ /]
5+ [%reads %ames `%x ~ /peers]
6+ ==
7+~
desk/doc.tocnew file+15
@@ -0,0 +1,15 @@
1+/overview/udon Overview
2+/usr User
3+ /urbit-id/udon What is an Urbit ID?
4+ /galaxy/udon Galaxies
5+ /star/udon Stars
6+ /planet/udon Planets
7+ /moon/udon Moons
8+ /comet/udon Comets
9+ /patpee/udon What is a @p?
10+ /phonemes/udon Phonemes - Prefixes & Suffixes
11+ /sigil/udon What is a Sigil?
12+ /azimuth/udon What is Azimuth?
13+ /l2/udon Layer 1 and Layer 2
14+ /keys/udon Networking Keys
15+ /astrolabe/udon About Astrolabe
desk/doc/overview.udonnew file+26
@@ -0,0 +1,26 @@
1+;>
2+# Astrolabe
3+
4+Currently Astrolabe lets you input `@p`s, Azimuth point numbers, or sigils
5+to look up ships on the network. Use the Star Chart to explore visually.
6+There's also Help Documentation if you want to learn more about how Urbit IDs work.
7+
8+[How to Use Astrolabe](/~/scry/docs/usr/astrolabe/astrolabe.html)
9+
10+## Info
11+
12+- Developer: ~midlev-mindyr
13+- License: MIT
14+- App link: [~dister-midlev-mindyr/astrolabe](web+urbitgraph://~dister-midlev-mindyr/astrolabe)
15+- Source repo: [https://github.com/johnhyde/astrolabe](https://github.com/johnhyde/astrolabe)
16+- Bug reports: [https://github.com/johnhyde/astrolabe/issues](https://github.com/johnhyde/astrolabe/issues)
17+
18+## Feedback
19+
20+If you run into issues with the app, or want to voice comments or concerns,
21+please post in the group `~poster-hoster-midlev-mindyr/astrolabe`, send a DM to `~midlev-mindyr`,
22+or [create an Issue on GitHub](https://github.com/johnhyde/astrolabe/issues).
23+
24+If you see something you want to improve, please fork the [GitHub repository](https://github.com/johnhyde/astrolabe) and make a pull request.
25+
26+Thanks for using Astrolabe. I hope it serves you well.
desk/doc/usr/astrolabe.udonnew file+107
@@ -0,0 +1,107 @@
1+;>
2+# Astrolabe
3+
4+Astrolabe is your one-stop shop for exploring Urbit address space.
5+Currently, Astrolabe lets you type in `@p`s or Azimuth point numbers
6+to look up ships on the network. You can search your contacts and
7+spawned ships with partial or wildcard searches, e.g. `sampel-***net`.
8+
9+There's also Help Documentation if
10+you want to learn more about how Urbit IDs work.
11+
12+## Keyboard Shortcuts
13+
14+- `/` - focus the search bar
15+- `escape` - leave text fields, close help pages, etc
16+- `?` - open the help docs
17+- `s` - switch to sigil search
18+- `p` - switch to patp search
19+- `backspace` or `x` - clear sigil input info
20+
21+
22+## How to Use Search
23+
24+When you type part of a `@p` into the search bar, all your contacts and peers will be
25+searched for IDs matching that string. You can use an asterisk (`*`) to
26+stand in for any character. If you wanted to search for both `~samnec` and `~sarbec`,
27+you could type `~sa**ec`.
28+Contacts are listed before other ships, with a gold border on the left.
29+
30+You can exclude moons or include comets you've met with the toggles in the gold
31+settings box under the search bar.
32+
33+The records of all spawned ships will also be searched, but if the search is
34+too general it will be narrowed in scope, or not run at all. For example,
35+if you search for `***hec`, it will search for all stars under `~hec`,
36+and all planets that match `~***hec-******`, but planets matching `~******-***hec`
37+will be ignored to prevent the search from taking too long.
38+
39+## Sigil Search
40+
41+Clicking the symbol at the right of the search bar opens the Sigil Input Tool.
42+Use the dropdown at the top to select Galaxy, Star, or Planet.
43+Click on a square to start selecting sigil components.
44+
45+Select component categories on the right, and then click the options on the sigil
46+to add them to your search.
47+
48+The ^ button goes up a level so you can select another category.
49+The X button will clear sigil components from the current symbol,
50+except the basic shape. If only the basic shape remains, the X button will clear that.
51+At the top level, the X button will clear all inputs.
52+
53+Your contacts will be searched for any input.
54+When the search has become specific enough,
55+all spawned ships with matching sigils will be shown.
56+If your input is unambiguous, the page for the matching ship will be shown,
57+whether the ship is spawned or not.
58+
59+NOTE: Some sigil inputs are considered ambiguous, even if they exactly match
60+a particular sigil, because further details could match a different sigil.
61+E.g. `~zod` is a circle, but a circle in the suffix position might be intended as a more general search.
62+A future version of Astrolabe will allow you to view the ship
63+whose sigil most closely matches your search, even if the search is ambiguous.
64+
65+Read more about Sigils [here](/~/scry/docs/usr/astrolabe/sigil.html).
66+
67+## The Star Chart
68+
69+Click and drag to move your view; use the mouse wheel to zoom in and out. Click on a dot
70+to see the full Ship View. Enter full `@p`s in the search bar to find a specific point.
71+
72+Please note that stars [locked in the Linear Release Contract](/~/scry/docs/usr/astrolabe/star.html)
73+are not shown in the Star Chart, as they are not yet a part of the network (though they've technically
74+been spawned).
75+
76+The Sponsors/Parents toggle lets you switch between two different views of the network.
77+The default Sponsors view shows each planet under its sponsoring star and each
78+star under its sponsoring galaxy. Planets and Stars without sponsors are not
79+present in this view.
80+The Parent view simply shows each point under the point that spawned it. All spawned points
81+are shown in this view, with the exception of locked stars.
82+In both views, all galaxies are shown for completeness.
83+
84+The All/Peers/Pals selector lets you filter which points are easily visible in the graph.
85+If you select Peers, only those ships that your ship has talked to will be full-colored.
86+If you select Pals, only ships you've added in `%pals` will be full-colored.
87+
88+## Info
89+
90+- Developer: ~midlev-mindyr
91+- License: MIT
92+- App link: [~dister-midlev-mindyr/astrolabe](web+urbitgraph://~dister-midlev-mindyr/astrolabe)
93+- Discussion Group: [~poster-hoster-midlev-mindyr/astrolabe](web+urbitgraph://group/~poster-hoster-midlev-mindyr/astrolabe)
94+- [%quorum](web+urbitgraph://~dister-dister-sidnym-ladrut/quorum) board: ~poster-hoster-midlev-mindyr/astrolabe
95+- Grant/Proposal: [https://urbit.org/grants/astrolabe](https://urbit.org/grants/astrolabe)
96+- Source repo: [https://github.com/johnhyde/astrolabe](https://github.com/johnhyde/astrolabe)
97+- Bug reports: [https://github.com/johnhyde/astrolabe/issues](https://github.com/johnhyde/astrolabe/issues)
98+
99+## Feedback
100+
101+If you run into issues with the app, or want to voice comments or concerns,
102+please post in the group `~poster-hoster-midlev-mindyr/astrolabe`, send a DM to `~midlev-mindyr`,
103+or [create an Issue on GitHub](https://github.com/johnhyde/astrolabe/issues).
104+
105+If you see something you want to improve, please fork the [GitHub repository](https://github.com/johnhyde/astrolabe) and make a pull request.
106+
107+Thanks for using Astrolabe. I hope it serves you well.
desk/doc/usr/azimuth.udonnew file+51
@@ -0,0 +1,51 @@
1+;>
2+# Azimuth
3+
4+_Adapted from [the Glossary](https://urbit.org/docs/glossary/azimuth)_
5+
6+Azimuth is Urbit's identity layer, built as a suite of smart contracts on
7+the Ethereum blockchain and several apps running locally on your
8+[ship](/~/scry/docs/usr/astrolabe/urbit-id.html).
9+It is Urbit's method of securing the digital identities that are required to use
10+the [Arvo](https://urbit.org/docs/glossary/arvo) peer-to-peer network,
11+without the need for a central authority.
12+Azimuth identities (also called points) exist as non-fungible tokens (NFTs),
13+which are owned by Ethereum addresses and can be transferred between such addresses.
14+Identities can use the [claims](https://urbit.org/docs/glossary/claims)
15+contract to make assertions – real-world or otherwise – about their owner.
16+
17+The primary way to interact with Azimuth and to manage your (also called points)
18+is through the [Bridge](https://bridge.urbit.org/) application.
19+Bridge is a front-end for [Ecliptic](https://urbit.org/docs/glossary/ecliptic),
20+the Azimuth contract that's used to perform actions on the blockchain.
21+
22+There are a limited number of Azimuth identities, which results in identities having value.
23+Users are therefore more careful to maintain a good reputation,
24+rather than using identities disposably.
25+Undesirable behavior—spamming, scamming, and malware-spreading—will generally result in
26+a [censure](https://urbit.org/docs/glossary/censure)
27+from [galaxies](/~/scry/docs/usr/astrolabe/galaxy.html)
28+and [stars](/~/scry/docs/usr/astrolabe/star.html), marking the bad actor.
29+
30+It should be noted that Azimuth isn't built just for Arvo.
31+It can be used as an identity system for other projects.
32+
33+## Layer 1 and Layer 2
34+
35+All Azimuth transactions that happen directly on Ethereum (the default) are considered to
36+be on "Layer 1", or L1 for short.
37+However, Ethereum gas prices can make simple L1 transactions like spawning a planet very
38+expensive.
39+In 2021, Tlon developed a "Layer 2" solution (a.k.a. L2) whereby many transactions can be
40+"rolled up" and posted to Ethereum at once, to be validated by each Urbit ship.
41+This dramatically reduces gas costs, and Tlon provides a roller which is free for public use.
42+
43+[Read More about L1 and L2](/~/scry/docs/usr/astrolabe/l2.html)
44+
45+## Further Reading
46+
47+- [The Azimuth concepts page](https://urbit.org/docs/azimuth/azimuth):
48+ A more in-depth explanation of Azimuth.
49+- [Install instructions](https://urbit.org/getting-started/):
50+ Guide to installing Urbit, which includes instructions on booting with your Urbit identity.
51+- [Understanding Urbit ID](https://urbit.org/understanding-urbit/urbit-id)
desk/doc/usr/comet.udonnew file+10
@@ -0,0 +1,10 @@
1+;>
2+[< What is an Urbit ID?](/~/scry/docs/usr/astrolabe/urbit-id.html)
3+
4+# Comets
5+
6+Comets are essentially unlimited, and can be created for free by anyone.
7+They're good for new people exploring the network, operating somewhat anonymously,
8+and testing things out. However, the keys for a comet can't be changed, so it's not
9+not a viable long-term ID. Also, since anyone can boot a comet, comets might be viewed
10+with distrust in some contexts.
desk/doc/usr/galaxy.udonnew file+36
@@ -0,0 +1,36 @@
1+;>
2+[< What is an Urbit ID?](/~/scry/docs/usr/astrolabe/urbit-id.html)
3+
4+# Galaxies
5+
6+Galaxies are the rarest and highest ranking class of Urbit ID, as there are only 256 of them.
7+Together, they form the [Galactic Senate](https://urbit.org/docs/glossary/senate)
8+which has the power make changes to the Urbit ID system.
9+Galaxies help route communication on the network, and each one can spawn 255 [stars](/~/scry/docs/usr/astrolabe/star.html).
10+
11+## @p
12+
13+A galaxy `@p` is just one phoneme, 3 letters. E.g. `~zod`, `~bus`, and `~fes` are galaxies.
14+
15+## Spawning
16+
17+Each galaxy can spawn 255 stars.
18+These stars will have 2-phoneme `@p`s starting with a prefix, and ending with the galaxy's `@p`.
19+E.g. `~zod` spawned `~marzod`, `~binzod`, and `~wanzod`, among others.
20+
21+## Sponsoring
22+
23+A galaxy can sponsor stars and planets, although usually planets are sponsored by stars.
24+By default, a galaxy will sponsor all its children, although it can sponsor others as well.
25+
26+Galaxies perform peer discovery for their sponsees, meaning that they tell other Urbit IDs
27+where they can find their sponsees so that they can communicate directly withthem—similar to
28+asking a DNS server to tell you where to look for google.com.
29+Thus, it is crucially important that galaxies be online and reachable.
30+
31+## The Galactic Senate
32+
33+All galaxy owners are members of the [Galactic Senate](https://urbit.org/docs/glossary/senate).
34+Galaxy owners can [vote](https://urbit.org/docs/glossary/voting) on proposals
35+to upgrade the logic of [Azimuth](/~/scry/docs/usr/astrolabe/azimuth.html)
36+or approve the content of a document.
desk/doc/usr/keys.udonnew file+63
@@ -0,0 +1,63 @@
1+;>
2+# Networking Keys
3+
4+Each Urbit ship proves its identity on the network by signing its messages
5+with a pair of networking keys. By signing a message with a private key,
6+you prove that you are the owner of the associated public key.
7+
8+Since public keys are stored in [Azimuth](/~/scry/docs/usr/astrolabe/azimuth.html),
9+other ships can verify your identity by checking your signatures.
10+
11+## Keyfile
12+
13+A keyfile is just a file containing your networking keys. It is used when
14+booting Arvo (Urbit's OS) for the first time, and the information within
15+is baked into the resulting ship. After this, the keyfile should be deleted
16+to prevent accidentally double-booting in the future.
17+
18+## Changing Keys
19+
20+If your private key is compromised, you can change your keys in Bridge and
21+update your ship by running `|rekey 'new-private-key-goes-here'` in Dojo (the terminal).
22+This will increase your `life` number in Azimuth, which is just a record of how many
23+times your keys have been revised. This number will also be incremented if you
24+set new keys in the course of performing a factory reset.
25+
26+Since keys must be set before a ship can be booted,
27+all active Urbit IDs will have a `life` of at least 1.
28+
29+# Performing a Factory Reset (a.k.a. Breaching)
30+
31+When using the network, ships keep track of the order of all the messages they've sent
32+and received, and use this to ensure that they process messages properly.
33+This is called continuity.
34+
35+Performing a factory reset means breaking continuity—asking the rest of the network
36+to forget your past messages and treat you like a new ship. It also involves clearing
37+your own event log, and consequently all apps and data on the ship.
38+Sometimes this is done to resolve networking errors, like those caused by double-booting.
39+This is also appropriate when transferring an ID to someone else, to give them a fresh start.
40+
41+Because factory resets involve booting a fresh ship, you'll need to rejoin groups,
42+reinstall apps, and generally start from scratch. Trying to continue using your old pier
43+(the folder containing your data) will just cause more networking issues.
44+There are, however, a few unofficial tools with which you can restore some data from
45+a previous pier, and more will likely be built over time.
46+
47+If you want to avoid breaching, avoid double-booting and don't delete your pier.
48+If you want to move your pier (e.g. to host your ship on a remote server), it is
49+crucial that you shut down your ship before you start it somewhere else.
50+If you have two different instances of the same ship trying to run at the same time,
51+other ships will get confused and you will need to breach to communicate with them properly.
52+Deleting your pier, or using an outdated archive of your pier will have the same effect.
53+
54+Breaching, or performing a factory reset, will increment your `rift` number in Azimuth,
55+so this number is an indicator of how many times a ship has breached.
56+Ships which have never breached have a `rift` of 0.
57+
58+# Further Reading
59+
60+- [Setting initial networking keys](https://urbit.org/using/id/using-bridge#set-your-networking-keys)
61+- [Guide to Factory Resets](https://urbit.org/using/id/guide-to-resets)
62+- [Life and Rift](https://urbit.org/docs/azimuth/life-and-rift)
63+- [Glossary: Keyfile](https://urbit.org/docs/glossary/keyfile)
desk/doc/usr/l2.udonnew file+60
@@ -0,0 +1,60 @@
1+;>
2+# What are Layer 1 and Layer 2?
3+
4+## Layer 1 (L1) - Azimuth smart contracts
5+
6+All Azimuth transactions that happen directly on Ethereum (the default) are considered to
7+be on "Layer 1", or L1 for short. The effects of these transactions are calculated and
8+stored on the Ethereum blockchain, so a nontrivial amount of "gas" must be expended for
9+each L1 transaction.
10+
11+## The need for a workaround
12+
13+In 2021, the Ethereum blockchain saw a large increase in traffic which caused
14+gas prices to skyrocket. It became prohibitively expensive for many to spawn or set keys
15+for new IDs, so Tlon started developing a workaround.
16+
17+## Layer 2 (L2) - Naive Rollups
18+
19+Tlon developed a "Layer 2" solution (a.k.a. L2) whereby many transactions can be
20+"rolled up" and posted to Ethereum at once, to be validated by each Urbit ship.
21+
22+The technical term for this is "naive rollups" because transactions are combined and
23+posted to Ethereum without being validated.
24+Each Urbit ship validates the transactions locally to determine who actually owns what.
25+
26+Combining transactions and offloading computation
27+from Ethereum to Urbit dramatically reduces gas costs.
28+Using L2 is so cheap that Tlon provides a free "roller" which is used when performing
29+L2 actions through Bridge.
30+
31+The introduction of L2 also makes it possible for new users to receive and start using
32+Urbit IDs without ever interacting with the blockchain themselves, making Urbit generally
33+more accessible.
34+
35+### Moving to Layer 2
36+
37+Most L2 actions require the ship to first "move to L2", which can be done through Bridge.
38+Technically, this consists of transferring the ID to `0x1111111111111111111111111111111111111111`.
39+This tells the Layer 2 code that the ship is on L2.
40+After that, all Azimuth transactions will be done on L2. It is not possible to move
41+an L2 ship back to L1.
42+
43+For galaxies and stars that want to spawn new IDs on L2, they can move only their spawn proxy
44+to L2. They will remain on L1, but any new children will be on L2. This change is also irreversible.
45+
46+Galaxies cannot move fully to L2, but they can move their spawn proxy to L2. Note, however, that
47+any stars locked in the Linear Release Contract are technically already spawned on L1,
48+and would need to be transferred to L2 separately.
49+
50+### Sponsorship between L1 and L2
51+
52+A sponsor and its sponsee can live on separate layers, but unless they are both on L1,
53+most sponsorship actions will need to take place on L2. This is the situation where an L1 ID
54+can take actions on L2 without moving to L2.
55+
56+# Further Reading
57+
58+- [Technical Overview of L2](https://urbit.org/docs/azimuth/l2/layer2)
59+- [Blog on Naive Rollups](https://urbit.org/blog/rollups)
60+- [Technical Details about which ships can perform which L2 actions](https://urbit.org/docs/azimuth/l2/l2-actions)
desk/doc/usr/moon.udonnew file+8
@@ -0,0 +1,8 @@
1+;>
2+[< What is an Urbit ID?](/~/scry/docs/usr/astrolabe/urbit-id.html)
3+
4+# Moons
5+
6+Moons are created, owned, and controlled by a parent ID, either a galaxy, star, or planet.
7+Moons are free and easy to create, and each Azimuth point can create about 4 billion.
8+Moons can use the Urbit network just like any other ID, but they are inextricably linked to their parents.
desk/doc/usr/patpee.udonnew file+104
@@ -0,0 +1,104 @@
1+;>
2+# What is a @p?
3+
4+First of all, it's pronounced "pat-pee", and we'll see why later.
5+
6+## It's a name
7+
8+Your `@p` is your name on Urbit, and it's designed to be pronounceable.
9+A `@p` starts with a tilde (`~`), and is made up of 3-letter phonemes/syllables, a combination of prefixes and suffixes.
10+There are 256 prefixes, and 256 suffixes.
11+`~zod` and `~bus` are galaxies, so their whole `@p`s are just one suffix.
12+
13+Most `@p`s are made up of 6-letter "words" ( a prefix + a suffix), joined by hyphens.
14+E.g. `~midlev-mindyr` has the prefixes `mid` and `min` and the suffixes `lev` and `dyr`.
15+You can see a list of prefixes and suffixes [here](/~/scry/docs/usr/astrolabe/phonemes.html).
16+
17+## It's a number
18+
19+A `@p` is actually just a way to write a non-negative integer with phonemes.
20+That means every `@p` can be written as a number, and any non-negative integer can be written as a `@p`.
21+- `~zod` is 0 (the first galaxy)
22+- `~marzod` is 256 (the first star)
23+- `~dapnep-ronmyl` is 65536 (256², the first planet)
24+- `~sampel-palnet` is 1624961343.
25+- `~doznec-dozzod-dozzod` is 4294967296 (256⁴, the first moon, moon of `~zod`)
26+
27+For [Azimuth points](/~/scry/docs/usr/astrolabe/azimuth.html), this number is also
28+called the Azimuth number, and it's stored on the blockchain instead of a `@p`.
29+The highest Azimuth number is 256⁴ - 1 (4294967295).
30+Everything above that is a moon, a comet, or not a valid ID number.
31+
32+## It's a username / email address / phone number
33+
34+A `@p` is the unique identifier for a ship, and it's used all throughout Urbit, in the code and in user-facing apps.
35+A `@p` can't be changed.
36+It will always refer to the same Urbit ID, and that Urbit ID will always have the same `@p`.
37+A given ID may change owners, however, and you can always buy a new ID with a new `@p`.
38+
39+## How to tell a ship's class
40+
41+It's easy to tell the class of a ship by looking at its `@p`.
42+- If it's just 1 phoneme, a suffix, like `~zod` or `~bus`, it's a [galaxy](/~/scry/docs/usr/astrolabe/galaxy.html).
43+
44+- If it has 2 phonemes, a prefix and a suffix, like `~marzod` or `~batbus`, it's a [star](/~/scry/docs/usr/astrolabe/star.html).
45+
46+ The suffix of a star `@p` is its parent galaxy, so the parent of `~marzod` is `~zod`, and the parent of `~batbus` is `~bus`.
47+
48+- If it has 4 phonemes separated by a hyphen, like `~sampel-palnet`, it's a [planet](/~/scry/docs/usr/astrolabe/planet.html).
49+
50+ Unlike stars, planet `@p`s don't contain the `@p` of their parent—the names are scrambled
51+ to give each star a good variety of planet `@p`s to spawn.
52+
53+- If it has 8 phonemes, like `~poster-hoster-midlev-mindyr`, it's a [moon](/~/scry/docs/usr/astrolabe/moon.html).
54+
55+ If it has 4 phonemes separated by a caret, like `~midlev^mindyr`, that's an abbreviated moon `@p`.
56+ The last 4 phonemes of a moon `@p` give its parent, and are used in the abbreviation.
57+
58+- If it has 16 phonemes, like `~dirbec-morfeb-ritlys-timsef--padnum-mapnep-nolfel-binzod`,
59+ or more likely 4 phonemes separated by an underscore, like `~dirbec_binzod`,
60+ it's a [comet](/~/scry/docs/usr/astrolabe/comet.html).
61+
62+ You may notice a double hyphen in the center of the full comet `@p`.
63+ This is part of the required syntax of a `@p`, and makes it easier to read.
64+ The abbreviation combines the first and last "words" of the `@p` with an underscore.
65+
66+
67+## The thing about `doz` and `zod`
68+
69+Remember that a `@p` is actually just a way of writing a number.
70+Technically, a `@p` is a base-256 number, as it's composed of prefixes and suffixes,
71+and there are 256 of each. Sure, you could write a number with just prefixes, or just suffixes,
72+but it wouldn't be as interesting to read, and it wouldn't be a valid `@p`.
73+
74+So each phoneme is equivalent to a number, 0-255.
75+`doz` is the prefix version of 0, and `zod` is the suffix version of 0.
76+Just as we usually don't write leading zeroes in our numbers, we omit the equivalent
77+of leading zeroes in `@p`s.
78+This is why you will never see `~dozler`, or `~dozzod-palnet`. It would be sort of like writing `000218` or `0000032591`. It's just `~ler` and `~palnet`. You might, however, run into `~dozler-palnet`, as planet `@p`s are never shortened to 3 phonemes.
79+
80+One place you're likely to see these show up is in moon `@p`s.
81+A moon `@p` is one or two "words" of the parent's choosing, plus the parent's `@p`.
82+E.g. `~sampel-palnet` could create `~dister-sampel-palnet` or `~mister-master-sampel-palnet`,
83+among others.
84+
85+If a galaxy or a star creates a moon,
86+its `@p` must be "padded out" to make up the last 4 phonemes of the moon `@p`.
87+`~ler` could thus create `~faster-dozzod-dozler` or `~poster-hoster-dozzod-dozler`.
88+See how `doz` and `zod` were used to pad out `ler` to 4 phonemes?
89+Similarly, `~palnet` could create `~walrus-dozzod-palnet` or `~doznec-tortul-dozzod-palnet`.
90+
91+## Why is it called a "patpee"?
92+
93+In Hoon, Urbit's typed programming language, numbers can have different "auras",
94+depending on what they represent. Some auras include `@u` for an unsigned integer,
95+`@t` for arbitrary text stored as a number, `@if` for an IPv4 address, and of course
96+`@p` for writing a number in phonemes.
97+
98+So why the "pat"?
99+Hoon involves a lot more symbols than most programming languages (e.g. `.!=?|+:%^$;~-` and so on).
100+To help programmers talk out loud about Hoon, each symbol is associated with a 3-letter phoneme.
101+In this system, `=/` is pronounced "tisfas", `%-` is "cenhep", and, you guessed it, `@` is "pat".
102+
103+In short, `@p` is originally a programming term, the programmers pronounce it "pat-pee",
104+so that's how it's pronounced.
desk/doc/usr/phonemes.udonnew file+45
@@ -0,0 +1,45 @@
1+;>
2+# Phonemes - Prefixes & Suffixes
3+
4+[< What is a @p?](/~/scry/docs/usr/astrolabe/patpee.html)
5+
6+`@p`s are made up of 3-letter phonemes, a mixture of prefixes and suffixes.
7+Here's an exhaustive list of each:
8+
9+## Prefixes
10+
11+`doz` `mar` `bin` `wan` `sam` `lit` `sig` `hid` `fid` `lis` `sog` `dir` `wac` `sab` `wis` `sib`
12+`rig` `sol` `dop` `mod` `fog` `lid` `hop` `dar` `dor` `lor` `hod` `fol` `rin` `tog` `sil` `mir`
13+`hol` `pas` `lac` `rov` `liv` `dal` `sat` `lib` `tab` `han` `tic` `pid` `tor` `bol` `fos` `dot`
14+`los` `dil` `for` `pil` `ram` `tir` `win` `tad` `bic` `dif` `roc` `wid` `bis` `das` `mid` `lop`
15+`ril` `nar` `dap` `mol` `san` `loc` `nov` `sit` `nid` `tip` `sic` `rop` `wit` `nat` `pan` `min`
16+`rit` `pod` `mot` `tam` `tol` `sav` `pos` `nap` `nop` `som` `fin` `fon` `ban` `mor` `wor` `sip`
17+`ron` `nor` `bot` `wic` `soc` `wat` `dol` `mag` `pic` `dav` `bid` `bal` `tim` `tas` `mal` `lig`
18+`siv` `tag` `pad` `sal` `div` `dac` `tan` `sid` `fab` `tar` `mon` `ran` `nis` `wol` `mis` `pal`
19+`las` `dis` `map` `rab` `tob` `rol` `lat` `lon` `nod` `nav` `fig` `nom` `nib` `pag` `sop` `ral`
20+`bil` `had` `doc` `rid` `moc` `pac` `rav` `rip` `fal` `tod` `til` `tin` `hap` `mic` `fan` `pat`
21+`tac` `lab` `mog` `sim` `son` `pin` `lom` `ric` `tap` `fir` `has` `bos` `bat` `poc` `hac` `tid`
22+`hav` `sap` `lin` `dib` `hos` `dab` `bit` `bar` `rac` `par` `lod` `dos` `bor` `toc` `hil` `mac`
23+`tom` `dig` `fil` `fas` `mit` `hob` `har` `mig` `hin` `rad` `mas` `hal` `rag` `lag` `fad` `top`
24+`mop` `hab` `nil` `nos` `mil` `fop` `fam` `dat` `nol` `din` `hat` `nac` `ris` `fot` `rib` `hoc`
25+`nim` `lar` `fit` `wal` `rap` `sar` `nal` `mos` `lan` `don` `dan` `lad` `dov` `riv` `bac` `pol`
26+`lap` `tal` `pit` `nam` `bon` `ros` `ton` `fod` `pon` `sov` `noc` `sor` `lav` `mat` `mip` `fip`
27+
28+## Suffixes
29+
30+`zod` `nec` `bud` `wes` `sev` `per` `sut` `let` `ful` `pen` `syt` `dur` `wep` `ser` `wyl` `sun`
31+`ryp` `syx` `dyr` `nup` `heb` `peg` `lup` `dep` `dys` `put` `lug` `hec` `ryt` `tyv` `syd` `nex`
32+`lun` `mep` `lut` `sep` `pes` `del` `sul` `ped` `tem` `led` `tul` `met` `wen` `byn` `hex` `feb`
33+`pyl` `dul` `het` `mev` `rut` `tyl` `wyd` `tep` `bes` `dex` `sef` `wyc` `bur` `der` `nep` `pur`
34+`rys` `reb` `den` `nut` `sub` `pet` `rul` `syn` `reg` `tyd` `sup` `sem` `wyn` `rec` `meg` `net`
35+`sec` `mul` `nym` `tev` `web` `sum` `mut` `nyx` `rex` `teb` `fus` `hep` `ben` `mus` `wyx` `sym`
36+`sel` `ruc` `dec` `wex` `syr` `wet` `dyl` `myn` `mes` `det` `bet` `bel` `tux` `tug` `myr` `pel`
37+`syp` `ter` `meb` `set` `dut` `deg` `tex` `sur` `fel` `tud` `nux` `rux` `ren` `wyt` `nub` `med`
38+`lyt` `dus` `neb` `rum` `tyn` `seg` `lyx` `pun` `res` `red` `fun` `rev` `ref` `mec` `ted` `rus`
39+`bex` `leb` `dux` `ryn` `num` `pyx` `ryg` `ryx` `fep` `tyr` `tus` `tyc` `leg` `nem` `fer` `mer`
40+`ten` `lus` `nus` `syl` `tec` `mex` `pub` `rym` `tuc` `fyl` `lep` `deb` `ber` `mug` `hut` `tun`
41+`byl` `sud` `pem` `dev` `lur` `def` `bus` `bep` `run` `mel` `pex` `dyt` `byt` `typ` `lev` `myl`
42+`wed` `duc` `fur` `fex` `nul` `luc` `len` `ner` `lex` `rup` `ned` `lec` `ryd` `lyd` `fen` `wel`
43+`nyd` `hus` `rel` `rud` `nes` `hes` `fet` `des` `ret` `dun` `ler` `nyr` `seb` `hul` `ryl` `lud`
44+`rem` `lys` `fyn` `wer` `ryc` `sug` `nys` `nyl` `lyn` `dyn` `dem` `lux` `fed` `sed` `bec` `mun`
45+`lyr` `tes` `mud` `nyt` `byr` `sen` `weg` `fyr` `mur` `tel` `rep` `teg` `pec` `nel` `nev` `fes`
desk/doc/usr/planet.udonnew file+9
@@ -0,0 +1,9 @@
1+;>
2+[< What is an Urbit ID?](/~/scry/docs/usr/astrolabe/urbit-id.html)
3+
4+# Planets
5+
6+There are about 4.3 billion potential planets, so while they are not unlimited, they are
7+widely accessible for the average user. Most people pilot a planet or a moon when using Urbit.
8+As planets are the lowest rank of Azimuth point, they cannot spawn other points. Like galaxies
9+and stars, however, they can create [moons](/~/scry/docs/usr/astrolabe/moon.html).
desk/doc/usr/sigil-input.udonnew file+27
@@ -0,0 +1,27 @@
1+;>
2+# How to Search by Sigil
3+
4+Use the dropdown at the top to select Galaxy, Star, or Planet.
5+Click on an empty square to start selecting sigil components.
6+
7+Select component categories on the right, and then click the options on the sigil
8+to add them to your search.
9+
10+The ^ button goes up a level so you can select another category.
11+The X button will clear sigil components from the current symbol,
12+except the basic shape. If only the basic shape remains, the X button will clear that.
13+At the top level, the X button will clear all inputs.
14+
15+Your contacts will be searched for any input.
16+When the search has become specific enough,
17+all spawned ships with matching sigils will be shown.
18+If your input is unambiguous, the page for the matching ship will be shown,
19+whether the ship is spawned or not.
20+
21+_NOTE:_ Some sigil inputs are considered ambiguous, even if they exactly match
22+a particular sigil, because further details could match a different sigil.
23+E.g. `~zod` is a circle, but a circle in the suffix position might be intended as a more general search.
24+A future version of Astrolabe will allow you to view the ship
25+whose sigil most closely matches your search, even if the search is ambiguous.
26+
27+_See Also:_ [*What is a Sigil?*](/~/scry/docs/usr/astrolabe/sigil.html)
desk/doc/usr/sigil.udonnew file+22
@@ -0,0 +1,22 @@
1+;>
2+# What is a Sigil?
3+
4+It's a default profile picture, based on your [`@p`](/~/scry/docs/usr/astrolabe/patpee.html).
5+Each 3-letter syllable corresponds to a sigil shape, or "symbol".
6+Since planet `@p`s have 4 syllables, a planet sigil is a 2x2 grid of 4 symbols.
7+Star sigils have 2 symbols, and galaxies have just 1.
8+
9+![planet sigils](/apps/astrolabe/sigil-example.png)
10+
11+## Is there a pattern to the sigil shapes?
12+
13+Some syllables which sound similar have similar symbols,
14+but there's no real system to it. The sigil shapes were manually selected and assigned,
15+with a focus on visual design rather than algorithmic purity.
16+
17+## Where did they come from?
18+
19+Tlon saw that Urbit IDs need a visual representation,
20+so they designed a system for generating default avatars.
21+You can read about it in the blog post [_Creating Sigils_](https://urbit.org/blog/creating-sigils).
22+
desk/doc/usr/star.udonnew file+21
@@ -0,0 +1,21 @@
1+;>
2+[< What is an Urbit ID?](/~/scry/docs/usr/astrolabe/urbit-id.html)
3+
4+# Stars
5+
6+Stars are scarce and valuable—a natural fit for businesses, communities, or other organizations.
7+The maximum supply of stars is 65,280.
8+
9+Each star can spawn 65,535 [planets](/~/scry/docs/usr/astrolabe/planet.html), and provides network routing, software updates,
10+and other services for the planets it sponsors.
11+Stars can also choose to de-sponsor planets which abuse the network.
12+
13+Stars are NFTs, but they can be exchanged 1:1 for WSTR at [star.market](https://star.market/),
14+and you can trade fractional amounts of WSTR for ETH [on Uniswap V3](https://info.uniswap.org/#/pools/0x7f4a0822a6e3c085df795a8d78acbcd36f210ebf).
15+
16+## Locked stars and the Linear Release Contract
17+
18+To prevent galaxies from spawning too many stars all at once, many galaxies' stars were locked
19+in an Ethereum contract, to be slowly released (at a linear rate) over time.
20+Stars which are locked in this way will show the contract address as their owner,
21+and any stars held by this contract are considered locked, even if they are ready to be released.
desk/doc/usr/test.udonnew file+24
@@ -0,0 +1,24 @@
1+;>
2+# Test Doc
3+
4+### served from /doc/usr/test/udon
5+
6+# H1
7+
8+## H2
9+
10+### H3
11+
12+#### H4
13+
14+*Urbit IDs* are _*cool*_:
15+- secure
16+- unique
17+- fun to say (_sometimes_)
18+
19+#### Todo
20+
21++ test out markdown
22++ write actual docs
23++ ???
24++ profit
desk/doc/usr/urbit-id.udonnew file+118
@@ -0,0 +1,118 @@
1+;>
2+# What is an Urbit ID?
3+
4+An Urbit ID is like an account on the Urbit network. You can’t use Urbit without an Urbit ID.
5+
6+Every active Urbit ID has a number of properties:
7+
8+- `@p` (pronounced pat-pee) - A permanent, unique identifier, e.g. `~zod` or `~midlev-mindyr`.
9+ This often functions like a username or email address.
10+ Every `@p` is equivalent to a number ≥ 0 and > 256¹⁶, with longer `@p`s giving larger numbers.
11+ The length of a `@p` indicates what class of ID it is.
12+ [Read More](/~/scry/docs/usr/astrolabe/patpee.html)
13+
14+- Public and Private Keys - These allow you to cryptographically prove your ownership of an ID.
15+ This is a bit like having a password for an account, or signing a document.
16+ All messages on Urbit are automatically signed and verified, so you know they’re authentic.
17+
18+- Ship - A ship is an Urbit computer, which is always tied to the Urbit ID it was booted with.
19+ When you boot Urbit for the first time, you provide your keys and we call this booting a “ship”.
20+ When you use this computer on the network, you are “piloting” your “ship”.
21+ Your ship stores all your data and apps.
22+
23+## Azimuth Points
24+
25+An [Azimuth point](/~/scry/docs/usr/astrolabe/azimuth.html) is an Urbit ID which is secured on the Ethereum blockchain.
26+Azimuth points are NFTs, governed by the Azimuth smart contracts.
27+Owning an Azimuth point lets you reset your [keys](/~/scry/docs/usr/astrolabe/keys.html),
28+spawn new IDs, and transfer ownership to someone else, among other things.
29+
30+When Ethereum got popular and transactions became very expensive a
31+[Layer 2 solution](/~/scry/docs/usr/astrolabe/l2.html)
32+was developed (commonly called "L2"), which allows Azimuth points to be spawned, transferred,
33+etc. basically for free.
34+
35+### Spawning and Sponsoring
36+
37+By thinking about possible combinations of syllables, we can predict every Urbit ID that might exist.
38+But galaxies, stars, and planets, being Azimuth points, don't come into existence until
39+a transaction is posted to Azimuth which explicitly "spawns" that point.
40+
41+All 256 galaxies have already been spawned. Those galaxies can spawn stars.
42+Those stars can spawn planets. Planets can't spawn anything, but all Azimuth points can
43+create moons, which is sometimes called "spawning" even though it's not done through Azimuth.
44+
45+By default, a galaxy will sponsor any stars it spawns, and a star will sponsor any planets it spawns.
46+This means helping route network traffic between the sponsee and other ships, providing OTA (over the air)
47+software updates, and potentially providing other services.
48+
49+A sponsee (star or planet) may choose to leave their sponsor and find another one. Conversely,
50+a sponsor (galaxy or star) may choose to de-sponsor their sponsee or sponsor additional points
51+which they didn't spawn. This lets the network hierarchy adjust itself in case someone misbehaves.
52+
53+## Classes of Urbit ID
54+
55+There are 5 classes of Urbit ID:
56+[Galaxy](/~/scry/docs/usr/astrolabe/galaxy.html),
57+[Star](/~/scry/docs/usr/astrolabe/star.html),
58+[Planet](/~/scry/docs/usr/astrolabe/planet.html),
59+[Moon](/~/scry/docs/usr/astrolabe/moon.html), and
60+[Comet](/~/scry/docs/usr/astrolabe/comet.html).
61+
62+Galaxies, stars, and planets are [Azimuth points](/~/scry/docs/usr/astrolabe/azimuth.html),
63+and are therefore very similar anatomically, although they have different roles.
64+Moons and comets are a bit different.
65+
66+### Galaxies (e.g. `~bus`)
67+
68+Galaxies are the rarest and highest ranking class of ID, as there are only 256 of them.
69+Together, they form the Galactic Senate.
70+Galaxies help route communication on the network, and each one can spawn 255 stars.
71+
72+[Read More](/~/scry/docs/usr/astrolabe/galaxy.html)
73+
74+### Stars (e.g. `~batbus`)
75+
76+Stars are fairly scarce and valuable—a natural fit for businesses, communities, or other organizations.
77+Each star can spawn 65,535 planets, and provides network routing, software updates,
78+and other services for the planets it sponsors.
79+Stars can also choose to de-sponsor planets which abuse the network.
80+Stars are NFTs, but they can be exchanged 1:1 for WSTR at [star.market](https://star.market/),
81+and you can trade fractional amounts of WSTR for ETH [on Uniswap V3](https://info.uniswap.org/#/pools/0x7f4a0822a6e3c085df795a8d78acbcd36f210ebf).
82+
83+[Read More](/~/scry/docs/usr/astrolabe/star.html)
84+
85+### Planets (e.g. `~midlev-mindyr`)
86+
87+There are about 4.3 billion potential planets, so while they are not unlimited, they are
88+widely accessible for the average user. Most people pilot a planet or a moon when using Urbit.
89+As planets are the lowest rank of Azimuth point, they cannot spawn other points. Like galaxies
90+and stars, however, they can create moons.
91+
92+[Read More](/~/scry/docs/usr/astrolabe/planet.html)
93+
94+### Moons (e.g. `~poster-hoster-midlev-mindyr` (`~midlev^mindyr` for short))
95+
96+Moons are created, owned, and controlled by a parent ID, either a galaxy, star, or planet.
97+Moons are free and easy to create, and each Azimuth point can create about 4 billion.
98+Moons can use the Urbit network just like any other ID, but they are inextricably linked to their parents.
99+
100+[Read More](/~/scry/docs/usr/astrolabe/moon.html)
101+
102+### Comets (e.g. `~dirbec-morfeb-ritlys-timsef--padnum-mapnep-nolfel-binzod` (`~dirbec_binzod` for short))
103+
104+Comets are essentially unlimited, and can be created for free by anyone.
105+They're good for new people exploring the network, operating somewhat anonymously,
106+and testing things out. However, the keys for a comet can't be changed, so it's not
107+not a viable long-term ID. Also, since anyone can boot a comet, comets might be viewed
108+with distrust in some contexts.
109+
110+[Read More](/~/scry/docs/usr/astrolabe/comet.html)
111+
112+# Further Reading
113+
114+- [A more technical overview](https://urbit.org/using/id/overview)
115+- From the Operator’s Guide:
116+ [Which ID should I buy?](https://operators.urbit.org/guides/which-id-should-i-buy)
117+- [Azimuth FAQ](https://azimuth.network/#faq)
118+- [Understanding Urbit ID](https://urbit.org/understanding-urbit/urbit-id)
desk/lib/astrolabe.hoonnew file+234
@@ -0,0 +1,234 @@
1+/- sur=astrolabe
2+/+ azimuth, naive
3+=< [sur .]
4+=, sur
5+|%
6+++ to-q fein:ob
7+++ to-p fynd:ob
8+++ rev-q
9+ |= a=@
10+ (rev 3 4 a)
11+++ switch-words
12+ |= a=@
13+ (rev 4 2 a)
14+++ add-d
15+ |= [a=@ b=@]
16+ (rev-q (add (rev-q a) b))
17+++ sub-d
18+ |= [a=@ b=@]
19+ (rev-q (sub (rev-q a) b))
20+++ rev-f
21+ |* [f=$-([@ @] *) a=@ b=@]
22+ (f (rev-q a) (rev-q b))
23+++ rpor :: reversed parent order
24+ |= [a=@ b=@]
25+ ^- ?
26+ (rev-f lte a b)
27+::
28+++ ors ((on @q @) rpor)
29+++ or-meta ((on @p tape) por:naive)
30+++ bi-meta
31+ =| a=(map * (map))
32+ |@
33+ ++ put
34+ |* [b=* c=* d=*]
35+ %+ ~(put by a) b
36+ %+ put:or-meta
37+ (~(gut by a) b ~)
38+ [c d]
39+ --
40+::
41++$ page-info [size=_100 page=_0]
42+++ fits-on-page
43+ |= [i=@ =page-info]
44+ ^- ?
45+ =, page-info
46+ ?: =(0 size) %.y
47+ =/ page-start (mul size page)
48+ =/ page-end (add page-start size)
49+ &((gte i page-start) (lth i page-end))
50+::
51+++ is-npoint-locked
52+ |= p=npoint
53+ .= linear-star-release:contracts:azimuth
54+ address.owner.own.p
55+::
56+++ split
57+ |* [nedl=(list) hstk=(list)]
58+ |- ^- (list _hstk)
59+ =/ brk (find nedl hstk)
60+ ?~ brk ~[hstk]
61+ =/ next (add u.brk (lent nedl))
62+ :- (scag u.brk hstk)
63+ $(hstk (slag next hstk))
64+::
65+++ smel
66+ |%
67+ ++ ship
68+ |= =^ship
69+ ^- tape
70+ (slag 1 (scow %p ship))
71+ ++ dom
72+ |= =dominion:naive
73+ ?- dominion
74+ %l1 ""
75+ %l2 "t"
76+ %spawn "s"
77+ ==
78+ ++ spo
79+ |= [self=^ship has=? spo=^ship]
80+ ?. has "~"
81+ =/ parent (^sein:title self)
82+ ?: =(spo parent)
83+ ""
84+ :(weld ":" (ship spo) "!" (ship parent))
85+ ++ pmeta
86+ |= [self=^ship point=npoint]
87+ ^- tape
88+ =/ self-str (ship self)
89+ =/ extras (weld (dom dominion.point) (spo self sponsor.net.point))
90+ ?~ extras self-str
91+ :(weld self-str ":" extras)
92+ ++ spa
93+ |= children=(list tape)
94+ =/ chil-str=tape (zing children)
95+ :: =/ chil-str=tape (reel children |=([a=tape b=tape] (weld a b)))
96+ ?~ chil-str ";"
97+ :(weld "[" chil-str "]")
98+ ++ pdata
99+ |= [pmeta=tape children=(list tape)]
100+ ^- tape
101+ (weld pmeta (spa children))
102+ --
103+::
104+++ nu :: parse number as hex
105+ |= jon=json
106+ ?> ?=([%s *] jon)
107+ (rash p.jon hex)
108+::
109+++ enjs
110+ =, enjs:format
111+ |%
112+ ++ point-set
113+ |= points=(list ^ship)
114+ ^- json
115+ %+ frond %points
116+ :- %a
117+ %+ turn
118+ points
119+ |= who=^ship
120+ (ship who)
121+ ++ point
122+ |= =^point
123+ ^- json
124+ =* unpoint unpoint.point
125+ =* npoint u.unpoint
126+ %+ frond %point
127+ %- pairs :*
128+ ship+(ship ship.point)
129+ spa-count+(numb spa-count.point)
130+ [%probable-dominion s+probable-dominion.point]
131+ [%sponsor-chain a+(turn sponsor-chain.point ship)]
132+ ?~ unpoint ~
133+ :_ ~
134+ :- %npoint
135+ %- pairs :~
136+ [%dominion s+dominion.npoint]
137+ :- %own
138+ =* own own.npoint
139+ %- pairs :~
140+ owner+(address owner.own)
141+ spawn-proxy+(address spawn-proxy.own)
142+ management-proxy+(address management-proxy.own)
143+ voting-proxy+(address voting-proxy.own)
144+ transfer-proxy+(address transfer-proxy.own)
145+ ==
146+ :- %net
147+ =* net net.npoint
148+ %- pairs
149+ :~ rift+(numb rift.net)
150+ :- %keys
151+ %- pairs :~
152+ life+(numb life.keys.net)
153+ suite+(numb suite.keys.net)
154+ auth+(numb auth.keys.net)
155+ crypt+(numb crypt.keys.net)
156+ ==
157+ :- %sponsor
158+ %- pairs :~
159+ has+b+has.sponsor.net
160+ who+(ship who.sponsor.net)
161+ ==
162+ :- %escape
163+ (biff escape.net ship)
164+ ==
165+ ==
166+ ==
167+ ++ address
168+ |= [address=@ux nonce=@ud]
169+ ^- json
170+ %- pairs
171+ :~ address+(numb-ux address)
172+ nonce+(numb nonce)
173+ ==
174+ ++ numb-ux
175+ |= a=@
176+ ^- json
177+ ?~ a ~
178+ s+(remove-dots (scot %ux a))
179+ ++ remove-dots
180+ |= a=@ta
181+ ^- @ta
182+ =+ b=(rip 3 a)
183+ %+ rap 3
184+ |- ^- ^tape
185+ ?~ b
186+ ~
187+ ?: =('.' i.b) $(b t.b)
188+ [i.b $(b t.b)]
189+ --
190+::
191+++ dejs
192+ =, dejs:format
193+ |%
194+ ++ point
195+ |= jon=json
196+ *^point
197+ --
198+::
199+++ share-dejs
200+ =, dejs:format
201+ |%
202+ ++ share
203+ ^- $-(json [%share ship])
204+ (of share+(su ;~(pfix sig fed:ag)) ~)
205+ --
206+::
207+::
208+++ groups-link-thatch
209+'''
210+const buttonText = 'View in Astrolabe';
211+setInterval(() => {
212+ const footer = document.querySelectorAll('section > div > footer')?.[0];
213+ if (!footer) return;
214+ if (footer.children[0].innerText === buttonText) return;
215+ const spans = document.querySelectorAll('section > div > div > div > span > span:first-child');
216+ spans.forEach((span) => {
217+ if (span.innerHTML !== '~') return;
218+ if (footer.children[0].innerText === buttonText) return;
219+ let cspan = span.parentElement;
220+ let patp = cspan.innerText;
221+ let b = document.createElement('a');
222+ b.innerHTML = buttonText;
223+ b.className = 'button';
224+ // b.href = 'web+urbitgraph://astrolabe/ship/' + patp;
225+ b.href = '/apps/astrolabe/#/ship/' + patp;
226+ b.target = '_blank';
227+ b.style.backgroundColor = "navy";
228+ b.style.marginLeft = "1rem";
229+ b.style.color = "white";
230+ footer.prepend(b);
231+ });
232+}, 100);
233+'''
234+--
desk/lib/search.hoonnew file+373

This diff is too big to show here.

desk/lib/state.hoonnew file+21

This diff is too big to show here.

desk/mar/astrolabe/point-set.hoonnew file+13

This diff is too big to show here.

desk/mar/astrolabe/point.hoonnew file+14

This diff is too big to show here.

desk/mar/ico.hoonnew file+12

This diff is too big to show here.

desk/mar/seal.hoonnew file+12

This diff is too big to show here.

desk/mar/webmanifest.hoonnew file+12

This diff is too big to show here.

desk/sur/astrolabe.hoonnew file+58

This diff is too big to show here.

desk/sys.kelvin+1−1

This diff is too big to show here.

desk/tests/lib/state.hoonnew file+59

This diff is too big to show here.

docs-dev-desk/lib/docs.hoonnew file+205

This diff is too big to show here.

docs-dev-desk/lib/gemtext.hoonnew file+190

This diff is too big to show here.

docs-dev-desk/mar/clue.hoonnew file+28

This diff is too big to show here.

docs-dev-desk/mar/docu.hoonnew file+23

This diff is too big to show here.

docs-dev-desk/mar/elem.hoonnew file+18

This diff is too big to show here.

docs-dev-desk/mar/gmi-diff.hoonnew file+13

This diff is too big to show here.

docs-dev-desk/mar/gmi.hoonnew file+37

This diff is too big to show here.

docs-dev-desk/mar/toc.hoonnew file+16

This diff is too big to show here.

docs-dev-desk/mar/x-htm.hoonnew file+12

This diff is too big to show here.

docs-dev-desk/sur/docs.hoonnew file+9

This diff is too big to show here.

docs-dev-desk/sur/gemtext.hoonnew file+10

This diff is too big to show here.

flake.locknew file+27

This diff is too big to show here.

flake.nixnew file+73

This diff is too big to show here.

install.shdeleted−39

This diff is too big to show here.

ui/.envnew file+3

This diff is too big to show here.

ui/.env.localdeleted−2

This diff is too big to show here.

ui/index.html+7−3

This diff is too big to show here.

ui/package-lock.json+401−55

This diff is too big to show here.

ui/package.json+28−7

This diff is too big to show here.

ui/public/android-chrome-192x192.pngnew file

Binary file not shown.

ui/public/android-chrome-512x512.pngnew file

Binary file not shown.

ui/public/apple-touch-icon.pngnew file

Binary file not shown.

ui/public/favicon-16x16.pngnew file

Binary file not shown.

ui/public/favicon-32x32.pngnew file

Binary file not shown.

ui/public/favicon.ico

Binary file not shown.

ui/public/sigil-example.pngnew file

Binary file not shown.

ui/public/site.webmanifestnew file+1

This diff is too big to show here.

ui/scraps/tirrel-graph-main.jsnew file+198

This diff is too big to show here.

ui/src/App.svelte+63−13

This diff is too big to show here.

ui/src/actions/docLinks.tsnew file+26

This diff is too big to show here.

ui/src/actions/symbolPartClick.tsnew file+27

This diff is too big to show here.

ui/src/actions/tooltip.tsnew file+73

This diff is too big to show here.

ui/src/assets/astrolabe-tile.svgnew file+23

This diff is too big to show here.

ui/src/assets/astrolabe.svgnew file+206

This diff is too big to show here.

ui/src/assets/up-arrow.svgnew file+1

This diff is too big to show here.

ui/src/assets/x.svgnew file+1

This diff is too big to show here.

ui/src/components/CollapsibleContent.sveltenew file+18

This diff is too big to show here.

ui/src/components/ExtensionWindow.sveltenew file+25

This diff is too big to show here.

ui/src/components/HomeScreenTiles.sveltenew file+42

This diff is too big to show here.

ui/src/components/SearchBar.sveltedeleted−35

This diff is too big to show here.

ui/src/components/SearchResults.sveltedeleted−63

This diff is too big to show here.

ui/src/components/ShipListing.svelte+37−11

This diff is too big to show here.

ui/src/components/ShipListings.sveltenew file+19

This diff is too big to show here.

ui/src/components/ShipView.sveltedeleted−58

This diff is too big to show here.

ui/src/components/Sigil.sveltedeleted−36

This diff is too big to show here.

ui/src/components/StarChart.sveltenew file+233

This diff is too big to show here.

ui/src/components/ValidationProblems.svelte+6−2

This diff is too big to show here.

ui/src/components/buttons/CloseButton.sveltenew file+4

This diff is too big to show here.

ui/src/components/buttons/Hamburger.sveltenew file+5

This diff is too big to show here.

ui/src/components/buttons/InlineSelect.sveltenew file+16

This diff is too big to show here.

ui/src/components/buttons/ToggleButton.sveltenew file+11

This diff is too big to show here.

ui/src/components/common/ChartLink.sveltenew file+11

This diff is too big to show here.

ui/src/components/common/EthAddressLink.sveltenew file+37

This diff is too big to show here.

ui/src/components/common/GoldBadge.sveltenew file+10

This diff is too big to show here.

ui/src/components/common/Legil.sveltenew file+47

This diff is too big to show here.

ui/src/components/common/LoadingSpinner.sveltenew file+8

This diff is too big to show here.

ui/src/components/common/ShipLink.sveltenew file+10

This diff is too big to show here.

ui/src/components/common/Sigil.sveltenew file+65

This diff is too big to show here.

ui/src/components/common/Tooltip.sveltenew file+37

This diff is too big to show here.

ui/src/components/common/TooltipAndDocLink.sveltenew file+14

This diff is too big to show here.

ui/src/components/docs/Doc.sveltenew file+50

This diff is too big to show here.

ui/src/components/docs/DocContent.sveltenew file+37

This diff is too big to show here.

ui/src/components/docs/DocHome.sveltenew file+76

This diff is too big to show here.

ui/src/components/docs/DocLink.sveltenew file+26

This diff is too big to show here.

ui/src/components/docs/HelpModal.sveltenew file+25

This diff is too big to show here.

ui/src/components/extensions/AppIcon.sveltenew file+61

This diff is too big to show here.

ui/src/components/extensions/AppsShipViewExtension.sveltenew file+56

This diff is too big to show here.

ui/src/components/extensions/GroupsShipViewExtension.sveltenew file+15

This diff is too big to show here.

ui/src/components/extensions/ProfileShipViewExtension.sveltenew file+52

This diff is too big to show here.

ui/src/components/pals/PalStatusIndicator.sveltenew file+191

This diff is too big to show here.

ui/src/components/pals/PalTagger.sveltenew file+40

This diff is too big to show here.

ui/src/components/pals/PalsShipViewExtension.sveltenew file+34

This diff is too big to show here.

ui/src/components/search/SearchBar.sveltenew file+152

This diff is too big to show here.

ui/src/components/SearchResultNavButtons.svelte → ui/src/components/search/SearchResultNavButtons.svelterenamed

The content is the same.

ui/src/components/search/SearchResults.sveltenew file+147

This diff is too big to show here.

ui/src/components/search/SearchResultsNavButtons.sveltenew file+54

This diff is too big to show here.

ui/src/components/search/SearchSettings.sveltenew file+25

This diff is too big to show here.

ui/src/components/search/sigil/ClanSelect.sveltenew file+44

This diff is too big to show here.

ui/src/components/search/sigil/ClanSelectOption.sveltenew file+17

This diff is too big to show here.

ui/src/components/search/sigil/GeonSelector.sveltenew file+30

This diff is too big to show here.

ui/src/components/search/sigil/MiniFakeSigil.sveltenew file+25

This diff is too big to show here.

ui/src/components/search/sigil/SigilInput.sveltenew file+104

This diff is too big to show here.

ui/src/components/search/sigil/Symbol.sveltenew file+79

This diff is too big to show here.

ui/src/components/search/sigil/SymbolInput.sveltenew file+105

This diff is too big to show here.

ui/src/components/search/sigil/SymbolInputModeSelector.sveltenew file+168

This diff is too big to show here.

ui/src/components/search/sigil/SymbolInputModeSelectorButton.sveltenew file+33

This diff is too big to show here.

ui/src/components/search/sigil/SymbolInputNavButtons.sveltenew file+30

This diff is too big to show here.

ui/src/components/ship_view/AzimuthDetails.sveltenew file+90

This diff is too big to show here.

ui/src/components/ship_view/ShipChain.sveltenew file+11

This diff is too big to show here.

ui/src/components/ship_view/ShipChildrenTabs.sveltenew file+136

This diff is too big to show here.

ui/src/components/ship_view/ShipView.sveltenew file+130

This diff is too big to show here.

ui/src/fake_data/fake-contacts.ts+6−1

This diff is too big to show here.

ui/src/lib/api.tsnew file+102

This diff is too big to show here.

ui/src/lib/apps.tsnew file+177

This diff is too big to show here.

ui/src/lib/colors.tsnew file+17

This diff is too big to show here.

ui/src/lib/graph.tsnew file+422

This diff is too big to show here.

ui/src/lib/id.ts+430−147

This diff is too big to show here.

ui/src/lib/link.ts+15−2

This diff is too big to show here.

ui/src/lib/pals.tsnew file+91

This diff is too big to show here.

ui/src/lib/ship.tsnew file+114

This diff is too big to show here.

ui/src/lib/sigil.tsnew file+387

This diff is too big to show here.

ui/src/lib/utils.ts+58−4

This diff is too big to show here.

ui/src/main.ts+5−2

This diff is too big to show here.

ui/src/routes/HelpPage.sveltenew file+26

This diff is too big to show here.

ui/src/routes/Home.svelte+191−7

This diff is too big to show here.

ui/src/routes/ShipViewPage.sveltedeleted−26

This diff is too big to show here.

ui/src/routes/SigilPage.sveltenew file+61

This diff is too big to show here.

ui/src/stores/docs.tsnew file+44

This diff is too big to show here.

ui/src/stores/keys.tsnew file+68

This diff is too big to show here.

ui/src/stores/pageName.tsnew file+12

This diff is too big to show here.

ui/src/stores/searchStores.tsnew file+66

This diff is too big to show here.

ui/src/stores/store.ts+66−24

This diff is too big to show here.

ui/src/styles/docs.scssnew file+49

This diff is too big to show here.

ui/src/styles/styles.scssnew file+13

This diff is too big to show here.

ui/src/styles/tailwind-output.css+1556−74

This diff is too big to show here.

ui/src/styles/tippy.cssnew file+5

This diff is too big to show here.

ui/src/types/id.tsnew file+1

This diff is too big to show here.

ui/src/types/sigil.tsnew file+148

This diff is too big to show here.

ui/src/types/store.ts+66−4

This diff is too big to show here.

ui/svelte.config.js+2−2

This diff is too big to show here.

ui/tailwind.config.cjs+38−3

This diff is too big to show here.

ui/tsconfig.json+9

This diff is too big to show here.

ui/vite.config.ts+22−2

This diff is too big to show here.